[
  {
    "path": ".gitignore",
    "content": "a.out\ngc\nchrome_beta\nchrome_dev\nchrome_stable\nlinux-*\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2021-2026 bata24 (@bata_24)\n\nThis is a fork of GEF (https://github.com/hugsy/gef).\nThis software is released under the MIT license.\nSee https://opensource.org/licenses/MIT\n\nCopyright (c) 2013-2026 crazy rabbidz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![](images/logo.png)\n\n## Image\n![](images/context.png)\n\n## Table of Contents\n- [What Is This?](#what-is-this)\n- [Setup](#setup)\n    - [Supported Environment](#supported-environment)\n    - [Install](#install)\n    - [Upgrade](#upgrade)\n    - [Uninstall](#uninstall)\n    - [Dependencies](#dependencies)\n- [Added / Improved Features](#added--improved-features)\n    - [Supported Modes](#supported-modes)\n    - [Qemu-system Cooperation](#qemu-system-cooperation)\n    - [Qemu-user Cooperation](#qemu-user-cooperation)\n    - [Heap Dump Features](#heap-dump-features)\n    - [Improved Features](#improved-features)\n    - [Added Features](#added-features)\n    - [Other](#other)\n- [FAQ](#faq)\n- [Links](#links)\n\n## What Is This?\nThis is a fork of [GEF](https://github.com/hugsy/gef) that includes three major improvements:\n1. Adds heuristic commands for kernel debugging __without requiring a symbolized `vmlinux`__ (for `qemu-system`, supports Linux kernel 3.x-6.19.x).\n2. Expands support to [many architectures](docs/QEMU-USER-SUPPORTED-ARCH.md) (for `qemu-user`).\n3. Provides heap dump commands for multiple memory allocators.\n\nNumerous other commands have been added and enhanced. Enjoy!\n\n## Setup\n\n### Supported Environment\n- Verified on Ubuntu 24.04-25.10.\n- Expected to work on Ubuntu 22.04-23.10.\n- Might work on Ubuntu 20.04-21.10, though not recommended.\n\n### Install\n- Run the following command:\n    ```bash\n    wget -q https://raw.githubusercontent.com/bata24/gef/dev/install-uv.sh -O- | sudo sh\n    ```\n    - Notes\n        - To simplify installation, `gef.py` is always installed to `/root/.gef/gef.py`\n        - The required Python packages are in `/root/.gef/.venv-gef`.\n        - GEF's directory (`/root/.gef`) is also registered in `/root/.gdbinit`.\n        - For more installation options (for non-`root` user, etc), see [docs/FAQ.md](docs/FAQ.md).\n\n- Or, quick trial (no installation):\n    ```bash\n    wget https://raw.githubusercontent.com/bata24/gef/dev/gef.py\n    echo \"source $(pwd)/gef.py\" >> ~/.gdbinit\n    ```\n    - Notes\n        - Most features work fine even without external tools or `root` privileges.\n        - For limitations, see [docs/FAQ.md](docs/FAQ.md).\n\n### Upgrade\n```bash\npython3 /root/.gef/gef.py --upgrade\n```\n\n- Note\n    - If you get errors after upgrading, it may be due to old config. Try renaming `/root/.gef.rc`.\n\n### Uninstall\n```bash\nrm -rf /root/.gef\nrm -f /root/.gef.rc\nrm -rf /tmp/gef\nsed -i -e '/from gef import/d' /root/.gdbinit\n```\n\n### Dependencies\nPlease refer to [install-uv.sh](install-uv.sh) for installation requirements.\n\n## Added / Improved Features\n\n### Supported Modes\n- Standard debugging\n- Attaching to a running process\n- Attaching to a process in an isolated namespace (e.g., attaching from outside a **Docker** container)\n- Connecting to **Gdbserver**\n- Connecting to the GDB stub of **Qemu-system**\n- Connecting to the GDB stub of **Qemu-user**\n- Connecting to the GDB stub of **Intel Pin**\n- Connecting to the GDB stub of **Intel SDE**\n- Connecting to the GDB stub of **Qiling framework**\n- Connecting to the GDB stub of **KGDB** (requires GDB version 12 or later)\n- Connecting to the GDB stub of **VMWare**\n- Connecting to the GDB stub of **Wine**\n- Debugging with **Record and replay** (`rr replay`)\n\nFor a comprehensive list and additional details, see [docs/SUPPORTED-MODE.md](docs/SUPPORTED-MODE.md).\n\n### Qemu-system Cooperation\n- `pagewalk`: dumps page tables.\n    - x64 (Supported: 4-Level/5-Level Paging)\n        - ![](images/pagewalk-x64.png)\n    - x86 (Supported: PAE/Non-PAE)\n        - ![](images/pagewalk-x86.png)\n    - ARM64 (Supported: Cortex-A only, EL0-EL3, Stage1-2)\n        - ARM v8.7 base. 32bit mode is NOT supported.\n        - ![](images/pagewalk-arm64.png)\n        - Here is a sample of each level pagewalk from HITCON CTF 2018 `super_hexagon`.\n        - ![](images/pagewalk-arm64-el123.png)\n        - Secure memory scanning is also supported, but you have to break in the secure world.\n        - ![](images/pagewalk-arm64-secure.png)\n        - Pseudo memory map without detailed flags and permissions can be output even in the normal world (when OP-TEE).\n        - ![](images/pagewalk-arm64-secure-pseudo.png)\n    - ARM (Supported: Cortex-A only, LPAE/Non-LPAE, PL0/PL1)\n        - ARM v7 base. PL2 is NOT supported.\n        - ![](images/pagewalk-arm.png)\n        - Secure memory scanning is also supported, and you don't have to break in the secure world (unlike ARM64).\n        - ![](images/pagewalk-arm-secure.png)\n- `v2p`/`p2v`: displays the transformation between virtual addresses and physical addresses.\n    - ![](images/v2p-p2v.png)\n- `xp`: is a shortcut for physical memory dump.\n    - ![](images/xp.png)\n- `qreg`: displays the register values from qemu-monitor (allows getting values like `$cs` even under qemu 2.x).\n    - It is a shortcut for `monitor info registers`.\n    - It also prints the details of each bit of the system register when x64/x86.\n    - ![](images/qreg.png)\n- `sysreg`: pretty prints system registers.\n    - It shows `info registers` results, excluding general registers.\n    - ![](images/sysreg.png)\n- `msr`: reads/writes MSR (Model Specific Registers) value by embedding/executing dynamic assembly.\n    - Supported on x64 and x86.\n    - ![](images/msr.png)\n- `cet`: displays Intel CET settings.\n- `vbar`: displays ARM/ARM64 vector table.\n    - ![](images/vbar.png)\n- `kbase`: displays the kernel base address.\n- `kversion`: displays the kernel version.\n- `kcmdline`: displays the kernel cmdline used at boot time.\n- `kcurrent`: displays current task address.\n    - ![](images/kbase-kversion-kcmdline-kcurrent.png)\n- `kvmmap`: prints kernel memory map.\n    - ![](images/kvmmap.png)\n- `ksymaddr-remote`: displays kallsyms information from scanning kernel memory.\n    - Supported kernel versions: 3.x to 6.19.x.\n    - ![](images/ksymaddr-remote.png)\n- `ksymaddr-remote-apply`/`vmlinux-to-elf-apply`: applies kallsyms information obtained by `ksymaddr-remote` or `vmlinux-to-elf` to gdb.\n    - ![](images/ksymaddr-remote-apply.png)\n    - ![](images/vmlinux-to-elf-apply.png)\n    - Once you get a symboled pseudo ELF file, you can reuse and apply it automatically even after rebooting qemu-system.\n    - `vmlinux-to-elf-apply` and `ksymaddr-remote-apply` provide almost the same functionality.\n        - `vmlinux-to-elf-apply`: Requires installation of external tools. Create `vmlinux` with symbols.\n        - `ksymaddr-remote-apply`: Requires no external tools. Create a blank ELF with embedded symbols only.\n- `ktypes`: displays kernel type information from scanning kernel memory.\n    - ![](images/ktypes.png)\n- `ktypes-load`: loads kernel type information from scanning kernel memory.\n    - ![](images/ktypes-load.png)\n- `slub-dump`: dumps slub free-list.\n    - Supported on x64/x86/ARM64/ARM + `SLUB` + no-symbol + kASLR.\n    - Supported regardless of whether `CONFIG_SLAB_FREELIST_HARDENED` is `y` or `n`.\n    - Supported regardless of whether `CONFIG_SLAB_VIRTUAL` is `y` or `n` (x64 only).\n    - It supports `sheaf/barn` mechanism for linux 6.18~.\n    - It supports dumping partial pages (`-v`) and NUMA node pages (`-vv`).\n    - Since `page_to_virt` is difficult to implement, it will heuristically determine the virtual address from the free-list.\n    - ![](images/slub-dump.png)\n- `slab-dump`: dumps slab free-list.\n    - Supported on x64/x86/ARM64/ARM + `SLAB` + no-symbol + kASLR.\n    - ![](images/slab-dump.png)\n- `slob-dump`: dumps slob free-list.\n    - Supported on x64/x86/ARM64/ARM + `SLOB` + no-symbol + kASLR.\n    - ![](images/slob-dump.png)\n- `slub-tiny-dump`: dumps slub-tiny free-list.\n    - Supported on x64/x86/ARM64/ARM + `SLUB-TINY` + no-symbol + kASLR.\n    - ![](images/slub-tiny-dump.png)\n- `slab-contains`: resolves the slab cache (`kmem_cache`) that a certain address (object) belongs to (for `SLUB`/`SLUB-TINY`/`SLAB`).\n    - ![](images/slab-contains.png)\n    - For `SLUB`/`SLUB-TINY`, if all chunks belonging to a certain `page` are in use, they will not be displayed by `slub-dump`/`slub-tiny-dump` command.\n    - Even with such an address (object), this command may be able to resolve `kmem_cache`.\n- `kmem-cache-alias`: dumps `kmem_cache` alias name.\n    - ![](images/kmem-cache-alias.png)\n- `buddy-dump`: dumps the zone of the page allocator (buddy allocator) free-list.\n    - ![](images/buddy-dump.png)\n- `vmalloc-dump`: dumps `vmalloc` used-list and freed-list.\n    - ![](images/vmalloc-dump.png)\n- `page`: displays the transformation between a `struct page` and its virtual/physical address.\n    - ![](images/page.png)\n    - There are shortcuts: `virt2page`, `page2virt`, `phys2page` and `page2phys`.\n- `slab-virtual`: displays the transformation between slab-meta and its slab-data/`struct page` address (for `CONFIG_SLAB_VIRTUAL=y`).\n    - ![](images/slab-virtual.png)\n- `pageinfo`: dumps `struct page->{flags,page_type}`.\n- `highmem-dump`: dumps `HighMem` mappings.\n    - ![](images/highmem-dump.png)\n- `kchecksec`: checks kernel security.\n    - ![](images/kchecksec.png)\n- `kmagic`: displays useful addresses in the kernel.\n    - ![](images/kmagic.png)\n- `kconfig`: dumps the kernel config if available.\n    - ![](images/kconfig.png)\n- `syscall-table-view`: displays the system call table.\n    - ![](images/syscall-table-view.png)\n    - It also dumps the ia32/x32 syscall table under x64.\n    - It also dumps the compat syscall table under ARM64.\n- `ksysctl`: dumps the sysctl parameters.\n    - ![](images/ksysctl.png)\n- `ktask`: displays each task's address.\n    - ![](images/ktask.png)\n    - It also displays the memory map of the userland process.\n    - ![](images/ktask-maps.png)\n    - It also displays the register values saved on the kstack of the userland process.\n    - ![](images/ktask-regs.png)\n    - It also displays the file descriptors of the userland process.\n    - ![](images/ktask-fd.png)\n    - It also displays the signal handlers of the userland process.\n    - ![](images/ktask-sighands.png)\n    - It also displays the namespaces of the userland process.\n    - ![](images/ktask-namespaces.png)\n    - It also displays the seccomp-filter.\n    - ![](images/ktask-seccomp.png)\n- `kmod`: displays each module's address.\n    - ![](images/kmod.png)\n    - It also displays the symbols of each module.\n    - ![](images/kmod-syms.png)\n- `kload`: loads `vmlinux` without a load address.\n    - It is useful if you have a `vmlinux` with `debuginfo` at hand.\n- `kmod-load`: loads the kernel module without a load address.\n    - It is useful if you have a kernel module with `debuginfo` at hand.\n- `kops`: displays each operation's member.\n    - ![](images/kops.png)\n- `kcdev`: displays information for each character device.\n    - ![](images/kcdev.png)\n- `kbdev`: displays information for each block device.\n    - If there are too many block devices, detection will not be successful.\n    - This is because block devices are not managed in one place, so I use the list of `bdev_cache` obtained from the slub-dump results.\n    - ![](images/kbdev.png)\n- `kfilesystems`: dumps supported file systems.\n    - ![](images/kfilesystems.png)\n- `kclock-source`: dumps the clocksource list.\n    - ![](images/kclock-source.png)\n- `kdmesg`: dumps the ring buffer of the dmesg area.\n    - ![](images/kdmesg.png)\n- `kpipe`: displays information for each pipe.\n    - ![](images/kpipe.png)\n- `kbpf`: dumps the BPF information.\n    - ![](images/kbpf.png)\n- `ktimer`: dumps the timer.\n    - ![](images/ktimer.png)\n- `kpcidev`: dumps the PCI devices.\n    - ![](images/kpcidev.png)\n- `kipcs`: dumps IPCs information (System V semaphore, message queue and shared memory).\n    - ![](images/kipcs.png)\n- `kdevio`: dumps I/O-port and I/O-memory information.\n    - ![](images/kdevio.png)\n- `kdmabuf`: dumps DMA-BUF information.\n    - ![](images/kdmabuf.png)\n- `kirq`: dumps irq information.\n    - ![](images/kirq.png)\n- `knetdev`: displays net devices.\n    - ![](images/knetdev.png)\n- `ksearch-code-ptr`: searches for the code pointer in kernel data area.\n    - ![](images/ksearch-code-ptr.png)\n- `thunk-tracer`: collects and displays the thunk function addresses that are called automatically (x64/x86 only).\n    - If this address comes from RW area, this is useful for getting RIP.\n    - ![](images/thunk-tracer.png)\n- `usermodehelper-tracer`: collects and displays the information that is executed by `call_usermodehelper_setup`.\n    - ![](images/usermodehelper-tracer.png)\n- `kmalloc-tracer`: collects and displays information when `kmalloc`/`kfree`.\n    - ![](images/kmalloc-tracer.png)\n- `kmalloc-allocated-by`: calls a predefined set of system calls and prints structures allocated by `kmalloc` or freed by `kfree`.\n    - ![](images/kmalloc-allocated-by.png)\n- `ktrace`: traces kernel functions and arguments.\n    - ![](images/ktrace.png)\n- `xsm`: dumps secure memory when gdb is in normal world.\n    - Supported on ARM64 and ARM.\n    - ![](images/xsm.png)\n- `wsm`: writes the value to secure memory when gdb is in normal world.\n    - Supported on ARM64 and ARM.\n    - ![](images/wsm.png)\n- `bsm`: sets the breakpoint to secure memory when gdb is in normal world.\n    - Supported on ARM64 and ARM.\n    - ![](images/bsm.png)\n- `optee-break-ta`: sets the breakpoint to the offset of OPTEE-Trusted-App when gdb is in normal world.\n    - Supported on ARM64 and ARM.\n    - ![](images/optee-break-ta.png)\n- `optee-smc-service-dump`: dumps OPTEE SMC services.\n    - Supported on ARM64.\n    - ![](images/optee-smc-service-dump.png)\n- `optee-ta-dump`: dumps the information of OPTEE-Trusted-Apps from the memory or specified host directory.\n    - Supported on ARM64 and ARM.\n    - ![](images/optee-ta-dump.png)\n- `optee-shm-list`: shows the information of dynamic shared-memory buffers.\n    - Supported on ARM64 and ARM.\n    - ![](images/optee-shm-list.png)\n- `pac-keys`: pretty prints ARM64 PAC keys.\n    - Supported on ARM64.\n    - ![](images/pac-keys.png)\n- `uefi-ovmf-info`: dumps addresses of some important structures in each boot phase of UEFI when OVMF is used.\n    - Supported on x64.\n    - ![](images/uefi-ovmf-info.png)\n- `qemu-device-info`: dumps device information for qemu-escape.\n\n### Qemu-user Cooperation\n- `si`/`ni`: are wrappers for native `si`/`ni` if OpenRISC 1000 or CRIS.\n    - On OpenRISC 1000 architecture, branch operations don't work well, so GEF uses breakpoints to simulate.\n    - On CRIS architecture, `stepi`/`nexti` commands don't work well, so GEF uses breakpoints to simulate.\n    - If you want to use native `si`/`ni`, use the full form `stepi`/`nexti`.\n- `c`: is the wrapper for native `c` if gdb is connected to `qemu-user` or `Intel Pin`.\n    - When connecting to gdb stub of `qemu-user` or `Intel Pin`, gdb does not trap `SIGINT` during `continue`.\n    - If you want to trap, you need to issue `SIGTRAP` on the `qemu-user` or `pin` side, but switching screens is annoying.\n    - This command realizes a pseudo `SIGTRAP` trap by trapping `SIGINT` on the Python side and throwing `SIGTRAP` back to `qemu-user` or `Intel Pin`.\n    - It works only for local `qemu-user` or `Intel Pin`.\n    - If you want to use native `c`, use the full form `continue`.\n\n### Heap Dump Features\n- Glibc heap commands has been improved. Supports up to glibc 2.43.\n    - It changes the color and prints a symbol if it exists.\n        - ![](images/heap-bins.png)\n    - They print bins information if the chunk is in free-list.\n        - ![](images/heap-if-in-freelist.png)\n    - Thread arena is supported for all `heap` commands.\n        - Use `-a` option.\n    - It supports some new sub-commands.\n        - `heap arenas`\n            - ![](images/heap-arenas.png)\n        - `heap top`\n            - ![](images/heap-top.png)\n        - `heap bins-simple`: displays the heap like pwndbg style.\n            - ![](images/heap-bins-simple.png)\n        - `heap parse`: displays the heap like as Pwngdb/angelheap style.\n            - ![](images/heap-parse.png)\n        - `heap try-malloc`\n            - ![](images/heap-try-malloc.png)\n        - `heap try-free`\n            - ![](images/heap-try-free.png)\n            - You can also execute any command on the memory status after emulation is completed.\n                - ![](images/heap-try-free-bs.png)\n        - `heap try-realloc`\n        - `heap try-calloc`\n        - `heap tcache-index-helper`\n            - ![](images/heap-index-helper.png)\n        - `heap find-fake-fast`: searches for a memory with a size-like value that can be linked to the fastbin free-list.\n            - ![](images/heap-find-fake-fast.png)\n        - `heap extract-heap-addr`: analyzes tcache-protected-fd introduced from glibc-2.32.\n            - ![](images/heap-extract-heap-addr.png)\n        - `heap calc-protected-fd`: calculates a valid value as protected fd.\n            - ![](images/heap-calc-protected-fd.png)\n        - `heap visual-heap`: is colorized heap viewer.\n            - ![](images/heap-visual-heap.png)\n        - `heap tracer`: has been integrated from `heap-analysis-helper` and rewritten.\n            - ![](images/heap-tracer.png)\n        - `heap dump-image`: visualizes chunks on a heap as composition image.\n            - ![](images/heap-dump-image.png)\n        - `heap snapshot`: takes a snapshot of the heap.\n        - `heap snapshot-compare`: compares current heap with a previously saved heap-snapshot.\n            - ![](images/heap-snapshot-compare.png)\n- uClibc heap commands are added.\n    - `uclibc-ng-heap-dump`: dumps uClibc-ng heap chunks.\n        - Supported on x64 and x86, based on uClibc-ng malloc-standard.\n        - ![](images/uclibc-ng-heap-dump.png)\n        - How to test (x64):\n            - Download and extract `x86-64--uclibc--stable-2025.08-1.tar.bz2` from https://toolchains.bootlin.com/\n            - Add `/PATH/TO/x86_64-buildroot-linux-uclibc/bin` to `$PATH`, then build as `x86_64-linux-gcc test.c`.\n            - Fix interpreter by `patchelf --set-interpreter /PATH/TO/x86_64-buildroot-linux-uclibc/sysroot/lib/ld64-uClibc.so.0 a.out`.\n    - `uclibc-ng-visual-heap`: is colorized heap viewer for uClibc-ng.\n        - ![](images/uclibc-ng-visual-heap.png)\n- `partition-alloc-dump`: dumps Partition-Alloc free-list for chromium.\n    - ![](images/partition-alloc-dump.png)\n    - This command is reserved for the implementation of the latest version of Chromium.\n        - Currently tested: v146.x / [1579809](https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/1579809/) / e1b69f3442bc215bd78dc42426c6b3232b5cd8be\n    - Supported on x64 and ARM64 (maybe it works on x86/ARM too, but not tested).\n    - It will try heuristic search if the binary has no symbol.\n    - How to test:\n        - See [dev/partition-alloc-dump/downloader.py](dev/partition-alloc-dump/downloader.py).\n- `tcmalloc-dump`: dumps TCMalloc (`gperftools-2.16-1` or named `libgoogle-perftools{4,-dev}`) free-list (x64 only).\n    - ![](images/tcmalloc-dump.png)\n    - How to test:\n        - Execute as `LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc.so ./a.out`.\n- `musl-heap-dump`: dumps Musl-Libc v1.2.5 heap chunks (x64/x86 only).\n    - ![](images/musl-heap-dump.png)\n    - How to test:\n        - Get and extract the latest source from https://musl.libc.org/\n        - Build with `./configure && make install`.\n        - Build as `/usr/local/musl/bin/musl-gcc test.c`.\n- `go-heap-dump`: dumps Go Language v1.24.4 mheap (x64 only).\n    - ![](images/go-heap-dump.png)\n- `tlsf-heap-dump`: dumps TLSF (Two-Level Segregated Fit) v2.4.6 free-list (x64 only).\n    - ![](images/tlsf-heap-dump.png)\n    - How to test (x64):\n        - Get and extract the latest source from http://www.gii.upv.es/tlsf/\n        - Build with `cd TLSF-2.4.6/src && make && cd ../examples && make` then use `test1` etc.\n- `hoard-heap-dump`: dumps Hoard v3.2 (2025/12/31) free-list (x64 only).\n    - ![](images/hoard-heap-dump.png)\n    - How to test (x64):\n        - Get and extract the latest source from https://github.com/emeryberger/Hoard\n        - Build with `cd Hoard/src && make`.\n        - Execute as `LD_PRELOAD=/PATH/TO/libhoard.so ./a.out`.\n- `mimalloc-heap-dump`: dumps mimalloc free-list (x64 only).\n    - ![](images/mimalloc-heap-dump.png)\n    - How to test (x64):\n        - Get and extract the latest source from https://github.com/microsoft/mimalloc\n        - Build with `mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && make`.\n        - Execute as `LD_PRELOAD=/PATH/TO/libmimalloc.so ./a.out`.\n- `scalloc-heap-dump`: dumps scalloc free-list (x64 only).\n    - ![](images/scalloc-heap-dump.png)\n    - How to test (x64):\n        - Get and extract the latest source from https://github.com/cksystemsgroup/scalloc\n        - Fix the bug with `sed -i -e 's/\\(strncat(.*\\), 1);/\\1, 2);/' src/log.h`.\n        - Build with `gyp --depth . scalloc.gyp && make`.\n        - Enable overcommit with `echo 1 > /proc/sys/vm/overcommit_memory`.\n        - Execute as `LD_PRELOAD=/PATH/TO/libscalloc.so ./a.out`.\n- `snmalloc-heap-dump`: dumps snmalloc free-list (x64 only).\n    * ![](https://raw.githubusercontent.com/bata24/gef/dev/images/snmalloc-heap-dump.png)\n    * How to test (x64):\n        - Get and extract the latest source from https://github.com/microsoft/snmalloc\n        - Build with `mkdir build && cd build && cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Debug && ninja`.\n        - Execute as `LD_PRELOAD=/PATH/TO/libsnmallocshim.so ./a.out`.\n- `optee-bget-dump`: dumps bget allocator of OPTEE-Trusted-App.\n    - ![](images/optee-bget-dump.png)\n- `v8`: displays v8 (Chromium and `d8`) tagged object.\n    - ![](images/v8.png)\n    - It also loads more commands from latest gdbinit for v8.\n    - ![](images/v8-load.png)\n- `cage`: displays v8 (Chromium and `d8`) ubercage.\n    - ![](images/cage.png)\n- `v8-list-maps`: lists v8 (Chromium and `d8`) built-in maps.\n    - ![](images/v8-list-maps.png)\n- `v8-dump-space`: dumps v8 (Chromium and `d8`) heap objects in each space.\n    - ![](images/v8-dump-space.png)\n\n### Improved Features\n- `vmmap`\n    - It displays the memory map information even when connecting to gdb stub of `qemu-user`.\n        - ![](images/vmmap-qemu-user.png)\n    - It also supports `Intel Pin`.\n        - ![](images/vmmap-pin.png)\n    - It also supports `Intel SDE`.\n        - ![](images/vmmap-sde.png)\n    - It is redirected to `kvmmap` when connecting to gdb stub of `qemu-system`.\n    - It supports detection and coloring of `Writable`, `ReadOnly`, `None` and `RWX` regions.\n    - It shows the area each register points to.\n- `registers`\n    - It also shows raw values of the flag register, the current ring, the exception level, the secure state, etc.\n        - ![](images/registers-x64.png)\n        - ![](images/registers-arm64.png)\n        - ![](images/registers-arm.png)\n- `context`\n    - It supports automatic display of system call arguments when calling a system call.\n        - ![](images/context-syscall-args.png)\n    - It supports new commands:\n        - `context on`\n        - `context off`\n    - It supports automatic display of address and value when accessing memory.\n        - ![](images/context-memory-access.png)\n    - It supports smart symbol printing for C++ function.\n        - ex: `std::map<int, std::map<int, int>>` will be replaced by `std::map<...>`.\n        - ![](images/smart-cpp-function-name.png)\n        - command: `gef config context.smart_cpp_function_name true` or `smart-cpp-function-name` (later is used to toggle).\n- `telescope`\n    - It displays ordinal numbers as well as offsets.\n    - It displays if there are canaries and return addresses in the target area.\n        - ![](images/telescope.png)\n    - It supports blacklist address features (to avoid dying when touching the address mapped to the serial device).\n    - It also shows the symbol if available.\n    - It supports some new options:\n        - `--is-addr`\n        - `--is-not-addr`\n        - `--is-zero`\n        - `--is-not-zero`\n        - `--tag`\n        - `--uniq`\n        - `--interval`\n        - `--depth`\n        - `--phys`\n        - `--list-head`\n        - `--slab-contains`\n        - `--slab-contains-unaligned`\n- `proc-info`\n    - It displays some additional information.\n        - ![](images/proc-info.png)\n- `elf-info`\n    - It displays Program Header and Section Header.\n    - It supports parsing from memory.\n    - It supports parsing remote binary (if download feature is available).\n        - ![](images/elf-info.png)\n- `xinfo`\n    - It shows more information.\n        - ![](images/xinfo.png)\n    - It also supports kernel debugging.\n- `checksec`\n    - It shows additional information.\n        - Static or Dynamic or Static-PIE\n        - Stripped or not\n        - Debuginfo or not\n        - Intel CET IBT/SHSTK\n        - ARMv8 PAC, ARMv8 MTE\n        - RPATH, RUNPATH\n        - Clang CFI/SafeStack\n        - System-ASLR, GDB ASLR setting\n    - It supports parsing remote binary (if download feature is available).\n    - ![](images/checksec.png)\n- `got`\n    - It displays not only GOT address but also PLT address.\n        - ![](images/got.png)\n    - It scans `.plt.sec` section if Intel CET is enabled.\n    - It can also display the GOT of the library.\n        - ![](images/got-libc.png)\n    - It can also display `type`, `offset`, `reloc_arg`, `section` and `permission`.\n        - ![](images/got-v.png)\n- `canary`\n    - It displays all canary positions in memory.\n        - ![](images/canary.png)\n- `edit-flags`\n    - It displays the meaning of each bit if `-v` option is provided.\n        - ![](images/edit-flags-x64.png)\n        - ![](images/edit-flags-arm.png)\n        - ![](images/edit-flags-arm64.png)\n- `unicorn-emulate`\n    - It reads and writes correctly to the address pointed to by `$fs`/`$gs`.\n    - It supports a new mode to stop after executing N instructions (`-g`).\n    - It shows changed memories.\n        - ![](images/unicorn-emulate.png)\n    - It supports replacing the GOT of string functions using avx2 or NEON, which unicorn does not support, with slower original functions.\n- `ropper`\n    - It does not reset autocomplete settings after calling imported `ropper`.\n- `hexdump`\n    - It supports physical memory if under qemu-system.\n    - It will retry with adjusting read size if reading memory fails.\n    - By default, the same line is omitted.\n    - ![](images/hexdump.png)\n- `patch`\n    - It supports physical memory if under qemu-system.\n    - Added some new modes:\n        - `patch hex`\n        - `patch pattern`\n        - `patch nop`\n        - `patch inf`\n        - `patch trap`\n        - `patch ret`\n        - `patch syscall`\n        - `patch history`\n        - `patch revert`\n        - `patch range-replace`\n    - `nop` command has been integrated into `patch` as sub-command.\n    - ![](images/patch.png)\n- `search-pattern`\n    - It is supported under qemu-system (in short, it works without `/proc/self/maps`)\n    - It supports some new options:\n        - `--hex`\n        - `--hex-regex`\n        - `--aligned`\n        - `--perm`\n        - `--interval`\n        - `--limit`\n        - `--max-region-size`\n        - `--phys`\n    - It also searches for UTF-16 string if target string is ASCII.\n    - ![](images/search-pattern.png)\n- `mprotect`\n    - Rewritten to use `call-syscall`.\n- `hijack-fd`\n    - It supports more architectures.\n    - ![](images/hijack-fd.png)\n- `format-string-helper`\n    - It supports more `printf`-like functions.\n- `theme`\n    - Supports many colors.\n    - ![](images/theme.png)\n    - ![](images/theme-colors-sample.png)\n- `reset-cache`\n    - It has been integrated into `gef` as sub-command.\n    - The cache structure within GEF has changed significantly. This command corresponds to them.\n- `tmux-setup`\n    - It has been integrated into `gef` as sub-command.\n    - `screen` is no longer supported.\n    - `tmux` settings are predefined and cannot be customized.\n    - If you want to customize it, edit [dev/tmux/tmux_setup.py](dev/tmux/tmux_setup.py) and run `source /path/to/tmux_setup.py`.\n    - If you're a `zellij` user, you can use [dev/zellij/zellij-wrapper.py](dev/zellij/zellij-wrapper.py). Run this script before starting `gdb` or `zellij`.\n\n### Added Features\n- `pid`/`tid`: prints pid and tid.\n- `filename`: prints filename.\n- `fds`: shows opened file descriptors.\n- `auxv`: pretty prints ELF auxiliary vector.\n    - Supported also under `qemu-user`.\n    - ![](images/auxv.png)\n- `argv`/`envp`: pretty prints argv and envp.\n    - ![](images/argv-envp.png)\n- `dumpargs`: dumps arguments of current function.\n    - ![](images/dumpargs.png)\n- `vdso`: disassembles the text area of vdso smartly.\n    - ![](images/vdso.png)\n- `vvar`: dumps the area of vvar.\n    - This area is mapped to userland, but cannot be accessed from gdb.\n    - Therefore, it executes the assembly code and retrieves the contents.\n    - ![](images/vvar.png)\n- `gdtinfo`: pretty prints GDT entries. If userland, show sample entries.\n    - ![](images/gdtinfo.png)\n- `idtinfo`: pretty prints IDT entries. If userland, show sample entries.\n    - ![](images/idtinfo.png)\n- `tls`: pretty prints TLS area. Requires glibc.\n    - ![](images/tls.png)\n- `fsbase`/`gsbase`: pretty prints `$fs_base`, `$gs_base`.\n    - ![](images/fsbase_gsbase.png)\n- `libc`/`ld`/`heapbase`/`codebase`: displays each of the base address.\n    - ![](images/base.png)\n- `got-all`: shows got entries for all libraries.\n- `break-rva`: sets a breakpoint at relative offset from codebase.\n    - ![](images/break-rva.png)\n- `command-break`: sets a breakpoint which executes user defined command if hit.\n    - ![](images/command-break.png)\n- `main-break`: sets a breakpoint at `main` with or without symbols, then continue.\n    - This is useful when you just want to run to `main` using `qemu-user` or `pin`, or debugging no-symbol ELF.\n- `load-break`: breaks if something is loaded.\n- `regdump-break`: sets a breakpoint which dumps specified registers if hit.\n- `multi-break`: sets multiple breakpoints easily.\n- `break-if-taken`/`break-if-not-taken`: sets a breakpoint which breaks if branch is taken (or not taken).\n- `distance`: calculates the offset from its base address.\n    - ![](images/distance.png)\n- `fpu`/`mmx`/`sse`/`avx`/`avx512`: pretty prints FPU/MMX/SSE/AVX/AVX512 registers.\n    - ![](images/fpu-mmx-sse-avx.png)\n- `xmmset`: sets the value to xmm/ymm/zmm register simply.\n    - ![](images/xmmset.png)\n- `mmxset`: sets the value to mm register simply.\n    - ![](images/mmxset.png)\n- `exec-until`: executes until specified operation.\n    - Supports the following patterns:\n        - call\n        - jmp\n        - syscall\n        - ret\n        - indirect-branch (x64/x86 only)\n        - all-branch (call || jmp || ret)\n        - memory-access (detect just `[...]`)\n        - specified-keyword-regex\n        - specified-condition (expressions using register or memory values)\n        - user-code\n        - libc-code\n        - secure-world\n        - region-change\n    - ![](images/exec-until.png)\n- `call-trace`: traces call, ret, and syscall instructions.\n    - ![](images/call-trace.png)\n- `xuntil`: executes until specified address.\n    - It is slightly easier to use than the original until command.\n- `add-symbol-temporary`: adds symbol information from command-line.\n    - ![](images/add-symbol-temporary.png)\n- `errno`: displays errno list or specified errno.\n    - ![](images/errno.png)\n- `u2d`: shows cast/convert u64 <-> double/float.\n    - ![](images/u2d.png)\n- `unsigned`: shows unsigned value.\n    - ![](images/unsigned.png)\n- `convert`: shows various conversion.\n    - ![](images/convert.png)\n- `addressify`: converts reverse-order hex values to address.\n    - ![](images/addressify.png)\n- `walk-link-list`: walks the link list.\n    - ![](images/walk-link-list.png)\n- `hexdump-flexible`: displays the hexdump with user defined format.\n    - ![](images/hexdump-flexible.png)\n- `hash`: calculates various hashes, or show known-collisions.\n    - ![](images/hash.png)\n- `crc`: calculates various CRCs.\n    - ![](images/crc.png)\n- `json`: pretty prints json.\n    - ![](images/json.png)\n- `base-n-decode`/`base-n-encode`: decodes/encodes various baseN.\n    - ![](images/base-n-decode.png)\n- `morse-decode`/`morse-encode`: decodes/encodes morse code.\n    - ![](images/morse-decode.png)\n- `saveo`/`diffo`: saves and diffs the command outputs.\n    - ![](images/saveo-diffo.png)\n- `memcmp`: compares the contents of the address A and B, whether virtual or physical.\n    - ![](images/memcmp.png)\n- `memset`: sets the value to the memory range, whether virtual or physical.\n- `memcpy`: copies the contents from the address A to B, whether virtual or physical.\n- `memswap`: swaps the contents of the address A and B, whether virtual or physical.\n- `meminsert`: inserts the contents of the address A to B, whether virtual or physical.\n    - ![](images/meminsert.png)\n- `strlen`: detects the length of the string.\n    - ![](images/strlen.png)\n- `is-mem-zero`: checks the contents of address range are all 0x00 or 0xff.\n    - ![](images/is-mem-zero.png)\n- `seq-length`: detects consecutive length of the same sequence.\n    - ![](images/seq-length.png)\n- `strings`: searches for ASCII string from specific location.\n    - ![](images/strings.png)\n- `xs`: dumps string like `x/s` command, but with hex-string style.\n    - ![](images/xs.png)\n- `xc`: dumps address like `x/x` command, but with coloring at some intervals.\n    - ![](images/xc.png)\n- `ii`: is a shortcut for `x/50i $pc` with opcode bytes.\n    - It prints the value if it is memory access operation.\n    - ![](images/ii.png)\n- `extra`: manages user specified command to execute when each step.\n- `comment`: manages user specified temporary comment.\n- `seccomp`: invokes `ceccomp` or `seccomp-tools`.\n- `onegadget`: invokes `one_gadget`.\n    - ![](images/onegadget.png)\n- `rp`: invokes `rp++` with commonly used options.\n- `call-syscall`: calls system call with specified values.\n    - ![](images/call-syscall.png)\n- `mmap`: allocates a new memory by `call-syscall`.\n- `munmap`: unmaps a memory by `call-syscall`.\n- `killthreads`: kills specific or all threads (for `pthread`).\n- `constgrep`: invokes `grep` under `/usr/include/`.\n    - ![](images/constgrep.png)\n- `proc-dump`: dumps each file under `/proc/PID/`.\n    - ![](images/proc-dump.png)\n- `up`/`down`: are wrappers for native `up`/`down`.\n    - It shows also backtrace.\n- `time`: measures the time of the GDB command.\n    - ![](images/time.png)\n- `multi-line`: executes multiple GDB commands in sequence.\n    - ![](images/multi-line.png)\n- `cpuid`: shows the result of cpuid(eax=0,1,2...).\n    - ![](images/cpuid.png)\n- `read-system-register-for-qemu-arm`: reads system register for old `qemu-system-arm`.\n- `read-system-register-for-kgdb`: reads system register for kgdb (x64/ARM64 only).\n- `capability`: shows the capabilities of the debugging process.\n    - ![](images/capability.png)\n- `dasm`: disassembles the code by capstone.\n    - ![](images/dasm.png)\n- `asm-list`: lists instructions. (x64/x86 only)\n    - ![](images/asm-list.png)\n    - This command uses x86data.js from https://github.com/asmjit/asmdb\n- `syscall-search`: searches for system call by regex.\n    - ![](images/syscall-search.png)\n- `dwarf-exception-handler`: dumps the DWARF exception handler information.\n    - ![](images/dwarf-exception-handler.png)\n- `magic`: displays useful addresses in glibc etc.\n    - ![](images/magic.png)\n- `dynamic`: dumps the `_DYNAMIC` area.\n    - ![](images/dynamic.png)\n- `link-map`: dumps useful members of `link_map` with iterating.\n    - ![](images/link-map.png)\n- `dtor-dump`: dumps some destructor functions list.\n    - ![](images/dtor-dump.png)\n- `ptr-mangle`: shows the mangled value that will be mangled by `PTR_MANGLE`.\n- `ptr-demangle`: shows the demangled value of the value mangled by `PTR_MANGLE`.\n    - ![](images/ptr-mangle-demangle.png)\n- `search-mangled-ptr`: searches for the mangled value from RW memory.\n    - ![](images/search-mangled-ptr.png)\n- `follow`: changes `follow-fork-mode` setting.\n    - ![](images/follow.png)\n- `smart-cpp-function-name`: toggles `context.smart_cpp_function_name` setting.\n- `ret2dl-hint`: shows the structure used by return-to-dl-resolve as hint.\n    - ![](images/ret2dl-hint.png)\n- `srop-hint`: shows the code for sigreturn-oriented-programming as hint.\n    - ![](images/srop-hint.png)\n- `sigreturn`: displays stack values for sigreturn syscall.\n    - ![](images/sigreturn.png)\n- `smart-memory-dump`: dumps all regions of the memory to each file.\n    - ![](images/smart-memory-dump.png)\n- `load-file`: loads the file into memory.\n- `load-file-mmap`: loads the file into memory that allocated by `mmap`.\n- `search-cfi-gadgets`: searches for CFI-valid (for CET IBT) and controllable generally gadgets in the executable area.\n    - ![](images/search-cfi-gadgets.png)\n- `symbols`: lists all symbols with coloring.\n    - ![](images/symbols.png)\n- `types`: lists all types with compaction.\n    - ![](images/types.png)\n- `dt`: makes it easier to use `ptype /ox TYPE` and `p ((TYPE*) ADDRESS)[0]`.\n    - ![](images/dt.png)\n    - This command is designed for several purposes.\n        1. When displaying very large struct, you may want to go through a pager because the results will not fit on one screen.\n           However, using a pager, the color information disappears. This command calls the pager with preserving colors.\n        2. When `ptype /ox TYPE`, interpreting member type recursively often result is too long and difficult to read.\n           This command keeps result compact by displaying only top-level members.\n        3. When `p ((TYPE*) ADDRESS)[0]` for large struct, the setting of `max-value-size` is too small to display.\n           This command adjusts it automatically.\n        4. When debugging a binary written in the Golang, the offset information of the type is not displayed.\n           This command also displays the offset.\n        5. When debugging a binary written in the Golang, the `p ((TYPE*) ADDRESS)[0]` command will be broken.\n           This is because the Golang helper script is automatically loaded and overwrites the behavior of `p` command.\n           This command creates the display results on the Python side, so we can display it without any problems.\n- `mte-tags`: displays the MTE tags for the specified address.\n    - Supported on ARM64.\n    - ![](images/mte-tags.png)\n- `iouring-dump`: dumps the area of iouring (x64 only).\n    - This area is mapped to userland, but cannot be accessed from gdb.\n    - Therefore, it executes the assembly code and retrieves the contents.\n    - ![](images/iouring-dump.png)\n- `gef version`: shows software versions that GEF uses.\n    - ![](images/gef-version.png)\n- `gef status`: shows architecture information used in GEF.\n    - ![](images/gef-status.png)\n- `gef reset-breakpoint`: shows and resets all breakpoints.\n- `gef arch-list`: displays defined architecture information.\n    - ![](images/gef-arch-list.png)\n- `gef pyobj-list`: displays defined global Python objects.\n    - ![](images/gef-pyobj-list.png)\n- `gef avail-comm-list`: displays a list of commands which are available or not for the current architecture and gdb execution mode.\n    - ![](images/gef-avail-comm-list.png)\n- `gef set-arch`: sets a specific architecture to GEF.\n- `gef check-update`: checks for GEF updates.\n- `binwalk-memory`: scans memory by `binwalk`.\n    - ![](images/binwalk-memory.png)\n- `filetype-memory`: scans memory by `file` and `magika`.\n    - ![](images/filetype-memory.png)\n- `sixel-memory`: shows image to terminal by `imagemagick`.\n    - ![](images/sixel-memory.png)\n    - If you have `pillow` and `pyzbar` installed, a barcode detection option is also available.\n- `stdio-dump`: dumps members of stdin/stdout/stderr.\n    - ![](images/stdio-dump.png)\n- `peek-pageframe`: reads page frame data.\n    - ![](images/peek-pageframe.png)\n- `peek-pageflags`: reads page flags of a page frame.\n    - ![](images/peek-pageflags.png)\n- `angr`: finds simple constraints by `angr`.\n    - ![](images/angr.png)\n- `history`: shows gdb command history easily.\n    - ![](images/history.png)\n- `crc32rev`: performs CRC32 reverse calculation limited to ASCII character range.\n    - ![](images/crc32rev.png)\n- `vdump`: visualizes memory data like an image.\n    - ![](images/vdump.png)\n- `freq-analysis`: visualizes the frequency of occurrence of each byte.\n- `qemu-system-memory-region-dump`: dumps memory regions for `qemu-system`.\n    - ![](images/qemu-system-memory-region-dump.png)\n- `find-syscall`: searches the syscall gadget.\n    - ![](images/find-syscall.png)\n- `fpchain`: dumps chains from `__IO_list_all`.\n    - ![](images/fpchain.png)\n- `stepi-for-kgdb`: is wrapper for AArch64 KGDB that avoids stepping into pending IRQ handlers.\n\n### Other\n- The category is introduced in `gef help`.\n    - ![](images/gef-help.png)\n- Combined into one file (from `gef-extras`). The following are moved from `gef-extras`.\n    - `current-stack-frame`, `xref-telescope`, `bytearray`, and `bincompare`.\n    - This is because a single file is more attractive for me than ease of maintenance.\n- The system-call table used by `syscall-args` is moved from `gef-extras`.\n    - It was updated up to Linux kernel 6.19 for each architecture.\n- Removed some features that I don't use.\n    - `$`\n    - `ida-interact`\n    - `gef-remote`\n    - `pie`\n    - `pcustom`\n    - `ksymaddr`\n    - `trace-run`\n    - `shellcode`\n- Many bug fixes / formatting improvements / usability enhancements (made it easy for me to use).\n\n## FAQ\n- See [docs/FAQ.md](docs/FAQ.md).\n\n## Links\n- Why I decided to make this\n    - [gefを改造した話](https://hackmd.io/@bata24/rJVtBJsrP)\n- The story behind each command, etc.\n    - [bata24/gefの機能紹介とか](https://hackmd.io/@bata24/SycIO4qPi)\n- The story behind each command, etc. 2024 Edition\n    - [bata24/gefの機能紹介とか 2024](https://hackmd.io/@bata24/SJOzjzqQ1e)\n- The story behind each command, etc. 2025 Edition\n    - [bata24/gefの機能紹介とか 2025](https://hackmd.io/@bata24/rkut9rU7Zg)\n- Orynth project page\n    - https://www.orynth.dev/projects/bata24-gef-8901\n    - Fan token symbol: `B24G` (details in [docs/FAQ.md](docs/FAQ.md))\n"
  },
  {
    "path": "asmdb/x86data.js",
    "content": "// [x86data.js]\n// X86/X64 instruction-set data.\n//\n// [License]\n// Public Domain.\n\n\n// This file can be parsed as pure JSON, locate ${JSON:BEGIN} and ${JSON:END}\n// marks and strip everything outside, a sample JS function that would do the job:\n//\n// function strip(s) {\n//   return s.replace(/(^.*\\$\\{JSON:BEGIN\\}\\s+)|(\\/\\/\\s*\\$\\{JSON:END\\}\\s*.*$)/g, \"\");\n// }\n\n\n// INSTRUCTIONS\n// ============\n//\n// Each instruction definition consists of 5 strings:\n//\n//   [0] - Instruction name.\n//   [1] - Instruction operands.\n//   [2] - Instruction encoding.\n//   [3] - Instruction opcode.\n//   [4] - Instruction metadata - CPU features, FLAGS (read/write), and other metadata.\n//\n// The definition tries to match Intel and AMD instruction set manuals, but there\n// are small differences to make the definition more informative and compact.\n\n\n// OPERANDS\n// ========\n//\n//   * \"op\"    - Explicit operand, must always be part of the instruction. If a fixed\n//               register (like \"cl\") is used, it means that the instruction uses this\n//               register implicitly, but it must be specified anyway.\n//\n//   * \"<op>\"  - Implicit operand - some assemblers allow implicit operands the be passed\n//               explicitly for documenting purposes. And some assemblers like AsmJit's\n//               Compiler infrastructure requires implicit operands to be passed explicitly\n//               for register allocation purposes.\n//\n//   * \"{op}\"  - Optional operand. Mostly used by AVX_512:\n//\n//               - {k} mask selector.\n//               - {z} zeroing.\n//               - {1tox} broadcast.\n//               - {er} embedded-rounding.\n//               - {sae} suppress-all-exceptions.\n//\n//   * \"?:Op\"  - Each operand can provide metadata that can be used to describe which\n//               operands are used as a destination, and which operands are source-only.\n//               Each instruction in general assumes that the first operand is always\n//               read/write and all following operands are read-only. However, this is\n//               not correct for all instructions, thus, instructions that don't match\n//               this assumption must provide additional information:\n//\n//               - \"R:Op\" - The operand is read-only.\n//               - \"w:Op\" - The operand is write-only (does not zero-extend).\n//               - \"W:Op\" - The operand is write-only (implicit zero-extend).\n//               - \"x:Op\" - The operand is read/write (does not zero-extend).\n//               - \"X:Op\" - The operand is read/write (implicit zero-extend).\n//\n//   * Op[A:B] - Optional bit-range that describes which bits are read and written.\n//\n//   * \"~Op\"   - Operand is commutative with other operands prefixed by \"~\". Commutativity\n//               means that all operands marked by '~' can be swapped and the result of the\n//               instruction would be the same.\n\n// WHAT IS MISSING\n// ===============\n//\n// Here is a list of missing instructions to keep track of it:\n//\n// [ ] xlat/xlatb\n\n(function($export, $as) {\n\"use strict\";\n\n$export[$as] =\n// ${JSON:BEGIN}\n{\n  \"architectures\": [\n    \"ANY\",\n    \"X86\",\n    \"X64\"\n  ],\n\n  \"extensions\": [\n    { \"name\": \"3DNOW\"               },\n    { \"name\": \"3DNOW2\"              },\n    { \"name\": \"ADX\"                 },\n    { \"name\": \"AESNI\"               },\n    { \"name\": \"AMX_TILE\"            },\n    { \"name\": \"AMX_BF16\"            },\n    { \"name\": \"AMX_INT8\"            },\n    { \"name\": \"AVX\"                 },\n    { \"name\": \"AVX_VNNI\"            },\n    { \"name\": \"AVX2\"                },\n    { \"name\": \"AVX512_4FMAPS\"       },\n    { \"name\": \"AVX512_4VNNIW\"       },\n    { \"name\": \"AVX512_BF16\"         },\n    { \"name\": \"AVX512_BITALG\"       },\n    { \"name\": \"AVX512_BW\"           },\n    { \"name\": \"AVX512_CDI\"          },\n    { \"name\": \"AVX512_DQ\"           },\n    { \"name\": \"AVX512_ERI\"          },\n    { \"name\": \"AVX512_F\"            },\n    { \"name\": \"AVX512_FP16\"         },\n    { \"name\": \"AVX512_IFMA\"         },\n    { \"name\": \"AVX512_PFI\"          },\n    { \"name\": \"AVX512_VBMI\"         },\n    { \"name\": \"AVX512_VBMI2\"        },\n    { \"name\": \"AVX512_VNNI\"         },\n    { \"name\": \"AVX512_VL\"           },\n    { \"name\": \"AVX512_VP2INTERSECT\" },\n    { \"name\": \"AVX512_VPOPCNTDQ\"    },\n    { \"name\": \"BMI\"                 },\n    { \"name\": \"BMI2\"                },\n    { \"name\": \"CET_IBT\"             },\n    { \"name\": \"CET_SS\"              },\n    { \"name\": \"CLDEMOTE\"            },\n    { \"name\": \"CLFLUSH\"             },\n    { \"name\": \"CLFLUSHOPT\"          },\n    { \"name\": \"CLWB\"                },\n    { \"name\": \"CLZERO\"              },\n    { \"name\": \"CMOV\"                },\n    { \"name\": \"CMPXCHG8B\"           },\n    { \"name\": \"CMPXCHG16B\"          },\n    { \"name\": \"ENCLV\"               },\n    { \"name\": \"ENQCMD\"              },\n    { \"name\": \"F16C\"                },\n    { \"name\": \"FMA\"                 },\n    { \"name\": \"FMA4\"                },\n    { \"name\": \"FSGSBASE\"            },\n    { \"name\": \"FXSR\"                },\n    { \"name\": \"GEODE\"               },\n    { \"name\": \"HLE\"                 },\n    { \"name\": \"HRESET\"              },\n    { \"name\": \"GFNI\"                },\n    { \"name\": \"I486\"                },\n    { \"name\": \"LAHFSAHF\"            },\n    { \"name\": \"LWP\"                 },\n    { \"name\": \"LZCNT\"               },\n    { \"name\": \"MCOMMIT\"             },\n    { \"name\": \"MMX\"                 },\n    { \"name\": \"MMX2\"                },\n    { \"name\": \"MONITOR\"             },\n    { \"name\": \"MONITORX\"            },\n    { \"name\": \"MOVBE\"               },\n    { \"name\": \"MOVDIR64B\"           },\n    { \"name\": \"MOVDIRI\"             },\n    { \"name\": \"MPX\"                 },\n    { \"name\": \"MSR\"                 },\n    { \"name\": \"OSPKE\"               },\n    { \"name\": \"PCLMULQDQ\"           },\n    { \"name\": \"PCOMMIT\"             },\n    { \"name\": \"PCONFIG\"             },\n    { \"name\": \"POPCNT\"              },\n    { \"name\": \"PREFETCHW\"           },\n    { \"name\": \"PREFETCHWT1\"         },\n    { \"name\": \"PTWRITE\"             },\n    { \"name\": \"RDPID\"               },\n    { \"name\": \"RDPRU\"               },\n    { \"name\": \"RDRAND\"              },\n    { \"name\": \"RDSEED\"              },\n    { \"name\": \"RDTSC\"               },\n    { \"name\": \"RDTSCP\"              },\n    { \"name\": \"RTM\"                 },\n    { \"name\": \"SEAM\"                },\n    { \"name\": \"SERIALIZE\"           },\n    { \"name\": \"SHA\"                 },\n    { \"name\": \"SKINIT\"              },\n    { \"name\": \"SMAP\"                },\n    { \"name\": \"SMX\"                 },\n    { \"name\": \"SNP\"                 },\n    { \"name\": \"SSE\"                 },\n    { \"name\": \"SSE2\"                },\n    { \"name\": \"SSE3\"                },\n    { \"name\": \"SSE4_1\"              },\n    { \"name\": \"SSE4_2\"              },\n    { \"name\": \"SSE4A\"               },\n    { \"name\": \"SSSE3\"               },\n    { \"name\": \"SVM\"                 },\n    { \"name\": \"TBM\"                 },\n    { \"name\": \"TSX\"                 },\n    { \"name\": \"TSXLDTRK\"            },\n    { \"name\": \"UINTR\"               },\n    { \"name\": \"VAES\"                },\n    { \"name\": \"VPCLMULQDQ\"          },\n    { \"name\": \"VMX\"                 },\n    { \"name\": \"WAITPKG\"             },\n    { \"name\": \"WBNOINVD\"            },\n    { \"name\": \"XOP\"                 },\n    { \"name\": \"XSAVE\"               },\n    { \"name\": \"XSAVEC\"              },\n    { \"name\": \"XSAVEOPT\"            },\n    { \"name\": \"XSAVES\"              }\n  ],\n\n  \"attributes\": [\n    { \"name\": \"Control\"          , \"type\": \"string\"      , \"doc\": \"Describes control flow.\" },\n    { \"name\": \"Volatile\"         , \"type\": \"flag\"        , \"doc\": \"Instruction can have side effects (hint for instruction scheduler).\" },\n    { \"name\": \"Deprecated\"       , \"type\": \"flag\"        , \"doc\": \"Deprecated instruction.\" },\n\n    { \"name\": \"AltForm\"          , \"type\": \"flag\"        , \"doc\": \"Alternative form that is shorter, but has restrictions.\" },\n    { \"name\": \"Lock\"             , \"type\": \"flag\"        , \"doc\": \"Can be used with LOCK prefix.\" },\n    { \"name\": \"ImplicitLock\"     , \"type\": \"flag\"        , \"doc\": \"Instruction is always atomic, regardless of use of the LOCK prefix.\" },\n    { \"name\": \"XAcquire\"         , \"type\": \"flag\"        , \"doc\": \"A hint used to start lock elision on the instruction memory operand address.\" },\n    { \"name\": \"XRelease\"         , \"type\": \"flag\"        , \"doc\": \"A hint used to end lock elision on the instruction memory operand address.\" },\n\n    { \"name\": \"REP\"              , \"type\": \"flag\"        , \"doc\": \"Can be used with REP (REPE/REPZ) prefix.\" },\n    { \"name\": \"REPNE\"            , \"type\": \"flag\"        , \"doc\": \"Can be used with REPNE (REPNZ) prefix.\" },\n    { \"name\": \"RepIgnored\"       , \"type\": \"flag\"        , \"doc\": \"Rep prefix can be used, but has no effect.\" },\n\n    { \"name\": \"AliasOf\"          , \"type\": \"string\"      , \"doc\": \"Instruction is an alias to another instruction, must apply to all instructions within the same group.\" },\n    { \"name\": \"EncodeAs\"         , \"type\": \"string\"      , \"doc\": \"Similar to AliasOf, but doesn't apply to all instructions in the group.\" }\n  ],\n\n  \"specialRegs\": [\n    { \"name\": \"FLAGS.CF\"         , \"group\": \"FLAGS.CF\"   , \"doc\": \"Carry flag.\" },\n    { \"name\": \"FLAGS.PF\"         , \"group\": \"FLAGS.PF\"   , \"doc\": \"Parity flag.\" },\n    { \"name\": \"FLAGS.AF\"         , \"group\": \"FLAGS.AF\"   , \"doc\": \"Adjust flag.\" },\n    { \"name\": \"FLAGS.ZF\"         , \"group\": \"FLAGS.ZF\"   , \"doc\": \"Zero flag.\" },\n    { \"name\": \"FLAGS.SF\"         , \"group\": \"FLAGS.SF\"   , \"doc\": \"Sign flag.\" },\n    { \"name\": \"FLAGS.TF\"         , \"group\": \"FLAGS.TF\"   , \"doc\": \"Trap flag.\" },\n    { \"name\": \"FLAGS.IF\"         , \"group\": \"FLAGS.IF\"   , \"doc\": \"Interrupt enable flag.\" },\n    { \"name\": \"FLAGS.DF\"         , \"group\": \"FLAGS.DF\"   , \"doc\": \"Direction flag.\" },\n    { \"name\": \"FLAGS.OF\"         , \"group\": \"FLAGS.OF\"   , \"doc\": \"Overflow flag.\" },\n    { \"name\": \"FLAGS.AC\"         , \"group\": \"FLAGS.Other\", \"doc\": \"Alignment check flag.\" },\n    { \"name\": \"FLAGS.IOPL\"       , \"group\": \"FLAGS.Other\", \"doc\": \"I/O privilege level.\" },\n    { \"name\": \"FLAGS.NT\"         , \"group\": \"FLAGS.Other\", \"doc\": \"Nested task flag.\" },\n    { \"name\": \"FLAGS.RF\"         , \"group\": \"FLAGS.Other\", \"doc\": \"Resume flag.\" },\n    { \"name\": \"FLAGS.VM\"         , \"group\": \"FLAGS.Other\", \"doc\": \"Virtual 8086 mode flag.\" },\n    { \"name\": \"FLAGS.VIF\"        , \"group\": \"FLAGS.Other\", \"doc\": \"Virtual interrupt flag.\" },\n    { \"name\": \"FLAGS.VIP\"        , \"group\": \"FLAGS.Other\", \"doc\": \"Virtual interrupt pending.\" },\n    { \"name\": \"FLAGS.CPUID\"      , \"group\": \"FLAGS.Other\", \"doc\": \"CPUID instruction available.\" },\n\n    { \"name\": \"X87CW.INVALID_OP\" , \"group\": \"X87CW.EXC\"  , \"doc\": \"Invalid operation exception enable bit.\" },\n    { \"name\": \"X87CW.DENORMAL\"   , \"group\": \"X87CW.EXC\"  , \"doc\": \"Dernormalized exception enable bit.\" },\n    { \"name\": \"X87CW.ZERO_DIVIDE\", \"group\": \"X87CW.EXC\"  , \"doc\": \"Division by zero exception enable bit.\" },\n    { \"name\": \"X87CW.OVERFLOW\"   , \"group\": \"X87CW.EXC\"  , \"doc\": \"Overflow exception enable bit.\" },\n    { \"name\": \"X87CW.UNDERFLOW\"  , \"group\": \"X87CW.EXC\"  , \"doc\": \"Underflow exception enable bit.\" },\n    { \"name\": \"X87CW.PRECISION\"  , \"group\": \"X87CW.EXC\"  , \"doc\": \"Lost of precision exception enable bit.\" },\n    { \"name\": \"X87CW.PC\"         , \"group\": \"X87CW.PC\"   , \"doc\": \"Precision control.\" },\n    { \"name\": \"X87CW.RC\"         , \"group\": \"X87CW.RC\"   , \"doc\": \"Rounding control.\" },\n\n    { \"name\": \"X87SW.INVALID_OP\" , \"group\": \"X87SW.EXC\"  , \"doc\": \"Invalid operation exception flag.\" },\n    { \"name\": \"X87SW.DENORMAL\"   , \"group\": \"X87SW.EXC\"  , \"doc\": \"Dernormalized exception flag.\" },\n    { \"name\": \"X87SW.ZERO_DIVIDE\", \"group\": \"X87SW.EXC\"  , \"doc\": \"Division by zero exception flag.\" },\n    { \"name\": \"X87SW.OVERFLOW\"   , \"group\": \"X87SW.EXC\"  , \"doc\": \"Overflow exception flag.\" },\n    { \"name\": \"X87SW.UNDERFLOW\"  , \"group\": \"X87SW.EXC\"  , \"doc\": \"Underflow exception flag.\" },\n    { \"name\": \"X87SW.PRECISION\"  , \"group\": \"X87SW.EXC\"  , \"doc\": \"Lost of precision exception flag.\" },\n    { \"name\": \"X87SW.STACK_FAULT\", \"group\": \"X87SW.EXC\"  , \"doc\": \"Stack fault.\" },\n    { \"name\": \"X87SW.EF\"         , \"group\": \"X87SW.EXC\"  , \"doc\": \"Exception flag.\" },\n    { \"name\": \"X87SW.C0\"         , \"group\": \"X87SW.C0\"   , \"doc\": \"C0 condifion.\" },\n    { \"name\": \"X87SW.C1\"         , \"group\": \"X87SW.C1\"   , \"doc\": \"C1 condifion.\" },\n    { \"name\": \"X87SW.C2\"         , \"group\": \"X87SW.C2\"   , \"doc\": \"C2 condifion.\" },\n    { \"name\": \"X87SW.TOP\"        , \"group\": \"X87SW.TOP\"  , \"doc\": \"Top of the FPU stack.\" },\n    { \"name\": \"X87SW.C3\"         , \"group\": \"X87SW.C3\"   , \"doc\": \"C3 condifion.\" },\n\n    { \"name\": \"MSR\"              , \"group\": \"MSR\"        , \"doc\": \"MSR register.\" },\n    { \"name\": \"XCR\"              , \"group\": \"XCR\"        , \"doc\": \"XCR register.\" }\n  ],\n\n  \"shortcuts\": [\n    { \"name\": \"CF\"               , \"expand\": \"FLAGS.CF\" },\n    { \"name\": \"PF\"               , \"expand\": \"FLAGS.PF\" },\n    { \"name\": \"AF\"               , \"expand\": \"FLAGS.AF\" },\n    { \"name\": \"ZF\"               , \"expand\": \"FLAGS.ZF\" },\n    { \"name\": \"SF\"               , \"expand\": \"FLAGS.SF\" },\n    { \"name\": \"TF\"               , \"expand\": \"FLAGS.TF\" },\n    { \"name\": \"IF\"               , \"expand\": \"FLAGS.IF\" },\n    { \"name\": \"DF\"               , \"expand\": \"FLAGS.DF\" },\n    { \"name\": \"OF\"               , \"expand\": \"FLAGS.OF\" },\n    { \"name\": \"AC\"               , \"expand\": \"FLAGS.AC\" },\n\n    { \"name\": \"C0\"               , \"expand\": \"X87SW.C0\" },\n    { \"name\": \"C1\"               , \"expand\": \"X87SW.C1\" },\n    { \"name\": \"C2\"               , \"expand\": \"X87SW.C2\" },\n    { \"name\": \"C3\"               , \"expand\": \"X87SW.C3\" },\n\n    { \"name\": \"_ILock\"           , \"expand\": \"Lock|ImplicitLock\" },\n    { \"name\": \"_XLock\"           , \"expand\": \"Lock|XAcquire|XRelease\" },\n    { \"name\": \"BND\"              , \"expand\": \"REPNE|RepIgnored\" },\n    { \"name\": \"_Rep\"             , \"expand\": \"REP|REPNE\" },\n    { \"name\": \"DummyRep\"         , \"expand\": \"REP|REPNE|RepIgnored\" }\n  ],\n\n  \"registers\": {\n    \"r8\"  : { \"kind\": \"gp\"  , \"any\": \"r8\"   , \"names\": [\"al\", \"cl\", \"dl\", \"bl\", \"spl\", \"bpl\", \"sil\", \"dil\", \"r8-15b\"] },\n    \"r8hi\": { \"kind\": \"gp\"                  , \"names\": [\"ah\", \"ch\", \"dh\", \"bh\"] },\n    \"r16\" : { \"kind\": \"gp\"  , \"any\": \"r16\"  , \"names\": [\"ax\", \"cx\", \"dx\", \"bx\", \"sp\", \"bp\", \"si\", \"di\", \"r8-15w\"] },\n    \"r32\" : { \"kind\": \"gp\"  , \"any\": \"r32\"  , \"names\": [\"eax\", \"ecx\", \"edx\", \"ebx\", \"esp\", \"ebp\", \"esi\", \"edi\", \"r8-15d\"] },\n    \"r64\" : { \"kind\": \"gp\"  , \"any\": \"r64\"  , \"names\": [\"rax\", \"rcx\", \"rdx\", \"rbx\", \"rsp\", \"rbp\", \"rsi\", \"rdi\", \"r8-15\"] },\n    \"rxx\" : { \"kind\": \"gp\"                  , \"names\": [\"zax\", \"zcx\", \"zdx\", \"zbx\", \"zsp\", \"zbp\", \"zsi\", \"zdi\"] },\n    \"sreg\": { \"kind\": \"sreg\", \"any\": \"sreg\" , \"names\": [\"es\", \"cs\", \"ss\", \"ds\", \"fs\", \"gs\" ] },\n    \"creg\": { \"kind\": \"creg\", \"any\": \"creg\" , \"names\": [\"cr0-15\"]  },\n    \"dreg\": { \"kind\": \"dreg\", \"any\": \"dreg\" , \"names\": [\"dr0-15\"]  },\n    \"bnd\" : { \"kind\": \"bnd\" , \"any\": \"bnd\"  , \"names\": [\"bnd0-3\"]  },\n    \"st\"  : { \"kind\": \"st\"  , \"any\": \"st(i)\", \"names\": [\"st(0-7)\"] },\n    \"mm\"  : { \"kind\": \"mm\"  , \"any\": \"mm\"   , \"names\": [\"mm0-7\"]   },\n    \"k\"   : { \"kind\": \"k\"   , \"any\": \"k\"    , \"names\": [\"k0-7\"]    },\n    \"xmm\" : { \"kind\": \"vec\" , \"any\": \"xmm\"  , \"names\": [\"xmm0-31\"] },\n    \"ymm\" : { \"kind\": \"vec\" , \"any\": \"ymm\"  , \"names\": [\"ymm0-31\"] },\n    \"zmm\" : { \"kind\": \"vec\" , \"any\": \"zmm\"  , \"names\": [\"zmm0-31\"] },\n    \"tmm\" : { \"kind\": \"tile\", \"any\": \"tmm\"  , \"names\": [\"tmm0-7\"]  }\n  },\n\n  \"instructions\": [\n    [\"adc\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"14 ib\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 15 iw\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"15 id\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 15 id\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /2 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /2 iw\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /2 id\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /2 id\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /2 ib\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /2 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /2 ib\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:~r8/m8,~r8\"                                    , \"MR\"      , \"10 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:~r16/m16,~r16\"                                 , \"MR\"      , \"66 11 /r\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:~r32/m32,~r32\"                                 , \"MR\"      , \"11 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:~r64/m64,~r64\"                                 , \"MR\"      , \"REX.W 11 /r\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:~r8,~r8/m8\"                                    , \"RM\"      , \"12 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"x:~r16,~r16/m16\"                                 , \"RM\"      , \"66 13 /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:~r32,~r32/m32\"                                 , \"RM\"      , \"13 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"adc\"              , \"X:~r64,~r64/m64\"                                 , \"RM\"      , \"REX.W 13 /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n\n    [\"add\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"04 ib\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 05 iw\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"05 id\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 05 id\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /0 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /0 iw\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /0 id\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /0 id\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /0 ib\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /0 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /0 ib\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:~r8/m8,~r8\"                                    , \"MR\"      , \"00 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:~r16/m16,~r16\"                                 , \"MR\"      , \"66 01 /r\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:~r32/m32,~r32\"                                 , \"MR\"      , \"01 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:~r64/m64,~r64\"                                 , \"MR\"      , \"REX.W 01 /r\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:~r8,~r8/m8\"                                    , \"RM\"      , \"02 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"x:~r16,~r16/m16\"                                 , \"RM\"      , \"66 03 /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:~r32,~r32/m32\"                                 , \"RM\"      , \"03 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"add\"              , \"X:~r64,~r64/m64\"                                 , \"RM\"      , \"REX.W 03 /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"and\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"24 ib\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 25 iw\"                     , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"25 id\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:rax, ud\"                                       , \"I\"       , \"25 id\"                        , \"X64 AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 25 id\"                  , \"X64 AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /4 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /4 iw\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /4 id\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:r64, ud\"                                       , \"MI\"      , \"81 /4 id\"                     , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /4 id\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 83 /4 ib\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"83 /4 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W 83 /4 ib\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:~r8/m8,~r8\"                                    , \"MR\"      , \"20 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:~r16/m16,~r16\"                                 , \"MR\"      , \"66 21 /r\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:~r32/m32,~r32\"                                 , \"MR\"      , \"21 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:~r64/m64,~r64\"                                 , \"MR\"      , \"REX.W 21 /r\"                  , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:~r8,~r8/m8\"                                    , \"RM\"      , \"22 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"x:~r16,~r16/m16\"                                 , \"RM\"      , \"66 23 /r\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:~r32,~r32/m32\"                                 , \"RM\"      , \"23 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"and\"              , \"X:~r64,~r64/m64\"                                 , \"RM\"      , \"REX.W 23 /r\"                  , \"X64              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n\n    [\"bound\"            , \"R:r16, R:m32\"                                    , \"RM\"      , \"66 62 /r\"                     , \"X86 Deprecated\"],\n    [\"bound\"            , \"R:r32, R:m64\"                                    , \"RM\"      , \"62 /r\"                        , \"X86 Deprecated\"],\n\n    [\"bsf\"              , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 0F BC /r\"                  , \"ANY              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n    [\"bsf\"              , \"W:r32, r32/m32\"                                  , \"RM\"      , \"0F BC /r\"                     , \"ANY              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n    [\"bsf\"              , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F BC /r\"               , \"X64              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n    [\"bsr\"              , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 0F BD /r\"                  , \"ANY              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n    [\"bsr\"              , \"W:r32, r32/m32\"                                  , \"RM\"      , \"0F BD /r\"                     , \"ANY              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n    [\"bsr\"              , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F BD /r\"               , \"X64              OF=U SF=U ZF=W AF=U PF=U CF=U\"],\n\n    [\"bswap\"            , \"X:r16\"                                           , \"O\"       , \"66 0F C8+r\"                   , \"ANY\"],\n    [\"bswap\"            , \"X:r32\"                                           , \"O\"       , \"0F C8+r\"                      , \"ANY\"],\n    [\"bswap\"            , \"X:r64\"                                           , \"O\"       , \"REX.W 0F C8+r\"                , \"X64\"],\n\n    [\"bt\"               , \"R:r16/m16, ib/ub\"                                , \"MI\"      , \"66 0F BA /4 ib\"               , \"ANY              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bt\"               , \"R:r32/m32, ib/ub\"                                , \"MI\"      , \"0F BA /4 ib\"                  , \"ANY              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bt\"               , \"R:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W 0F BA /4 ib\"            , \"X64              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bt\"               , \"R:r16/m16, r16\"                                  , \"MR\"      , \"66 0F A3 /r\"                  , \"ANY              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bt\"               , \"R:r32/m32, r32\"                                  , \"MR\"      , \"0F A3 /r\"                     , \"ANY              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bt\"               , \"R:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F A3 /r\"               , \"X64              OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 0F BA /7 ib\"               , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"0F BA /7 ib\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W 0F BA /7 ib\"            , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"x:r16/m16, r16\"                                  , \"MR\"      , \"66 0F BB /r\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"X:r32/m32, r32\"                                  , \"MR\"      , \"0F BB /r\"                     , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btc\"              , \"X:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F BB /r\"               , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 0F BA /6 ib\"               , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"0F BA /6 ib\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W 0F BA /6 ib\"            , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"x:r16/m16, r16\"                                  , \"MR\"      , \"66 0F B3 /r\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"X:r32/m32, r32\"                                  , \"MR\"      , \"0F B3 /r\"                     , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"btr\"              , \"X:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F B3 /r\"               , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 0F BA /5 ib\"               , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"0F BA /5 ib\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W 0F BA /5 ib\"            , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"x:r16/m16, r16\"                                  , \"MR\"      , \"66 0F AB /r\"                  , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"X:r32/m32, r32\"                                  , \"MR\"      , \"0F AB /r\"                     , \"ANY _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n    [\"bts\"              , \"X:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F AB /r\"               , \"X64 _XLock       OF=U SF=U AF=U PF=U CF=W\"],\n\n    [\"call\"             , \"rel16\"                                           , \"D\"       , \"66 E8 cw\"                     , \"X86 BND          Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"call\"             , \"rel32\"                                           , \"D\"       , \"E8 cd\"                        , \"ANY BND          Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"call\"             , \"R:r16/m16\"                                       , \"M\"       , \"66 FF /2\"                     , \"X86 BND          Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"call\"             , \"R:r32/m32\"                                       , \"M\"       , \"FF /2\"                        , \"X86 BND          Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"call\"             , \"R:r64/m64\"                                       , \"M\"       , \"FF /2\"                        , \"X64 BND          Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"cbw\"              , \"x:<ax>\"                                          , \"NONE\"    , \"66 98\"                        , \"ANY\"],\n    [\"cwde\"             , \"X:<eax>\"                                         , \"NONE\"    , \"98\"                           , \"ANY\"],\n    [\"cdqe\"             , \"X:<rax>\"                                         , \"NONE\"    , \"REX.W 98\"                     , \"X64\"],\n\n    [\"cwd\"              , \"w:<dx>, <ax>\"                                    , \"NONE\"    , \"66 99\"                        , \"ANY\"],\n    [\"cdq\"              , \"W:<edx>, <eax>\"                                  , \"NONE\"    , \"99\"                           , \"ANY\"],\n    [\"cqo\"              , \"W:<rdx>, <rax>\"                                  , \"NONE\"    , \"REX.W 99\"                     , \"X64\"],\n\n    [\"cmovo\"            , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 40 /r\"                  , \"CMOV             OF=R\"],\n    [\"cmovo\"            , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 40 /r\"                     , \"CMOV             OF=R\"],\n    [\"cmovo\"            , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 40 /r\"               , \"CMOV X64         OF=R\"],\n    [\"cmovno\"           , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 41 /r\"                  , \"CMOV             OF=R\"],\n    [\"cmovno\"           , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 41 /r\"                     , \"CMOV             OF=R\"],\n    [\"cmovno\"           , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 41 /r\"               , \"CMOV X64         OF=R\"],\n    [\"cmovb/cmovnae/cmovc\" , \"x:r16, r16/m16\"                               , \"RM\"      , \"66 0F 42 /r\"                  , \"CMOV             CF=R\"],\n    [\"cmovb/cmovnae/cmovc\" , \"X:r32, r32/m32\"                               , \"RM\"      , \"0F 42 /r\"                     , \"CMOV             CF=R\"],\n    [\"cmovb/cmovnae/cmovc\" , \"X:r64, r64/m64\"                               , \"RM\"      , \"REX.W 0F 42 /r\"               , \"CMOV X64         CF=R\"],\n    [\"cmovae/cmovnb/cmovnc\", \"x:r16, r16/m16\"                               , \"RM\"      , \"66 0F 43 /r\"                  , \"CMOV             CF=R\"],\n    [\"cmovae/cmovnb/cmovnc\", \"X:r32, r32/m32\"                               , \"RM\"      , \"0F 43 /r\"                     , \"CMOV             CF=R\"],\n    [\"cmovae/cmovnb/cmovnc\", \"X:r64, r64/m64\"                               , \"RM\"      , \"REX.W 0F 43 /r\"               , \"CMOV X64         CF=R\"],\n    [\"cmove/cmovz\"      , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 44 /r\"                  , \"CMOV             ZF=R\"],\n    [\"cmove/cmovz\"      , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 44 /r\"                     , \"CMOV             ZF=R\"],\n    [\"cmove/cmovz\"      , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 44 /r\"               , \"CMOV X64         ZF=R\"],\n    [\"cmovne/cmovnz\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 45 /r\"                  , \"CMOV             ZF=R\"],\n    [\"cmovne/cmovnz\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 45 /r\"                     , \"CMOV             ZF=R\"],\n    [\"cmovne/cmovnz\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 45 /r\"               , \"CMOV X64         ZF=R\"],\n    [\"cmovbe/cmovna\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 46 /r\"                  , \"CMOV             CF=R ZF=R\"],\n    [\"cmovbe/cmovna\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 46 /r\"                     , \"CMOV             CF=R ZF=R\"],\n    [\"cmovbe/cmovna\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 46 /r\"               , \"CMOV X64         CF=R ZF=R\"],\n    [\"cmova/cmovnbe\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 47 /r\"                  , \"CMOV             CF=R ZF=R\"],\n    [\"cmova/cmovnbe\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 47 /r\"                     , \"CMOV             CF=R ZF=R\"],\n    [\"cmova/cmovnbe\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 47 /r\"               , \"CMOV X64         CF=R ZF=R\"],\n    [\"cmovs\"            , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 48 /r\"                  , \"CMOV             SF=R\"],\n    [\"cmovs\"            , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 48 /r\"                     , \"CMOV             SF=R\"],\n    [\"cmovs\"            , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 48 /r\"               , \"CMOV X64         SF=R\"],\n    [\"cmovns\"           , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 49 /r\"                  , \"CMOV             SF=R\"],\n    [\"cmovns\"           , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 49 /r\"                     , \"CMOV             SF=R\"],\n    [\"cmovns\"           , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 49 /r\"               , \"CMOV X64         SF=R\"],\n    [\"cmovp/cmovpe\"     , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4A /r\"                  , \"CMOV             PF=R\"],\n    [\"cmovp/cmovpe\"     , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4A /r\"                     , \"CMOV             PF=R\"],\n    [\"cmovp/cmovpe\"     , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4A /r\"               , \"CMOV X64         PF=R\"],\n    [\"cmovnp/cmovpo\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4B /r\"                  , \"CMOV             PF=R\"],\n    [\"cmovnp/cmovpo\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4B /r\"                     , \"CMOV             PF=R\"],\n    [\"cmovnp/cmovpo\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4B /r\"               , \"CMOV X64         PF=R\"],\n    [\"cmovl/cmovnge\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4C /r\"                  , \"CMOV             SF=R OF=R\"],\n    [\"cmovl/cmovnge\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4C /r\"                     , \"CMOV             SF=R OF=R\"],\n    [\"cmovl/cmovnge\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4C /r\"               , \"CMOV X64         SF=R OF=R\"],\n    [\"cmovge/cmovnl\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4D /r\"                  , \"CMOV             SF=R OF=R\"],\n    [\"cmovge/cmovnl\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4D /r\"                     , \"CMOV             SF=R OF=R\"],\n    [\"cmovge/cmovnl\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4D /r\"               , \"CMOV X64         SF=R OF=R\"],\n    [\"cmovle/cmovng\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4E /r\"                  , \"CMOV             ZF=R SF=R OF=R\"],\n    [\"cmovle/cmovng\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4E /r\"                     , \"CMOV             ZF=R SF=R OF=R\"],\n    [\"cmovle/cmovng\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4E /r\"               , \"CMOV X64         ZF=R SF=R OF=R\"],\n    [\"cmovg/cmovnle\"    , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 0F 4F /r\"                  , \"CMOV             ZF=R SF=R OF=R\"],\n    [\"cmovg/cmovnle\"    , \"X:r32, r32/m32\"                                  , \"RM\"      , \"0F 4F /r\"                     , \"CMOV             ZF=R SF=R OF=R\"],\n    [\"cmovg/cmovnle\"    , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 0F 4F /r\"               , \"CMOV X64         ZF=R SF=R OF=R\"],\n\n    [\"cmp\"              , \"R:al, ib/ub\"                                     , \"I\"       , \"3C ib\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:ax, iw/uw\"                                     , \"I\"       , \"66 3D iw\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:eax, id/ud\"                                    , \"I\"       , \"3D id\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:rax, id\"                                       , \"I\"       , \"REX.W 3D id\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /7 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /7 iw\"                  , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r32/m32, id/ud\"                                , \"MI\"      , \"81 /7 id\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /7 id\"               , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /7 ib\"                  , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r32/m32, ib\"                                   , \"MI\"      , \"83 /7 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /7 ib\"               , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r8/m8, r8\"                                     , \"MR\"      , \"38 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r16/m16, r16\"                                  , \"MR\"      , \"66 39 /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r32/m32, r32\"                                  , \"MR\"      , \"39 /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 39 /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r8, r8/m8\"                                     , \"RM\"      , \"3A /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r16, r16/m16\"                                  , \"RM\"      , \"66 3B /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r32, r32/m32\"                                  , \"RM\"      , \"3B /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmp\"              , \"R:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 3B /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"cmpsb\"            , \"R:<ds:zsi>, R:<es:zdi>\"                          , \"NONE\"    , \"A6\"                           , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"cmpsw\"            , \"R:<ds:zsi>, R:<es:zdi>\"                          , \"NONE\"    , \"66 A7\"                        , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"cmpsd\"            , \"R:<ds:zsi>, R:<es:zdi>\"                          , \"NONE\"    , \"A7\"                           , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"cmpsq\"            , \"R:<ds:zsi>, R:<es:zdi>\"                          , \"NONE\"    , \"REX.W A7\"                     , \"X64 _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n\n    [\"cmpxchg\"          , \"x:r8/m8, r8, <al>\"                               , \"MR\"      , \"0F B0 /r\"                     , \"I486             _XLock Volatile OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmpxchg\"          , \"x:r16/m16, r16, <ax>\"                            , \"MR\"      , \"66 0F B1 /r\"                  , \"I486             _XLock Volatile OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmpxchg\"          , \"X:r32/m32, r32, <eax>\"                           , \"MR\"      , \"0F B1 /r\"                     , \"I486             _XLock Volatile OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmpxchg\"          , \"X:r64/m64, r64, <rax>\"                           , \"MR\"      , \"REX.W 0F B1 /r\"               , \"I486 X64         _XLock Volatile OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"cmpxchg8b\"        , \"X:m64, X:<edx>, X:<eax>, <ecx>, <ebx>\"           , \"M\"       , \"0F C7 /1\"                     , \"CMPXCHG8B        _XLock Volatile ZF=W\"],\n    [\"cmpxchg16b\"       , \"X:m128, X:<rdx>, X:<rax>, <rcx>, <rbx>\"          , \"M\"       , \"REX.W 0F C7 /1\"               , \"CMPXCHG16B X64   _XLock Volatile ZF=W\"],\n\n    [\"dec\"              , \"x:r16\"                                           , \"O\"       , \"66 48+r\"                      , \"X86              OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"dec\"              , \"X:r32\"                                           , \"O\"       , \"48+r\"                         , \"X86              OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"dec\"              , \"x:r8/m8\"                                         , \"M\"       , \"FE /1\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"dec\"              , \"x:r16/m16\"                                       , \"M\"       , \"66 FF /1\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"dec\"              , \"X:r32/m32\"                                       , \"M\"       , \"FF /1\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"dec\"              , \"X:r64/m64\"                                       , \"M\"       , \"REX.W FF /1\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n\n    [\"div\"              , \"x:<ax>, r8/m8\"                                   , \"M\"       , \"F6 /6\"                        , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"div\"              , \"x:<dx>, x:<ax>, r16/m16\"                         , \"M\"       , \"66 F7 /6\"                     , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"div\"              , \"X:<edx>, X:<eax>, r32/m32\"                       , \"M\"       , \"F7 /6\"                        , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"div\"              , \"X:<rdx>, X:<rax>, r64/m64\"                       , \"M\"       , \"REX.W F7 /6\"                  , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"idiv\"             , \"x:<ax>, r8/m8\"                                   , \"M\"       , \"F6 /7\"                        , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"idiv\"             , \"x:<dx>, x:<ax>, r16/m16\"                         , \"M\"       , \"66 F7 /7\"                     , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"idiv\"             , \"X:<edx>, X:<eax>, r32/m32\"                       , \"M\"       , \"F7 /7\"                        , \"ANY              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"idiv\"             , \"X:<rdx>, X:<rax>, r64/m64\"                       , \"M\"       , \"REX.W F7 /7\"                  , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"imul\"             , \"x:<ax>, r8/m8\"                                   , \"M\"       , \"F6 /5\"                        , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"w:<dx>, x:<ax>, r16/m16\"                         , \"M\"       , \"66 F7 /5\"                     , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:<edx>, X:<eax>, r32/m32\"                       , \"M\"       , \"F7 /5\"                        , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:<rdx>, X:<rax>, r64/m64\"                       , \"M\"       , \"REX.W F7 /5\"                  , \"X64              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"x:~r16,~r16/m16\"                                 , \"RM\"      , \"66 0F AF /r\"                  , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"X:~r32,~r32/m32\"                                 , \"RM\"      , \"0F AF /r\"                     , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"X:~r64,~r64/m64\"                                 , \"RM\"      , \"REX.W 0F AF /r\"               , \"X64              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"w:r16, r16/m16, ib\"                              , \"RMI\"     , \"66 6B /r ib\"                  , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:r32, r32/m32, ib\"                              , \"RMI\"     , \"6B /r ib\"                     , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:r64, r64/m64, ib\"                              , \"RMI\"     , \"REX.W 6B /r ib\"               , \"X64              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"w:r16, r16/m16, iw/uw\"                           , \"RMI\"     , \"66 69 /r iw\"                  , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:r32, r32/m32, id/ud\"                           , \"RMI\"     , \"69 /r id\"                     , \"ANY              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n    [\"imul\"             , \"W:r64, r64/m64, id\"                              , \"RMI\"     , \"REX.W 69 /r id\"               , \"X64              OF=W SF=W ZF=U AF=U PF=U CF=W\"],\n\n    [\"inc\"              , \"x:r16\"                                           , \"O\"       , \"66 40+r\"                      , \"X86              OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"inc\"              , \"X:r32\"                                           , \"O\"       , \"40+r\"                         , \"X86              OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"inc\"              , \"x:r8/m8\"                                         , \"M\"       , \"FE /0\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"inc\"              , \"x:r16/m16\"                                       , \"M\"       , \"66 FF /0\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"inc\"              , \"X:r32/m32\"                                       , \"M\"       , \"FF /0\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"inc\"              , \"X:r64/m64\"                                       , \"M\"       , \"REX.W FF /0\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W\"],\n\n    [\"iret\"             , \"\"                                                , \"NONE\"    , \"66 CF\"                        , \"ANY              Control=Return OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"iretd\"            , \"\"                                                , \"NONE\"    , \"CF\"                           , \"ANY              Control=Return OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"iretq\"            , \"\"                                                , \"NONE\"    , \"REX.W CF\"                     , \"X64              Control=Return OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"jo\"               , \"rel8\"                                            , \"D\"       , \"70 cb\"                        , \"ANY BND          Control=Branch OF=R\"],\n    [\"jno\"              , \"rel8\"                                            , \"D\"       , \"71 cb\"                        , \"ANY BND          Control=Branch OF=R\"],\n    [\"jb/jnae/jc\"       , \"rel8\"                                            , \"D\"       , \"72 cb\"                        , \"ANY BND          Control=Branch CF=R\"],\n    [\"jae/jnb/jnc\"      , \"rel8\"                                            , \"D\"       , \"73 cb\"                        , \"ANY BND          Control=Branch CF=R\"],\n    [\"je/jz\"            , \"rel8\"                                            , \"D\"       , \"74 cb\"                        , \"ANY BND          Control=Branch ZF=R\"],\n    [\"jne/jnz\"          , \"rel8\"                                            , \"D\"       , \"75 cb\"                        , \"ANY BND          Control=Branch ZF=R\"],\n    [\"jbe/jna\"          , \"rel8\"                                            , \"D\"       , \"76 cb\"                        , \"ANY BND          Control=Branch CF=R ZF=R\"],\n    [\"ja/jnbe\"          , \"rel8\"                                            , \"D\"       , \"77 cb\"                        , \"ANY BND          Control=Branch CF=R ZF=R\"],\n    [\"js\"               , \"rel8\"                                            , \"D\"       , \"78 cb\"                        , \"ANY BND          Control=Branch SF=R\"],\n    [\"jns\"              , \"rel8\"                                            , \"D\"       , \"79 cb\"                        , \"ANY BND          Control=Branch SF=R\"],\n    [\"jp/jpe\"           , \"rel8\"                                            , \"D\"       , \"7A cb\"                        , \"ANY BND          Control=Branch PF=R\"],\n    [\"jnp/jpo\"          , \"rel8\"                                            , \"D\"       , \"7B cb\"                        , \"ANY BND          Control=Branch PF=R\"],\n    [\"jl/jnge\"          , \"rel8\"                                            , \"D\"       , \"7C cb\"                        , \"ANY BND          Control=Branch SF=R OF=R\"],\n    [\"jge/jnl\"          , \"rel8\"                                            , \"D\"       , \"7D cb\"                        , \"ANY BND          Control=Branch SF=R OF=R\"],\n    [\"jle/jng\"          , \"rel8\"                                            , \"D\"       , \"7E cb\"                        , \"ANY BND          Control=Branch ZF=R SF=R OF=R\"],\n    [\"jg/jnle\"          , \"rel8\"                                            , \"D\"       , \"7F cb\"                        , \"ANY BND          Control=Branch ZF=R SF=R OF=R\"],\n\n    [\"jo\"               , \"rel16\"                                           , \"D\"       , \"66 0F 80 cw\"                  , \"X86 BND          Control=Branch OF=R\"],\n    [\"jo\"               , \"rel32\"                                           , \"D\"       , \"0F 80 cd\"                     , \"ANY BND          Control=Branch OF=R\"],\n    [\"jno\"              , \"rel16\"                                           , \"D\"       , \"66 0F 81 cw\"                  , \"X86 BND          Control=Branch OF=R\"],\n    [\"jno\"              , \"rel32\"                                           , \"D\"       , \"0F 81 cd\"                     , \"ANY BND          Control=Branch OF=R\"],\n    [\"jb/jnae/jc\"       , \"rel16\"                                           , \"D\"       , \"66 0F 82 cw\"                  , \"X86 BND          Control=Branch CF=R\"],\n    [\"jb/jnae/jc\"       , \"rel32\"                                           , \"D\"       , \"0F 82 cd\"                     , \"ANY BND          Control=Branch CF=R\"],\n    [\"jae/jnb/jnc\"      , \"rel16\"                                           , \"D\"       , \"66 0F 83 cw\"                  , \"X86 BND          Control=Branch CF=R\"],\n    [\"jae/jnb/jnc\"      , \"rel32\"                                           , \"D\"       , \"0F 83 cd\"                     , \"ANY BND          Control=Branch CF=R\"],\n    [\"je/jz\"            , \"rel16\"                                           , \"D\"       , \"66 0F 84 cw\"                  , \"X86 BND          Control=Branch ZF=R\"],\n    [\"je/jz\"            , \"rel32\"                                           , \"D\"       , \"0F 84 cd\"                     , \"ANY BND          Control=Branch ZF=R\"],\n    [\"jne/jnz\"          , \"rel16\"                                           , \"D\"       , \"66 0F 85 cw\"                  , \"X86 BND          Control=Branch ZF=R\"],\n    [\"jne/jnz\"          , \"rel32\"                                           , \"D\"       , \"0F 85 cd\"                     , \"ANY BND          Control=Branch ZF=R\"],\n    [\"jbe/jna\"          , \"rel16\"                                           , \"D\"       , \"66 0F 86 cw\"                  , \"X86 BND          Control=Branch CF=R ZF=R\"],\n    [\"jbe/jna\"          , \"rel32\"                                           , \"D\"       , \"0F 86 cd\"                     , \"ANY BND          Control=Branch CF=R ZF=R\"],\n    [\"ja/jnbe\"          , \"rel16\"                                           , \"D\"       , \"66 0F 87 cw\"                  , \"X86 BND          Control=Branch CF=R ZF=R\"],\n    [\"ja/jnbe\"          , \"rel32\"                                           , \"D\"       , \"0F 87 cd\"                     , \"ANY BND          Control=Branch CF=R ZF=R\"],\n    [\"js\"               , \"rel16\"                                           , \"D\"       , \"66 0F 88 cw\"                  , \"X86 BND          Control=Branch SF=R\"],\n    [\"js\"               , \"rel32\"                                           , \"D\"       , \"0F 88 cd\"                     , \"ANY BND          Control=Branch SF=R\"],\n    [\"jns\"              , \"rel16\"                                           , \"D\"       , \"66 0F 89 cw\"                  , \"X86 BND          Control=Branch SF=R\"],\n    [\"jns\"              , \"rel32\"                                           , \"D\"       , \"0F 89 cd\"                     , \"ANY BND          Control=Branch SF=R\"],\n    [\"jp/jpe\"           , \"rel16\"                                           , \"D\"       , \"66 0F 8A cw\"                  , \"X86 BND          Control=Branch PF=R\"],\n    [\"jp/jpe\"           , \"rel32\"                                           , \"D\"       , \"0F 8A cd\"                     , \"ANY BND          Control=Branch PF=R\"],\n    [\"jnp/jpo\"          , \"rel16\"                                           , \"D\"       , \"66 0F 8B cw\"                  , \"X86 BND          Control=Branch PF=R\"],\n    [\"jnp/jpo\"          , \"rel32\"                                           , \"D\"       , \"0F 8B cd\"                     , \"ANY BND          Control=Branch PF=R\"],\n    [\"jl/jnge\"          , \"rel16\"                                           , \"D\"       , \"66 0F 8C cw\"                  , \"X86 BND          Control=Branch SF=R OF=R\"],\n    [\"jl/jnge\"          , \"rel32\"                                           , \"D\"       , \"0F 8C cd\"                     , \"ANY BND          Control=Branch SF=R OF=R\"],\n    [\"jge/jnl\"          , \"rel16\"                                           , \"D\"       , \"66 0F 8D cw\"                  , \"X86 BND          Control=Branch SF=R OF=R\"],\n    [\"jge/jnl\"          , \"rel32\"                                           , \"D\"       , \"0F 8D cd\"                     , \"ANY BND          Control=Branch SF=R OF=R\"],\n    [\"jle/jng\"          , \"rel16\"                                           , \"D\"       , \"66 0F 8E cw\"                  , \"X86 BND          Control=Branch ZF=R SF=R OF=R\"],\n    [\"jle/jng\"          , \"rel32\"                                           , \"D\"       , \"0F 8E cd\"                     , \"ANY BND          Control=Branch ZF=R SF=R OF=R\"],\n    [\"jg/jnle\"          , \"rel16\"                                           , \"D\"       , \"66 0F 8F cw\"                  , \"X86 BND          Control=Branch ZF=R SF=R OF=R\"],\n    [\"jg/jnle\"          , \"rel32\"                                           , \"D\"       , \"0F 8F cd\"                     , \"ANY BND          Control=Branch ZF=R SF=R OF=R\"],\n\n    [\"jecxz\"            , \"R:<cx>, rel8\"                                    , \"D\"       , \"67 E3 cb\"                     , \"X86 BND          Control=Branch\"],\n    [\"jecxz\"            , \"R:<ecx>, rel8\"                                   , \"D\"       , \"E3 cb\"                        , \"X86 BND          Control=Branch\"],\n    [\"jecxz\"            , \"R:<ecx>, rel8\"                                   , \"D\"       , \"67 E3 cb\"                     , \"X64 BND          Control=Branch\"],\n    [\"jecxz\"            , \"R:<rcx>, rel8\"                                   , \"D\"       , \"E3 cb\"                        , \"X64 BND          Control=Branch\"],\n\n    [\"jmp\"              , \"rel8\"                                            , \"D\"       , \"EB cb\"                        , \"ANY BND          Control=Jump\"],\n    [\"jmp\"              , \"rel16\"                                           , \"D\"       , \"66 E9 cw\"                     , \"X86 BND          Control=Jump\"],\n    [\"jmp\"              , \"rel32\"                                           , \"D\"       , \"E9 cd\"                        , \"ANY BND          Control=Jump\"],\n    [\"jmp\"              , \"R:r32/m32\"                                       , \"D\"       , \"FF /4\"                        , \"X86 BND          Control=Jump\"],\n    [\"jmp\"              , \"R:r64/m64\"                                       , \"D\"       , \"FF /4\"                        , \"X64 BND          Control=Jump\"],\n\n    [\"lcall\"            , \"iw, iw\"                                          , \"II\"      , \"66 9A iw iw\"                  , \"X86              Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"lcall\"            , \"iw, id\"                                          , \"II\"      , \"9A id iw\"                     , \"X86              Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"lcall\"            , \"R:m16_16\"                                        , \"M\"       , \"66 FF /3\"                     , \"ANY              Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"lcall\"            , \"R:m16_32\"                                        , \"M\"       , \"FF /3\"                        , \"ANY              Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"lcall\"            , \"R:m16_64\"                                        , \"M\"       , \"REX.W FF /3\"                  , \"X64              Control=Call OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"lea\"              , \"w:r16, mem\"                                      , \"RM\"      , \"67 8D /r\"                     , \"ANY\"],\n    [\"lea\"              , \"W:r32, mem\"                                      , \"RM\"      , \"8D /r\"                        , \"ANY\"],\n    [\"lea\"              , \"W:r64, mem\"                                      , \"RM\"      , \"REX.W 8D /r\"                  , \"X64\"],\n\n    [\"ljmp\"             , \"iw, iw\"                                          , \"II\"      , \"66 EA iw iw\"                  , \"X86              Control=Jump\"],\n    [\"ljmp\"             , \"iw, id\"                                          , \"II\"      , \"EA id iw\"                     , \"X86              Control=Jump\"],\n    [\"ljmp\"             , \"R:m16_16\"                                        , \"M\"       , \"66 FF /5\"                     , \"ANY              Control=Jump\"],\n    [\"ljmp\"             , \"R:m16_32\"                                        , \"M\"       , \"FF /5\"                        , \"ANY              Control=Jump\"],\n    [\"ljmp\"             , \"R:m16_64\"                                        , \"M\"       , \"REX.W FF /5\"                  , \"X64              Control=Jump\"],\n\n    [\"lodsb\"            , \"w:<al>, R:<ds:zsi>\"                              , \"NONE\"    , \"AC\"                           , \"ANY _Rep         DF=R\"],\n    [\"lodsw\"            , \"w:<ax>, R:<ds:zsi>\"                              , \"NONE\"    , \"66 AD\"                        , \"ANY _Rep         DF=R\"],\n    [\"lodsd\"            , \"W:<eax>, R:<ds:zsi>\"                             , \"NONE\"    , \"AD\"                           , \"ANY _Rep         DF=R\"],\n    [\"lodsq\"            , \"W:<rax>, R:<ds:zsi>\"                             , \"NONE\"    , \"REX.W AD\"                     , \"X64 _Rep         DF=R\"],\n\n    [\"loop\"             , \"x:<cx>, rel8\"                                    , \"D\"       , \"67 E2 cb\"                     , \"X86              Control=Branch\"],\n    [\"loop\"             , \"X:<ecx>, rel8\"                                   , \"D\"       , \"E2 cb\"                        , \"X86              Control=Branch\"],\n    [\"loop\"             , \"X:<ecx>, rel8\"                                   , \"D\"       , \"67 E2 cb\"                     , \"X64              Control=Branch\"],\n    [\"loop\"             , \"X:<rcx>, rel8\"                                   , \"D\"       , \"E2 cb\"                        , \"X64              Control=Branch\"],\n    [\"loope\"            , \"x:<cx>, rel8\"                                    , \"D\"       , \"67 E1 cb\"                     , \"X86              Control=Branch ZF=R\"],\n    [\"loope\"            , \"X:<ecx>, rel8\"                                   , \"D\"       , \"E1 cb\"                        , \"X86              Control=Branch ZF=R\"],\n    [\"loope\"            , \"X:<ecx>, rel8\"                                   , \"D\"       , \"67 E1 cb\"                     , \"X64              Control=Branch ZF=R\"],\n    [\"loope\"            , \"X:<rcx>, rel8\"                                   , \"D\"       , \"E1 cb\"                        , \"X64              Control=Branch ZF=R\"],\n    [\"loopne\"           , \"x:<cx>, rel8\"                                    , \"D\"       , \"67 E0 cb\"                     , \"X86              Control=Branch ZF=R\"],\n    [\"loopne\"           , \"X:<ecx>, rel8\"                                   , \"D\"       , \"E0 cb\"                        , \"X86              Control=Branch ZF=R\"],\n    [\"loopne\"           , \"X:<ecx>, rel8\"                                   , \"D\"       , \"67 E0 cb\"                     , \"X64              Control=Branch ZF=R\"],\n    [\"loopne\"           , \"X:<rcx>, rel8\"                                   , \"D\"       , \"E0 cb\"                        , \"X64              Control=Branch ZF=R\"],\n\n    [\"mov\"              , \"w:r8/m8, r8\"                                     , \"MR\"      , \"88 /r\"                        , \"ANY XRelease\"],\n    [\"mov\"              , \"w:r16/m16, r16\"                                  , \"MR\"      , \"66 89 /r\"                     , \"ANY XRelease\"],\n    [\"mov\"              , \"W:r32/m32, r32\"                                  , \"MR\"      , \"89 /r\"                        , \"ANY XRelease\"],\n    [\"mov\"              , \"W:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 89 /r\"                  , \"X64 XRelease\"],\n    [\"mov\"              , \"w:r8/m8, ib/ub\"                                  , \"MI\"      , \"C6 /0 ib\"                     , \"ANY XRelease\"],\n    [\"mov\"              , \"w:r16/m16, iw/uw\"                                , \"MI\"      , \"66 C7 /0 iw\"                  , \"ANY XRelease\"],\n    [\"mov\"              , \"W:r32/m32, id/ud\"                                , \"MI\"      , \"C7 /0 id\"                     , \"ANY XRelease\"],\n    [\"mov\"              , \"W:r64/m64, id\"                                   , \"MI\"      , \"REX.W C7 /0 id\"               , \"X64 XRelease\"],\n    [\"mov\"              , \"w:r8, ib/ub\"                                     , \"I\"       , \"B0+r ib\"                      , \"ANY\"],\n    [\"mov\"              , \"w:r16, iw/uw\"                                    , \"I\"       , \"66 B8+r iw\"                   , \"ANY\"],\n    [\"mov\"              , \"W:r32, id/ud\"                                    , \"I\"       , \"B8+r id\"                      , \"ANY\"],\n    [\"mov\"              , \"W:r64, iq/uq\"                                    , \"I\"       , \"REX.W B8+r iq\"                , \"X64\"],\n    [\"mov\"              , \"w:r8, r8/m8\"                                     , \"RM\"      , \"8A /r\"                        , \"ANY\"],\n    [\"mov\"              , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 8B /r\"                     , \"ANY\"],\n    [\"mov\"              , \"W:r32, r32/m32\"                                  , \"RM\"      , \"8B /r\"                        , \"ANY\"],\n    [\"mov\"              , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 8B /r\"                  , \"X64\"],\n    [\"mov\"              , \"w:r16/m16, sreg\"                                 , \"MR\"      , \"66 8C /r\"                     , \"ANY\"],\n    [\"mov\"              , \"W:r32/m16, sreg\"                                 , \"MR\"      , \"8C /r\"                        , \"ANY\"],\n    [\"mov\"              , \"W:r64/m16, sreg\"                                 , \"MR\"      , \"REX.W 8C /r\"                  , \"X64\"],\n    [\"mov\"              , \"W:sreg, r16/m16\"                                 , \"RM\"      , \"66 8E /r\"                     , \"ANY\"],\n    [\"mov\"              , \"W:sreg, r32/m16\"                                 , \"RM\"      , \"8E /r\"                        , \"ANY\"],\n    [\"mov\"              , \"W:sreg, r64/m16\"                                 , \"RM\"      , \"REX.W 8E /r\"                  , \"X64\"],\n    [\"mov\"              , \"w:al, moff8\"                                     , \"NONE\"    , \"A0\"                           , \"ANY\"],\n    [\"mov\"              , \"w:ax, moff16\"                                    , \"NONE\"    , \"66 A1\"                        , \"ANY\"],\n    [\"mov\"              , \"W:eax, moff32\"                                   , \"NONE\"    , \"A1\"                           , \"ANY\"],\n    [\"mov\"              , \"W:rax, moff64\"                                   , \"NONE\"    , \"REX.W A1\"                     , \"X64\"],\n    [\"mov\"              , \"W:moff8, al\"                                     , \"NONE\"    , \"A2\"                           , \"ANY\"],\n    [\"mov\"              , \"W:moff16, ax\"                                    , \"NONE\"    , \"66 A3\"                        , \"ANY\"],\n    [\"mov\"              , \"W:moff32, eax\"                                   , \"NONE\"    , \"A3\"                           , \"ANY\"],\n    [\"mov\"              , \"W:moff64, rax\"                                   , \"NONE\"    , \"REX.W A3\"                     , \"X64\"],\n    [\"mov\"              , \"W:r32, creg\"                                     , \"MR\"      , \"0F 20 /r\"                     , \"X86              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:r64, creg\"                                     , \"MR\"      , \"0F 20 /r\"                     , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:creg, r32\"                                     , \"RM\"      , \"0F 22 /r\"                     , \"X86              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:creg, r64\"                                     , \"RM\"      , \"0F 22 /r\"                     , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:r32, dreg\"                                     , \"MR\"      , \"0F 21 /r\"                     , \"X86              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:r64, dreg\"                                     , \"MR\"      , \"0F 21 /r\"                     , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:dreg, r32\"                                     , \"RM\"      , \"0F 23 /r\"                     , \"X86              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"mov\"              , \"W:dreg, r64\"                                     , \"RM\"      , \"0F 23 /r\"                     , \"X64              OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"movsb\"            , \"W:<es:zdi>, R:<ds:zsi>\"                          , \"NONE\"    , \"A4\"                           , \"ANY _Rep         DF=R\"],\n    [\"movsw\"            , \"W:<es:zdi>, R:<ds:zsi>\"                          , \"NONE\"    , \"66 A5\"                        , \"ANY _Rep         DF=R\"],\n    [\"movsd\"            , \"W:<es:zdi>, R:<ds:zsi>\"                          , \"NONE\"    , \"A5\"                           , \"ANY _Rep         DF=R\"],\n    [\"movsq\"            , \"W:<es:zdi>, R:<ds:zsi>\"                          , \"NONE\"    , \"REX.W A5\"                     , \"X64 _Rep         DF=R\"],\n\n    [\"movsx\"            , \"w:r16, r8/m8\"                                    , \"RM\"      , \"66 0F BE /r\"                  , \"ANY\"],\n    [\"movsx\"            , \"W:r32, r8/m8\"                                    , \"RM\"      , \"0F BE /r\"                     , \"ANY\"],\n    [\"movsx\"            , \"W:r64, r8/m8\"                                    , \"RM\"      , \"REX.W 0F BE /r\"               , \"X64\"],\n    [\"movsx\"            , \"W:r32, r16/m16\"                                  , \"RM\"      , \"0F BF /r\"                     , \"ANY\"],\n    [\"movsx\"            , \"W:r64, r16/m16\"                                  , \"RM\"      , \"REX.W 0F BF /r\"               , \"X64\"],\n    [\"movsxd\"           , \"W:r16, r16/m16\"                                  , \"RM\"      , \"66 63 /r\"                     , \"X64\"],\n    [\"movsxd\"           , \"W:r32, r32/m32\"                                  , \"RM\"      , \"63 /r\"                        , \"X64\"],\n    [\"movsxd\"           , \"W:r64, r32/m32\"                                  , \"RM\"      , \"REX.W 63 /r\"                  , \"X64\"],\n    [\"movzx\"            , \"w:r16, r8/m8\"                                    , \"RM\"      , \"66 0F B6 /r\"                  , \"ANY\"],\n    [\"movzx\"            , \"W:r32, r8/m8\"                                    , \"RM\"      , \"0F B6 /r\"                     , \"ANY\"],\n    [\"movzx\"            , \"W:r64, r8/m8\"                                    , \"RM\"      , \"REX.W 0F B6 /r\"               , \"X64\"],\n    [\"movzx\"            , \"W:r32, r16/m16\"                                  , \"RM\"      , \"0F B7 /r\"                     , \"ANY\"],\n    [\"movzx\"            , \"W:r64, r16/m16\"                                  , \"RM\"      , \"REX.W 0F B7 /r\"               , \"X64\"],\n\n    [\"mul\"              , \"x:<ax>, r8/m8\"                                   , \"M\"       , \"F6 /4\"                        , \"ANY              OF=W SF=U ZF=U AF=U PF=U CF=W\"],\n    [\"mul\"              , \"w:<dx>, x:<ax>, r16/m16\"                         , \"M\"       , \"66 F7 /4\"                     , \"ANY              OF=W SF=U ZF=U AF=U PF=U CF=W\"],\n    [\"mul\"              , \"W:<edx>, X:<eax>, r32/m32\"                       , \"M\"       , \"F7 /4\"                        , \"ANY              OF=W SF=U ZF=U AF=U PF=U CF=W\"],\n    [\"mul\"              , \"W:<rdx>, X:<rax>, r64/m64\"                       , \"M\"       , \"REX.W F7 /4\"                  , \"X64              OF=W SF=U ZF=U AF=U PF=U CF=W\"],\n\n    [\"neg\"              , \"x:r8/m8\"                                         , \"M\"       , \"F6 /3\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"neg\"              , \"x:r16/m16\"                                       , \"M\"       , \"66 F7 /3\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"neg\"              , \"X:r32/m32\"                                       , \"M\"       , \"F7 /3\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"neg\"              , \"X:r64/m64\"                                       , \"M\"       , \"REX.W F7 /3\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"nop\"              , \"\"                                                , \"NONE\"    , \"90\"                           , \"\"],\n    [\"nop\"              , \"R:r16/m16\"                                       , \"M\"       , \"66 0F 1F /0\"                  , \"\"],\n    [\"nop\"              , \"R:r32/m32\"                                       , \"M\"       , \"0F 1F /0\"                     , \"\"],\n    [\"nop\"              , \"R:r64/m64\"                                       , \"M\"       , \"REX.W 0F 1F /0\"               , \"\"],\n    [\"nop\"              , \"R:r16/m16, r16\"                                  , \"MR\"      , \"66 0F 1F /r\"                  , \"\"],\n    [\"nop\"              , \"R:r32/m32, r32\"                                  , \"MR\"      , \"0F 1F /r\"                     , \"\"],\n    [\"nop\"              , \"R:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F 1F /r\"               , \"\"],\n\n    [\"not\"              , \"x:r8/m8\"                                         , \"M\"       , \"F6 /2\"                        , \"ANY _XLock\"],\n    [\"not\"              , \"x:r16/m16\"                                       , \"M\"       , \"66 F7 /2\"                     , \"ANY _XLock\"],\n    [\"not\"              , \"X:r32/m32\"                                       , \"M\"       , \"F7 /2\"                        , \"ANY _XLock\"],\n    [\"not\"              , \"X:r64/m64\"                                       , \"M\"       , \"REX.W F7 /2\"                  , \"X64 _XLock\"],\n\n    [\"or\"               , \"x:al, ib/ub\"                                     , \"I\"       , \"0C ib\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 0D iw\"                     , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:eax, id/ud\"                                    , \"I\"       , \"0D id\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:rax, id\"                                       , \"I\"       , \"REX.W 0D id\"                  , \"X64 AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /1 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /1 iw\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /1 id\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /1 id\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /1 ib\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /1 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /1 ib\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:~r8/m8,~r8\"                                    , \"MR\"      , \"08 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:~r16/m16,~r16\"                                 , \"MR\"      , \"66 09 /r\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:~r32/m32,~r32\"                                 , \"MR\"      , \"09 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:~r64/m64,~r64\"                                 , \"MR\"      , \"REX.W 09 /r\"                  , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:~r8,~r8/m8\"                                    , \"RM\"      , \"0A /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"x:~r16,~r16/m16\"                                 , \"RM\"      , \"66 0B /r\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:~r32,~r32/m32\"                                 , \"RM\"      , \"0B /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"or\"               , \"X:~r64,~r64/m64\"                                 , \"RM\"      , \"REX.W 0B /r\"                  , \"X64              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n\n    [\"pop\"              , \"w:r16/m16\"                                       , \"M\"       , \"66 8F /0\"                     , \"ANY\"],\n    [\"pop\"              , \"W:r32/m32\"                                       , \"M\"       , \"8F /0\"                        , \"X86\"],\n    [\"pop\"              , \"W:r64/m64\"                                       , \"M\"       , \"8F /0\"                        , \"X64\"],\n    [\"pop\"              , \"w:r16\"                                           , \"O\"       , \"66 58+r\"                      , \"ANY\"],\n    [\"pop\"              , \"W:r32\"                                           , \"O\"       , \"58+r\"                         , \"X86\"],\n    [\"pop\"              , \"W:r64\"                                           , \"O\"       , \"58+r\"                         , \"X64\"],\n    [\"pop\"              , \"W:ds\"                                            , \"NONE\"    , \"1F\"                           , \"X86\"],\n    [\"pop\"              , \"W:es\"                                            , \"NONE\"    , \"07\"                           , \"X86\"],\n    [\"pop\"              , \"W:ss\"                                            , \"NONE\"    , \"17\"                           , \"X86\"],\n    [\"pop\"              , \"W:fs\"                                            , \"NONE\"    , \"0F A1\"                        , \"ANY\"],\n    [\"pop\"              , \"W:gs\"                                            , \"NONE\"    , \"0F A9\"                        , \"ANY\"],\n    [\"popa\"             , \"\"                                                , \"NONE\"    , \"66 61\"                        , \"X86 Deprecated\"],\n    [\"popad\"            , \"\"                                                , \"NONE\"    , \"61\"                           , \"X86 Deprecated\"],\n    [\"popf\"             , \"\"                                                , \"NONE\"    , \"66 9D\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W DF=W IF=W TF=W\"],\n    [\"popfd\"            , \"\"                                                , \"NONE\"    , \"9D\"                           , \"X86              OF=W SF=W ZF=W AF=W PF=W CF=W DF=W IF=W TF=W\"],\n    [\"popfq\"            , \"\"                                                , \"NONE\"    , \"9D\"                           , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W DF=W IF=W TF=W\"],\n\n    [\"push\"             , \"R:r16/m16\"                                       , \"M\"       , \"66 FF /6\"                     , \"ANY\"],\n    [\"push\"             , \"R:r32/m32\"                                       , \"M\"       , \"FF /6\"                        , \"X86\"],\n    [\"push\"             , \"R:r64/m64\"                                       , \"M\"       , \"FF /6\"                        , \"X64\"],\n    [\"push\"             , \"R:r16\"                                           , \"O\"       , \"66 50+r\"                      , \"ANY\"],\n    [\"push\"             , \"R:r32\"                                           , \"O\"       , \"50+r\"                         , \"X86\"],\n    [\"push\"             , \"R:r64\"                                           , \"O\"       , \"50+r\"                         , \"X64\"],\n    [\"push\"             , \"ib\"                                              , \"I\"       , \"6A ib\"                        , \"ANY\"],\n    [\"push\"             , \"iw\"                                              , \"I\"       , \"66 68 iw\"                     , \"ANY\"],\n    [\"push\"             , \"id/ud\"                                           , \"I\"       , \"68 id\"                        , \"X86\"],\n    [\"push\"             , \"id\"                                              , \"I\"       , \"68 id\"                        , \"X64\"],\n    [\"push\"             , \"R:cs\"                                            , \"NONE\"    , \"0E\"                           , \"X86\"],\n    [\"push\"             , \"R:ss\"                                            , \"NONE\"    , \"16\"                           , \"X86\"],\n    [\"push\"             , \"R:ds\"                                            , \"NONE\"    , \"1E\"                           , \"X86\"],\n    [\"push\"             , \"R:es\"                                            , \"NONE\"    , \"06\"                           , \"X86\"],\n    [\"push\"             , \"R:fs\"                                            , \"NONE\"    , \"0F A0\"                        , \"ANY\"],\n    [\"push\"             , \"R:gs\"                                            , \"NONE\"    , \"0F A8\"                        , \"ANY\"],\n    [\"pusha\"            , \"\"                                                , \"NONE\"    , \"66 60\"                        , \"X86 Deprecated\"],\n    [\"pushad\"           , \"\"                                                , \"NONE\"    , \"60\"                           , \"X86 Deprecated\"],\n    [\"pushf\"            , \"\"                                                , \"NONE\"    , \"66 9C\"                        , \"ANY              OF=R SF=R ZF=R AF=R PF=R CF=R DF=R IF=R TF=R\"],\n    [\"pushfd\"           , \"\"                                                , \"NONE\"    , \"9C\"                           , \"X86              OF=R SF=R ZF=R AF=R PF=R CF=R DF=R IF=R TF=R\"],\n    [\"pushfq\"           , \"\"                                                , \"NONE\"    , \"9C\"                           , \"X64              OF=R SF=R ZF=R AF=R PF=R CF=R DF=R IF=R TF=R\"],\n\n    [\"rcl\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /2\"                        , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcl\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /2\"                        , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /2 ib\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /2\"                     , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcl\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /2\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /2 ib\"                  , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /2\"                        , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcl\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /2\"                        , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /2 ib\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcl\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /2\"                  , \"X64 AltForm      CF=X OF=X\"],\n    [\"rcl\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /2\"                  , \"X64              CF=X OF=X\"],\n    [\"rcl\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /2 ib\"               , \"X64              CF=X OF=X\"],\n\n    [\"rcr\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /3\"                        , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcr\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /3\"                        , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /3 ib\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /3\"                     , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcr\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /3\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /3 ib\"                  , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /3\"                        , \"ANY AltForm      CF=X OF=X\"],\n    [\"rcr\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /3\"                        , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /3 ib\"                     , \"ANY              CF=X OF=X\"],\n    [\"rcr\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /3\"                  , \"X64 AltForm      CF=X OF=X\"],\n    [\"rcr\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /3\"                  , \"X64              CF=X OF=X\"],\n    [\"rcr\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /3 ib\"               , \"X64              CF=X OF=X\"],\n\n    [\"ret\"              , \"\"                                                , \"NONE\"    , \"C3\"                           , \"ANY BND DummyRep Control=Return\"],\n    [\"ret\"              , \"uw\"                                              , \"I\"       , \"C2 iw\"                        , \"ANY BND DummyRep Control=Return\"],\n    [\"retf\"             , \"\"                                                , \"NONE\"    , \"CB\"                           , \"ANY              Control=Return\"],\n    [\"retf\"             , \"uw\"                                              , \"I\"       , \"CA iw\"                        , \"ANY              Control=Return\"],\n\n    [\"rol\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /0\"                        , \"ANY AltForm      CF=W OF=W\"],\n    [\"rol\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /0\"                        , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /0 ib\"                     , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /0\"                     , \"ANY AltForm      CF=W OF=W\"],\n    [\"rol\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /0\"                     , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /0 ib\"                  , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /0\"                        , \"ANY AltForm      CF=W OF=W\"],\n    [\"rol\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /0\"                        , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /0 ib\"                     , \"ANY              CF=W OF=W\"],\n    [\"rol\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /0\"                  , \"X64 AltForm      CF=W OF=W\"],\n    [\"rol\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /0\"                  , \"X64              CF=W OF=W\"],\n    [\"rol\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /0 ib\"               , \"X64              CF=W OF=W\"],\n\n    [\"ror\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /1\"                        , \"ANY AltForm      CF=W OF=W\"],\n    [\"ror\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /1\"                        , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /1 ib\"                     , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /1\"                     , \"ANY AltForm      CF=W OF=W\"],\n    [\"ror\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /1\"                     , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /1 ib\"                  , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /1\"                        , \"ANY AltForm      CF=W OF=W\"],\n    [\"ror\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /1\"                        , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /1 ib\"                     , \"ANY              CF=W OF=W\"],\n    [\"ror\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /1\"                  , \"X64 AltForm      CF=W OF=W\"],\n    [\"ror\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /1\"                  , \"X64              CF=W OF=W\"],\n    [\"ror\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /1 ib\"               , \"X64              CF=W OF=W\"],\n\n    [\"sar\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /7\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /7\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /7 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /7\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /7\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /7 ib\"                  , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /7\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /7\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /7 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /7\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /7\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sar\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /7 ib\"               , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"sbb\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"1C ib\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 1D iw\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"1D id\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 1D id\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /3 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /3 iw\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /3 id\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /3 id\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /3 ib\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /3 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /3 ib\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r8/m8, r8\"                                     , \"MR\"      , \"18 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r16/m16, r16\"                                  , \"MR\"      , \"66 19 /r\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r32/m32, r32\"                                  , \"MR\"      , \"19 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 19 /r\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r8, r8/m8\"                                     , \"RM\"      , \"1A /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 1B /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r32, r32/m32\"                                  , \"RM\"      , \"1B /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n    [\"sbb\"              , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 1B /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=X\"],\n\n    [\"scasb\"            , \"R:<al>, R:<es:zdi>\"                              , \"NONE\"    , \"AE\"                           , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"scasw\"            , \"R:<ax>, R:<es:zdi>\"                              , \"NONE\"    , \"66 AF\"                        , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"scasd\"            , \"R:<eax>, R:<es:zdi>\"                             , \"NONE\"    , \"AF\"                           , \"ANY _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n    [\"scasq\"            , \"R:<rax>, R:<es:zdi>\"                             , \"NONE\"    , \"REX.W AF\"                     , \"X64 _Rep         OF=W SF=W ZF=W AF=W PF=W CF=W DF=R\"],\n\n    [\"seto\"             , \"w:r8/m8\"                                         , \"M\"       , \"0F 90 /r\"                     , \"ANY              OF=R\"],\n    [\"setno\"            , \"w:r8/m8\"                                         , \"M\"       , \"0F 91 /r\"                     , \"ANY              OF=R\"],\n    [\"setb/setnae/setc\" , \"w:r8/m8\"                                         , \"M\"       , \"0F 92 /r\"                     , \"ANY              CF=R\"],\n    [\"setae/setnb/setnc\", \"w:r8/m8\"                                         , \"M\"       , \"0F 93 /r\"                     , \"ANY              CF=R\"],\n    [\"sete/setz\"        , \"w:r8/m8\"                                         , \"M\"       , \"0F 94 /r\"                     , \"ANY              ZF=R\"],\n    [\"setne/setnz\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 95 /r\"                     , \"ANY              ZF=R\"],\n    [\"setbe/setna\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 96 /r\"                     , \"ANY              CF=R ZF=R\"],\n    [\"seta/setnbe\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 97 /r\"                     , \"ANY              CF=R ZF=R\"],\n    [\"sets\"             , \"w:r8/m8\"                                         , \"M\"       , \"0F 98 /r\"                     , \"ANY              SF=R\"],\n    [\"setns\"            , \"w:r8/m8\"                                         , \"M\"       , \"0F 99 /r\"                     , \"ANY              SF=R\"],\n    [\"setp/setpe\"       , \"w:r8/m8\"                                         , \"M\"       , \"0F 9A /r\"                     , \"ANY              PF=R\"],\n    [\"setnp/setpo\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 9B /r\"                     , \"ANY              PF=R\"],\n    [\"setl/setnge\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 9C /r\"                     , \"ANY              SF=R OF=R\"],\n    [\"setge/setnl\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 9D /r\"                     , \"ANY              SF=R OF=R\"],\n    [\"setle/setng\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 9E /r\"                     , \"ANY              ZF=R SF=R OF=R\"],\n    [\"setg/setnle\"      , \"w:r8/m8\"                                         , \"M\"       , \"0F 9F /r\"                     , \"ANY              ZF=R SF=R OF=R\"],\n\n    [\"shl/sal\"          , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /4\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /4\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /4 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /4\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /4\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /4 ib\"                  , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /4\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /4\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /4 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /4\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /4\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shl/sal\"          , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /4 ib\"               , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"shr\"              , \"x:r8/m8, 1\"                                      , \"M\"       , \"D0 /5\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"x:r8/m8, cl\"                                     , \"M\"       , \"D2 /5\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"C0 /5 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"x:r16/m16, 1\"                                    , \"M\"       , \"66 D1 /5\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"x:r16/m16, cl\"                                   , \"M\"       , \"66 D3 /5\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"x:r16/m16, ib/ub\"                                , \"MI\"      , \"66 C1 /5 ib\"                  , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r32/m32, 1\"                                    , \"M\"       , \"D1 /5\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r32/m32, cl\"                                   , \"M\"       , \"D3 /5\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r32/m32, ib/ub\"                                , \"MI\"      , \"C1 /5 ib\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r64/m64, 1\"                                    , \"M\"       , \"REX.W D1 /5\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r64/m64, cl\"                                   , \"M\"       , \"REX.W D3 /5\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"shr\"              , \"X:r64/m64, ib/ub\"                                , \"MI\"      , \"REX.W C1 /5 ib\"               , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"shld\"             , \"x:r16/m16, r16, cl\"                              , \"MR\"      , \"66 0F A5 /r\"                  , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shld\"             , \"x:r16/m16, r16, ib/ub\"                           , \"MRI\"     , \"66 0F A4 /r ib\"               , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shld\"             , \"X:r32/m32, r32, cl\"                              , \"MR\"      , \"0F A5 /r\"                     , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shld\"             , \"X:r32/m32, r32, ib/ub\"                           , \"MRI\"     , \"0F A4 /r ib\"                  , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shld\"             , \"X:r64/m64, r64, cl\"                              , \"MR\"      , \"REX.W 0F A5 /r\"               , \"X64              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shld\"             , \"X:r64/m64, r64, ib/ub\"                           , \"MRI\"     , \"REX.W 0F A4 /r ib\"            , \"X64              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n\n    [\"shrd\"             , \"x:r16/m16, r16, cl\"                              , \"MR\"      , \"66 0F AD /r\"                  , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shrd\"             , \"x:r16/m16, r16, ib/ub\"                           , \"MRI\"     , \"66 0F AC /r ib\"               , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shrd\"             , \"X:r32/m32, r32, cl\"                              , \"MR\"      , \"0F AD /r\"                     , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shrd\"             , \"X:r32/m32, r32, ib/ub\"                           , \"MRI\"     , \"0F AC /r ib\"                  , \"ANY              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shrd\"             , \"X:r64/m64, r64, cl\"                              , \"MR\"      , \"REX.W 0F AD /r\"               , \"X64              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n    [\"shrd\"             , \"X:r64/m64, r64, ib/ub\"                           , \"MRI\"     , \"REX.W 0F AC /r ib\"            , \"X64              OF=W SF=W ZF=W AF=U PF=W CF=W\"],\n\n    [\"stosb\"            , \"W:<es:zdi>, R:<al>\"                              , \"NONE\"    , \"AA\"                           , \"ANY _Rep         DF=R\"],\n    [\"stosw\"            , \"W:<es:zdi>, R:<ax>\"                              , \"NONE\"    , \"66 AB\"                        , \"ANY _Rep         DF=R\"],\n    [\"stosd\"            , \"W:<es:zdi>, R:<eax>\"                             , \"NONE\"    , \"AB\"                           , \"ANY _Rep         DF=R\"],\n    [\"stosq\"            , \"W:<es:zdi>, R:<rax>\"                             , \"NONE\"    , \"REX.W AB\"                     , \"X64 _Rep         DF=R\"],\n\n    [\"sub\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"2C ib\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 2D iw\"                     , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"2D id\"                        , \"ANY AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 2D id\"                  , \"X64 AltForm      OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /5 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /5 iw\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /5 id\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /5 id\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /5 ib\"                  , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /5 ib\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /5 ib\"               , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r8/m8, r8\"                                     , \"MR\"      , \"28 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r16/m16, r16\"                                  , \"MR\"      , \"66 29 /r\"                     , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r32/m32, r32\"                                  , \"MR\"      , \"29 /r\"                        , \"ANY _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 29 /r\"                  , \"X64 _XLock       OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r8, r8/m8\"                                     , \"RM\"      , \"2A /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"x:r16, r16/m16\"                                  , \"RM\"      , \"66 2B /r\"                     , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r32, r32/m32\"                                  , \"RM\"      , \"2B /r\"                        , \"ANY              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"sub\"              , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W 2B /r\"                  , \"X64              OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"test\"             , \"R:al, ib/ub\"                                     , \"I\"       , \"A8 ib\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:ax, iw/uw\"                                     , \"I\"       , \"66 A9 iw\"                     , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:eax, id/ud\"                                    , \"I\"       , \"A9 id\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:rax, id\"                                       , \"I\"       , \"REX.W A9 id\"                  , \"X64 AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:r8/m8, ib/ub\"                                  , \"MI\"      , \"F6 /0 ib\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:r16/m16, iw/uw\"                                , \"MI\"      , \"66 F7 /0 iw\"                  , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:r32/m32, id/ud\"                                , \"MI\"      , \"F7 /0 id\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:r64/m64, id\"                                   , \"MI\"      , \"REX.W F7 /0 id\"               , \"X64              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:~r8/m8,~r8\"                                    , \"MR\"      , \"84 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:~r16/m16,~r16\"                                 , \"MR\"      , \"66 85 /r\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:~r32/m32,~r32\"                                 , \"MR\"      , \"85 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"test\"             , \"R:~r64/m64,~r64\"                                 , \"MR\"      , \"REX.W 85 /r\"                  , \"X64              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n\n    [\"ud0\"              , \"r32, r32/m32\"                                    , \"RM\"      , \"0F FF /r\"                     , \"ANY\"],\n    [\"ud1\"              , \"r32, r32/m32\"                                    , \"RM\"      , \"0F B9 /r\"                     , \"ANY\"],\n    [\"ud2\"              , \"\"                                                , \"NONE\"    , \"0F 0B\"                        , \"ANY\"],\n\n    [\"xadd\"             , \"x:r8/m8, x:r8\"                                   , \"MR\"      , \"0F C0 /r\"                     , \"I486     _XLock  OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"xadd\"             , \"x:r16/m16, x:r16\"                                , \"MR\"      , \"66 0F C1 /r\"                  , \"I486     _XLock  OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"xadd\"             , \"X:r32/m32, X:r32\"                                , \"MR\"      , \"0F C1 /r\"                     , \"I486     _XLock  OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"xadd\"             , \"X:r64/m64, X:r64\"                                , \"MR\"      , \"REX.W 0F C1 /r\"               , \"I486 X64 _XLock  OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"xchg\"             , \"x:~ax, x:~r16\"                                   , \"O\"       , \"66 90+r\"                      , \"ANY AltForm\"],\n    [\"xchg\"             , \"X:~eax, X:~r32\"                                  , \"O\"       , \"90+r\"                         , \"ANY AltForm\"],\n    [\"xchg\"             , \"X:~rax, X:~r64\"                                  , \"O\"       , \"REX.W 90+r\"                   , \"X64 AltForm\"],\n    [\"xchg\"             , \"x:~r16, x:~ax\"                                   , \"O\"       , \"66 90+r\"                      , \"ANY AltForm\"],\n    [\"xchg\"             , \"X:~r32, X:~eax\"                                  , \"O\"       , \"90+r\"                         , \"ANY AltForm\"],\n    [\"xchg\"             , \"X:~r64, X:~rax\"                                  , \"O\"       , \"REX.W 90+r\"                   , \"X64 AltForm\"],\n    [\"xchg\"             , \"x:~r8/m8, x:~r8\"                                 , \"MR\"      , \"86 /r\"                        , \"ANY _ILock XAcquire\"],\n    [\"xchg\"             , \"x:~r16/m16, x:~r16\"                              , \"MR\"      , \"66 87 /r\"                     , \"ANY _ILock XAcquire\"],\n    [\"xchg\"             , \"X:~r32/m32, X:~r32\"                              , \"MR\"      , \"87 /r\"                        , \"ANY _ILock XAcquire\"],\n    [\"xchg\"             , \"X:~r64/m64, X:~r64\"                              , \"MR\"      , \"REX.W 87 /r\"                  , \"X64 _ILock XAcquire\"],\n    [\"xchg\"             , \"x:~r8, x:~r8/m8\"                                 , \"RM\"      , \"86 /r\"                        , \"ANY _ILock\"],\n    [\"xchg\"             , \"x:~r16, x:~r16/m16\"                              , \"RM\"      , \"66 87 /r\"                     , \"ANY _ILock\"],\n    [\"xchg\"             , \"X:~r32, X:~r32/m32\"                              , \"RM\"      , \"87 /r\"                        , \"ANY _ILock\"],\n    [\"xchg\"             , \"X:~r64, X:~r64/m64\"                              , \"RM\"      , \"REX.W 87 /r\"                  , \"X64 _ILock\"],\n\n    [\"xor\"              , \"x:al, ib/ub\"                                     , \"I\"       , \"34 ib\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:ax, iw/uw\"                                     , \"I\"       , \"66 35 iw\"                     , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:eax, id/ud\"                                    , \"I\"       , \"35 id\"                        , \"ANY AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:rax, id\"                                       , \"I\"       , \"REX.W 35 id\"                  , \"X64 AltForm      OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:r8/m8, ib/ub\"                                  , \"MI\"      , \"80 /6 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:r16/m16, iw/uw\"                                , \"MI\"      , \"66 81 /6 iw\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:r32/m32, id/ud\"                                , \"MI\"      , \"81 /6 id\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:r64/m64, id\"                                   , \"MI\"      , \"REX.W 81 /6 id\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:r16/m16, ib\"                                   , \"MI\"      , \"66 83 /6 ib\"                  , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:r32/m32, ib\"                                   , \"MI\"      , \"83 /6 ib\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:r64/m64, ib\"                                   , \"MI\"      , \"REX.W 83 /6 ib\"               , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:~r8/m8, ~r8\"                                   , \"MR\"      , \"30 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:~r16/m16, ~r16\"                                , \"MR\"      , \"66 31 /r\"                     , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:~r32/m32, ~r32\"                                , \"MR\"      , \"31 /r\"                        , \"ANY _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:~r64/m64, ~r64\"                                , \"MR\"      , \"REX.W 31 /r\"                  , \"X64 _XLock       OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:~r8, ~r8/m8\"                                   , \"RM\"      , \"32 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"x:~r16, ~r16/m16\"                                , \"RM\"      , \"66 33 /r\"                     , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:~r32, ~r32/m32\"                                , \"RM\"      , \"33 /r\"                        , \"ANY              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n    [\"xor\"              , \"X:~r64, ~r64/m64\"                                , \"RM\"      , \"REX.W 33 /r\"                  , \"X64              OF=0 SF=W ZF=W AF=U PF=W CF=0\"],\n\n    [\"aaa\"              , \"x:<ax>\"                                          , \"NONE\"    , \"37\"                           , \"X86 Deprecated   OF=U SF=U ZF=U AF=W PF=U CF=W\"],\n    [\"aas\"              , \"x:<ax>\"                                          , \"NONE\"    , \"3F\"                           , \"X86 Deprecated   OF=U SF=U ZF=U AF=W PF=U CF=W\"],\n    [\"aad\"              , \"x:<ax>, ib/ub\"                                   , \"I\"       , \"D5 ib\"                        , \"X86 Deprecated   OF=U SF=W ZF=W AF=U PF=W CF=U\"],\n    [\"aam\"              , \"x:<ax>, ib/ub\"                                   , \"I\"       , \"D4 ib\"                        , \"X86 Deprecated   OF=U SF=W ZF=W AF=U PF=W CF=U\"],\n    [\"daa\"              , \"x:<ax>\"                                          , \"NONE\"    , \"27\"                           , \"X86 Deprecated   OF=U SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"das\"              , \"x:<ax>\"                                          , \"NONE\"    , \"2F\"                           , \"X86 Deprecated   OF=U SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"enter\"            , \"iw/uw, ib/ub\"                                    , \"II\"      , \"C8 iw ib\"                     , \"ANY              Volatile\"],\n    [\"leave\"            , \"\"                                                , \"NONE\"    , \"C9\"                           , \"ANY              Volatile\"],\n\n    [\"in\"               , \"w:al, ib/ub\"                                     , \"I\"       , \"E4 ib\"                        , \"ANY              Volatile\"],\n    [\"in\"               , \"w:ax, ib/ub\"                                     , \"I\"       , \"66 E5 ib\"                     , \"ANY              Volatile\"],\n    [\"in\"               , \"W:eax, ib/ub\"                                    , \"I\"       , \"E5 ib\"                        , \"ANY              Volatile\"],\n    [\"in\"               , \"w:al, dx\"                                        , \"NONE\"    , \"EC\"                           , \"ANY              Volatile\"],\n    [\"in\"               , \"w:ax, dx\"                                        , \"NONE\"    , \"66 ED\"                        , \"ANY              Volatile\"],\n    [\"in\"               , \"W:eax, dx\"                                       , \"NONE\"    , \"ED\"                           , \"ANY              Volatile\"],\n    [\"insb\"             , \"W:es:zdi, dx\"                                    , \"NONE\"    , \"6C\"                           , \"ANY _Rep         Volatile\"],\n    [\"insw\"             , \"W:es:zdi, dx\"                                    , \"NONE\"    , \"66 6D\"                        , \"ANY _Rep         Volatile\"],\n    [\"insd\"             , \"W:es:zdi, dx\"                                    , \"NONE\"    , \"6D\"                           , \"ANY _Rep         Volatile\"],\n    [\"out\"              , \"ub, al\"                                          , \"I\"       , \"E6 ib\"                        , \"ANY              Volatile\"],\n    [\"out\"              , \"ub, ax\"                                          , \"I\"       , \"66 E7 ib\"                     , \"ANY              Volatile\"],\n    [\"out\"              , \"ub, eax\"                                         , \"I\"       , \"E7 ib\"                        , \"ANY              Volatile\"],\n    [\"out\"              , \"R:dx, R:al\"                                      , \"NONE\"    , \"EE\"                           , \"ANY              Volatile\"],\n    [\"out\"              , \"R:dx, R:ax\"                                      , \"NONE\"    , \"66 EF\"                        , \"ANY              Volatile\"],\n    [\"out\"              , \"R:dx, R:eax\"                                     , \"NONE\"    , \"EF\"                           , \"ANY              Volatile\"],\n    [\"outsb\"            , \"R:dx, R:ds:zsi\"                                  , \"NONE\"    , \"6E\"                           , \"ANY _Rep         Volatile\"],\n    [\"outsw\"            , \"R:dx, R:ds:zsi\"                                  , \"NONE\"    , \"66 6F\"                        , \"ANY _Rep         Volatile\"],\n    [\"outsd\"            , \"R:dx, R:ds:zsi\"                                  , \"NONE\"    , \"6F\"                           , \"ANY _Rep         Volatile\"],\n\n    [\"clc\"              , \"\"                                                , \"NONE\"    , \"F8\"                           , \"ANY              CF=0\"],\n    [\"cld\"              , \"\"                                                , \"NONE\"    , \"FC\"                           , \"ANY              DF=0\"],\n    [\"cmc\"              , \"\"                                                , \"NONE\"    , \"F5\"                           , \"ANY              CF=X\"],\n    [\"stc\"              , \"\"                                                , \"NONE\"    , \"F9\"                           , \"ANY              CF=1\"],\n    [\"std\"              , \"\"                                                , \"NONE\"    , \"FD\"                           , \"ANY              DF=1\"],\n\n    [\"lahf\"             , \"w:<ah>\"                                          , \"NONE\"    , \"9F\"                           , \"LAHFSAHF         Volatile SF=R ZF=R AF=R PF=R CF=R\"],\n    [\"sahf\"             , \"R:<ah>\"                                          , \"NONE\"    , \"9E\"                           , \"LAHFSAHF         Volatile SF=W ZF=W AF=W PF=W CF=W\"],\n\n    [\"adcx\"             , \"X:~r32, ~r32/m32\"                                , \"RM\"      , \"66 0F 38 F6 /r\"               , \"ADX              CF=X\"],\n    [\"adcx\"             , \"X:~r64, ~r64/m64\"                                , \"RM\"      , \"REX.W 66 0F 38 F6 /r\"         , \"ADX X64          CF=X\"],\n    [\"adox\"             , \"X:~r32, ~r32/m32\"                                , \"RM\"      , \"F3 0F 38 F6 /r\"               , \"ADX              OF=X\"],\n    [\"adox\"             , \"X:~r64, ~r64/m64\"                                , \"RM\"      , \"REX.W F3 0F 38 F6 /r\"         , \"ADX X64          OF=X\"],\n\n    [\"lzcnt\"            , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 F3 0F BD /r\"               , \"LZCNT            OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n    [\"lzcnt\"            , \"W:r32, r32/m32\"                                  , \"RM\"      , \"F3 0F BD /r\"                  , \"LZCNT            OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n    [\"lzcnt\"            , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W F3 0F BD /r\"            , \"LZCNT X64        OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n    [\"popcnt\"           , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 F3 0F B8 /r\"               , \"POPCNT           OF=0 SF=0 ZF=W AF=0 PF=0 CF=0\"],\n    [\"popcnt\"           , \"W:r32, r32/m32\"                                  , \"RM\"      , \"F3 0F B8 /r\"                  , \"POPCNT           OF=0 SF=0 ZF=W AF=0 PF=0 CF=0\"],\n    [\"popcnt\"           , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W F3 0F B8 /r\"            , \"POPCNT X64       OF=0 SF=0 ZF=W AF=0 PF=0 CF=0\"],\n\n    [\"andn\"             , \"W:r32, r32, r32/m32\"                             , \"RVM\"     , \"VEX.LZ.0F38.W0 F2 /r\"         , \"BMI              OF=0 SF=W ZF=W AF=U PF=U CF=0\"],\n    [\"andn\"             , \"W:r64, r64, r64/m64\"                             , \"RVM\"     , \"VEX.LZ.0F38.W1 F2 /r\"         , \"BMI X64          OF=0 SF=W ZF=W AF=U PF=U CF=0\"],\n    [\"bextr\"            , \"W:r32, r32/m32, r32\"                             , \"RMV\"     , \"VEX.LZ.0F38.W0 F7 /r\"         , \"BMI              OF=0 SF=U ZF=W AF=U PF=U CF=0\"],\n    [\"bextr\"            , \"W:r64, r64/m64, r64\"                             , \"RMV\"     , \"VEX.LZ.0F38.W1 F7 /r\"         , \"BMI X64          OF=0 SF=U ZF=W AF=U PF=U CF=0\"],\n    [\"blsi\"             , \"W:r32, r32/m32\"                                  , \"VM\"      , \"VEX.LZ.0F38.W0 F3 /3\"         , \"BMI              OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"blsi\"             , \"W:r64, r64/m64\"                                  , \"VM\"      , \"VEX.LZ.0F38.W1 F3 /3\"         , \"BMI X64          OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"blsmsk\"           , \"W:r32, r32/m32\"                                  , \"VM\"      , \"VEX.LZ.0F38.W0 F3 /2\"         , \"BMI              OF=0 SF=W ZF=0 AF=U PF=U CF=W\"],\n    [\"blsmsk\"           , \"W:r64, r64/m64\"                                  , \"VM\"      , \"VEX.LZ.0F38.W1 F3 /2\"         , \"BMI X64          OF=0 SF=W ZF=0 AF=U PF=U CF=W\"],\n    [\"blsr\"             , \"W:r32, r32/m32\"                                  , \"VM\"      , \"VEX.LZ.0F38.W0 F3 /1\"         , \"BMI              OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"blsr\"             , \"W:r64, r64/m64\"                                  , \"VM\"      , \"VEX.LZ.0F38.W1 F3 /1\"         , \"BMI X64          OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"bzhi\"             , \"W:r32, r32/m32, r32\"                             , \"RMV\"     , \"VEX.LZ.0F38.W0 F5 /r\"         , \"BMI2             OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"bzhi\"             , \"W:r64, r64/m64, r64\"                             , \"RMV\"     , \"VEX.LZ.0F38.W1 F5 /r\"         , \"BMI2 X64         OF=0 SF=W ZF=W AF=U PF=U CF=W\"],\n    [\"mulx\"             , \"W:r32, W:r32, ~r32/m32, ~<edx>\"                  , \"RVM\"     , \"VEX.LZ.F2.0F38.W0 F6 /r\"      , \"BMI2\"],\n    [\"mulx\"             , \"W:r64, W:r64, ~r64/m64, ~<rdx>\"                  , \"RVM\"     , \"VEX.LZ.F2.0F38.W1 F6 /r\"      , \"BMI2 X64\"],\n    [\"pdep\"             , \"W:r32, r32, r32/m32\"                             , \"RVM\"     , \"VEX.LZ.F2.0F38.W0 F5 /r\"      , \"BMI2\"],\n    [\"pdep\"             , \"W:r64, r64, r64/m64\"                             , \"RVM\"     , \"VEX.LZ.F2.0F38.W1 F5 /r\"      , \"BMI2 X64\"],\n    [\"pext\"             , \"W:r32, r32, r32/m32\"                             , \"RVM\"     , \"VEX.LZ.F3.0F38.W0 F5 /r\"      , \"BMI2\"],\n    [\"pext\"             , \"W:r64, r64, r64/m64\"                             , \"RVM\"     , \"VEX.LZ.F3.0F38.W1 F5 /r\"      , \"BMI2 X64\"],\n    [\"rorx\"             , \"W:r32, r32/m32, ib/ub\"                           , \"RMI\"     , \"VEX.LZ.F2.0F3A.W0 F0 /r ib\"   , \"BMI2\"],\n    [\"rorx\"             , \"W:r64, r64/m64, ib/ub\"                           , \"RMI\"     , \"VEX.LZ.F2.0F3A.W1 F0 /r ib\"   , \"BMI2 X64\"],\n    [\"sarx\"             , \"W:r32, r32/m32, r32\"                             , \"RMV\"     , \"VEX.LZ.F3.0F38.W0 F7 /r\"      , \"BMI2\"],\n    [\"sarx\"             , \"W:r64, r64/m64, r64\"                             , \"RMV\"     , \"VEX.LZ.F3.0F38.W1 F7 /r\"      , \"BMI2 X64\"],\n    [\"shlx\"             , \"W:r32, r32/m32, r32\"                             , \"RMV\"     , \"VEX.LZ.66.0F38.W0 F7 /r\"      , \"BMI2\"],\n    [\"shlx\"             , \"W:r64, r64/m64, r64\"                             , \"RMV\"     , \"VEX.LZ.66.0F38.W1 F7 /r\"      , \"BMI2 X64\"],\n    [\"shrx\"             , \"W:r32, r32/m32, r32\"                             , \"RMV\"     , \"VEX.LZ.F2.0F38.W0 F7 /r\"      , \"BMI2\"],\n    [\"shrx\"             , \"W:r64, r64/m64, r64\"                             , \"RMV\"     , \"VEX.LZ.F2.0F38.W1 F7 /r\"      , \"BMI2 X64\"],\n    [\"tzcnt\"            , \"w:r16, r16/m16\"                                  , \"RM\"      , \"66 F3 0F BC /r\"               , \"BMI              OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n    [\"tzcnt\"            , \"W:r32, r32/m32\"                                  , \"RM\"      , \"F3 0F BC /r\"                  , \"BMI              OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n    [\"tzcnt\"            , \"W:r64, r64/m64\"                                  , \"RM\"      , \"REX.W F3 0F BC /r\"            , \"BMI X64          OF=U SF=U ZF=W AF=U PF=U CF=W\"],\n\n    [\"blci\"             , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 02 /6\"          , \"TBM\"],\n    [\"blci\"             , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 02 /6\"          , \"TBM X64\"],\n    [\"blcic\"            , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /5\"          , \"TBM\"],\n    [\"blcic\"            , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /5\"          , \"TBM X64\"],\n    [\"blsic\"            , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /6\"          , \"TBM\"],\n    [\"blsic\"            , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /6\"          , \"TBM X64\"],\n    [\"blcfill\"          , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /1\"          , \"TBM\"],\n    [\"blcfill\"          , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /1\"          , \"TBM X64\"],\n    [\"blsfill\"          , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /2\"          , \"TBM\"],\n    [\"blsfill\"          , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /2\"          , \"TBM X64\"],\n    [\"blcmsk\"           , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 02 /1\"          , \"TBM\"],\n    [\"blcmsk\"           , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 02 /1\"          , \"TBM X64\"],\n    [\"blcs\"             , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /3\"          , \"TBM\"],\n    [\"blcs\"             , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /3\"          , \"TBM X64\"],\n    [\"tzmsk\"            , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /4\"          , \"TBM\"],\n    [\"tzmsk\"            , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /4\"          , \"TBM X64\"],\n    [\"t1mskc\"           , \"W:r32, r32/m32\"                                  , \"VM\"      , \"XOP.LZ.M09.W0 01 /7\"          , \"TBM\"],\n    [\"t1mskc\"           , \"W:r64, r64/m64\"                                  , \"VM\"      , \"XOP.LZ.M09.W1 01 /7\"          , \"TBM X64\"],\n\n    [\"crc32\"            , \"X:r32, r8/m8\"                                    , \"RM\"      , \"F2 0F 38 F0 /r\"               , \"SSE4_2\"],\n    [\"crc32\"            , \"X:r32, r16/m16\"                                  , \"RM\"      , \"66 F2 0F 38 F1 /r\"            , \"SSE4_2\"],\n    [\"crc32\"            , \"X:r32, r32/m32\"                                  , \"RM\"      , \"F2 0F 38 F1 /r\"               , \"SSE4_2\"],\n    [\"crc32\"            , \"X:r64, r8/m8\"                                    , \"RM\"      , \"REX.W F2 0F 38 F0 /r\"         , \"SSE4_2 X64\"],\n    [\"crc32\"            , \"X:r64, r64/m64\"                                  , \"RM\"      , \"REX.W F2 0F 38 F1 /r\"         , \"SSE4_2 X64\"],\n\n    [\"movbe\"            , \"w:r16, m16\"                                      , \"RM\"      , \"66 0F 38 F0 /r\"               , \"MOVBE\"],\n    [\"movbe\"            , \"W:r32, m32\"                                      , \"RM\"      , \"0F 38 F0 /r\"                  , \"MOVBE\"],\n    [\"movbe\"            , \"W:r64, m64\"                                      , \"RM\"      , \"REX.W 0F 38 F0 /r\"            , \"MOVBE X64\"],\n    [\"movbe\"            , \"W:m16, r16\"                                      , \"MR\"      , \"66 0F 38 F1 /r\"               , \"MOVBE\"],\n    [\"movbe\"            , \"W:m32, r32\"                                      , \"MR\"      , \"0F 38 F1 /r\"                  , \"MOVBE\"],\n    [\"movbe\"            , \"W:m64, r64\"                                      , \"MR\"      , \"REX.W 0F 38 F1 /r\"            , \"MOVBE X64\"],\n    [\"movdiri\"          , \"W:m32, r32\"                                      , \"MR\"      , \"0F 38 F9 /r\"                  , \"MOVDIRI\"],\n    [\"movdiri\"          , \"W:m64, r64\"                                      , \"MR\"      , \"REX.W 0F 38 F9 /r\"            , \"MOVDIRI X64\"],\n    [\"movdir64b\"        , \"W:es:r32, m512\"                                  , \"RM\"      , \"66 0F 38 F8 /r\"               , \"MOVDIR64B\"],\n    [\"movdir64b\"        , \"W:es:r64, m512\"                                  , \"RM\"      , \"66 0F 38 F8 /r\"               , \"MOVDIR64B X64\"],\n\n    [\"ldmxcsr\"          , \"R:m32\"                                           , \"M\"       , \"0F AE /2\"                     , \"SSE              Volatile\"],\n    [\"stmxcsr\"          , \"W:m32\"                                           , \"M\"       , \"0F AE /3\"                     , \"SSE              Volatile\"],\n\n    [\"lfence\"           , \"\"                                                , \"NONE\"    , \"0F AE E8\"                     , \"SSE2             Volatile\"],\n    [\"mfence\"           , \"\"                                                , \"NONE\"    , \"0F AE F0\"                     , \"SSE2             Volatile\"],\n    [\"sfence\"           , \"\"                                                , \"NONE\"    , \"0F AE F8\"                     , \"MMX2             Volatile\"],\n\n    [\"prefetch\"         , \"R:mem\"                                           , \"M\"       , \"0F 0D /0\"                     , \"3DNOW\"],\n    [\"prefetchnta\"      , \"R:mem\"                                           , \"M\"       , \"0F 18 /0\"                     , \"MMX2\"],\n    [\"prefetcht0\"       , \"R:mem\"                                           , \"M\"       , \"0F 18 /1\"                     , \"MMX2\"],\n    [\"prefetcht1\"       , \"R:mem\"                                           , \"M\"       , \"0F 18 /2\"                     , \"MMX2\"],\n    [\"prefetcht2\"       , \"R:mem\"                                           , \"M\"       , \"0F 18 /3\"                     , \"MMX2\"],\n    [\"prefetchw\"        , \"R:mem\"                                           , \"M\"       , \"0F 0D /1\"                     , \"PREFETCHW        OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"prefetchwt1\"      , \"R:mem\"                                           , \"M\"       , \"0F 0D /2\"                     , \"PREFETCHWT1      OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n\n    [\"cpuid\"            , \"X:<eax>, W:<ebx>, X:<ecx>, W:<edx>\"              , \"NONE\"    , \"0F A2\"                        , \"I486             Volatile\"],\n\n    [\"cldemote\"         , \"R:mem\"                                           , \"M\"       , \"0F 1C /0\"                     , \"CLDEMOTE         Volatile\"],\n    [\"clflush\"          , \"R:mem\"                                           , \"M\"       , \"0F AE /7\"                     , \"CLFLUSH          Volatile\"],\n    [\"clflushopt\"       , \"R:mem\"                                           , \"M\"       , \"66 0F AE /7\"                  , \"CLFLUSHOPT       Volatile\"],\n    [\"clwb\"             , \"R:mem\"                                           , \"M\"       , \"66 0F AE /6\"                  , \"CLWB             Volatile\"],\n    [\"clzero\"           , \"R:<ds:zax>\"                                      , \"NONE\"    , \"0F 01 FC\"                     , \"CLZERO           Volatile\"],\n\n    [\"ptwrite\"          , \"R:r32/m32\"                                       , \"M\"       , \"F3 0F AE /4\"                  , \"PTWRITE          Volatile\"],\n    [\"ptwrite\"          , \"R:r64/m64\"                                       , \"M\"       , \"REX.W F3 0F AE /4\"            , \"PTWRITE X64      Volatile\"],\n\n    [\"serialize\"        , \"\"                                                , \"NONE\"    , \"0F 01 E8\"                     , \"SERIALIZE        Volatile\"],\n\n    [\"rdpid\"            , \"W:r32\"                                           , \"R\"       , \"F3 0F C7 /7\"                  , \"RDPID X86        Volatile\"],\n    [\"rdpid\"            , \"W:r64\"                                           , \"R\"       , \"F3 0F C7 /7\"                  , \"RDPID X64        Volatile\"],\n    [\"rdpkru\"           , \"W:<edx>, W:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 01 EE\"                     , \"OSPKE            Volatile\"],\n    [\"rdpru\"            , \"W:<edx>, W:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 01 FD\"                     , \"RDPRU            Volatile\"],\n    [\"rdtsc\"            , \"W:<edx>, W:<eax>\"                                , \"NONE\"    , \"0F 31\"                        , \"RDTSC            Volatile\"],\n    [\"rdtscp\"           , \"W:<edx>, W:<eax>, W:<ecx>\"                       , \"NONE\"    , \"0F 01 F9\"                     , \"RDTSCP           Volatile\"],\n\n    [\"arpl\"             , \"x:r16/m16, R:r16\"                                , \"MR\"      , \"63 /r\"                        , \"X86 ZF=W\"],\n    [\"cli\"              , \"\"                                                , \"NONE\"    , \"FA\"                           , \"ANY              Volatile IF=W\"],\n    [\"getsec\"           , \"\"                                                , \"NONE\"    , \"0F 37\"                        , \"SMX              Volatile\"],\n    [\"int\"              , \"ib/ub\"                                           , \"I\"       , \"CD ib\"                        , \"ANY              Volatile\"],\n    [\"int3\"             , \"\"                                                , \"NONE\"    , \"CC\"                           , \"ANY              Volatile\"],\n    [\"into\"             , \"\"                                                , \"NONE\"    , \"CE\"                           , \"X86 Deprecated   Volatile OF=R\"],\n    [\"lar\"              , \"w:r16, R:r16/m16\"                                , \"RM\"      , \"66 0F 02 /r\"                  , \"ANY              Volatile ZF=W\"],\n    [\"lar\"              , \"W:r32, R:r32/m16\"                                , \"RM\"      , \"0F 02 /r\"                     , \"ANY              Volatile ZF=W\"],\n    [\"lds\"              , \"x:r16, m16_16\"                                   , \"RM\"      , \"66 C5 /r\"                     , \"X86              Volatile\"],\n    [\"lds\"              , \"X:r32, m16_32\"                                   , \"RM\"      , \"C5 /r\"                        , \"X86              Volatile\"],\n    [\"les\"              , \"x:r16, m16_16\"                                   , \"RM\"      , \"66 C4 /r\"                     , \"X86              Volatile\"],\n    [\"les\"              , \"X:r32, m16_32\"                                   , \"RM\"      , \"C4 /r\"                        , \"X86              Volatile\"],\n    [\"lfs\"              , \"x:r16, m16_16\"                                   , \"RM\"      , \"66 0F B4 /r\"                  , \"ANY              Volatile\"],\n    [\"lfs\"              , \"X:r32, m16_32\"                                   , \"RM\"      , \"0F B4 /r\"                     , \"ANY              Volatile\"],\n    [\"lfs\"              , \"X:r64, m16_64\"                                   , \"RM\"      , \"REX.W 0F B4 /r\"               , \"X64              Volatile\"],\n    [\"lgs\"              , \"x:r16, m16_16\"                                   , \"RM\"      , \"66 0F B5 /r\"                  , \"ANY              Volatile\"],\n    [\"lgs\"              , \"X:r32, m16_32\"                                   , \"RM\"      , \"0F B5 /r\"                     , \"ANY              Volatile\"],\n    [\"lgs\"              , \"X:r64, m16_64\"                                   , \"RM\"      , \"REX.W 0F B5 /r\"               , \"X64              Volatile\"],\n    [\"lsl\"              , \"w:r16, R:r16/m16\"                                , \"RM\"      , \"66 0F 03 /r\"                  , \"ANY              Volatile ZF=W\"],\n    [\"lsl\"              , \"W:r32, R:r32/m16\"                                , \"RM\"      , \"0F 03 /r\"                     , \"ANY              Volatile ZF=W\"],\n    [\"lsl\"              , \"W:r64, R:r32/m16\"                                , \"RM\"      , \"REX.W 0F 03 /r\"               , \"X64              Volatile ZF=W\"],\n    [\"lss\"              , \"x:r16, m16_16\"                                   , \"RM\"      , \"66 0F B2 /r\"                  , \"ANY              Volatile\"],\n    [\"lss\"              , \"X:r32, m16_32\"                                   , \"RM\"      , \"0F B2 /r\"                     , \"ANY              Volatile\"],\n    [\"lss\"              , \"X:r64, m16_64\"                                   , \"RM\"      , \"REX.W 0F B2 /r\"               , \"X64              Volatile\"],\n    [\"pause\"            , \"\"                                                , \"NONE\"    , \"F3 90\"                        , \"ANY              Volatile\"],\n    [\"rsm\"              , \"\"                                                , \"NONE\"    , \"0F AA\"                        , \"X86              Volatile OF=U SF=U ZF=U AF=U PF=U CF=U\"],\n    [\"sgdt\"             , \"W:mem\"                                           , \"M\"       , \"0F 01 /0\"                     , \"ANY              Volatile\"],\n    [\"sidt\"             , \"W:mem\"                                           , \"M\"       , \"0F 01 /1\"                     , \"ANY              Volatile\"],\n    [\"sldt\"             , \"w:r16/m16\"                                       , \"M\"       , \"66 0F 00 /0\"                  , \"ANY              Volatile\"],\n    [\"sldt\"             , \"W:r32/m16\"                                       , \"M\"       , \"0F 00 /0\"                     , \"ANY              Volatile\"],\n    [\"sldt\"             , \"W:r64/m16\"                                       , \"M\"       , \"REX.W 0F 00 /0\"               , \"X64              Volatile\"],\n    [\"smsw\"             , \"w:r16/m16\"                                       , \"M\"       , \"66 0F 01 /4\"                  , \"ANY              Volatile\"],\n    [\"smsw\"             , \"W:r32/m16\"                                       , \"M\"       , \"0F 01 /4\"                     , \"ANY              Volatile\"],\n    [\"smsw\"             , \"W:r64/m16\"                                       , \"M\"       , \"REX.W 0F 01 /4\"               , \"X64              Volatile\"],\n    [\"sti\"              , \"\"                                                , \"NONE\"    , \"FB\"                           , \"ANY              Volatile IF=1\"],\n    [\"str\"              , \"w:r16/m16\"                                       , \"M\"       , \"66 0F 00 /1\"                  , \"ANY              Volatile\"],\n    [\"str\"              , \"W:r32/m16\"                                       , \"M\"       , \"0F 00 /1\"                     , \"ANY              Volatile\"],\n    [\"str\"              , \"W:r64/m16\"                                       , \"M\"       , \"REX.W 0F 00 /1\"               , \"X64              Volatile\"],\n    [\"verr\"             , \"R:r16/m16\"                                       , \"M\"       , \"0F 00 /4\"                     , \"ANY              Volatile ZF=W\"],\n    [\"verw\"             , \"R:r16/m16\"                                       , \"M\"       , \"0F 00 /5\"                     , \"ANY              Volatile ZF=W\"],\n    [\"xlatb\"            , \"\"                                                , \"NONE\"    , \"D7\"                           , \"ANY              Volatile\"],\n\n    [\"rdfsbase\"         , \"W:r32\"                                           , \"M\"       , \"F3 0F AE /0\"                  , \"FSGSBASE X64     Volatile\"],\n    [\"rdfsbase\"         , \"W:r64\"                                           , \"M\"       , \"REX.W F3 0F AE /0\"            , \"FSGSBASE X64     Volatile\"],\n    [\"rdgsbase\"         , \"W:r32\"                                           , \"M\"       , \"F3 0F AE /1\"                  , \"FSGSBASE X64     Volatile\"],\n    [\"rdgsbase\"         , \"W:r64\"                                           , \"M\"       , \"REX.W F3 0F AE /1\"            , \"FSGSBASE X64     Volatile\"],\n    [\"wrfsbase\"         , \"R:r32\"                                           , \"M\"       , \"F3 0F AE /2\"                  , \"FSGSBASE X64     Volatile\"],\n    [\"wrfsbase\"         , \"R:r64\"                                           , \"M\"       , \"REX.W F3 0F AE /2\"            , \"FSGSBASE X64     Volatile\"],\n    [\"wrgsbase\"         , \"R:r32\"                                           , \"M\"       , \"F3 0F AE /3\"                  , \"FSGSBASE X64     Volatile\"],\n    [\"wrgsbase\"         , \"R:r64\"                                           , \"M\"       , \"REX.W F3 0F AE /3\"            , \"FSGSBASE X64     Volatile\"],\n\n    [\"fxrstor\"          , \"R:mem\"                                           , \"NONE\"    , \"0F AE /1\"                     , \"FXSR             Volatile C0=W C1=W C2=W C3=W\"],\n    [\"fxrstor64\"        , \"R:mem\"                                           , \"NONE\"    , \"REX.W 0F AE /1\"               , \"FXSR X64         Volatile C0=W C1=W C2=W C3=W\"],\n    [\"fxsave\"           , \"W:mem\"                                           , \"NONE\"    , \"0F AE /0\"                     , \"FXSR             Volatile\"],\n    [\"fxsave64\"         , \"W:mem\"                                           , \"NONE\"    , \"REX.W 0F AE /0\"               , \"FXSR X64         Volatile\"],\n\n    [\"xgetbv\"           , \"W:<edx>, W:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 01 D0\"                     , \"XSAVE            Volatile XCR=R\"],\n    [\"xrstor\"           , \"R:mem, <edx>, <eax>\"                             , \"M\"       , \"0F AE /5\"                     , \"XSAVE            Volatile XCR=R\"],\n    [\"xrstor64\"         , \"R:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F AE /5\"               , \"XSAVE X64        Volatile XCR=R\"],\n    [\"xrstors\"          , \"R:mem, <edx>, <eax>\"                             , \"M\"       , \"0F C7 /3\"                     , \"XSAVES           Volatile XCR=R\"],\n    [\"xrstors64\"        , \"R:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F C7 /3\"               , \"XSAVES X64       Volatile XCR=R\"],\n    [\"xsave\"            , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"0F AE /4\"                     , \"XSAVE            Volatile XCR=R\"],\n    [\"xsave64\"          , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F AE /4\"               , \"XSAVE X64        Volatile XCR=R\"],\n    [\"xsavec\"           , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"0F C7 /4\"                     , \"XSAVEC           Volatile XCR=R\"],\n    [\"xsavec64\"         , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F C7 /4\"               , \"XSAVEC X64       Volatile XCR=R\"],\n    [\"xsaveopt\"         , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"0F AE /6\"                     , \"XSAVEOPT         Volatile XCR=R\"],\n    [\"xsaveopt64\"       , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F AE /6\"               , \"XSAVEOPT X64     Volatile XCR=R\"],\n    [\"xsaves\"           , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"0F C7 /5\"                     , \"XSAVES           Volatile XCR=R\"],\n    [\"xsaves64\"         , \"W:mem, <edx>, <eax>\"                             , \"M\"       , \"REX.W 0F C7 /5\"               , \"XSAVES X64       Volatile XCR=R\"],\n\n    [\"bndcl\"            , \"R:bnd, r32/m32\"                                  , \"RM\"      , \"F3 0F 1A /r\"                  , \"MPX X86\"],\n    [\"bndcl\"            , \"R:bnd, r64/m64\"                                  , \"RM\"      , \"F3 0F 1A /r\"                  , \"MPX X64\"],\n    [\"bndcn\"            , \"R:bnd, r32/m32\"                                  , \"RM\"      , \"F2 0F 1B /r\"                  , \"MPX X86\"],\n    [\"bndcn\"            , \"R:bnd, r64/m64\"                                  , \"RM\"      , \"F2 0F 1B /r\"                  , \"MPX X64\"],\n    [\"bndcu\"            , \"R:bnd, r32/m32\"                                  , \"RM\"      , \"F2 0F 1A /r\"                  , \"MPX X86\"],\n    [\"bndcu\"            , \"R:bnd, r64/m64\"                                  , \"RM\"      , \"F2 0F 1A /r\"                  , \"MPX X64\"],\n    [\"bndldx\"           , \"W:bnd, mib\"                                      , \"RM\"      , \"0F 1A /r\"                     , \"MPX\"],\n    [\"bndmk\"            , \"W:bnd, mem\"                                      , \"RM\"      , \"F3 0F 1B /r\"                  , \"MPX\"],\n    [\"bndmov\"           , \"W:bnd, bnd/mem\"                                  , \"RM\"      , \"66 0F 1A /r\"                  , \"MPX\"],\n    [\"bndmov\"           , \"W:bnd/mem, bnd\"                                  , \"MR\"      , \"66 0F 1B /r\"                  , \"MPX\"],\n    [\"bndstx\"           , \"W:mib, bnd\"                                      , \"MR\"      , \"0F 1B /r\"                     , \"MPX\"],\n\n    [\"monitorx\"         , \"R:<ds:zax>, R:<ecx>, R:<edx>\"                    , \"NONE\"    , \"0F 01 FA\"                     , \"MONITORX         Volatile\"],\n    [\"mwaitx\"           , \"R:<eax>, R:<ecx>, R:<ebx>\"                       , \"NONE\"    , \"0F 01 FB\"                     , \"MONITORX         Volatile\"],\n\n    [\"mcommit\"          , \"\"                                                , \"NONE\"    , \"F3 0F 01 FA\"                  , \"MCOMMIT          Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n\n    [\"enqcmd\"           , \"W:es:r32, m512\"                                  , \"RM\"      , \"F2 0F 38 F8 /r\"               , \"ENQCMD X86       Volatile\"],\n    [\"enqcmd\"           , \"W:es:r64, m512\"                                  , \"RM\"      , \"F2 0F 38 F8 /r\"               , \"ENQCMD X64       Volatile\"],\n    [\"enqcmds\"          , \"W:es:r32, m512\"                                  , \"RM\"      , \"F3 0F 38 F8 /r\"               , \"ENQCMD X86       Volatile\"],\n    [\"enqcmds\"          , \"W:es:r64, m512\"                                  , \"RM\"      , \"F3 0F 38 F8 /r\"               , \"ENQCMD X64       Volatile\"],\n\n    [\"tpause\"           , \"R:r32, <edx>, <eax>\"                             , \"M\"       , \"66 0F AE /6\"                  , \"WAITPKG          Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"umonitor\"         , \"R:ds:r32\"                                        , \"M\"       , \"F3 0F AE /6\"                  , \"WAITPKG          Volatile\"],\n    [\"umonitor\"         , \"R:ds:r64\"                                        , \"M\"       , \"F3 0F AE /6\"                  , \"WAITPKG X64      Volatile\"],\n    [\"umwait\"           , \"R:r32, <edx>, <eax>\"                             , \"M\"       , \"F2 0F AE /6\"                  , \"WAITPKG          Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n\n    [\"rdrand\"           , \"w:r16\"                                           , \"M\"       , \"66 0F C7 /6\"                  , \"RDRAND           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"rdrand\"           , \"W:r32\"                                           , \"M\"       , \"0F C7 /6\"                     , \"RDRAND           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"rdrand\"           , \"W:r64\"                                           , \"M\"       , \"REX.W 0F C7 /6\"               , \"RDRAND X64       Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"rdseed\"           , \"w:r16\"                                           , \"M\"       , \"66 0F C7 /7\"                  , \"RDSEED           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"rdseed\"           , \"W:r32\"                                           , \"M\"       , \"0F C7 /7\"                     , \"RDSEED           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"rdseed\"           , \"W:r64\"                                           , \"M\"       , \"REX.W 0F C7 /7\"               , \"RDSEED X64       Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n\n    [\"syscall\"          , \"\"                                                , \"NONE\"    , \"0F 05\"                        , \"X64              Volatile\"],\n    [\"sysenter\"         , \"\"                                                , \"NONE\"    , \"0F 34\"                        , \"ANY              Volatile\"],\n\n    [\"llwpcb\"           , \"R:r32\"                                           , \"M\"       , \"XOP.L0.P0.M09.W0 12 /0\"       , \"LWP              Volatile\"],\n    [\"llwpcb\"           , \"R:r64\"                                           , \"M\"       , \"XOP.L0.P0.M09.W1 12 /0\"       , \"LWP X64          Volatile\"],\n    [\"lwpins\"           , \"R:r32, R:r32/m32, id/ud\"                         , \"VMI\"     , \"XOP.L0.P0.M0A.W0 12 /0 id\"    , \"LWP              Volatile\"],\n    [\"lwpins\"           , \"R:r64, R:r32/m32, id/ud\"                         , \"VMI\"     , \"XOP.L0.P0.M0A.W1 12 /0 id\"    , \"LWP X64          Volatile\"],\n    [\"lwpval\"           , \"R:r32, R:r32/m32, id/ud\"                         , \"VMI\"     , \"XOP.L0.P0.M0A.W0 12 /1 id\"    , \"LWP              Volatile\"],\n    [\"lwpval\"           , \"R:r64, R:r32/m32, id/ud\"                         , \"VMI\"     , \"XOP.L0.P0.M0A.W1 12 /1 id\"    , \"LWP X64          Volatile\"],\n    [\"slwpcb\"           , \"W:r32\"                                           , \"M\"       , \"XOP.L0.P0.M09.W0 12 /1\"       , \"LWP              Volatile\"],\n    [\"slwpcb\"           , \"W:r64\"                                           , \"M\"       , \"XOP.L0.P0.M09.W1 12 /1\"       , \"LWP X64          Volatile\"],\n\n    [\"xabort\"           , \"ib/ub\"                                           , \"I\"       , \"C6 /7 ib\"                     , \"RTM              Volatile\"],\n    [\"xbegin\"           , \"rel16\"                                           , \"NONE\"    , \"66 C7 /7 cw\"                  , \"RTM              Volatile\"],\n    [\"xbegin\"           , \"rel32\"                                           , \"NONE\"    , \"C7 /7 cd\"                     , \"RTM              Volatile\"],\n    [\"xend\"             , \"\"                                                , \"NONE\"    , \"0F 01 D5\"                     , \"RTM              Volatile\"],\n    [\"xtest\"            , \"\"                                                , \"NONE\"    , \"0F 01 D6\"                     , \"TSX              Volatile OF=0 SF=0 ZF=W AF=0 PF=0 CF=0\"],\n\n    [\"xresldtrk\"        , \"\"                                                , \"NONE\"    , \"F2 0F 01 E9\"                  , \"TSXLDTRK         Volatile\"],\n    [\"xsusldtrk\"        , \"\"                                                , \"NONE\"    , \"F2 0F 01 E8\"                  , \"TSXLDTRK         Volatile\"],\n\n    [\"endbr32\"          , \"\"                                                , \"NONE\"    , \"F3 0F 1E FB\"                  , \"CET_IBT          Volatile\"],\n    [\"endbr64\"          , \"\"                                                , \"NONE\"    , \"F3 0F 1E FA\"                  , \"CET_IBT          Volatile\"],\n\n    [\"clrssbsy\"         , \"R:m64\"                                           , \"M\"       , \"F3 0F AE /6\"                  , \"CET_SS           Volatile PRIVILEGE=L0 OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"setssbsy\"         , \"\"                                                , \"NONE\"    , \"F3 0F 01 E8\"                  , \"CET_SS           Volatile PRIVILEGE=L0\"],\n    [\"incsspd\"          , \"r32\"                                             , \"M\"       , \"F3 0F AE /5\"                  , \"CET_SS           Volatile\"],\n    [\"incsspq\"          , \"r64\"                                             , \"M\"       , \"REX.W F3 0F AE /5\"            , \"CET_SS X64       Volatile\"],\n    [\"rdsspd\"           , \"W:r32\"                                           , \"M\"       , \"F3 0F 1E /1\"                  , \"CET_SS           Volatile\"],\n    [\"rdsspq\"           , \"W:r64\"                                           , \"M\"       , \"REX.W F3 0F 1E /1\"            , \"CET_SS X64       Volatile\"],\n    [\"rstorssp\"         , \"R:m64\"                                           , \"M\"       , \"F3 0F 01 /5\"                  , \"CET_SS           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"saveprevssp\"      , \"\"                                                , \"NONE\"    , \"F3 0F 01 EA\"                  , \"CET_SS           Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"wrssd\"            , \"W:r32/m32, r32\"                                  , \"MR\"      , \"0F 38 F6 /r\"                  , \"CET_SS           Volatile\"],\n    [\"wrssq\"            , \"W:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 0F 38 F6 /r\"            , \"CET_SS X64       Volatile\"],\n    [\"wrussd\"           , \"W:r32/m32, r32\"                                  , \"MR\"      , \"66 0F 38 F5 /r\"               , \"CET_SS           Volatile\"],\n    [\"wrussq\"           , \"W:r64/m64, r64\"                                  , \"MR\"      , \"REX.W 66 0F 38 F5 /r\"         , \"CET_SS X64       Volatile\"],\n\n    [\"hreset\"           , \"ib/ub, W:<eax>\"                                  , \"I\"       , \"F3 0F 3A F0 /0 ib\"            , \"HRESET           Volatile\"],\n\n    [\"uiret\"            , \"\"                                                , \"NONE\"    , \"F3 0F 01 EC\"                  , \"UINTR X64        Volatile\"],\n    [\"clui\"             , \"\"                                                , \"NONE\"    , \"F3 0F 01 EE\"                  , \"UINTR X64        Volatile\"],\n    [\"stui\"             , \"\"                                                , \"NONE\"    , \"F3 0F 01 EF\"                  , \"UINTR X64        Volatile\"],\n    [\"testui\"           , \"\"                                                , \"NONE\"    , \"F3 0F 01 ED\"                  , \"UINTR X64        Volatile OF=0 SF=0 ZF=0 AF=0 PF=0 CF=W\"],\n    [\"senduipi\"         , \"R:r64\"                                           , \"R\"       , \"F3 0F C7 /6\"                  , \"UINTR X64        Volatile\"],\n\n    [\"seamcall\"         , \"\"                                                , \"NONE\"    , \"66 0F 01 CF\"                  , \"SEAM             Volatile\"],\n    [\"seamops\"          , \"\"                                                , \"NONE\"    , \"66 0F 01 CE\"                  , \"SEAM             Volatile\"],\n    [\"seamret\"          , \"\"                                                , \"NONE\"    , \"66 0F 01 CD\"                  , \"SEAM             Volatile\"],\n    [\"tdcall\"           , \"\"                                                , \"NONE\"    , \"66 0F 01 CC\"                  , \"SEAM             Volatile\"],\n\n    [\"clts\"             , \"\"                                                , \"NONE\"    , \"0F 06\"                        , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"hlt\"              , \"\"                                                , \"NONE\"    , \"F4\"                           , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"invd\"             , \"\"                                                , \"NONE\"    , \"0F 08\"                        , \"I486             Volatile PRIVILEGE=L0\"],\n    [\"invlpg\"           , \"R:mem\"                                           , \"M\"       , \"0F 01 /7\"                     , \"I486             Volatile PRIVILEGE=L0\"],\n    [\"invpcid\"          , \"R:r32, R:m128\"                                   , \"RM\"      , \"66 0F 38 82 /r\"               , \"I486 X86         Volatile PRIVILEGE=L0\"],\n    [\"invpcid\"          , \"R:r64, R:m128\"                                   , \"RM\"      , \"66 0F 38 82 /r\"               , \"I486 X64         Volatile PRIVILEGE=L0\"],\n    [\"lgdt\"             , \"R:mem\"                                           , \"M\"       , \"0F 01 /2\"                     , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"lidt\"             , \"R:mem\"                                           , \"M\"       , \"0F 01 /3\"                     , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"lldt\"             , \"R:r16/m16\"                                       , \"M\"       , \"0F 00 /2\"                     , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"lmsw\"             , \"R:r16/m16\"                                       , \"M\"       , \"0F 01 /6\"                     , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"ltr\"              , \"R:r16/m16\"                                       , \"M\"       , \"0F 00 /3\"                     , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"pconfig\"          , \"\"                                                , \"NONE\"    , \"0F 01 C5\"                     , \"PCONFIG          Volatile PRIVILEGE=L0\"],\n    [\"rdpmc\"            , \"W:<edx>, W:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 33\"                        , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"rdmsr\"            , \"W:<edx>, W:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 32\"                        , \"ANY              Volatile PRIVILEGE=L0 MSR=R\"],\n    [\"swapgs\"           , \"\"                                                , \"NONE\"    , \"0F 01 F8\"                     , \"X64              Volatile PRIVILEGE=L0\"],\n    [\"sysexit\"          , \"\"                                                , \"NONE\"    , \"0F 35\"                        , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"sysexitq\"         , \"\"                                                , \"NONE\"    , \"REX.W 0F 35\"                  , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"sysret\"           , \"\"                                                , \"NONE\"    , \"0F 07\"                        , \"X64              Volatile PRIVILEGE=L0\"],\n    [\"sysretq\"          , \"\"                                                , \"NONE\"    , \"REX.W 0F 07\"                  , \"X64              Volatile PRIVILEGE=L0\"],\n    [\"wbinvd\"           , \"\"                                                , \"NONE\"    , \"0F 09\"                        , \"ANY              Volatile PRIVILEGE=L0\"],\n    [\"wbnoinvd\"         , \"\"                                                , \"NONE\"    , \"F3 0F 09\"                     , \"WBNOINVD         Volatile PRIVILEGE=L0\"],\n    [\"wrmsr\"            , \"R:<edx>, R:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 30\"                        , \"ANY              Volatile PRIVILEGE=L0 MSR=W\"],\n    [\"xsetbv\"           , \"R:<edx>, R:<eax>, R:<ecx>\"                       , \"NONE\"    , \"0F 01 D1\"                     , \"XSAVE            Volatile PRIVILEGE=L0 XCR=W\"],\n\n    [\"monitor\"          , \"R:<ds:zax>, R:<ecx>, R:<edx>\"                    , \"NONE\"    , \"0F 01 C8\"                     , \"MONITOR          Volatile PRIVILEGE=L0\"],\n    [\"mwait\"            , \"R:<eax>, R:<ecx>\"                                , \"NONE\"    , \"0F 01 C9\"                     , \"MONITOR          Volatile PRIVILEGE=L0\"],\n\n    [\"clac\"             , \"\"                                                , \"NONE\"    , \"0F 01 CA\"                     , \"SMAP             Volatile PRIVILEGE=L0 AC=0\"],\n    [\"stac\"             , \"\"                                                , \"NONE\"    , \"0F 01 CB\"                     , \"SMAP             Volatile PRIVILEGE=L0 AC=1\"],\n\n    [\"skinit\"           , \"X:<eax>\"                                         , \"NONE\"    , \"0F 01 DE\"                     , \"SKINIT           Volatile PRIVILEGE=L0\"],\n    [\"stgi\"             , \"\"                                                , \"NONE\"    , \"0F 01 DC\"                     , \"SKINIT           Volatile PRIVILEGE=L0\"],\n\n    [\"psmash\"           , \"\"                                                , \"NONE\"    , \"F3 0F 01 FF\"                  , \"SNP X64          Volatile PRIVILEGE=L0 OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"pvalidate\"        , \"\"                                                , \"NONE\"    , \"F2 0F 01 FF\"                  , \"SNP              Volatile PRIVILEGE=L0 OF=W SF=W ZF=W AF=W PF=W CF=W\"],\n    [\"rmpadjust\"        , \"\"                                                , \"NONE\"    , \"F3 0F 01 FE\"                  , \"SNP X64          Volatile PRIVILEGE=L0 OF=W SF=W ZF=W AF=W PF=W\"],\n    [\"rmpupdate\"        , \"\"                                                , \"NONE\"    , \"F2 0F 01 FE\"                  , \"SNP X64          Volatile PRIVILEGE=L0 OF=W SF=W ZF=W AF=W PF=W\"],\n\n    [\"invept\"           , \"R:r32, R:m128\"                                   , \"RM\"      , \"66 0F 38 80 /r\"               , \"VMX X86          Volatile PRIVILEGE=L0\"],\n    [\"invept\"           , \"R:r64, R:m128\"                                   , \"RM\"      , \"66 0F 38 80 /r\"               , \"VMX X64          Volatile PRIVILEGE=L0\"],\n    [\"invvpid\"          , \"R:r32, R:m128\"                                   , \"RM\"      , \"66 0F 38 81 /r\"               , \"VMX X86          Volatile PRIVILEGE=L0\"],\n    [\"invvpid\"          , \"R:r64, R:m128\"                                   , \"RM\"      , \"66 0F 38 81 /r\"               , \"VMX X64          Volatile PRIVILEGE=L0\"],\n    [\"vmcall\"           , \"\"                                                , \"NONE\"    , \"0F 01 C1\"                     , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmclear\"          , \"W:m64\"                                           , \"M\"       , \"66 0F C7 /6\"                  , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmfunc\"           , \"\"                                                , \"NONE\"    , \"0F 01 D4\"                     , \"VMX              Volatile\"],\n    [\"vmlaunch\"         , \"\"                                                , \"NONE\"    , \"0F 01 C2\"                     , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmptrld\"          , \"R:m64\"                                           , \"M\"       , \"0F C7 /6\"                     , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmptrst\"          , \"W:m64\"                                           , \"M\"       , \"0F C7 /7\"                     , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmread\"           , \"W:r32/m32, R:r32\"                                , \"MR\"      , \"0F 78 /r\"                     , \"VMX X86          Volatile PRIVILEGE=L0\"],\n    [\"vmread\"           , \"W:r64/m64, R:r64\"                                , \"MR\"      , \"0F 78 /r\"                     , \"VMX X64          Volatile PRIVILEGE=L0\"],\n    [\"vmresume\"         , \"\"                                                , \"NONE\"    , \"0F 01 C3\"                     , \"VMX              Volatile PRIVILEGE=L0\"],\n    [\"vmwrite\"          , \"R:r32, R:r32/m32\"                                , \"RM\"      , \"0F 79 /r\"                     , \"VMX X86          Volatile PRIVILEGE=L0\"],\n    [\"vmwrite\"          , \"R:r64, R:r64/m64\"                                , \"RM\"      , \"0F 79 /r\"                     , \"VMX X64          Volatile PRIVILEGE=L0\"],\n    [\"vmxon\"            , \"R:m64\"                                           , \"M\"       , \"F3 0F C7 /6\"                  , \"VMX\"],\n\n    [\"clgi\"             , \"\"                                                , \"NONE\"    , \"0F 01 DD\"                     , \"SVM              Volatile PRIVILEGE=L0\"],\n    [\"invlpga\"          , \"R:<eax>, R:<ecx>\"                                , \"NONE\"    , \"0F 01 DF\"                     , \"SVM X86          Volatile PRIVILEGE=L0\"],\n    [\"invlpga\"          , \"R:<eax>, R:<ecx>\"                                , \"NONE\"    , \"67 0F 01 DF\"                  , \"SVM X64          Volatile PRIVILEGE=L0\"],\n    [\"invlpga\"          , \"R:<rax>, R:<ecx>\"                                , \"NONE\"    , \"0F 01 DF\"                     , \"SVM X64          Volatile PRIVILEGE=L0\"],\n    [\"vmload\"           , \"R:<eax>\"                                         , \"NONE\"    , \"0F 01 DA\"                     , \"SVM X86          Volatile PRIVILEGE=L0\"],\n    [\"vmload\"           , \"R:<rax>\"                                         , \"NONE\"    , \"0F 01 DA\"                     , \"SVM X64          Volatile PRIVILEGE=L0\"],\n    [\"vmmcall\"          , \"\"                                                , \"NONE\"    , \"0F 01 D9\"                     , \"SVM              Volatile\"],\n    [\"vmrun\"            , \"X:<eax>\"                                         , \"NONE\"    , \"0F 01 D8\"                     , \"SVM X86          Volatile PRIVILEGE=L0\"],\n    [\"vmrun\"            , \"X:<rax>\"                                         , \"NONE\"    , \"0F 01 D8\"                     , \"SVM X64          Volatile PRIVILEGE=L0\"],\n    [\"vmsave\"           , \"R:<eax>\"                                         , \"NONE\"    , \"0F 01 DB\"                     , \"SVM X86          Volatile PRIVILEGE=L0\"],\n    [\"vmsave\"           , \"R:<rax>\"                                         , \"NONE\"    , \"0F 01 DB\"                     , \"SVM X64          Volatile PRIVILEGE=L0\"],\n\n    [\"f2xm1\"            , \"\"                                                , \"NONE\"    , \"D9 F0\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fabs\"             , \"\"                                                , \"NONE\"    , \"D9 E1\"                        , \"FPU              C0=U C1=0 C2=U C3=U\"],\n    [\"fadd\"             , \"R:m32fp\"                                         , \"M\"       , \"D8 /0\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fadd\"             , \"R:m64fp\"                                         , \"M\"       , \"DC /0\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fadd\"             , \"st(0), st(i)\"                                    , \"O\"       , \"D8 C0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fadd\"             , \"st(i), st(0)\"                                    , \"O\"       , \"DC C0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"faddp\"            , \"\"                                                , \"NONE\"    , \"DE C1\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"faddp\"            , \"st(i)\"                                           , \"O\"       , \"DE C0+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fbld\"             , \"R:m80dec\"                                        , \"M\"       , \"DF /4\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fbstp\"            , \"W:m80bcd\"                                        , \"M\"       , \"DF /6\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fchs\"             , \"\"                                                , \"NONE\"    , \"D9 E0\"                        , \"FPU              C0=U C1=0 C2=U C3=U\"],\n    [\"fclex\"            , \"\"                                                , \"NONE\"    , \"9B DB E2\"                     , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fcmovb\"           , \"st(i)\"                                           , \"O\"       , \"DA C0+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U CF=R\"],\n    [\"fcmovbe\"          , \"st(i)\"                                           , \"O\"       , \"DA D0+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U CF=R ZF=R\"],\n    [\"fcmove\"           , \"st(i)\"                                           , \"O\"       , \"DA C8+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U ZF=R\"],\n    [\"fcmovnb\"          , \"st(i)\"                                           , \"O\"       , \"DB C0+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U CF=R\"],\n    [\"fcmovnbe\"         , \"st(i)\"                                           , \"O\"       , \"DB D0+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U CF=R ZF=R\"],\n    [\"fcmovne\"          , \"st(i)\"                                           , \"O\"       , \"DB C8+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U ZF=R\"],\n    [\"fcmovnu\"          , \"st(i)\"                                           , \"O\"       , \"DB D8+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U PF=R\"],\n    [\"fcmovu\"           , \"st(i)\"                                           , \"O\"       , \"DA D8+i\"                      , \"FPU CMOV         C0=U C1=W C2=U C3=U PF=R\"],\n    [\"fcom\"             , \"\"                                                , \"NONE\"    , \"D8 D1\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fcom\"             , \"R:m32fp\"                                         , \"M\"       , \"D8 /2\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fcom\"             , \"R:m64fp\"                                         , \"M\"       , \"DC /2\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fcom\"             , \"R:st(i)\"                                         , \"O\"       , \"D8 D0+i\"                      , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fcomi\"            , \"R:st(i)\"                                         , \"O\"       , \"DB F0+i\"                      , \"FPU              C1=0 ZF=W PF=W CF=W\"],\n    [\"fcomip\"           , \"R:st(i)\"                                         , \"O\"       , \"DF F0+i\"                      , \"FPU_POP          C1=0 ZF=W PF=W CF=W\"],\n    [\"fcomp\"            , \"\"                                                , \"NONE\"    , \"D8 D9\"                        , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fcomp\"            , \"R:m32fp\"                                         , \"M\"       , \"D8 /3\"                        , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fcomp\"            , \"R:m64fp\"                                         , \"M\"       , \"DC /3\"                        , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fcomp\"            , \"R:st(i)\"                                         , \"O\"       , \"D8 D8+i\"                      , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fcompp\"           , \"\"                                                , \"NONE\"    , \"DE D9\"                        , \"FPU_POP=2        C0=W C1=W C2=W C3=W\"],\n    [\"fcos\"             , \"\"                                                , \"NONE\"    , \"D9 FF\"                        , \"FPU              C0=U C1=W C2=W C3=U\"],\n    [\"fdecstp\"          , \"\"                                                , \"NONE\"    , \"D9 F6\"                        , \"FPU_TOP=-1       C0=U C1=W C2=U C3=U\"],\n    [\"fdiv\"             , \"R:m32fp\"                                         , \"M\"       , \"D8 /6\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdiv\"             , \"R:m64fp\"                                         , \"M\"       , \"DC /6\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdiv\"             , \"st(0), st(i)\"                                    , \"O\"       , \"D8 F0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdiv\"             , \"st(i), st(0)\"                                    , \"O\"       , \"DC F8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdivp\"            , \"\"                                                , \"NONE\"    , \"DE F9\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fdivp\"            , \"st(i)\"                                           , \"O\"       , \"DE F8+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fdivr\"            , \"R:m32fp\"                                         , \"M\"       , \"D8 /7\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdivr\"            , \"R:m64fp\"                                         , \"M\"       , \"DC /7\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdivr\"            , \"st(0), st(i)\"                                    , \"O\"       , \"D8 F8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdivr\"            , \"st(i), st(0)\"                                    , \"O\"       , \"DC F0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fdivrp\"           , \"\"                                                , \"NONE\"    , \"DE F1\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fdivrp\"           , \"st(i)\"                                           , \"O\"       , \"DE F0+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"ffree\"            , \"st(i)\"                                           , \"O\"       , \"DD C0+i\"                      , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fiadd\"            , \"R:m16int\"                                        , \"M\"       , \"DE /0\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fiadd\"            , \"R:m32int\"                                        , \"M\"       , \"DA /0\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"ficom\"            , \"R:m16int\"                                        , \"M\"       , \"DE /2\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"ficom\"            , \"R:m32int\"                                        , \"M\"       , \"DA /2\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"ficomp\"           , \"R:m16int\"                                        , \"M\"       , \"DE /3\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"ficomp\"           , \"R:m32int\"                                        , \"M\"       , \"DA /3\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fidiv\"            , \"R:m16int\"                                        , \"M\"       , \"DE /6\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fidiv\"            , \"R:m32int\"                                        , \"M\"       , \"DA /6\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fidivr\"           , \"R:m16int\"                                        , \"M\"       , \"DE /7\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fidivr\"           , \"R:m32int\"                                        , \"M\"       , \"DA /7\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fild\"             , \"R:m16int\"                                        , \"M\"       , \"DF /0\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fild\"             , \"R:m32int\"                                        , \"M\"       , \"DB /0\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fild\"             , \"R:m64int\"                                        , \"M\"       , \"DF /5\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fimul\"            , \"R:m16int\"                                        , \"M\"       , \"DE /1\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fimul\"            , \"R:m32int\"                                        , \"M\"       , \"DA /1\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fincstp\"          , \"\"                                                , \"NONE\"    , \"D9 F7\"                        , \"FPU_TOP=+1       C0=U C1=0 C2=U C3=U\"],\n    [\"finit\"            , \"\"                                                , \"NONE\"    , \"9B DB E3\"                     , \"FPU              C0=0 C1=0 C2=0 C3=0\"],\n    [\"fist\"             , \"W:m16int\"                                        , \"M\"       , \"DF /2\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fist\"             , \"W:m32int\"                                        , \"M\"       , \"DB /2\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fistp\"            , \"W:m16int\"                                        , \"M\"       , \"DF /3\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fistp\"            , \"W:m32int\"                                        , \"M\"       , \"DB /3\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fistp\"            , \"W:m64int\"                                        , \"M\"       , \"DF /7\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fisttp\"           , \"W:m16int\"                                        , \"M\"       , \"DF /1\"                        , \"FPU_POP SSE3     C0=U C1=0 C2=U C3=U\"],\n    [\"fisttp\"           , \"W:m32int\"                                        , \"M\"       , \"DB /1\"                        , \"FPU_POP SSE3     C0=U C1=0 C2=U C3=U\"],\n    [\"fisttp\"           , \"W:m64int\"                                        , \"M\"       , \"DD /1\"                        , \"FPU_POP SSE3     C0=U C1=0 C2=U C3=U\"],\n    [\"fisub\"            , \"R:m16int\"                                        , \"M\"       , \"DE /4\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fisub\"            , \"R:m32int\"                                        , \"M\"       , \"DA /4\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fisubr\"           , \"R:m16int\"                                        , \"M\"       , \"DE /5\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fisubr\"           , \"R:m32int\"                                        , \"M\"       , \"DA /5\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fld\"              , \"R:m32fp\"                                         , \"M\"       , \"D9 /0\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fld\"              , \"R:m64fp\"                                         , \"M\"       , \"DD /0\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fld\"              , \"R:m80fp\"                                         , \"M\"       , \"DB /5\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fld\"              , \"R:st(i)\"                                         , \"O\"       , \"D9 C0+i\"                      , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fld1\"             , \"\"                                                , \"NONE\"    , \"D9 E8\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldcw\"            , \"R:m16\"                                           , \"M\"       , \"D9 /5\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fldenv\"           , \"R:mem\"                                           , \"M\"       , \"D9 /4\"                        , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fldl2e\"           , \"\"                                                , \"NONE\"    , \"D9 EA\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldl2t\"           , \"\"                                                , \"NONE\"    , \"D9 E9\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldlg2\"           , \"\"                                                , \"NONE\"    , \"D9 EC\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldln2\"           , \"\"                                                , \"NONE\"    , \"D9 ED\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldpi\"            , \"\"                                                , \"NONE\"    , \"D9 EB\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fldz\"             , \"\"                                                , \"NONE\"    , \"D9 EE\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fmul\"             , \"R:m32fp\"                                         , \"M\"       , \"D8 /1\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fmul\"             , \"R:m64fp\"                                         , \"M\"       , \"DC /1\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fmul\"             , \"st(0), st(i)\"                                    , \"O\"       , \"D8 C8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fmul\"             , \"st(i), st(0)\"                                    , \"O\"       , \"DC C8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fmulp\"            , \"\"                                                , \"NONE\"    , \"DE C9\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fmulp\"            , \"st(i)\"                                           , \"O\"       , \"DE C8+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fnclex\"           , \"\"                                                , \"NONE\"    , \"DB E2\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fninit\"           , \"\"                                                , \"NONE\"    , \"DB E3\"                        , \"FPU              C0=0 C1=0 C2=0 C3=0\"],\n    [\"fnop\"             , \"\"                                                , \"NONE\"    , \"D9 D0\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fnsave\"           , \"W:mem\"                                           , \"M\"       , \"DD /6\"                        , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fnstcw\"           , \"W:m16\"                                           , \"M\"       , \"D9 /7\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fnstenv\"          , \"W:mem\"                                           , \"M\"       , \"D9 /6\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fnstsw\"           , \"w:ax\"                                            , \"NONE\"    , \"DF E0\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fnstsw\"           , \"W:m16\"                                           , \"M\"       , \"DD /7\"                        , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fpatan\"           , \"\"                                                , \"NONE\"    , \"D9 F3\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fprem\"            , \"\"                                                , \"NONE\"    , \"D9 F8\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fprem1\"           , \"\"                                                , \"NONE\"    , \"D9 F5\"                        , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fptan\"            , \"\"                                                , \"NONE\"    , \"D9 F2\"                        , \"FPU_POP          C0=U C1=W C2=W C3=U\"],\n    [\"frndint\"          , \"\"                                                , \"NONE\"    , \"D9 FC\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"frstor\"           , \"R:mem\"                                           , \"M\"       , \"DD /4\"                        , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fsave\"            , \"W:mem\"                                           , \"M\"       , \"9B DD /6\"                     , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fscale\"           , \"\"                                                , \"NONE\"    , \"D9 FD\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsin\"             , \"\"                                                , \"NONE\"    , \"D9 FE\"                        , \"FPU              C0=U C1=W C2=W C3=U\"],\n    [\"fsincos\"          , \"\"                                                , \"NONE\"    , \"D9 FB\"                        , \"FPU_PUSH         C0=U C1=W C2=W C3=U\"],\n    [\"fsqrt\"            , \"\"                                                , \"NONE\"    , \"D9 FE\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fst\"              , \"W:m32fp\"                                         , \"M\"       , \"D9 /2\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fst\"              , \"W:m64fp\"                                         , \"M\"       , \"DD /2\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fst\"              , \"W:st(i)\"                                         , \"O\"       , \"DD D0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fstcw\"            , \"W:m16\"                                           , \"M\"       , \"9B D9 /7\"                     , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fstenv\"           , \"W:mem\"                                           , \"M\"       , \"9B D9 /6\"                     , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fstp\"             , \"W:m32fp\"                                         , \"M\"       , \"D9 /3\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fstp\"             , \"W:m64fp\"                                         , \"M\"       , \"DD /3\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fstp\"             , \"W:m80fp\"                                         , \"M\"       , \"DB /7\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fstp\"             , \"W:st(i)\"                                         , \"O\"       , \"DD D8+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fstsw\"            , \"w:ax\"                                            , \"NONE\"    , \"9B DF E0\"                     , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fstsw\"            , \"W:m16\"                                           , \"M\"       , \"9B DD /7\"                     , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fsub\"             , \"R:m32fp\"                                         , \"M\"       , \"D8 /4\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsub\"             , \"R:m64fp\"                                         , \"M\"       , \"DC /4\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsub\"             , \"st(0), st(i)\"                                    , \"O\"       , \"D8 E0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsub\"             , \"st(i), st(0)\"                                    , \"O\"       , \"DC E8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsubp\"            , \"\"                                                , \"NONE\"    , \"DE E9\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fsubp\"            , \"st(i)\"                                           , \"O\"       , \"DE E8+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fsubr\"            , \"R:m32fp\"                                         , \"M\"       , \"D8 /5\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsubr\"            , \"R:m64fp\"                                         , \"M\"       , \"DC /5\"                        , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsubr\"            , \"st(0), st(i)\"                                    , \"O\"       , \"D8 E8+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsubr\"            , \"st(i), st(0)\"                                    , \"O\"       , \"DC E0+i\"                      , \"FPU              C0=U C1=W C2=U C3=U\"],\n    [\"fsubrp\"           , \"\"                                                , \"NONE\"    , \"DE E1\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fsubrp\"           , \"st(i)\"                                           , \"O\"       , \"DE E0+i\"                      , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"ftst\"             , \"\"                                                , \"NONE\"    , \"D9 E4\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fucom\"            , \"\"                                                , \"NONE\"    , \"DD E1\"                        , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fucom\"            , \"R:st(i)\"                                         , \"O\"       , \"DD E0+i\"                      , \"FPU              C0=W C1=0 C2=W C3=W\"],\n    [\"fucomi\"           , \"R:st(i)\"                                         , \"O\"       , \"DB E8+i\"                      , \"FPU              C1=0 ZF=W PF=W CF=W\"],\n    [\"fucomip\"          , \"R:st(i)\"                                         , \"O\"       , \"DF E8+i\"                      , \"FPU_POP          C1=0 ZF=W PF=W CF=W\"],\n    [\"fucomp\"           , \"\"                                                , \"NONE\"    , \"DD E9\"                        , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fucomp\"           , \"R:st(i)\"                                         , \"O\"       , \"DD E8+i\"                      , \"FPU_POP          C0=W C1=W C2=W C3=W\"],\n    [\"fucompp\"          , \"\"                                                , \"NONE\"    , \"DA E9\"                        , \"FPU_POP=2        C0=W C1=W C2=W C3=W\"],\n    [\"fwait/wait\"       , \"\"                                                , \"NONE\"    , \"9B\"                           , \"FPU              C0=U C1=U C2=U C3=U\"],\n    [\"fxam\"             , \"\"                                                , \"NONE\"    , \"D9 E5\"                        , \"FPU              C0=W C1=W C2=W C3=W\"],\n    [\"fxch\"             , \"\"                                                , \"NONE\"    , \"D9 C9\"                        , \"FPU              C0=U C1=0 C2=U C3=U\"],\n    [\"fxch\"             , \"st(i)\"                                           , \"O\"       , \"D9 C8+i\"                      , \"FPU              C0=U C1=0 C2=U C3=U\"],\n    [\"fxtract\"          , \"\"                                                , \"NONE\"    , \"D9 F4\"                        , \"FPU_PUSH         C0=U C1=W C2=U C3=U\"],\n    [\"fyl2x\"            , \"\"                                                , \"NONE\"    , \"D9 F1\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n    [\"fyl2xp1\"          , \"\"                                                , \"NONE\"    , \"D9 F9\"                        , \"FPU_POP          C0=U C1=W C2=U C3=U\"],\n\n    [\"addpd\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 58 /r\"                  , \"SSE2\"],\n    [\"addps\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"0F 58 /r\"                     , \"SSE\"],\n    [\"addsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 58 /r\"                  , \"SSE2\"],\n    [\"addss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 58 /r\"                  , \"SSE\"],\n    [\"addsubpd\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D0 /r\"                  , \"SSE3\"],\n    [\"addsubps\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"F2 0F D0 /r\"                  , \"SSE3\"],\n    [\"andnpd\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 55 /r\"                  , \"SSE2\"],\n    [\"andnps\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 55 /r\"                     , \"SSE\"],\n    [\"andpd\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 54 /r\"                  , \"SSE2\"],\n    [\"andps\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"0F 54 /r\"                     , \"SSE\"],\n    [\"blendpd\"          , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 0D /r ib\"            , \"SSE4_1\"],\n    [\"blendps\"          , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 0C /r ib\"            , \"SSE4_1\"],\n    [\"blendvpd\"         , \"X:xmm, xmm/m128, <xmm0>\"                         , \"RM\"      , \"66 0F 38 15 /r\"               , \"SSE4_1\"],\n    [\"blendvps\"         , \"X:xmm, xmm/m128, <xmm0>\"                         , \"RM\"      , \"66 0F 38 14 /r\"               , \"SSE4_1\"],\n    [\"cmppd\"            , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F C2 /r ib\"               , \"SSE2\"],\n    [\"cmpps\"            , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"0F C2 /r ib\"                  , \"SSE\"],\n    [\"cmpsd\"            , \"x:xmm[63:0], xmm[63:0]/m64, ib/ub\"               , \"RMI\"     , \"F2 0F C2 /r ib\"               , \"SSE2\"],\n    [\"cmpss\"            , \"x:xmm[31:0], xmm[31:0]/m32, ib/ub\"               , \"RMI\"     , \"F3 0F C2 /r ib\"               , \"SSE\"],\n    [\"comisd\"           , \"R:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"66 0F 2F /r\"                  , \"SSE2 OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"comiss\"           , \"R:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"0F 2F /r\"                     , \"SSE  OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"cvtdq2pd\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"F3 0F E6 /r\"                  , \"SSE2\"],\n    [\"cvtdq2ps\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 5B /r\"                     , \"SSE2\"],\n    [\"cvtpd2dq\"         , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"F2 0F E6 /r\"                  , \"SSE2\"],\n    [\"cvtpd2pi\"         , \"W:mm, xmm/m128\"                                  , \"RM\"      , \"66 0F 2D /r\"                  , \"SSE2\"],\n    [\"cvtpd2ps\"         , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"66 0F 5A /r\"                  , \"SSE2\"],\n    [\"cvtpi2pd\"         , \"W:xmm, R:mm[63:0]/m64\"                           , \"RM\"      , \"66 0F 2A /r\"                  , \"SSE2\"],\n    [\"cvtpi2ps\"         , \"w:xmm[63:0], mm/m64\"                             , \"RM\"      , \"0F 2A /r\"                     , \"SSE\"],\n    [\"cvtps2dq\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 5B /r\"                  , \"SSE2\"],\n    [\"cvtps2pd\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"0F 5A /r\"                     , \"SSE2\"],\n    [\"cvtps2pi\"         , \"W:mm, xmm[63:0]/m64\"                             , \"RM\"      , \"0F 2D /r\"                     , \"SSE\"],\n    [\"cvtsd2si\"         , \"W:r32, xmm[63:0]/m64\"                            , \"RM\"      , \"F2 0F 2D /r\"                  , \"SSE2\"],\n    [\"cvtsd2si\"         , \"W:r64, xmm[63:0]/m64\"                            , \"RM\"      , \"REX.W F2 0F 2D /r\"            , \"SSE2 X64\"],\n    [\"cvtsd2ss\"         , \"w:xmm[31:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 5A /r\"                  , \"SSE2\"],\n    [\"cvtsi2sd\"         , \"w:xmm[63:0], r32/m32\"                            , \"RM\"      , \"F2 0F 2A /r\"                  , \"SSE2\"],\n    [\"cvtsi2sd\"         , \"w:xmm[63:0], r64/m64\"                            , \"RM\"      , \"REX.W F2 0F 2A /r\"            , \"SSE2 X64\"],\n    [\"cvtsi2ss\"         , \"w:xmm[31:0], r32/m32\"                            , \"RM\"      , \"F3 0F 2A /r\"                  , \"SSE\"],\n    [\"cvtsi2ss\"         , \"w:xmm[31:0], r64/m64\"                            , \"RM\"      , \"REX.W F3 0F 2A /r\"            , \"SSE X64\"],\n    [\"cvtss2sd\"         , \"w:xmm[63:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 5A /r\"                  , \"SSE2\"],\n    [\"cvtss2si\"         , \"W:r32, xmm[31:0]/m32\"                            , \"RM\"      , \"F3 0F 2D /r\"                  , \"SSE\"],\n    [\"cvtss2si\"         , \"W:r64, xmm[31:0]/m32\"                            , \"RM\"      , \"REX.W F3 0F 2D /r\"            , \"SSE X64\"],\n    [\"cvttpd2dq\"        , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"66 0F E6 /r\"                  , \"SSE2\"],\n    [\"cvttpd2pi\"        , \"W:mm, xmm/m128\"                                  , \"RM\"      , \"66 0F 2C /r\"                  , \"SSE2\"],\n    [\"cvttps2dq\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"F3 0F 5B /r\"                  , \"SSE2\"],\n    [\"cvttps2pi\"        , \"W:mm, xmm[63:0]/m64\"                             , \"RM\"      , \"0F 2C /r\"                     , \"SSE\"],\n    [\"cvttsd2si\"        , \"W:r32, xmm[63:0]/m64\"                            , \"RM\"      , \"F2 0F 2C /r\"                  , \"SSE2\"],\n    [\"cvttsd2si\"        , \"W:r64, xmm[63:0]/m64\"                            , \"RM\"      , \"REX.W F2 0F 2C /r\"            , \"SSE2 X64\"],\n    [\"cvttss2si\"        , \"W:r32, xmm[31:0]/m32\"                            , \"RM\"      , \"F3 0F 2C /r\"                  , \"SSE\"],\n    [\"cvttss2si\"        , \"W:r64, xmm[31:0]/m32\"                            , \"RM\"      , \"REX.W F3 0F 2C /r\"            , \"SSE X64\"],\n    [\"divpd\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 5E /r\"                  , \"SSE2\"],\n    [\"divps\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 5E /r\"                     , \"SSE\"],\n    [\"divsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 5E /r\"                  , \"SSE2\"],\n    [\"divss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 5E /r\"                  , \"SSE\"],\n    [\"dppd\"             , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 41 /r ib\"            , \"SSE4_1\"],\n    [\"dpps\"             , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 40 /r ib\"            , \"SSE4_1\"],\n    [\"extractps\"        , \"W:r32/m32, xmm, ib/ub\"                           , \"MRI\"     , \"66 0F 3A 17 /r ib\"            , \"SSE4_1\"],\n    [\"extrq\"            , \"X:xmm, ib/ub, ib/ub\"                             , \"RII\"     , \"66 0F 78 /0 ib ib\"            , \"SSE4A\"],\n    [\"extrq\"            , \"X:xmm, xmm\"                                      , \"RM\"      , \"66 0F 79 /r\"                  , \"SSE4A\"],\n    [\"haddpd\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 7C /r\"                  , \"SSE3\"],\n    [\"haddps\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"F2 0F 7C /r\"                  , \"SSE3\"],\n    [\"hsubpd\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 7D /r\"                  , \"SSE3\"],\n    [\"hsubps\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"F2 0F 7D /r\"                  , \"SSE3\"],\n    [\"insertps\"         , \"X:xmm, xmm[31:0]/m32, ib/ub\"                     , \"RMI\"     , \"66 0F 3A 21 /r ib\"            , \"SSE4_1\"],\n    [\"insertq\"          , \"X:xmm, xmm\"                                      , \"RM\"      , \"F2 0F 79 /r\"                  , \"SSE4A\"],\n    [\"insertq\"          , \"X:xmm, xmm, ib/ub, ib/ub\"                        , \"RMII\"    , \"F2 0F 78 /r ib ib\"            , \"SSE4A\"],\n    [\"lddqu\"            , \"W:xmm, m128\"                                     , \"RM\"      , \"F2 0F F0 /r\"                  , \"SSE3\"],\n    [\"maskmovdqu\"       , \"R:xmm, xmm, X:<ds:zdi>\"                          , \"RM\"      , \"66 0F F7 /r\"                  , \"SSE2\"],\n    [\"maskmovq\"         , \"R:mm, mm, X:<ds:zdi>\"                            , \"RM\"      , \"0F F7 /r\"                     , \"MMX2\"],\n    [\"maxpd\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 5F /r\"                  , \"SSE2\"],\n    [\"maxps\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 5F /r\"                     , \"SSE\"],\n    [\"maxsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 5F /r\"                  , \"SSE2\"],\n    [\"maxss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 5F /r\"                  , \"SSE\"],\n    [\"minpd\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 5D /r\"                  , \"SSE2\"],\n    [\"minps\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 5D /r\"                     , \"SSE\"],\n    [\"minsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 5D /r\"                  , \"SSE2\"],\n    [\"minss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 5D /r\"                  , \"SSE\"],\n    [\"movapd\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 28 /r\"                  , \"SSE2\"],\n    [\"movapd\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"66 0F 29 /r\"                  , \"SSE2\"],\n    [\"movaps\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 28 /r\"                     , \"SSE\"],\n    [\"movaps\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"0F 29 /r\"                     , \"SSE\"],\n    [\"movd\"             , \"W:mm[31:0], R:r32[31:0]/m32\"                     , \"RM\"      , \"0F 6E /r\"                     , \"MMX\"],\n    [\"movd\"             , \"W:r32[31:0]/m32, R:mm[31:0]\"                     , \"MR\"      , \"0F 7E /r\"                     , \"MMX\"],\n    [\"movd\"             , \"W:r32[31:0]/m32, xmm[31:0]\"                      , \"MR\"      , \"66 0F 7E /r\"                  , \"SSE2\"],\n    [\"movd\"             , \"W:xmm[31:0], R:r32[31:0]/m32\"                    , \"RM\"      , \"66 0F 6E /r\"                  , \"SSE2\"],\n    [\"movddup\"          , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"F2 0F 12 /r\"                  , \"SSE3\"],\n    [\"movdq2q\"          , \"W:mm, xmm[63:0]\"                                 , \"RM\"      , \"F2 0F D6 /r\"                  , \"SSE2\"],\n    [\"movdqa\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 6F /r\"                  , \"SSE2\"],\n    [\"movdqa\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"66 0F 7F /r\"                  , \"SSE2\"],\n    [\"movdqu\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"F3 0F 6F /r\"                  , \"SSE2\"],\n    [\"movdqu\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"F3 0F 7F /r\"                  , \"SSE2\"],\n    [\"movhlps\"          , \"w:xmm[63:0], xmm[127:64]\"                        , \"RM\"      , \"0F 12 /r\"                     , \"SSE\"],\n    [\"movhpd\"           , \"W:m64, xmm[127:64]\"                              , \"MR\"      , \"66 0F 17 /r\"                  , \"SSE2\"],\n    [\"movhpd\"           , \"w:xmm[127:64], m64\"                              , \"RM\"      , \"66 0F 16 /r\"                  , \"SSE2\"],\n    [\"movhps\"           , \"W:m64, xmm[127:64]\"                              , \"MR\"      , \"0F 17 /r\"                     , \"SSE\"],\n    [\"movhps\"           , \"w:xmm[127:64], m64\"                              , \"RM\"      , \"0F 16 /r\"                     , \"SSE\"],\n    [\"movlhps\"          , \"w:xmm[127:64], xmm[63:0]\"                        , \"RM\"      , \"0F 16 /r\"                     , \"SSE\"],\n    [\"movlpd\"           , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"66 0F 13 /r\"                  , \"SSE2\"],\n    [\"movlpd\"           , \"w:xmm[63:0], m64\"                                , \"RM\"      , \"66 0F 12 /r\"                  , \"SSE2\"],\n    [\"movlps\"           , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"0F 13 /r\"                     , \"SSE\"],\n    [\"movlps\"           , \"w:xmm[63:0], m64\"                                , \"RM\"      , \"0F 12 /r\"                     , \"SSE\"],\n    [\"movmskpd\"         , \"W:r32[1:0], xmm\"                                 , \"RM\"      , \"66 0F 50 /r\"                  , \"SSE2\"],\n    [\"movmskps\"         , \"W:r32[3:0], xmm\"                                 , \"RM\"      , \"0F 50 /r\"                     , \"SSE\"],\n    [\"movntdq\"          , \"W:m128, xmm\"                                     , \"MR\"      , \"66 0F E7 /r\"                  , \"SSE2\"],\n    [\"movntdqa\"         , \"W:xmm, m128\"                                     , \"RM\"      , \"66 0F 38 2A /r\"               , \"SSE4_1\"],\n    [\"movnti\"           , \"W:m32, r32\"                                      , \"MR\"      , \"0F C3 /r\"                     , \"SSE2\"],\n    [\"movnti\"           , \"W:m64, r64\"                                      , \"MR\"      , \"REX.W 0F C3 /r\"               , \"SSE2 X64\"],\n    [\"movntpd\"          , \"W:m128, xmm\"                                     , \"MR\"      , \"66 0F 2B /r\"                  , \"SSE2\"],\n    [\"movntps\"          , \"W:m128, xmm\"                                     , \"MR\"      , \"0F 2B /r\"                     , \"SSE\"],\n    [\"movntq\"           , \"W:m64, mm\"                                       , \"MR\"      , \"0F E7 /r\"                     , \"MMX2\"],\n    [\"movntsd\"          , \"W:m64, xmm[63:0]\"                                , \"RM\"      , \"F2 0F 2B /r\"                  , \"SSE4A\"],\n    [\"movntss\"          , \"W:m32, xmm[31:0]\"                                , \"RM\"      , \"F3 0F 2B /r\"                  , \"SSE4A\"],\n    [\"movq\"             , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 6F /r\"                     , \"MMX\"],\n    [\"movq\"             , \"W:mm, r64/m64\"                                   , \"RM\"      , \"REX.W 0F 6E /r\"               , \"MMX X64\"],\n    [\"movq\"             , \"W:mm/m64, mm\"                                    , \"MR\"      , \"0F 7F /r\"                     , \"MMX\"],\n    [\"movq\"             , \"W:r64/m64, mm\"                                   , \"MR\"      , \"REX.W 0F 7E /r\"               , \"MMX X64\"],\n    [\"movq\"             , \"W:r64/m64, xmm[63:0]\"                            , \"MR\"      , \"REX.W 66 0F 7E /r\"            , \"SSE2 X64\"],\n    [\"movq\"             , \"W:xmm[63:0], r64[63:0]/m64\"                      , \"RM\"      , \"REX.W 66 0F 6E /r\"            , \"SSE2 X64\"],\n    [\"movq\"             , \"W:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F3 0F 7E /r\"                  , \"SSE2\"],\n    [\"movq\"             , \"W:xmm[63:0]/m64, xmm[63:0]\"                      , \"MR\"      , \"66 0F D6 /r\"                  , \"SSE2\"],\n    [\"movq2dq\"          , \"W:xmm[63:0], mm\"                                 , \"RM\"      , \"F3 0F D6 /r\"                  , \"SSE2\"],\n    [\"movsd\"            , \"w:xmm[63:0], xmm[63:0]\"                          , \"RM\"      , \"F2 0F 10 /r\"                  , \"SSE2\"],\n    [\"movsd\"            , \"W:xmm[63:0], m64\"                                , \"RM\"      , \"F2 0F 10 /r\"                  , \"SSE2\"],\n    [\"movsd\"            , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"F2 0F 11 /r\"                  , \"SSE2\"],\n    [\"movshdup\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"F3 0F 16 /r\"                  , \"SSE3\"],\n    [\"movsldup\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"F3 0F 12 /r\"                  , \"SSE3\"],\n    [\"movss\"            , \"w:xmm[31:0], xmm[31:0]\"                          , \"RM\"      , \"F3 0F 10 /r\"                  , \"SSE\"],\n    [\"movss\"            , \"W:xmm[31:0], m32\"                                , \"RM\"      , \"F3 0F 10 /r\"                  , \"SSE\"],\n    [\"movss\"            , \"W:m32, xmm[31:0]\"                                , \"MR\"      , \"F3 0F 11 /r\"                  , \"SSE\"],\n    [\"movupd\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 10 /r\"                  , \"SSE2\"],\n    [\"movupd\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"66 0F 11 /r\"                  , \"SSE2\"],\n    [\"movups\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 10 /r\"                     , \"SSE\"],\n    [\"movups\"           , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"0F 11 /r\"                     , \"SSE\"],\n    [\"mpsadbw\"          , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 42 /r ib\"            , \"SSE4_1\"],\n    [\"mulpd\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 59 /r\"                  , \"SSE2\"],\n    [\"mulps\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"0F 59 /r\"                     , \"SSE\"],\n    [\"mulsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 59 /r\"                  , \"SSE2\"],\n    [\"mulss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 59 /r\"                  , \"SSE\"],\n    [\"orpd\"             , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 56 /r\"                  , \"SSE2\"],\n    [\"orps\"             , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"0F 56 /r\"                     , \"SSE\"],\n    [\"pabsb\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 1C /r\"                  , \"SSSE3\"],\n    [\"pabsb\"            , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 1C /r\"               , \"SSSE3\"],\n    [\"pabsd\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 1E /r\"                  , \"SSSE3\"],\n    [\"pabsd\"            , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 1E /r\"               , \"SSSE3\"],\n    [\"pabsw\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 1D /r\"                  , \"SSSE3\"],\n    [\"pabsw\"            , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 1D /r\"               , \"SSSE3\"],\n    [\"packssdw\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 6B /r\"                     , \"MMX\"],\n    [\"packssdw\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 6B /r\"                  , \"SSE2\"],\n    [\"packsswb\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 63 /r\"                     , \"MMX\"],\n    [\"packsswb\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 63 /r\"                  , \"SSE2\"],\n    [\"packusdw\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 2B /r\"               , \"SSE4_1\"],\n    [\"packuswb\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 67 /r\"                     , \"MMX\"],\n    [\"packuswb\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 67 /r\"                  , \"SSE2\"],\n    [\"paddb\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F FC /r\"                     , \"MMX\"],\n    [\"paddb\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F FC /r\"                  , \"SSE2\"],\n    [\"paddd\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F FE /r\"                     , \"MMX\"],\n    [\"paddd\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F FE /r\"                  , \"SSE2\"],\n    [\"paddq\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F D4 /r\"                     , \"SSE2\"],\n    [\"paddq\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F D4 /r\"                  , \"SSE2\"],\n    [\"paddsb\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F EC /r\"                     , \"MMX\"],\n    [\"paddsb\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F EC /r\"                  , \"SSE2\"],\n    [\"paddsw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F ED /r\"                     , \"MMX\"],\n    [\"paddsw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F ED /r\"                  , \"SSE2\"],\n    [\"paddusb\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F DC /r\"                     , \"MMX\"],\n    [\"paddusb\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F DC /r\"                  , \"SSE2\"],\n    [\"paddusw\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F DD /r\"                     , \"MMX\"],\n    [\"paddusw\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F DD /r\"                  , \"SSE2\"],\n    [\"paddw\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F FD /r\"                     , \"MMX\"],\n    [\"paddw\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F FD /r\"                  , \"SSE2\"],\n    [\"palignr\"          , \"X:mm, mm/m64, ib/ub\"                             , \"RMI\"     , \"0F 3A 0F /r ib\"               , \"SSE3\"],\n    [\"palignr\"          , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 0F /r ib\"            , \"SSE3\"],\n    [\"pand\"             , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F DB /r\"                     , \"MMX\"],\n    [\"pand\"             , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F DB /r\"                  , \"SSE2\"],\n    [\"pandn\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F DF /r\"                     , \"MMX\"],\n    [\"pandn\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F DF /r\"                  , \"SSE2\"],\n    [\"pavgb\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F E0 /r\"                     , \"MMX2\"],\n    [\"pavgb\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F E0 /r\"                  , \"SSE2\"],\n    [\"pavgw\"            , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F E3 /r\"                     , \"MMX2\"],\n    [\"pavgw\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F E3 /r\"                  , \"SSE2\"],\n    [\"pblendvb\"         , \"X:xmm, xmm/m128, <xmm0>\"                         , \"RM\"      , \"66 0F E0 /r\"                  , \"SSE4_1\"],\n    [\"pblendw\"          , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 0E /r ib\"            , \"SSE4_1\"],\n    [\"pclmulqdq\"        , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 44 /r ib\"            , \"PCLMULQDQ\"],\n    [\"pcmpeqb\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 74 /r\"                     , \"MMX\"],\n    [\"pcmpeqb\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 74 /r\"                  , \"SSE2\"],\n    [\"pcmpeqd\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 76 /r\"                     , \"MMX\"],\n    [\"pcmpeqd\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 76 /r\"                  , \"SSE2\"],\n    [\"pcmpeqq\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 29 /r\"               , \"SSE4_1\"],\n    [\"pcmpeqw\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 75 /r\"                     , \"MMX\"],\n    [\"pcmpeqw\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 75 /r\"                  , \"SSE2\"],\n    [\"pcmpestri\"        , \"R:xmm, xmm/m128, ib/ub, W:<ecx>,<eax>,<edx>\"     , \"RMI\"     , \"66 0F 3A 61 /r ib\"            , \"SSE4_2 OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"pcmpestrm\"        , \"R:xmm, xmm/m128, ib/ub, W:<xmm0>,<eax>,<edx>\"    , \"RMI\"     , \"66 0F 3A 60 /r ib\"            , \"SSE4_2 OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"pcmpgtb\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 64 /r\"                     , \"MMX\"],\n    [\"pcmpgtb\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 64 /r\"                  , \"SSE2\"],\n    [\"pcmpgtd\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 66 /r\"                     , \"MMX\"],\n    [\"pcmpgtd\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 66 /r\"                  , \"SSE2\"],\n    [\"pcmpgtq\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 37 /r\"               , \"SSE4_2\"],\n    [\"pcmpgtw\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 65 /r\"                     , \"MMX\"],\n    [\"pcmpgtw\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 65 /r\"                  , \"SSE2\"],\n    [\"pcmpistri\"        , \"R:xmm, xmm/m128, ib/ub, W:<ecx>\"                 , \"RMI\"     , \"66 0F 3A 63 /r ib\"            , \"SSE4_2 OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"pcmpistrm\"        , \"R:xmm, xmm/m128, ib/ub, W:<xmm0>\"                , \"RMI\"     , \"66 0F 3A 62 /r ib\"            , \"SSE4_2 OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"pextrb\"           , \"W:r32[7:0]/m8, xmm, ib/ub\"                       , \"MRI\"     , \"66 0F 3A 14 /r ib\"            , \"SSE4_1\"],\n    [\"pextrd\"           , \"W:r32[31:0]/m32, xmm, ib/ub\"                     , \"MRI\"     , \"66 0F 3A 16 /r ib\"            , \"SSE4_1\"],\n    [\"pextrq\"           , \"W:r64/m64, xmm, ib/ub\"                           , \"MRI\"     , \"REX.W 66 0F 3A 16 /r ib\"      , \"SSE4_1 X64\"],\n    [\"pextrw\"           , \"W:r32[15:0], mm, ib/ub\"                          , \"RMI\"     , \"0F C5 /r ib\"                  , \"MMX2\"],\n    [\"pextrw\"           , \"W:r32[15:0], xmm, ib/ub\"                         , \"RMI\"     , \"66 0F C5 /r ib\"               , \"SSE2\"],\n    [\"pextrw\"           , \"W:r32[15:0]/m16, xmm, ib/ub\"                     , \"MRI\"     , \"66 0F 3A 15 /r ib\"            , \"SSE4_1\"],\n    [\"phaddd\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 38 02 /r\"                  , \"SSSE3\"],\n    [\"phaddd\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 02 /r\"               , \"SSSE3\"],\n    [\"phaddsw\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 38 03 /r\"                  , \"SSSE3\"],\n    [\"phaddsw\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 03 /r\"               , \"SSSE3\"],\n    [\"phaddw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 38 01 /r\"                  , \"SSSE3\"],\n    [\"phaddw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 01 /r\"               , \"SSSE3\"],\n    [\"phminposuw\"       , \"W:xmm[18:0], xmm/m128\"                           , \"RM\"      , \"66 0F 38 41 /r\"               , \"SSE4_1\"],\n    [\"phsubd\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 06 /r\"                  , \"SSSE3\"],\n    [\"phsubd\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 06 /r\"               , \"SSSE3\"],\n    [\"phsubsw\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 07 /r\"                  , \"SSSE3\"],\n    [\"phsubsw\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 07 /r\"               , \"SSSE3\"],\n    [\"phsubw\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 05 /r\"                  , \"SSSE3\"],\n    [\"phsubw\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 05 /r\"               , \"SSSE3\"],\n    [\"pinsrb\"           , \"X:xmm, r32[7:0]/m8, ib/ub\"                       , \"RMI\"     , \"66 0F 3A 20 /r ib\"            , \"SSE4_1\"],\n    [\"pinsrd\"           , \"X:xmm, r32[31:0]/m32, ib/ub\"                     , \"RMI\"     , \"66 0F 3A 22 /r ib\"            , \"SSE4_1\"],\n    [\"pinsrq\"           , \"X:xmm, r64/m64, ib/ub\"                           , \"RMI\"     , \"REX.W 66 0F 3A 22 /r ib\"      , \"SSE4_1 X64\"],\n    [\"pinsrw\"           , \"X:mm, r32[15:0]/m16, ib/ub\"                      , \"RMI\"     , \"0F C4 /r ib\"                  , \"MMX2\"],\n    [\"pinsrw\"           , \"X:xmm, r32[15:0]/m16, ib/ub\"                     , \"RMI\"     , \"66 0F C4 /r ib\"               , \"SSE2\"],\n    [\"pmaddubsw\"        , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 38 04 /r\"                  , \"SSSE3\"],\n    [\"pmaddubsw\"        , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 04 /r\"               , \"SSSE3\"],\n    [\"pmaddwd\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F F5 /r\"                     , \"MMX\"],\n    [\"pmaddwd\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F F5 /r\"                  , \"SSE2\"],\n    [\"pmaxsb\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3C /r\"               , \"SSE4_1\"],\n    [\"pmaxsd\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3D /r\"               , \"SSE4_1\"],\n    [\"pmaxsw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F EE /r\"                     , \"MMX2\"],\n    [\"pmaxsw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F EE /r\"                  , \"SSE2\"],\n    [\"pmaxub\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F DE /r\"                     , \"MMX2\"],\n    [\"pmaxub\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F DE /r\"                  , \"SSE2\"],\n    [\"pmaxud\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3F /r\"               , \"SSE4_1\"],\n    [\"pmaxuw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3E /r\"               , \"SSE4_1\"],\n    [\"pminsb\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 38 /r\"               , \"SSE4_1\"],\n    [\"pminsd\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 39 /r\"               , \"SSE4_1\"],\n    [\"pminsw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F EA /r\"                     , \"MMX2\"],\n    [\"pminsw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F EA /r\"                  , \"SSE2\"],\n    [\"pminub\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F DA /r\"                     , \"MMX2\"],\n    [\"pminub\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F DA /r\"                  , \"SSE2\"],\n    [\"pminud\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3B /r\"               , \"SSE4_1\"],\n    [\"pminuw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 3A /r\"               , \"SSE4_1\"],\n    [\"pmovmskb\"         , \"W:r32[7:0], mm\"                                  , \"RM\"      , \"0F D7 /r\"                     , \"MMX2\"],\n    [\"pmovmskb\"         , \"W:r32[15:0], xmm\"                                , \"RM\"      , \"66 0F D7 /r\"                  , \"SSE2\"],\n    [\"pmovsxbd\"         , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"66 0F 38 21 /r\"               , \"SSE4_1\"],\n    [\"pmovsxbq\"         , \"W:xmm, xmm[15:0]/m16\"                            , \"RM\"      , \"66 0F 38 22 /r\"               , \"SSE4_1\"],\n    [\"pmovsxbw\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 20 /r\"               , \"SSE4_1\"],\n    [\"pmovsxdq\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 25 /r\"               , \"SSE4_1\"],\n    [\"pmovsxwd\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 23 /r\"               , \"SSE4_1\"],\n    [\"pmovsxwq\"         , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"66 0F 38 24 /r\"               , \"SSE4_1\"],\n    [\"pmovzxbd\"         , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"66 0F 38 31 /r\"               , \"SSE4_1\"],\n    [\"pmovzxbq\"         , \"W:xmm, xmm[15:0]/m16\"                            , \"RM\"      , \"66 0F 38 32 /r\"               , \"SSE4_1\"],\n    [\"pmovzxbw\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 30 /r\"               , \"SSE4_1\"],\n    [\"pmovzxdq\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 35 /r\"               , \"SSE4_1\"],\n    [\"pmovzxwd\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"66 0F 38 33 /r\"               , \"SSE4_1\"],\n    [\"pmovzxwq\"         , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"66 0F 38 34 /r\"               , \"SSE4_1\"],\n    [\"pmuldq\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 28 /r\"               , \"SSE4_1\"],\n    [\"pmulhrsw\"         , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F 38 0B /r\"                  , \"SSSE3\"],\n    [\"pmulhrsw\"         , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 0B /r\"               , \"SSSE3\"],\n    [\"pmulhuw\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F E4 /r\"                     , \"MMX2\"],\n    [\"pmulhuw\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F E4 /r\"                  , \"SSE2\"],\n    [\"pmulhw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F E5 /r\"                     , \"MMX\"],\n    [\"pmulhw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F E5 /r\"                  , \"SSE2\"],\n    [\"pmulld\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 40 /r\"               , \"SSE4_1\"],\n    [\"pmullw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F D5 /r\"                     , \"MMX\"],\n    [\"pmullw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F D5 /r\"                  , \"SSE2\"],\n    [\"pmuludq\"          , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F F4 /r\"                     , \"SSE2\"],\n    [\"pmuludq\"          , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F F4 /r\"                  , \"SSE2\"],\n    [\"por\"              , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F EB /r\"                     , \"MMX\"],\n    [\"por\"              , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F EB /r\"                  , \"SSE2\"],\n    [\"psadbw\"           , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F F6 /r\"                     , \"MMX2\"],\n    [\"psadbw\"           , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F F6 /r\"                  , \"SSE2\"],\n    [\"pshufb\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 00 /r\"                  , \"SSSE3\"],\n    [\"pshufb\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 00 /r\"               , \"SSSE3\"],\n    [\"pshufd\"           , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 70 /r ib\"               , \"SSE2\"],\n    [\"pshufhw\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"F3 0F 70 /r ib\"               , \"SSE2\"],\n    [\"pshuflw\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"F2 0F 70 /r ib\"               , \"SSE2\"],\n    [\"pshufw\"           , \"W:mm, mm/m64, ib/ub\"                             , \"RMI\"     , \"0F 70 /r ib\"                  , \"MMX2\"],\n    [\"psignb\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 08 /r\"                  , \"SSSE3\"],\n    [\"psignb\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 08 /r\"               , \"SSSE3\"],\n    [\"psignd\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 0A /r\"                  , \"SSSE3\"],\n    [\"psignd\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 0A /r\"               , \"SSSE3\"],\n    [\"psignw\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 38 09 /r\"                  , \"SSSE3\"],\n    [\"psignw\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 09 /r\"               , \"SSSE3\"],\n    [\"pslld\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 72 /6 ib\"                  , \"MMX\"],\n    [\"pslld\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F F2 /r\"                     , \"MMX\"],\n    [\"pslld\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 72 /6 ib\"               , \"SSE2\"],\n    [\"pslld\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F F2 /r\"                  , \"SSE2\"],\n    [\"pslldq\"           , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 73 /7 ib\"               , \"SSE2\"],\n    [\"psllq\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 73 /6 ib\"                  , \"MMX\"],\n    [\"psllq\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F F3 /r\"                     , \"MMX\"],\n    [\"psllq\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 73 /6 ib\"               , \"SSE2\"],\n    [\"psllq\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F F3 /r\"                  , \"SSE2\"],\n    [\"psllw\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 71 /6 ib\"                  , \"MMX\"],\n    [\"psllw\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F F1 /r\"                     , \"MMX\"],\n    [\"psllw\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 71 /6 ib\"               , \"SSE2\"],\n    [\"psllw\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F F1 /r\"                  , \"SSE2\"],\n    [\"psrad\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 72 /4 ib\"                  , \"MMX\"],\n    [\"psrad\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F E2 /r\"                     , \"MMX\"],\n    [\"psrad\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 72 /4 ib\"               , \"SSE2\"],\n    [\"psrad\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F E2 /r\"                  , \"SSE2\"],\n    [\"psraw\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 71 /4 ib\"                  , \"MMX\"],\n    [\"psraw\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F E1 /r\"                     , \"MMX\"],\n    [\"psraw\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 71 /4 ib\"               , \"SSE2\"],\n    [\"psraw\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F E1 /r\"                  , \"SSE2\"],\n    [\"psrld\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 72 /2 ib\"                  , \"MMX\"],\n    [\"psrld\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F D2 /r\"                     , \"MMX\"],\n    [\"psrld\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 72 /2 ib\"               , \"SSE2\"],\n    [\"psrld\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D2 /r\"                  , \"SSE2\"],\n    [\"psrldq\"           , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 73 /3 ib\"               , \"SSE2\"],\n    [\"psrlq\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 73 /2 ib\"                  , \"MMX\"],\n    [\"psrlq\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F D3 /r\"                     , \"MMX\"],\n    [\"psrlq\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 73 /2 ib\"               , \"SSE2\"],\n    [\"psrlq\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D3 /r\"                  , \"SSE2\"],\n    [\"psrlw\"            , \"X:mm, ib/ub\"                                     , \"MI\"      , \"0F 71 /2 ib\"                  , \"MMX\"],\n    [\"psrlw\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F D1 /r\"                     , \"MMX\"],\n    [\"psrlw\"            , \"X:xmm, ib/ub\"                                    , \"MI\"      , \"66 0F 71 /2 ib\"               , \"SSE2\"],\n    [\"psrlw\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D1 /r\"                  , \"SSE2\"],\n    [\"psubb\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F F8 /r\"                     , \"MMX\"],\n    [\"psubb\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F F8 /r\"                  , \"SSE2\"],\n    [\"psubd\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F FA /r\"                     , \"MMX\"],\n    [\"psubd\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F FA /r\"                  , \"SSE2\"],\n    [\"psubq\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F FB /r\"                     , \"SSE2\"],\n    [\"psubq\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F FB /r\"                  , \"SSE2\"],\n    [\"psubsb\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F E8 /r\"                     , \"MMX\"],\n    [\"psubsb\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F E8 /r\"                  , \"SSE2\"],\n    [\"psubsw\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F E9 /r\"                     , \"MMX\"],\n    [\"psubsw\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F E9 /r\"                  , \"SSE2\"],\n    [\"psubusb\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F D8 /r\"                     , \"MMX\"],\n    [\"psubusb\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D8 /r\"                  , \"SSE2\"],\n    [\"psubusw\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F D9 /r\"                     , \"MMX\"],\n    [\"psubusw\"          , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F D9 /r\"                  , \"SSE2\"],\n    [\"psubw\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F F9 /r\"                     , \"MMX\"],\n    [\"psubw\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F F9 /r\"                  , \"SSE2\"],\n    [\"ptest\"            , \"R:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 38 17 /r\"               , \"SSE4_1 OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"punpckhbw\"        , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 68 /r\"                     , \"MMX\"],\n    [\"punpckhbw\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 68 /r\"                  , \"SSE2\"],\n    [\"punpckhdq\"        , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 6A /r\"                     , \"MMX\"],\n    [\"punpckhdq\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 6A /r\"                  , \"SSE2\"],\n    [\"punpckhqdq\"       , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 6D /r\"                  , \"SSE2\"],\n    [\"punpckhwd\"        , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 69 /r\"                     , \"MMX\"],\n    [\"punpckhwd\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 69 /r\"                  , \"SSE2\"],\n    [\"punpcklbw\"        , \"X:mm, mm/m32\"                                    , \"RM\"      , \"0F 60 /r\"                     , \"MMX\"],\n    [\"punpcklbw\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 60 /r\"                  , \"SSE2\"],\n    [\"punpckldq\"        , \"X:mm, mm/m32\"                                    , \"RM\"      , \"0F 62 /r\"                     , \"MMX\"],\n    [\"punpckldq\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 62 /r\"                  , \"SSE2\"],\n    [\"punpcklqdq\"       , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 6C /r\"                  , \"SSE2\"],\n    [\"punpcklwd\"        , \"X:mm, mm/m32\"                                    , \"RM\"      , \"0F 61 /r\"                     , \"MMX\"],\n    [\"punpcklwd\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 61 /r\"                  , \"SSE2\"],\n    [\"pxor\"             , \"X:~mm, ~mm/m64\"                                  , \"RM\"      , \"0F EF /r\"                     , \"MMX\"],\n    [\"pxor\"             , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F EF /r\"                  , \"SSE2\"],\n    [\"rcpps\"            , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 53 /r\"                     , \"SSE\"],\n    [\"rcpss\"            , \"w:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 53 /r\"                  , \"SSE\"],\n    [\"roundpd\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 09 /r ib\"            , \"SSE4_1\"],\n    [\"roundps\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A 08 /r ib\"            , \"SSE4_1\"],\n    [\"roundsd\"          , \"w:xmm[63:0], xmm[63:0]/m64, ib/ub\"               , \"RMI\"     , \"66 0F 3A 0B /r ib\"            , \"SSE4_1\"],\n    [\"roundss\"          , \"w:xmm[31:0], xmm[31:0]/m32, ib/ub\"               , \"RMI\"     , \"66 0F 3A 0A /r ib\"            , \"SSE4_1\"],\n    [\"rsqrtps\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 52 /r\"                     , \"SSE\"],\n    [\"rsqrtss\"          , \"w:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 52 /r\"                  , \"SSE\"],\n    [\"shufpd\"           , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F C6 /r ib\"               , \"SSE2\"],\n    [\"shufps\"           , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"0F C6 /r ib\"                  , \"SSE\"],\n    [\"sqrtpd\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 51 /r\"                  , \"SSE2\"],\n    [\"sqrtps\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 51 /r\"                     , \"SSE\"],\n    [\"sqrtsd\"           , \"w:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 51 /r\"                  , \"SSE2\"],\n    [\"sqrtss\"           , \"w:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 51 /r\"                  , \"SSE\"],\n    [\"subpd\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 5C /r\"                  , \"SSE2\"],\n    [\"subps\"            , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 5C /r\"                     , \"SSE\"],\n    [\"subsd\"            , \"x:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"F2 0F 5C /r\"                  , \"SSE2\"],\n    [\"subss\"            , \"x:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"F3 0F 5C /r\"                  , \"SSE\"],\n    [\"ucomisd\"          , \"R:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"66 0F 2E /r\"                  , \"SSE2 OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"ucomiss\"          , \"R:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"0F 2E /r\"                     , \"SSE  OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"unpckhpd\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 15 /r\"                  , \"SSE2\"],\n    [\"unpckhps\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 15 /r\"                     , \"SSE\"],\n    [\"unpcklpd\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 14 /r\"                  , \"SSE2\"],\n    [\"unpcklps\"         , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"0F 14 /r\"                     , \"SSE\"],\n    [\"xorpd\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"66 0F 57 /r\"                  , \"SSE2\"],\n    [\"xorps\"            , \"X:~xmm, ~xmm/m128\"                               , \"RM\"      , \"0F 57 /r\"                     , \"SSE\"],\n\n    [\"pavgusb\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r BF\"                  , \"3DNOW\"],\n    [\"pf2id\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 1D\"                  , \"3DNOW\"],\n    [\"pf2iw\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 1C\"                  , \"3DNOW2\"],\n    [\"pfacc\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r AE\"                  , \"3DNOW\"],\n    [\"pfadd\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 9E\"                  , \"3DNOW\"],\n    [\"pfcmpeq\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r B0\"                  , \"3DNOW\"],\n    [\"pfcmpge\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 90\"                  , \"3DNOW\"],\n    [\"pfcmpgt\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r A0\"                  , \"3DNOW\"],\n    [\"pfmax\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r A4\"                  , \"3DNOW\"],\n    [\"pfmin\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 94\"                  , \"3DNOW\"],\n    [\"pfmul\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r B4\"                  , \"3DNOW\"],\n    [\"pfnacc\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 8A\"                  , \"3DNOW2\"],\n    [\"pfpnacc\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 8E\"                  , \"3DNOW2\"],\n    [\"pfrcp\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 96\"                  , \"3DNOW\"],\n    [\"pfrcpit1\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r A6\"                  , \"3DNOW\"],\n    [\"pfrcpit2\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r B6\"                  , \"3DNOW\"],\n    [\"pfrcpv\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 86\"                  , \"GEODE\"],\n    [\"pfrsqit1\"         , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r A7\"                  , \"3DNOW\"],\n    [\"pfrsqrt\"          , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 97\"                  , \"3DNOW\"],\n    [\"pfrsqrtv\"         , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 87\"                  , \"GEODE\"],\n    [\"pfsub\"            , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 9A\"                  , \"3DNOW\"],\n    [\"pfsubr\"           , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r AA\"                  , \"3DNOW\"],\n    [\"pi2fd\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 0D\"                  , \"3DNOW\"],\n    [\"pi2fw\"            , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r 0C\"                  , \"3DNOW2\"],\n    [\"pmulhrw\"          , \"X:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r B7\"                  , \"3DNOW\"],\n    [\"pswapd\"           , \"W:mm, mm/m64\"                                    , \"RM\"      , \"0F 0F /r BB\"                  , \"3DNOW2\"],\n\n    [\"emms\"             , \"\"                                                , \"NONE\"    , \"0F 77\"                        , \"MMX Volatile\"],\n    [\"femms\"            , \"\"                                                , \"NONE\"    , \"0F 0E\"                        , \"3DNOW Volatile\"],\n\n    [\"aesdec\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 DE /r\"               , \"AESNI\"],\n    [\"aesdeclast\"       , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 DF /r\"               , \"AESNI\"],\n    [\"aesenc\"           , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 DC /r\"               , \"AESNI\"],\n    [\"aesenclast\"       , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 DD /r\"               , \"AESNI\"],\n    [\"aesimc\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 DB /r\"               , \"AESNI\"],\n    [\"aeskeygenassist\"  , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A DF /r ib\"            , \"AESNI\"],\n\n    [\"sha1msg1\"         , \"xmm, xmm/m128\"                                   , \"RM\"      , \"0F 38 C9 /r\"                  , \"SHA\"],\n    [\"sha1msg2\"         , \"xmm, xmm/m128\"                                   , \"RM\"      , \"0F 38 CA /r\"                  , \"SHA\"],\n    [\"sha1nexte\"        , \"xmm, xmm/m128\"                                   , \"RM\"      , \"0F 38 C8 /r\"                  , \"SHA\"],\n    [\"sha1rnds4\"        , \"xmm, xmm/m128, ib/ub\"                            , \"RMI\"     , \"0F 3A CC /r ib\"               , \"SHA\"],\n    [\"sha256msg1\"       , \"xmm, xmm/m128\"                                   , \"RM\"      , \"0F 38 CC /r\"                  , \"SHA\"],\n    [\"sha256msg2\"       , \"xmm, xmm/m128\"                                   , \"RM\"      , \"0F 38 CD /r\"                  , \"SHA\"],\n    [\"sha256rnds2\"      , \"xmm, xmm/m128, <xmm0>\"                           , \"RM\"      , \"0F 38 CB /r\"                  , \"SHA\"],\n\n    [\"gf2p8affineinvqb\" , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A CF /r ib\"            , \"GFNI\"],\n    [\"gf2p8affineqb\"    , \"X:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"66 0F 3A CE /r ib\"            , \"GFNI\"],\n    [\"gf2p8mulb\"        , \"X:xmm, xmm/m128\"                                 , \"RM\"      , \"66 0F 38 CF /r\"               , \"GFNI\"],\n\n    [\"vaddpd\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 58 /r\"      , \"AVX\"],\n    [\"vaddpd\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 58 /r\"      , \"AVX\"],\n    [\"vaddps\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 58 /r\"         , \"AVX\"],\n    [\"vaddps\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 58 /r\"         , \"AVX\"],\n    [\"vaddsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 58 /r\"      , \"AVX\"],\n    [\"vaddss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 58 /r\"      , \"AVX\"],\n    [\"vaddsubpd\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D0 /r\"      , \"AVX\"],\n    [\"vaddsubpd\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D0 /r\"      , \"AVX\"],\n    [\"vaddsubps\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.F2.0F.WIG D0 /r\"      , \"AVX\"],\n    [\"vaddsubps\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.F2.0F.WIG D0 /r\"      , \"AVX\"],\n    [\"vaesdec\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG DE /r\"    , \"AVX AESNI\"],\n    [\"vaesdec\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG DE /r\"    , \"VAES\"],\n    [\"vaesdeclast\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG DF /r\"    , \"AVX AESNI\"],\n    [\"vaesdeclast\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG DF /r\"    , \"VAES\"],\n    [\"vaesenc\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG DC /r\"    , \"AVX AESNI\"],\n    [\"vaesenc\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG DC /r\"    , \"VAES\"],\n    [\"vaesenclast\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG DD /r\"    , \"AVX AESNI\"],\n    [\"vaesenclast\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG DD /r\"    , \"VAES\"],\n    [\"vaesimc\"          , \"W:xmm, xmm/m128\"                                 , \"RVM\"     , \"VEX.128.66.0F38.WIG DB /r\"    , \"AVX AESNI\"],\n    [\"vaeskeygenassist\" , \"W:xmm, xmm/m128, ib/ub\"                          , \"RVMI\"    , \"VEX.128.66.0F3A.WIG DF /r ib\" , \"AVX AESNI\"],\n    [\"vandnpd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 55 /r\"      , \"AVX\"],\n    [\"vandnpd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 55 /r\"      , \"AVX\"],\n    [\"vandnps\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 55 /r\"         , \"AVX\"],\n    [\"vandnps\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 55 /r\"         , \"AVX\"],\n    [\"vandpd\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 54 /r\"      , \"AVX\"],\n    [\"vandpd\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 54 /r\"      , \"AVX\"],\n    [\"vandps\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 54 /r\"         , \"AVX\"],\n    [\"vandps\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 54 /r\"         , \"AVX\"],\n    [\"vblendpd\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 0D /r ib\" , \"AVX\"],\n    [\"vblendpd\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 0D /r ib\" , \"AVX\"],\n    [\"vblendps\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 0C /r ib\" , \"AVX\"],\n    [\"vblendps\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 0C /r ib\" , \"AVX\"],\n    [\"vblendvpd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 4B /r /is4\", \"AVX\"],\n    [\"vblendvpd\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 4B /r /is4\", \"AVX\"],\n    [\"vblendvps\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 4A /r /is4\", \"AVX\"],\n    [\"vblendvps\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 4A /r /is4\", \"AVX\"],\n    [\"vbroadcastf128\"   , \"W:ymm, m128\"                                     , \"RM\"      , \"VEX.256.66.0F38.W0 1A /r\"     , \"AVX\"],\n    [\"vbroadcasti128\"   , \"W:ymm, m128\"                                     , \"RM\"      , \"VEX.256.66.0F38.W0 5A /r\"     , \"AVX2\"],\n    [\"vbroadcastsd\"     , \"W:ymm, m64\"                                      , \"RM\"      , \"VEX.256.66.0F38.W0 19 /r\"     , \"AVX\"],\n    [\"vbroadcastsd\"     , \"W:ymm, xmm[63:0]\"                                , \"RM\"      , \"VEX.256.66.0F38.W0 19 /r\"     , \"AVX2\"],\n    [\"vbroadcastss\"     , \"W:xmm, m32\"                                      , \"RM\"      , \"VEX.128.66.0F38.W0 18 /r\"     , \"AVX\"],\n    [\"vbroadcastss\"     , \"W:xmm, xmm[31:0]\"                                , \"RM\"      , \"VEX.128.66.0F38.W0 18 /r\"     , \"AVX2\"],\n    [\"vbroadcastss\"     , \"W:ymm, m32\"                                      , \"RM\"      , \"VEX.256.66.0F38.W0 18 /r\"     , \"AVX\"],\n    [\"vbroadcastss\"     , \"W:ymm, xmm[31:0]\"                                , \"RM\"      , \"VEX.256.66.0F38.W0 18 /r\"     , \"AVX2\"],\n    [\"vcmppd\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F.WIG C2 /r ib\"   , \"AVX\"],\n    [\"vcmppd\"           , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F.WIG C2 /r ib\"   , \"AVX\"],\n    [\"vcmpps\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.0F.WIG C2 /r ib\"      , \"AVX\"],\n    [\"vcmpps\"           , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.0F.WIG C2 /r ib\"      , \"AVX\"],\n    [\"vcmpsd\"           , \"W:xmm, xmm, xmm[63:0]/m64, ib/ub\"                , \"RVMI\"    , \"VEX.LIG.F2.0F.WIG C2 /r ib\"   , \"AVX\"],\n    [\"vcmpss\"           , \"W:xmm, xmm, xmm[31:0]/m32, ib/ub\"                , \"RVMI\"    , \"VEX.LIG.F3.0F.WIG C2 /r ib\"   , \"AVX\"],\n    [\"vcomisd\"          , \"R:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"VEX.LIG.66.0F.WIG 2F /r\"      , \"AVX OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vcomiss\"          , \"R:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"VEX.LIG.0F.WIG 2F /r\"         , \"AVX OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vcvtdq2pd\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.F3.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvtdq2pd\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.F3.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvtdq2ps\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 5B /r\"         , \"AVX\"],\n    [\"vcvtdq2ps\"        , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 5B /r\"         , \"AVX\"],\n    [\"vcvtpd2dq\"        , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"VEX.128.F2.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvtpd2dq\"        , \"W:xmm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F2.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvtpd2ps\"        , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"VEX.128.66.0F.WIG 5A /r\"      , \"AVX\"],\n    [\"vcvtpd2ps\"        , \"W:xmm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 5A /r\"      , \"AVX\"],\n    [\"vcvtps2dq\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 5B /r\"      , \"AVX\"],\n    [\"vcvtps2dq\"        , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 5B /r\"      , \"AVX\"],\n    [\"vcvtps2pd\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.0F.WIG 5A /r\"         , \"AVX\"],\n    [\"vcvtps2pd\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.0F.WIG 5A /r\"         , \"AVX\"],\n    [\"vcvtsd2si\"        , \"W:r32, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.LIG.F2.0F.W0 2D /r\"       , \"AVX\"],\n    [\"vcvtsd2si\"        , \"W:r64, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.LIG.F2.0F.W1 2D /r\"       , \"AVX X64\"],\n    [\"vcvtsd2ss\"        , \"W:xmm, xmm[127:32], xmm[63:0]/m64\"               , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 5A /r\"      , \"AVX\"],\n    [\"vcvtsi2sd\"        , \"W:xmm, xmm[127:64], r32/m32\"                     , \"RVM\"     , \"VEX.LIG.F2.0F.W0 2A /r\"       , \"AVX\"],\n    [\"vcvtsi2sd\"        , \"W:xmm, xmm[127:64], r64/m64\"                     , \"RVM\"     , \"VEX.LIG.F2.0F.W1 2A /r\"       , \"AVX X64\"],\n    [\"vcvtsi2ss\"        , \"W:xmm, xmm[127:32], r32/m32\"                     , \"RVM\"     , \"VEX.LIG.F3.0F.W0 2A /r\"       , \"AVX\"],\n    [\"vcvtsi2ss\"        , \"W:xmm, xmm[127:32], r64/m64\"                     , \"RVM\"     , \"VEX.LIG.F3.0F.W1 2A /r\"       , \"AVX X64\"],\n    [\"vcvtss2sd\"        , \"W:xmm, xmm[127:64], xmm[31:0]/m32\"               , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 5A /r\"      , \"AVX\"],\n    [\"vcvtss2si\"        , \"W:r32, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.LIG.F3.0F.W0 2D /r\"       , \"AVX\"],\n    [\"vcvtss2si\"        , \"W:r64, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.LIG.F3.0F.W1 2D /r\"       , \"AVX X64\"],\n    [\"vcvttpd2dq\"       , \"W:xmm[63:0], xmm/m128\"                           , \"RM\"      , \"VEX.128.66.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvttpd2dq\"       , \"W:xmm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG E6 /r\"      , \"AVX\"],\n    [\"vcvttps2dq\"       , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.F3.0F.WIG 5B /r\"      , \"AVX\"],\n    [\"vcvttps2dq\"       , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F3.0F.WIG 5B /r\"      , \"AVX\"],\n    [\"vcvttsd2si\"       , \"W:r32, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.LIG.F2.0F.W0 2C /r\"       , \"AVX\"],\n    [\"vcvttsd2si\"       , \"W:r64, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.LIG.F2.0F.W1 2C /r\"       , \"AVX X64\"],\n    [\"vcvttss2si\"       , \"W:r32, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.LIG.F3.0F.W0 2C /r\"       , \"AVX\"],\n    [\"vcvttss2si\"       , \"W:r64, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.LIG.F3.0F.W1 2C /r\"       , \"AVX X64\"],\n    [\"vdivpd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 5E /r\"      , \"AVX\"],\n    [\"vdivpd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 5E /r\"      , \"AVX\"],\n    [\"vdivps\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 5E /r\"         , \"AVX\"],\n    [\"vdivps\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 5E /r\"         , \"AVX\"],\n    [\"vdivsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 5E /r\"      , \"AVX\"],\n    [\"vdivss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 5E /r\"      , \"AVX\"],\n    [\"vdppd\"            , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 41 /r ib\" , \"AVX\"],\n    [\"vdpps\"            , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 40 /r ib\" , \"AVX\"],\n    [\"vdpps\"            , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 40 /r ib\" , \"AVX\"],\n    [\"vextractf128\"     , \"W:xmm/m128, ymm, ib/ub\"                          , \"MRI\"     , \"VEX.256.66.0F3A.W0 19 /r ib\"  , \"AVX\"],\n    [\"vextracti128\"     , \"W:xmm/m128, ymm, ib/ub\"                          , \"MRI\"     , \"VEX.256.66.0F3A.W0 39 /r ib\"  , \"AVX2\"],\n    [\"vextractps\"       , \"W:r32[31:0]/m32, xmm, ib/ub\"                     , \"MRI\"     , \"VEX.128.66.0F3A.WIG 17 /r ib\" , \"AVX\"],\n    [\"vgatherdpd\"       , \"X:xmm, vm32x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W1 92 /r\"     , \"AVX2\"],\n    [\"vgatherdpd\"       , \"X:ymm, vm32x, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W1 92 /r\"     , \"AVX2\"],\n    [\"vgatherdps\"       , \"X:xmm, vm32x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W0 92 /r\"     , \"AVX2\"],\n    [\"vgatherdps\"       , \"X:ymm, vm32y, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W0 92 /r\"     , \"AVX2\"],\n    [\"vgatherqpd\"       , \"X:xmm, vm64x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W1 93 /r\"     , \"AVX2\"],\n    [\"vgatherqpd\"       , \"X:ymm, vm64y, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W1 93 /r\"     , \"AVX2\"],\n    [\"vgatherqps\"       , \"X:xmm, vm64x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W0 93 /r\"     , \"AVX2\"],\n    [\"vgatherqps\"       , \"X:xmm, vm64y, X:xmm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W0 93 /r\"     , \"AVX2\"],\n    [\"vgf2p8affineinvqb\", \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.W1 CF /r ib\"  , \"AVX GFNI\"],\n    [\"vgf2p8affineinvqb\", \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W1 CF /r ib\"  , \"AVX GFNI\"],\n    [\"vgf2p8affineqb\"   , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.W1 CE /r ib\"  , \"AVX GFNI\"],\n    [\"vgf2p8affineqb\"   , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W1 CE /r ib\"  , \"AVX GFNI\"],\n    [\"vgf2p8mulb\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 CF /r\"     , \"AVX GFNI\"],\n    [\"vgf2p8mulb\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 CF /r\"     , \"AVX GFNI\"],\n    [\"vhaddpd\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 7C /r\"      , \"AVX\"],\n    [\"vhaddpd\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 7C /r\"      , \"AVX\"],\n    [\"vhaddps\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.F2.0F.WIG 7C /r\"      , \"AVX\"],\n    [\"vhaddps\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.F2.0F.WIG 7C /r\"      , \"AVX\"],\n    [\"vhsubpd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 7D /r\"      , \"AVX\"],\n    [\"vhsubpd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 7D /r\"      , \"AVX\"],\n    [\"vhsubps\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.F2.0F.WIG 7D /r\"      , \"AVX\"],\n    [\"vhsubps\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.F2.0F.WIG 7D /r\"      , \"AVX\"],\n    [\"vinsertf128\"      , \"W:ymm, ymm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W0 18 /r ib\"  , \"AVX\"],\n    [\"vinserti128\"      , \"W:ymm, ymm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W0 38 /r ib\"  , \"AVX2\"],\n    [\"vinsertps\"        , \"W:xmm, xmm, xmm[31:0]/m32, ib/ub\"                , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 21 /r ib\" , \"AVX\"],\n    [\"vlddqu\"           , \"W:xmm, m128\"                                     , \"RM\"      , \"VEX.128.F2.0F.WIG F0 /r\"      , \"AVX\"],\n    [\"vlddqu\"           , \"W:ymm, m256\"                                     , \"RM\"      , \"VEX.256.F2.0F.WIG F0 /r\"      , \"AVX\"],\n    [\"vmaskmovdqu\"      , \"R:xmm, xmm, X:<ds:zdi>\"                          , \"RM\"      , \"VEX.128.66.0F.WIG F7 /r\"      , \"AVX\"],\n    [\"vmaskmovpd\"       , \"X:m128, xmm, xmm\"                                , \"MVR\"     , \"VEX.128.66.0F38.W0 2F /r\"     , \"AVX\"],\n    [\"vmaskmovpd\"       , \"X:m256, ymm, ymm\"                                , \"MVR\"     , \"VEX.256.66.0F38.W0 2F /r\"     , \"AVX\"],\n    [\"vmaskmovpd\"       , \"W:xmm, xmm, m128\"                                , \"RVM\"     , \"VEX.128.66.0F38.W0 2D /r\"     , \"AVX\"],\n    [\"vmaskmovpd\"       , \"W:ymm, ymm, m256\"                                , \"RVM\"     , \"VEX.256.66.0F38.W0 2D /r\"     , \"AVX\"],\n    [\"vmaskmovps\"       , \"X:m128, xmm, xmm\"                                , \"MVR\"     , \"VEX.128.66.0F38.W0 2E /r\"     , \"AVX\"],\n    [\"vmaskmovps\"       , \"X:m256, ymm, ymm\"                                , \"MVR\"     , \"VEX.256.66.0F38.W0 2E /r\"     , \"AVX\"],\n    [\"vmaskmovps\"       , \"W:xmm, xmm, m128\"                                , \"RVM\"     , \"VEX.128.66.0F38.W0 2C /r\"     , \"AVX\"],\n    [\"vmaskmovps\"       , \"W:ymm, ymm, m256\"                                , \"RVM\"     , \"VEX.256.66.0F38.W0 2C /r\"     , \"AVX\"],\n    [\"vmaxpd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 5F /r\"      , \"AVX\"],\n    [\"vmaxpd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 5F /r\"      , \"AVX\"],\n    [\"vmaxps\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 5F /r\"         , \"AVX\"],\n    [\"vmaxps\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 5F /r\"         , \"AVX\"],\n    [\"vmaxsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 5F /r\"      , \"AVX\"],\n    [\"vmaxss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 5F /r\"      , \"AVX\"],\n    [\"vminpd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 5D /r\"      , \"AVX\"],\n    [\"vminpd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 5D /r\"      , \"AVX\"],\n    [\"vminps\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 5D /r\"         , \"AVX\"],\n    [\"vminps\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 5D /r\"         , \"AVX\"],\n    [\"vminsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 5D /r\"      , \"AVX\"],\n    [\"vminss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 5D /r\"      , \"AVX\"],\n    [\"vmovapd\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 28 /r\"      , \"AVX\"],\n    [\"vmovapd\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.66.0F.WIG 29 /r\"      , \"AVX\"],\n    [\"vmovapd\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 28 /r\"      , \"AVX\"],\n    [\"vmovapd\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.66.0F.WIG 29 /r\"      , \"AVX\"],\n    [\"vmovaps\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 28 /r\"         , \"AVX\"],\n    [\"vmovaps\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.0F.WIG 29 /r\"         , \"AVX\"],\n    [\"vmovaps\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 28 /r\"         , \"AVX\"],\n    [\"vmovaps\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.0F.WIG 29 /r\"         , \"AVX\"],\n    [\"vmovd\"            , \"W:r32[31:0]/m32, xmm[31:0]\"                      , \"MR\"      , \"VEX.128.66.0F.W0 7E /r\"       , \"AVX\"],\n    [\"vmovd\"            , \"W:xmm[31:0], r32[31:0]/m32\"                      , \"RM\"      , \"VEX.128.66.0F.W0 6E /r\"       , \"AVX\"],\n    [\"vmovddup\"         , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.F2.0F.WIG 12 /r\"      , \"AVX\"],\n    [\"vmovddup\"         , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F2.0F.WIG 12 /r\"      , \"AVX\"],\n    [\"vmovdqa\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 6F /r\"      , \"AVX\"],\n    [\"vmovdqa\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.66.0F.WIG 7F /r\"      , \"AVX\"],\n    [\"vmovdqa\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 6F /r\"      , \"AVX\"],\n    [\"vmovdqa\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.66.0F.WIG 7F /r\"      , \"AVX\"],\n    [\"vmovdqu\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.F3.0F.WIG 6F /r\"      , \"AVX\"],\n    [\"vmovdqu\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.F3.0F.WIG 7F /r\"      , \"AVX\"],\n    [\"vmovdqu\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F3.0F.WIG 6F /r\"      , \"AVX\"],\n    [\"vmovdqu\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.F3.0F.WIG 7F /r\"      , \"AVX\"],\n    [\"vmovhlps\"         , \"W:xmm, xmm[127:64], xmm[127:64]\"                 , \"RVM\"     , \"VEX.128.0F.WIG 12 /r\"         , \"AVX\"],\n    [\"vmovhpd\"          , \"W:m64, xmm[127:64]\"                              , \"MR\"      , \"VEX.128.66.0F.WIG 17 /r\"      , \"AVX\"],\n    [\"vmovhpd\"          , \"W:xmm, xmm[63:0], m64\"                           , \"RVM\"     , \"VEX.128.66.0F.WIG 16 /r\"      , \"AVX\"],\n    [\"vmovhps\"          , \"W:m64, xmm[127:64]\"                              , \"MR\"      , \"VEX.128.0F.WIG 17 /r\"         , \"AVX\"],\n    [\"vmovhps\"          , \"W:xmm, xmm[63:0], m64\"                           , \"RVM\"     , \"VEX.128.0F.WIG 16 /r\"         , \"AVX\"],\n    [\"vmovlhps\"         , \"W:xmm, xmm[63:0], xmm[63:0]\"                     , \"RVM\"     , \"VEX.128.0F.WIG 16 /r\"         , \"AVX\"],\n    [\"vmovlpd\"          , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"VEX.128.66.0F.WIG 13 /r\"      , \"AVX\"],\n    [\"vmovlpd\"          , \"W:xmm, xmm[127:64], m64\"                         , \"RVM\"     , \"VEX.128.66.0F.WIG 12 /r\"      , \"AVX\"],\n    [\"vmovlps\"          , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"VEX.128.0F.WIG 13 /r\"         , \"AVX\"],\n    [\"vmovlps\"          , \"W:xmm, xmm[127:64], m64\"                         , \"RVM\"     , \"VEX.128.0F.WIG 12 /r\"         , \"AVX\"],\n    [\"vmovmskpd\"        , \"W:r32[1:0], xmm\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 50 /r\"      , \"AVX\"],\n    [\"vmovmskpd\"        , \"W:r32[3:0], ymm\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 50 /r\"      , \"AVX\"],\n    [\"vmovmskps\"        , \"W:r32[3:0], xmm\"                                 , \"RM\"      , \"VEX.128.0F.WIG 50 /r\"         , \"AVX\"],\n    [\"vmovmskps\"        , \"W:r32[7:0], ymm\"                                 , \"RM\"      , \"VEX.256.0F.WIG 50 /r\"         , \"AVX\"],\n    [\"vmovntdq\"         , \"W:m128, xmm\"                                     , \"MR\"      , \"VEX.128.66.0F.WIG E7 /r\"      , \"AVX\"],\n    [\"vmovntdq\"         , \"W:m256, ymm\"                                     , \"MR\"      , \"VEX.256.66.0F.WIG E7 /r\"      , \"AVX\"],\n    [\"vmovntdqa\"        , \"W:xmm, m128\"                                     , \"RM\"      , \"VEX.128.66.0F38.WIG 2A /r\"    , \"AVX\"],\n    [\"vmovntdqa\"        , \"W:ymm, m256\"                                     , \"RM\"      , \"VEX.256.66.0F38.WIG 2A /r\"    , \"AVX2\"],\n    [\"vmovntpd\"         , \"W:m128, xmm\"                                     , \"MR\"      , \"VEX.128.66.0F.WIG 2B /r\"      , \"AVX\"],\n    [\"vmovntpd\"         , \"W:m256, ymm\"                                     , \"MR\"      , \"VEX.256.66.0F.WIG 2B /r\"      , \"AVX\"],\n    [\"vmovntps\"         , \"W:m128, xmm\"                                     , \"MR\"      , \"VEX.128.0F.WIG 2B /r\"         , \"AVX\"],\n    [\"vmovntps\"         , \"W:m256, ymm\"                                     , \"MR\"      , \"VEX.256.0F.WIG 2B /r\"         , \"AVX\"],\n    [\"vmovq\"            , \"W:r64/m64, xmm[63:0]\"                            , \"MR\"      , \"VEX.128.66.0F.W1 7E /r\"       , \"AVX X64\"],\n    [\"vmovq\"            , \"W:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"VEX.128.F3.0F.WIG 7E /r\"      , \"AVX\"],\n    [\"vmovq\"            , \"W:xmm[63:0], r64/m64\"                            , \"RM\"      , \"VEX.128.66.0F.W1 6E /r\"       , \"AVX X64\"],\n    [\"vmovq\"            , \"W:xmm[63:0]/m64, xmm[63:0]\"                      , \"MR\"      , \"VEX.128.66.0F.WIG D6 /r\"      , \"AVX\"],\n    [\"vmovsd\"           , \"W:m64, xmm[63:0]\"                                , \"MR\"      , \"VEX.LIG.F2.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmovsd\"           , \"W:xmm[63:0], m64\"                                , \"RM\"      , \"VEX.LIG.F2.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovsd\"           , \"W:xmm, xmm[127:64], xmm[63:0]\"                   , \"MVR\"     , \"VEX.LIG.F2.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmovsd\"           , \"W:xmm, xmm[127:64], xmm[63:0]\"                   , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovshdup\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.F3.0F.WIG 16 /r\"      , \"AVX\"],\n    [\"vmovshdup\"        , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F3.0F.WIG 16 /r\"      , \"AVX\"],\n    [\"vmovsldup\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.F3.0F.WIG 12 /r\"      , \"AVX\"],\n    [\"vmovsldup\"        , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.F3.0F.WIG 12 /r\"      , \"AVX\"],\n    [\"vmovss\"           , \"W:m32, xmm[31:0]\"                                , \"MR\"      , \"VEX.LIG.F3.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmovss\"           , \"W:xmm[31:0], m32\"                                , \"RM\"      , \"VEX.LIG.F3.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovss\"           , \"W:xmm, xmm[127:32], xmm[31:0]\"                   , \"MVR\"     , \"VEX.LIG.F3.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmovss\"           , \"W:xmm, xmm[127:32], xmm[31:0]\"                   , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovupd\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 10 /r\"         , \"AVX\"],\n    [\"vmovupd\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.0F.WIG 11 /r\"         , \"AVX\"],\n    [\"vmovupd\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 10 /r\"         , \"AVX\"],\n    [\"vmovupd\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.0F.WIG 11 /r\"         , \"AVX\"],\n    [\"vmovups\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovups\"          , \"W:xmm/m128, xmm\"                                 , \"MR\"      , \"VEX.128.66.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmovups\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 10 /r\"      , \"AVX\"],\n    [\"vmovups\"          , \"W:ymm/m256, ymm\"                                 , \"MR\"      , \"VEX.256.66.0F.WIG 11 /r\"      , \"AVX\"],\n    [\"vmpsadbw\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 42 /r ib\" , \"AVX\"],\n    [\"vmpsadbw\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 42 /r ib\" , \"AVX2\"],\n    [\"vmulpd\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 59 /r\"      , \"AVX\"],\n    [\"vmulpd\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 59 /r\"      , \"AVX\"],\n    [\"vmulps\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 59 /r\"         , \"AVX\"],\n    [\"vmulps\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 59 /r\"         , \"AVX\"],\n    [\"vmulsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 59 /r\"      , \"AVX\"],\n    [\"vmulss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 59 /r\"      , \"AVX\"],\n    [\"vorpd\"            , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 56 /r\"      , \"AVX\"],\n    [\"vorpd\"            , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 56 /r\"      , \"AVX\"],\n    [\"vorps\"            , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 56 /r\"         , \"AVX\"],\n    [\"vorps\"            , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 56 /r\"         , \"AVX\"],\n    [\"vpabsb\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F38.WIG 1C /r\"    , \"AVX\"],\n    [\"vpabsb\"           , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 1C /r\"    , \"AVX2\"],\n    [\"vpabsd\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F38.WIG 1E /r\"    , \"AVX\"],\n    [\"vpabsd\"           , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 1E /r\"    , \"AVX2\"],\n    [\"vpabsw\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F38.WIG 1D /r\"    , \"AVX\"],\n    [\"vpabsw\"           , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 1D /r\"    , \"AVX2\"],\n    [\"vpackssdw\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 6B /r\"      , \"AVX\"],\n    [\"vpackssdw\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 6B /r\"      , \"AVX2\"],\n    [\"vpacksswb\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 63 /r\"      , \"AVX\"],\n    [\"vpacksswb\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 63 /r\"      , \"AVX2\"],\n    [\"vpackusdw\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 2B /r\"    , \"AVX\"],\n    [\"vpackusdw\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 2B /r\"    , \"AVX2\"],\n    [\"vpackuswb\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 67 /r\"      , \"AVX\"],\n    [\"vpackuswb\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 67 /r\"      , \"AVX2\"],\n    [\"vpaddb\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG FC /r\"      , \"AVX\"],\n    [\"vpaddb\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG FC /r\"      , \"AVX2\"],\n    [\"vpaddd\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG FE /r\"      , \"AVX\"],\n    [\"vpaddd\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG FE /r\"      , \"AVX2\"],\n    [\"vpaddq\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D4 /r\"      , \"AVX\"],\n    [\"vpaddq\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D4 /r\"      , \"AVX2\"],\n    [\"vpaddsb\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG EC /r\"      , \"AVX\"],\n    [\"vpaddsb\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG EC /r\"      , \"AVX2\"],\n    [\"vpaddsw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG ED /r\"      , \"AVX\"],\n    [\"vpaddsw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG ED /r\"      , \"AVX2\"],\n    [\"vpaddusb\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DC /r\"      , \"AVX\"],\n    [\"vpaddusb\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DC /r\"      , \"AVX2\"],\n    [\"vpaddusw\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DD /r\"      , \"AVX\"],\n    [\"vpaddusw\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DD /r\"      , \"AVX2\"],\n    [\"vpaddw\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG FD /r\"      , \"AVX\"],\n    [\"vpaddw\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG FD /r\"      , \"AVX2\"],\n    [\"vpalignr\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 0F /r ib\" , \"AVX\"],\n    [\"vpalignr\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 0F /r ib\" , \"AVX2\"],\n    [\"vpand\"            , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DB /r\"      , \"AVX\"],\n    [\"vpand\"            , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DB /r\"      , \"AVX2\"],\n    [\"vpandn\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DF /r\"      , \"AVX\"],\n    [\"vpandn\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DF /r\"      , \"AVX2\"],\n    [\"vpavgb\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E0 /r\"      , \"AVX\"],\n    [\"vpavgb\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E0 /r\"      , \"AVX2\"],\n    [\"vpavgw\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E3 /r\"      , \"AVX\"],\n    [\"vpavgw\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E3 /r\"      , \"AVX2\"],\n    [\"vpblendd\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.W0 02 /r ib\"  , \"AVX2\"],\n    [\"vpblendd\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W0 02 /r ib\"  , \"AVX2\"],\n    [\"vpblendvb\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 4C /r /is4\", \"AVX\"],\n    [\"vpblendvb\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 4C /r /is4\", \"AVX2\"],\n    [\"vpblendw\"         , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 0E /r ib\" , \"AVX\"],\n    [\"vpblendw\"         , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 0E /r ib\" , \"AVX2\"],\n    [\"vpbroadcastb\"     , \"W:xmm, xmm[7:0]/m8\"                              , \"RM\"      , \"VEX.128.66.0F38.W0 78 /r\"     , \"AVX2\"],\n    [\"vpbroadcastb\"     , \"W:ymm, xmm[7:0]/m8\"                              , \"RM\"      , \"VEX.256.66.0F38.W0 78 /r\"     , \"AVX2\"],\n    [\"vpbroadcastd\"     , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.128.66.0F38.W0 58 /r\"     , \"AVX2\"],\n    [\"vpbroadcastd\"     , \"W:ymm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.256.66.0F38.W0 58 /r\"     , \"AVX2\"],\n    [\"vpbroadcastq\"     , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.W0 59 /r\"     , \"AVX2\"],\n    [\"vpbroadcastq\"     , \"W:ymm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.256.66.0F38.W0 59 /r\"     , \"AVX2\"],\n    [\"vpbroadcastw\"     , \"W:xmm, xmm[15:0]/m16\"                            , \"RM\"      , \"VEX.128.66.0F38.W0 79 /r\"     , \"AVX2\"],\n    [\"vpbroadcastw\"     , \"W:ymm, xmm[15:0]/m16\"                            , \"RM\"      , \"VEX.256.66.0F38.W0 79 /r\"     , \"AVX2\"],\n    [\"vpclmulqdq\"       , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F3A.WIG 44 /r ib\" , \"AVX PCLMULQDQ\"],\n    [\"vpclmulqdq\"       , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.WIG 44 /r ib\" , \"VPCLMULQDQ\"],\n    [\"vpcmpeqb\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 74 /r\"      , \"AVX\"],\n    [\"vpcmpeqb\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 74 /r\"      , \"AVX2\"],\n    [\"vpcmpeqd\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 76 /r\"      , \"AVX\"],\n    [\"vpcmpeqd\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 76 /r\"      , \"AVX2\"],\n    [\"vpcmpeqq\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 29 /r\"    , \"AVX\"],\n    [\"vpcmpeqq\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 29 /r\"    , \"AVX2\"],\n    [\"vpcmpeqw\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 75 /r\"      , \"AVX\"],\n    [\"vpcmpeqw\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 75 /r\"      , \"AVX2\"],\n    [\"vpcmpestri\"       , \"R:xmm, xmm/m128, ib/ub, W:<ecx>,<eax>,<edx>\"     , \"RMI\"     , \"VEX.128.66.0F3A.WIG 61 /r ib\" , \"AVX OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"vpcmpestrm\"       , \"R:xmm, xmm/m128, ib/ub, W:<xmm0>,<eax>,<edx>\"    , \"RMI\"     , \"VEX.128.66.0F3A.WIG 60 /r ib\" , \"AVX OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"vpcmpgtb\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 64 /r\"      , \"AVX\"],\n    [\"vpcmpgtb\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 64 /r\"      , \"AVX2\"],\n    [\"vpcmpgtd\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 66 /r\"      , \"AVX\"],\n    [\"vpcmpgtd\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 66 /r\"      , \"AVX2\"],\n    [\"vpcmpgtq\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 37 /r\"    , \"AVX\"],\n    [\"vpcmpgtq\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 37 /r\"    , \"AVX2\"],\n    [\"vpcmpgtw\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 65 /r\"      , \"AVX\"],\n    [\"vpcmpgtw\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 65 /r\"      , \"AVX2\"],\n    [\"vpcmpistri\"       , \"R:xmm, xmm/m128, ib/ub, W:<ecx>\"                 , \"RMI\"     , \"VEX.128.66.0F3A.WIG 63 /r ib\" , \"AVX OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"vpcmpistrm\"       , \"R:xmm, xmm/m128, ib/ub, W:<xmm0>\"                , \"RMI\"     , \"VEX.128.66.0F3A.WIG 62 /r ib\" , \"AVX OF=W SF=W ZF=W AF=0 PF=0 CF=W\"],\n    [\"vperm2f128\"       , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W0 06 /r ib\"  , \"AVX\"],\n    [\"vperm2i128\"       , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F3A.W0 46 /r ib\"  , \"AVX2\"],\n    [\"vpermd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 36 /r\"     , \"AVX2\"],\n    [\"vpermilpd\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 0D /r\"     , \"AVX\"],\n    [\"vpermilpd\"        , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.66.0F3A.W0 05 /r ib\"  , \"AVX\"],\n    [\"vpermilpd\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 0D /r\"     , \"AVX\"],\n    [\"vpermilpd\"        , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.W0 05 /r ib\"  , \"AVX\"],\n    [\"vpermilps\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 0C /r\"     , \"AVX\"],\n    [\"vpermilps\"        , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.66.0F3A.W0 04 /r ib\"  , \"AVX\"],\n    [\"vpermilps\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 0C /r\"     , \"AVX\"],\n    [\"vpermilps\"        , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.W0 04 /r ib\"  , \"AVX\"],\n    [\"vpermpd\"          , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.W1 01 /r ib\"  , \"AVX2\"],\n    [\"vpermps\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 16 /r\"     , \"AVX2\"],\n    [\"vpermq\"           , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.W1 00 /r ib\"  , \"AVX2\"],\n    [\"vpextrb\"          , \"W:r32[7:0]/m8, xmm, ib/ub\"                       , \"MRI\"     , \"VEX.128.66.0F3A.W0 14 /r ib\"  , \"AVX\"],\n    [\"vpextrd\"          , \"W:r32/m32, xmm, ib/ub\"                           , \"MRI\"     , \"VEX.128.66.0F3A.W0 16 /r ib\"  , \"AVX\"],\n    [\"vpextrq\"          , \"W:r64/m64, xmm, ib/ub\"                           , \"MRI\"     , \"VEX.128.66.0F3A.W1 16 /r ib\"  , \"AVX X64\"],\n    [\"vpextrw\"          , \"W:r32[15:0], xmm, ib/ub\"                         , \"RMI\"     , \"VEX.128.66.0F.W0 C5 /r ib\"    , \"AVX\"],\n    [\"vpextrw\"          , \"W:r32[15:0]/m16, xmm, ib/ub\"                     , \"MRI\"     , \"VEX.128.66.0F3A.W0 15 /r ib\"  , \"AVX\"],\n    [\"vpgatherdd\"       , \"X:xmm, vm32x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W0 90 /r\"     , \"AVX2\"],\n    [\"vpgatherdd\"       , \"X:ymm, vm32y, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W0 90 /r\"     , \"AVX2\"],\n    [\"vpgatherdq\"       , \"X:xmm, vm32x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W1 90 /r\"     , \"AVX2\"],\n    [\"vpgatherdq\"       , \"X:ymm, vm32x, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W1 90 /r\"     , \"AVX2\"],\n    [\"vpgatherqd\"       , \"X:xmm, vm64x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W0 91 /r\"     , \"AVX2\"],\n    [\"vpgatherqd\"       , \"X:xmm, vm64y, X:xmm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W0 91 /r\"     , \"AVX2\"],\n    [\"vpgatherqq\"       , \"X:xmm, vm64x, X:xmm\"                             , \"RMV\"     , \"VEX.128.66.0F38.W1 91 /r\"     , \"AVX2\"],\n    [\"vpgatherqq\"       , \"X:ymm, vm64y, X:ymm\"                             , \"RMV\"     , \"VEX.256.66.0F38.W1 91 /r\"     , \"AVX2\"],\n    [\"vphaddd\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 02 /r\"    , \"AVX\"],\n    [\"vphaddd\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 02 /r\"    , \"AVX2\"],\n    [\"vphaddsw\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 03 /r\"    , \"AVX\"],\n    [\"vphaddsw\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 03 /r\"    , \"AVX2\"],\n    [\"vphaddw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 01 /r\"    , \"AVX\"],\n    [\"vphaddw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 01 /r\"    , \"AVX2\"],\n    [\"vphminposuw\"      , \"W:xmm[18:0], xmm/m128\"                           , \"RM\"      , \"VEX.128.66.0F38.WIG 41 /r\"    , \"AVX\"],\n    [\"vphsubd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 06 /r\"    , \"AVX\"],\n    [\"vphsubd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 06 /r\"    , \"AVX2\"],\n    [\"vphsubsw\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 07 /r\"    , \"AVX\"],\n    [\"vphsubsw\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 07 /r\"    , \"AVX2\"],\n    [\"vphsubw\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 05 /r\"    , \"AVX\"],\n    [\"vphsubw\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 05 /r\"    , \"AVX2\"],\n    [\"vpinsrb\"          , \"W:xmm, xmm, r32[7:0]/m8, ib/ub\"                  , \"RVMI\"    , \"VEX.128.66.0F3A.W0 20 /r ib\"  , \"AVX\"],\n    [\"vpinsrd\"          , \"W:xmm, xmm, r32/m32, ib/ub\"                      , \"RVMI\"    , \"VEX.128.66.0F3A.W0 22 /r ib\"  , \"AVX\"],\n    [\"vpinsrq\"          , \"W:xmm, xmm, r64/m64, ib/ub\"                      , \"RVMI\"    , \"VEX.128.66.0F3A.W1 22 /r ib\"  , \"AVX X64\"],\n    [\"vpinsrw\"          , \"W:xmm, xmm, r32[15:0]/m16, ib/ub\"                , \"RVMI\"    , \"VEX.128.66.0F.W0 C4 /r ib\"    , \"AVX\"],\n    [\"vpmaddubsw\"       , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 04 /r\"    , \"AVX\"],\n    [\"vpmaddubsw\"       , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 04 /r\"    , \"AVX2\"],\n    [\"vpmaddwd\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F5 /r\"      , \"AVX\"],\n    [\"vpmaddwd\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F5 /r\"      , \"AVX2\"],\n    [\"vpmaskmovd\"       , \"X:m128, xmm, xmm\"                                , \"MVR\"     , \"VEX.128.66.0F38.W0 8E /r\"     , \"AVX2\"],\n    [\"vpmaskmovd\"       , \"X:m256, ymm, ymm\"                                , \"MVR\"     , \"VEX.256.66.0F38.W0 8E /r\"     , \"AVX2\"],\n    [\"vpmaskmovd\"       , \"W:xmm, xmm, m128\"                                , \"RVM\"     , \"VEX.128.66.0F38.W0 8C /r\"     , \"AVX2\"],\n    [\"vpmaskmovd\"       , \"W:ymm, ymm, m256\"                                , \"RVM\"     , \"VEX.256.66.0F38.W0 8C /r\"     , \"AVX2\"],\n    [\"vpmaskmovq\"       , \"X:m128, xmm, xmm\"                                , \"MVR\"     , \"VEX.128.66.0F38.W1 8E /r\"     , \"AVX2\"],\n    [\"vpmaskmovq\"       , \"X:m256, ymm, ymm\"                                , \"MVR\"     , \"VEX.256.66.0F38.W1 8E /r\"     , \"AVX2\"],\n    [\"vpmaskmovq\"       , \"W:xmm, xmm, m128\"                                , \"RVM\"     , \"VEX.128.66.0F38.W1 8C /r\"     , \"AVX2\"],\n    [\"vpmaskmovq\"       , \"W:ymm, ymm, m256\"                                , \"RVM\"     , \"VEX.256.66.0F38.W1 8C /r\"     , \"AVX2\"],\n    [\"vpmaxsb\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3C /r\"    , \"AVX\"],\n    [\"vpmaxsb\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3C /r\"    , \"AVX2\"],\n    [\"vpmaxsd\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3D /r\"    , \"AVX\"],\n    [\"vpmaxsd\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3D /r\"    , \"AVX2\"],\n    [\"vpmaxsw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG EE /r\"      , \"AVX\"],\n    [\"vpmaxsw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG EE /r\"      , \"AVX2\"],\n    [\"vpmaxub\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DE /r\"      , \"AVX\"],\n    [\"vpmaxub\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DE /r\"      , \"AVX2\"],\n    [\"vpmaxud\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3F /r\"    , \"AVX\"],\n    [\"vpmaxud\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3F /r\"    , \"AVX2\"],\n    [\"vpmaxuw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3E /r\"    , \"AVX\"],\n    [\"vpmaxuw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3E /r\"    , \"AVX2\"],\n    [\"vpminsb\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 38 /r\"    , \"AVX\"],\n    [\"vpminsb\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 38 /r\"    , \"AVX2\"],\n    [\"vpminsd\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 39 /r\"    , \"AVX\"],\n    [\"vpminsd\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 39 /r\"    , \"AVX2\"],\n    [\"vpminsw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG EA /r\"      , \"AVX\"],\n    [\"vpminsw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG EA /r\"      , \"AVX2\"],\n    [\"vpminub\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG DA /r\"      , \"AVX\"],\n    [\"vpminub\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG DA /r\"      , \"AVX2\"],\n    [\"vpminud\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3B /r\"    , \"AVX\"],\n    [\"vpminud\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3B /r\"    , \"AVX2\"],\n    [\"vpminuw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 3A /r\"    , \"AVX\"],\n    [\"vpminuw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 3A /r\"    , \"AVX2\"],\n    [\"vpmovmskb\"        , \"W:r32[15:0], xmm\"                                , \"RVM\"     , \"VEX.128.66.0F.WIG D7 /r\"      , \"AVX\"],\n    [\"vpmovmskb\"        , \"W:r32[31:0], ymm\"                                , \"RVM\"     , \"VEX.256.66.0F.WIG D7 /r\"      , \"AVX2\"],\n    [\"vpmovsxbd\"        , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 21 /r\"    , \"AVX\"],\n    [\"vpmovsxbd\"        , \"W:ymm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 21 /r\"    , \"AVX2\"],\n    [\"vpmovsxbq\"        , \"W:xmm, xmm[15:0]/m16\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 22 /r\"    , \"AVX\"],\n    [\"vpmovsxbq\"        , \"W:ymm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 22 /r\"    , \"AVX2\"],\n    [\"vpmovsxbw\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 20 /r\"    , \"AVX\"],\n    [\"vpmovsxbw\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 20 /r\"    , \"AVX2\"],\n    [\"vpmovsxdq\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 25 /r\"    , \"AVX\"],\n    [\"vpmovsxdq\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 25 /r\"    , \"AVX2\"],\n    [\"vpmovsxwd\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 23 /r\"    , \"AVX\"],\n    [\"vpmovsxwd\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 23 /r\"    , \"AVX2\"],\n    [\"vpmovsxwq\"        , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 24 /r\"    , \"AVX\"],\n    [\"vpmovsxwq\"        , \"W:ymm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 24 /r\"    , \"AVX2\"],\n    [\"vpmovzxbd\"        , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 31 /r\"    , \"AVX\"],\n    [\"vpmovzxbd\"        , \"W:ymm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 31 /r\"    , \"AVX2\"],\n    [\"vpmovzxbq\"        , \"W:xmm, xmm[15:0]/m16\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 32 /r\"    , \"AVX\"],\n    [\"vpmovzxbq\"        , \"W:ymm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 32 /r\"    , \"AVX2\"],\n    [\"vpmovzxbw\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 30 /r\"    , \"AVX\"],\n    [\"vpmovzxbw\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 30 /r\"    , \"AVX2\"],\n    [\"vpmovzxdq\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 35 /r\"    , \"AVX\"],\n    [\"vpmovzxdq\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 35 /r\"    , \"AVX2\"],\n    [\"vpmovzxwd\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 33 /r\"    , \"AVX\"],\n    [\"vpmovzxwd\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.WIG 33 /r\"    , \"AVX2\"],\n    [\"vpmovzxwq\"        , \"W:xmm, xmm[31:0]/m32\"                            , \"RM\"      , \"VEX.128.66.0F38.WIG 34 /r\"    , \"AVX\"],\n    [\"vpmovzxwq\"        , \"W:ymm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.256.66.0F38.WIG 34 /r\"    , \"AVX2\"],\n    [\"vpmuldq\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 28 /r\"    , \"AVX\"],\n    [\"vpmuldq\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 28 /r\"    , \"AVX2\"],\n    [\"vpmulhrsw\"        , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 0B /r\"    , \"AVX\"],\n    [\"vpmulhrsw\"        , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 0B /r\"    , \"AVX2\"],\n    [\"vpmulhuw\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E4 /r\"      , \"AVX\"],\n    [\"vpmulhuw\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E4 /r\"      , \"AVX2\"],\n    [\"vpmulhw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E5 /r\"      , \"AVX\"],\n    [\"vpmulhw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E5 /r\"      , \"AVX2\"],\n    [\"vpmulld\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 40 /r\"    , \"AVX\"],\n    [\"vpmulld\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 40 /r\"    , \"AVX2\"],\n    [\"vpmullw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D5 /r\"      , \"AVX\"],\n    [\"vpmullw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D5 /r\"      , \"AVX2\"],\n    [\"vpmuludq\"         , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F4 /r\"      , \"AVX\"],\n    [\"vpmuludq\"         , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F4 /r\"      , \"AVX2\"],\n    [\"vpor\"             , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG EB /r\"      , \"AVX\"],\n    [\"vpor\"             , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG EB /r\"      , \"AVX2\"],\n    [\"vpsadbw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F6 /r\"      , \"AVX\"],\n    [\"vpsadbw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F6 /r\"      , \"AVX2\"],\n    [\"vpshufb\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 00 /r\"    , \"AVX\"],\n    [\"vpshufb\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 00 /r\"    , \"AVX2\"],\n    [\"vpshufd\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.66.0F.WIG 70 /r ib\"   , \"AVX\"],\n    [\"vpshufd\"          , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F.WIG 70 /r ib\"   , \"AVX2\"],\n    [\"vpshufhw\"         , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.F3.0F.WIG 70 /r ib\"   , \"AVX\"],\n    [\"vpshufhw\"         , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.F3.0F.WIG 70 /r ib\"   , \"AVX2\"],\n    [\"vpshuflw\"         , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.F2.0F.WIG 70 /r ib\"   , \"AVX\"],\n    [\"vpshuflw\"         , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.F2.0F.WIG 70 /r ib\"   , \"AVX2\"],\n    [\"vpsignb\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 08 /r\"    , \"AVX\"],\n    [\"vpsignb\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 08 /r\"    , \"AVX2\"],\n    [\"vpsignd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 0A /r\"    , \"AVX\"],\n    [\"vpsignd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 0A /r\"    , \"AVX2\"],\n    [\"vpsignw\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.WIG 09 /r\"    , \"AVX\"],\n    [\"vpsignw\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.WIG 09 /r\"    , \"AVX2\"],\n    [\"vpslld\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 72 /6 ib\"   , \"AVX\"],\n    [\"vpslld\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F2 /r\"      , \"AVX\"],\n    [\"vpslld\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 72 /6 ib\"   , \"AVX2\"],\n    [\"vpslld\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F2 /r\"      , \"AVX2\"],\n    [\"vpslldq\"          , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 73 /7 ib\"   , \"AVX\"],\n    [\"vpslldq\"          , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 73 /7 ib\"   , \"AVX2\"],\n    [\"vpsllq\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 73 /6 ib\"   , \"AVX\"],\n    [\"vpsllq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F3 /r\"      , \"AVX\"],\n    [\"vpsllq\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 73 /6 ib\"   , \"AVX2\"],\n    [\"vpsllq\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F3 /r\"      , \"AVX2\"],\n    [\"vpsllvd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 47 /r\"     , \"AVX2\"],\n    [\"vpsllvd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 47 /r\"     , \"AVX2\"],\n    [\"vpsllvq\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 47 /r\"     , \"AVX2\"],\n    [\"vpsllvq\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 47 /r\"     , \"AVX2\"],\n    [\"vpsllw\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 71 /6 ib\"   , \"AVX\"],\n    [\"vpsllw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F1 /r\"      , \"AVX\"],\n    [\"vpsllw\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 71 /6 ib\"   , \"AVX2\"],\n    [\"vpsllw\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F1 /r\"      , \"AVX2\"],\n    [\"vpsrad\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 72 /4 ib\"   , \"AVX\"],\n    [\"vpsrad\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E2 /r\"      , \"AVX\"],\n    [\"vpsrad\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 72 /4 ib\"   , \"AVX2\"],\n    [\"vpsrad\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E2 /r\"      , \"AVX2\"],\n    [\"vpsravd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 46 /r\"     , \"AVX2\"],\n    [\"vpsravd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 46 /r\"     , \"AVX2\"],\n    [\"vpsraw\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 71 /4 ib\"   , \"AVX\"],\n    [\"vpsraw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E1 /r\"      , \"AVX\"],\n    [\"vpsraw\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 71 /4 ib\"   , \"AVX2\"],\n    [\"vpsraw\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E1 /r\"      , \"AVX2\"],\n    [\"vpsrld\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 72 /2 ib\"   , \"AVX\"],\n    [\"vpsrld\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D2 /r\"      , \"AVX\"],\n    [\"vpsrld\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 72 /2 ib\"   , \"AVX2\"],\n    [\"vpsrld\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D2 /r\"      , \"AVX2\"],\n    [\"vpsrldq\"          , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 73 /3 ib\"   , \"AVX\"],\n    [\"vpsrldq\"          , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 73 /3 ib\"   , \"AVX2\"],\n    [\"vpsrlq\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 73 /2 ib\"   , \"AVX\"],\n    [\"vpsrlq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D3 /r\"      , \"AVX\"],\n    [\"vpsrlq\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 73 /2 ib\"   , \"AVX2\"],\n    [\"vpsrlq\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D3 /r\"      , \"AVX2\"],\n    [\"vpsrlvd\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 45 /r\"     , \"AVX2\"],\n    [\"vpsrlvd\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 45 /r\"     , \"AVX2\"],\n    [\"vpsrlvq\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 45 /r\"     , \"AVX2\"],\n    [\"vpsrlvq\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 45 /r\"     , \"AVX2\"],\n    [\"vpsrlw\"           , \"W:xmm, xmm, ib/ub\"                               , \"VMI\"     , \"VEX.128.66.0F.WIG 71 /2 ib\"   , \"AVX\"],\n    [\"vpsrlw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D1 /r\"      , \"AVX\"],\n    [\"vpsrlw\"           , \"W:ymm, ymm, ib/ub\"                               , \"VMI\"     , \"VEX.256.66.0F.WIG 71 /2 ib\"   , \"AVX2\"],\n    [\"vpsrlw\"           , \"W:ymm, ymm, xmm/m128\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D1 /r\"      , \"AVX2\"],\n    [\"vpsubb\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F8 /r\"      , \"AVX\"],\n    [\"vpsubb\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F8 /r\"      , \"AVX2\"],\n    [\"vpsubd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG FA /r\"      , \"AVX\"],\n    [\"vpsubd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG FA /r\"      , \"AVX2\"],\n    [\"vpsubq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG FB /r\"      , \"AVX\"],\n    [\"vpsubq\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG FB /r\"      , \"AVX2\"],\n    [\"vpsubsb\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E8 /r\"      , \"AVX\"],\n    [\"vpsubsb\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E8 /r\"      , \"AVX2\"],\n    [\"vpsubsw\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG E9 /r\"      , \"AVX\"],\n    [\"vpsubsw\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG E9 /r\"      , \"AVX2\"],\n    [\"vpsubusb\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D8 /r\"      , \"AVX\"],\n    [\"vpsubusb\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D8 /r\"      , \"AVX2\"],\n    [\"vpsubusw\"         , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG D9 /r\"      , \"AVX\"],\n    [\"vpsubusw\"         , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG D9 /r\"      , \"AVX2\"],\n    [\"vpsubw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG F9 /r\"      , \"AVX\"],\n    [\"vpsubw\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG F9 /r\"      , \"AVX2\"],\n    [\"vptest\"           , \"R:~xmm, ~xmm/m128\"                               , \"RM\"      , \"VEX.128.66.0F38.WIG 17 /r\"    , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vptest\"           , \"R:~ymm, ~ymm/m256\"                               , \"RM\"      , \"VEX.256.66.0F38.WIG 17 /r\"    , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vpunpckhbw\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 68 /r\"      , \"AVX\"],\n    [\"vpunpckhbw\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 68 /r\"      , \"AVX2\"],\n    [\"vpunpckhdq\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 6A /r\"      , \"AVX\"],\n    [\"vpunpckhdq\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 6A /r\"      , \"AVX2\"],\n    [\"vpunpckhqdq\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 6D /r\"      , \"AVX\"],\n    [\"vpunpckhqdq\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 6D /r\"      , \"AVX2\"],\n    [\"vpunpckhwd\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 69 /r\"      , \"AVX\"],\n    [\"vpunpckhwd\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 69 /r\"      , \"AVX2\"],\n    [\"vpunpcklbw\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 60 /r\"      , \"AVX\"],\n    [\"vpunpcklbw\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 60 /r\"      , \"AVX2\"],\n    [\"vpunpckldq\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 62 /r\"      , \"AVX\"],\n    [\"vpunpckldq\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 62 /r\"      , \"AVX2\"],\n    [\"vpunpcklqdq\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 6C /r\"      , \"AVX\"],\n    [\"vpunpcklqdq\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 6C /r\"      , \"AVX2\"],\n    [\"vpunpcklwd\"       , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 61 /r\"      , \"AVX\"],\n    [\"vpunpcklwd\"       , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 61 /r\"      , \"AVX2\"],\n    [\"vpxor\"            , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG EF /r\"      , \"AVX\"],\n    [\"vpxor\"            , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG EF /r\"      , \"AVX2\"],\n    [\"vrcpps\"           , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 53 /r\"         , \"AVX\"],\n    [\"vrcpps\"           , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 53 /r\"         , \"AVX\"],\n    [\"vrcpss\"           , \"W:xmm, xmm[127:32], xmm[31:0]/m32\"               , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 53 /r\"      , \"AVX\"],\n    [\"vroundpd\"         , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.66.0F3A.WIG 09 /r ib\" , \"AVX\"],\n    [\"vroundpd\"         , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.WIG 09 /r ib\" , \"AVX\"],\n    [\"vroundps\"         , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"VEX.128.66.0F3A.WIG 08 /r ib\" , \"AVX\"],\n    [\"vroundps\"         , \"W:ymm, ymm/m256, ib/ub\"                          , \"RMI\"     , \"VEX.256.66.0F3A.WIG 08 /r ib\" , \"AVX\"],\n    [\"vroundsd\"         , \"W:xmm, xmm[127:64], xmm[63:0]/m64, ib/ub\"        , \"RVMI\"    , \"VEX.LIG.66.0F3A.WIG 0B /r ib\" , \"AVX\"],\n    [\"vroundss\"         , \"W:xmm, xmm[127:32], xmm[31:0]/m32, ib/ub\"        , \"RVMI\"    , \"VEX.LIG.66.0F3A.WIG 0A /r ib\" , \"AVX\"],\n    [\"vrsqrtps\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 52 /r\"         , \"AVX\"],\n    [\"vrsqrtps\"         , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 52 /r\"         , \"AVX\"],\n    [\"vrsqrtss\"         , \"W:xmm, xmm[127:32], xmm[31:0]/m32\"               , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 52 /r\"      , \"AVX\"],\n    [\"vshufpd\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.66.0F.WIG C6 /r ib\"   , \"AVX\"],\n    [\"vshufpd\"          , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.66.0F.WIG C6 /r ib\"   , \"AVX\"],\n    [\"vshufps\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"VEX.128.0F.WIG C6 /r ib\"      , \"AVX\"],\n    [\"vshufps\"          , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI\"    , \"VEX.256.0F.WIG C6 /r ib\"      , \"AVX\"],\n    [\"vsqrtpd\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.66.0F.WIG 51 /r\"      , \"AVX\"],\n    [\"vsqrtpd\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.66.0F.WIG 51 /r\"      , \"AVX\"],\n    [\"vsqrtps\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"VEX.128.0F.WIG 51 /r\"         , \"AVX\"],\n    [\"vsqrtps\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"VEX.256.0F.WIG 51 /r\"         , \"AVX\"],\n    [\"vsqrtsd\"          , \"W:xmm, xmm[127:64], xmm[63:0]/m64\"               , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 51 /r\"      , \"AVX\"],\n    [\"vsqrtss\"          , \"W:xmm, xmm[127:32], xmm[31:0]/m32\"               , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 51 /r\"      , \"AVX\"],\n    [\"vsubpd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 5C /r\"      , \"AVX\"],\n    [\"vsubpd\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 5C /r\"      , \"AVX\"],\n    [\"vsubps\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 5C /r\"         , \"AVX\"],\n    [\"vsubps\"           , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 5C /r\"         , \"AVX\"],\n    [\"vsubsd\"           , \"W:xmm, xmm, xmm[63:0]/m64\"                       , \"RVM\"     , \"VEX.LIG.F2.0F.WIG 5C /r\"      , \"AVX\"],\n    [\"vsubss\"           , \"W:xmm, xmm, xmm[31:0]/m32\"                       , \"RVM\"     , \"VEX.LIG.F3.0F.WIG 5C /r\"      , \"AVX\"],\n    [\"vtestpd\"          , \"R:~xmm, ~xmm/m128\"                               , \"RM\"      , \"VEX.128.66.0F38.W0 0F /r\"     , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vtestpd\"          , \"R:~ymm, ~ymm/m256\"                               , \"RM\"      , \"VEX.256.66.0F38.W0 0F /r\"     , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vtestps\"          , \"R:~xmm, ~xmm/m128\"                               , \"RM\"      , \"VEX.128.66.0F38.W0 0E /r\"     , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vtestps\"          , \"R:~ymm, ~ymm/m256\"                               , \"RM\"      , \"VEX.256.66.0F38.W0 0E /r\"     , \"AVX OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"vucomisd\"         , \"R:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"VEX.LIG.66.0F.WIG 2E /r\"      , \"AVX OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vucomiss\"         , \"R:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"VEX.LIG.0F.WIG 2E /r\"         , \"AVX OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vunpckhpd\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 15 /r\"      , \"AVX\"],\n    [\"vunpckhpd\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 15 /r\"      , \"AVX\"],\n    [\"vunpckhps\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 15 /r\"         , \"AVX\"],\n    [\"vunpckhps\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 15 /r\"         , \"AVX\"],\n    [\"vunpcklpd\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 14 /r\"      , \"AVX\"],\n    [\"vunpcklpd\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 14 /r\"      , \"AVX\"],\n    [\"vunpcklps\"        , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 14 /r\"         , \"AVX\"],\n    [\"vunpcklps\"        , \"W:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 14 /r\"         , \"AVX\"],\n    [\"vxorpd\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F.WIG 57 /r\"      , \"AVX\"],\n    [\"vxorpd\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F.WIG 57 /r\"      , \"AVX\"],\n    [\"vxorps\"           , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM\"     , \"VEX.128.0F.WIG 57 /r\"         , \"AVX\"],\n    [\"vxorps\"           , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM\"     , \"VEX.256.0F.WIG 57 /r\"         , \"AVX\"],\n\n    [\"vldmxcsr\"         , \"R:m32\"                                           , \"M\"       , \"VEX.LZ.0F.WIG AE /2\"          , \"AVX\"],\n    [\"vstmxcsr\"         , \"W:m32\"                                           , \"M\"       , \"VEX.LZ.0F.WIG AE /3\"          , \"AVX\"],\n    [\"vzeroall\"         , \"\"                                                , \"NONE\"    , \"VEX.256.0F.WIG 77\"            , \"AVX Volatile\"],\n    [\"vzeroupper\"       , \"\"                                                , \"NONE\"    , \"VEX.128.0F.WIG 77\"            , \"AVX Volatile\"],\n\n    [\"vcvtph2ps\"        , \"W:xmm, xmm[63:0]/m64\"                            , \"RM\"      , \"VEX.128.66.0F38.W0 13 /r\"     , \"F16C\"],\n    [\"vcvtph2ps\"        , \"W:ymm, xmm/m128\"                                 , \"RM\"      , \"VEX.256.66.0F38.W0 13 /r\"     , \"F16C\"],\n    [\"vcvtps2ph\"        , \"W:xmm[63:0]/m64, xmm, ib/ub\"                     , \"MRI\"     , \"VEX.128.66.0F3A.W0 1D /r ib\"  , \"F16C\"],\n    [\"vcvtps2ph\"        , \"W:xmm/m128, ymm, ib/ub\"                          , \"MRI\"     , \"VEX.256.66.0F3A.W0 1D /r ib\"  , \"F16C\"],\n\n    [\"vfmadd132pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 98 /r\"     , \"FMA\"],\n    [\"vfmadd132pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 98 /r\"     , \"FMA\"],\n    [\"vfmadd132ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 98 /r\"     , \"FMA\"],\n    [\"vfmadd132ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 98 /r\"     , \"FMA\"],\n    [\"vfmadd132sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 99 /r\"     , \"FMA\"],\n    [\"vfmadd132ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 99 /r\"     , \"FMA\"],\n    [\"vfmadd213pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 A8 /r\"     , \"FMA\"],\n    [\"vfmadd213pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 A8 /r\"     , \"FMA\"],\n    [\"vfmadd213ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 A8 /r\"     , \"FMA\"],\n    [\"vfmadd213ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 A8 /r\"     , \"FMA\"],\n    [\"vfmadd213sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 A9 /r\"     , \"FMA\"],\n    [\"vfmadd213ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 A9 /r\"     , \"FMA\"],\n    [\"vfmadd231pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 B8 /r\"     , \"FMA\"],\n    [\"vfmadd231pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 B8 /r\"     , \"FMA\"],\n    [\"vfmadd231ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 B8 /r\"     , \"FMA\"],\n    [\"vfmadd231ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 B8 /r\"     , \"FMA\"],\n    [\"vfmadd231sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 B9 /r\"     , \"FMA\"],\n    [\"vfmadd231ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 B9 /r\"     , \"FMA\"],\n    [\"vfmaddsub132pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 96 /r\"     , \"FMA\"],\n    [\"vfmaddsub132pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 96 /r\"     , \"FMA\"],\n    [\"vfmaddsub132ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 96 /r\"     , \"FMA\"],\n    [\"vfmaddsub132ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 96 /r\"     , \"FMA\"],\n    [\"vfmaddsub213pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 A6 /r\"     , \"FMA\"],\n    [\"vfmaddsub213pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 A6 /r\"     , \"FMA\"],\n    [\"vfmaddsub213ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 A6 /r\"     , \"FMA\"],\n    [\"vfmaddsub213ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 A6 /r\"     , \"FMA\"],\n    [\"vfmaddsub231pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 B6 /r\"     , \"FMA\"],\n    [\"vfmaddsub231pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 B6 /r\"     , \"FMA\"],\n    [\"vfmaddsub231ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 B6 /r\"     , \"FMA\"],\n    [\"vfmaddsub231ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 B6 /r\"     , \"FMA\"],\n    [\"vfmsub132pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 9A /r\"     , \"FMA\"],\n    [\"vfmsub132pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 9A /r\"     , \"FMA\"],\n    [\"vfmsub132ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 9A /r\"     , \"FMA\"],\n    [\"vfmsub132ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 9A /r\"     , \"FMA\"],\n    [\"vfmsub132sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 9B /r\"     , \"FMA\"],\n    [\"vfmsub132ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 9B /r\"     , \"FMA\"],\n    [\"vfmsub213pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 AA /r\"     , \"FMA\"],\n    [\"vfmsub213pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 AA /r\"     , \"FMA\"],\n    [\"vfmsub213ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 AA /r\"     , \"FMA\"],\n    [\"vfmsub213ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 AA /r\"     , \"FMA\"],\n    [\"vfmsub213sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 AB /r\"     , \"FMA\"],\n    [\"vfmsub213ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 AB /r\"     , \"FMA\"],\n    [\"vfmsub231pd\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 BA /r\"     , \"FMA\"],\n    [\"vfmsub231pd\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 BA /r\"     , \"FMA\"],\n    [\"vfmsub231ps\"      , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 BA /r\"     , \"FMA\"],\n    [\"vfmsub231ps\"      , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 BA /r\"     , \"FMA\"],\n    [\"vfmsub231sd\"      , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 BB /r\"     , \"FMA\"],\n    [\"vfmsub231ss\"      , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 BB /r\"     , \"FMA\"],\n    [\"vfmsubadd132pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 97 /r\"     , \"FMA\"],\n    [\"vfmsubadd132pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 97 /r\"     , \"FMA\"],\n    [\"vfmsubadd132ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 97 /r\"     , \"FMA\"],\n    [\"vfmsubadd132ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 97 /r\"     , \"FMA\"],\n    [\"vfmsubadd213pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 A7 /r\"     , \"FMA\"],\n    [\"vfmsubadd213pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 A7 /r\"     , \"FMA\"],\n    [\"vfmsubadd213ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 A7 /r\"     , \"FMA\"],\n    [\"vfmsubadd213ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 A7 /r\"     , \"FMA\"],\n    [\"vfmsubadd231pd\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 B7 /r\"     , \"FMA\"],\n    [\"vfmsubadd231pd\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 B7 /r\"     , \"FMA\"],\n    [\"vfmsubadd231ps\"   , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 B7 /r\"     , \"FMA\"],\n    [\"vfmsubadd231ps\"   , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 B7 /r\"     , \"FMA\"],\n    [\"vfnmadd132pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 9C /r\"     , \"FMA\"],\n    [\"vfnmadd132pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 9C /r\"     , \"FMA\"],\n    [\"vfnmadd132ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 9C /r\"     , \"FMA\"],\n    [\"vfnmadd132ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 9C /r\"     , \"FMA\"],\n    [\"vfnmadd132sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 9D /r\"     , \"FMA\"],\n    [\"vfnmadd132ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 9D /r\"     , \"FMA\"],\n    [\"vfnmadd213pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 AC /r\"     , \"FMA\"],\n    [\"vfnmadd213pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 AC /r\"     , \"FMA\"],\n    [\"vfnmadd213ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 AC /r\"     , \"FMA\"],\n    [\"vfnmadd213ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 AC /r\"     , \"FMA\"],\n    [\"vfnmadd213sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 AD /r\"     , \"FMA\"],\n    [\"vfnmadd213ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 AD /r\"     , \"FMA\"],\n    [\"vfnmadd231pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 BC /r\"     , \"FMA\"],\n    [\"vfnmadd231pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 BC /r\"     , \"FMA\"],\n    [\"vfnmadd231ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 BC /r\"     , \"FMA\"],\n    [\"vfnmadd231ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 BC /r\"     , \"FMA\"],\n    [\"vfnmadd231sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 BD /r\"     , \"FMA\"],\n    [\"vfnmadd231ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 BD /r\"     , \"FMA\"],\n    [\"vfnmsub132pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 9E /r\"     , \"FMA\"],\n    [\"vfnmsub132pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 9E /r\"     , \"FMA\"],\n    [\"vfnmsub132ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 9E /r\"     , \"FMA\"],\n    [\"vfnmsub132ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 9E /r\"     , \"FMA\"],\n    [\"vfnmsub132sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 9F /r\"     , \"FMA\"],\n    [\"vfnmsub132ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 9F /r\"     , \"FMA\"],\n    [\"vfnmsub213pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 AE /r\"     , \"FMA\"],\n    [\"vfnmsub213pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 AE /r\"     , \"FMA\"],\n    [\"vfnmsub213ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 AE /r\"     , \"FMA\"],\n    [\"vfnmsub213ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 AE /r\"     , \"FMA\"],\n    [\"vfnmsub213sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 AF /r\"     , \"FMA\"],\n    [\"vfnmsub213ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 AF /r\"     , \"FMA\"],\n    [\"vfnmsub231pd\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W1 BE /r\"     , \"FMA\"],\n    [\"vfnmsub231pd\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W1 BE /r\"     , \"FMA\"],\n    [\"vfnmsub231ps\"     , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 BE /r\"     , \"FMA\"],\n    [\"vfnmsub231ps\"     , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 BE /r\"     , \"FMA\"],\n    [\"vfnmsub231sd\"     , \"x:xmm[63:0], xmm[63:0], xmm[63:0]/m64\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W1 BF /r\"     , \"FMA\"],\n    [\"vfnmsub231ss\"     , \"x:xmm[31:0], xmm[31:0], xmm[31:0]/m32\"           , \"RVM\"     , \"VEX.LIG.66.0F38.W0 BF /r\"     , \"FMA\"],\n\n    [\"vfmaddpd\"         , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 69 /r /is4\", \"FMA4\"],\n    [\"vfmaddpd\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 69 /r /is4\", \"FMA4\"],\n    [\"vfmaddpd\"         , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 69 /r /is4\", \"FMA4\"],\n    [\"vfmaddpd\"         , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 69 /r /is4\", \"FMA4\"],\n    [\"vfmaddps\"         , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 68 /r /is4\", \"FMA4\"],\n    [\"vfmaddps\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 68 /r /is4\", \"FMA4\"],\n    [\"vfmaddps\"         , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 68 /r /is4\", \"FMA4\"],\n    [\"vfmaddps\"         , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 68 /r /is4\", \"FMA4\"],\n    [\"vfmaddsd\"         , \"W:xmm[63:0], xmm[63:0], xmm[63:0], xmm[63:0]/m64\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 6b /r /is4\", \"FMA4\"],\n    [\"vfmaddsd\"         , \"W:xmm[63:0], xmm[63:0], xmm[63:0]/m64, xmm[63:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 6b /r /is4\", \"FMA4\"],\n    [\"vfmaddss\"         , \"W:xmm[31:0], xmm[31:0], xmm[31:0], xmm[31:0]/m32\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 6a /r /is4\", \"FMA4\"],\n    [\"vfmaddss\"         , \"W:xmm[31:0], xmm[31:0], xmm[31:0]/m32, xmm[31:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 6a /r /is4\", \"FMA4\"],\n    [\"vfmaddsubpd\"      , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 5D /r /is4\", \"FMA4\"],\n    [\"vfmaddsubpd\"      , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 5D /r /is4\", \"FMA4\"],\n    [\"vfmaddsubpd\"      , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 5D /r /is4\", \"FMA4\"],\n    [\"vfmaddsubpd\"      , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 5D /r /is4\", \"FMA4\"],\n    [\"vfmaddsubps\"      , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 5C /r /is4\", \"FMA4\"],\n    [\"vfmaddsubps\"      , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 5C /r /is4\", \"FMA4\"],\n    [\"vfmaddsubps\"      , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 5C /r /is4\", \"FMA4\"],\n    [\"vfmaddsubps\"      , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 5C /r /is4\", \"FMA4\"],\n    [\"vfmsubaddpd\"      , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 5F /r /is4\", \"FMA4\"],\n    [\"vfmsubaddpd\"      , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 5F /r /is4\", \"FMA4\"],\n    [\"vfmsubaddpd\"      , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 5F /r /is4\", \"FMA4\"],\n    [\"vfmsubaddpd\"      , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 5F /r /is4\", \"FMA4\"],\n    [\"vfmsubaddps\"      , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 5E /r /is4\", \"FMA4\"],\n    [\"vfmsubaddps\"      , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 5E /r /is4\", \"FMA4\"],\n    [\"vfmsubaddps\"      , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 5E /r /is4\", \"FMA4\"],\n    [\"vfmsubaddps\"      , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 5E /r /is4\", \"FMA4\"],\n    [\"vfmsubpd\"         , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 6D /r /is4\", \"FMA4\"],\n    [\"vfmsubpd\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 6D /r /is4\", \"FMA4\"],\n    [\"vfmsubpd\"         , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 6D /r /is4\", \"FMA4\"],\n    [\"vfmsubpd\"         , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 6D /r /is4\", \"FMA4\"],\n    [\"vfmsubps\"         , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 6C /r /is4\", \"FMA4\"],\n    [\"vfmsubps\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 6C /r /is4\", \"FMA4\"],\n    [\"vfmsubps\"         , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 6C /r /is4\", \"FMA4\"],\n    [\"vfmsubps\"         , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 6C /r /is4\", \"FMA4\"],\n    [\"vfmsubsd\"         , \"W:xmm[63:0], xmm[63:0], xmm[63:0], xmm[63:0]/m64\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 6F /r /is4\", \"FMA4\"],\n    [\"vfmsubsd\"         , \"W:xmm[63:0], xmm[63:0], xmm[63:0]/m64, xmm[63:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 6F /r /is4\", \"FMA4\"],\n    [\"vfmsubss\"         , \"W:xmm[31:0], xmm[31:0], xmm[31:0], xmm[31:0]/m32\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 6E /r /is4\", \"FMA4\"],\n    [\"vfmsubss\"         , \"W:xmm[31:0], xmm[31:0], xmm[31:0]/m32, xmm[31:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 6E /r /is4\", \"FMA4\"],\n    [\"vfnmaddpd\"        , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 79 /r /is4\", \"FMA4\"],\n    [\"vfnmaddpd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 79 /r /is4\", \"FMA4\"],\n    [\"vfnmaddpd\"        , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 79 /r /is4\", \"FMA4\"],\n    [\"vfnmaddpd\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 79 /r /is4\", \"FMA4\"],\n    [\"vfnmaddps\"        , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 78 /r /is4\", \"FMA4\"],\n    [\"vfnmaddps\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 78 /r /is4\", \"FMA4\"],\n    [\"vfnmaddps\"        , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 78 /r /is4\", \"FMA4\"],\n    [\"vfnmaddps\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 78 /r /is4\", \"FMA4\"],\n    [\"vfnmaddsd\"        , \"W:xmm[63:0], xmm[63:0], xmm[63:0], xmm[63:0]/m64\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 7B /r /is4\", \"FMA4\"],\n    [\"vfnmaddsd\"        , \"W:xmm[63:0], xmm[63:0], xmm[63:0]/m64, xmm[63:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 7B /r /is4\", \"FMA4\"],\n    [\"vfnmaddss\"        , \"W:xmm[31:0], xmm[31:0], xmm[31:0], xmm[31:0]/m32\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 7A /r /is4\", \"FMA4\"],\n    [\"vfnmaddss\"        , \"W:xmm[31:0], xmm[31:0], xmm[31:0]/m32, xmm[31:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 7A /r /is4\", \"FMA4\"],\n    [\"vfnmsubpd\"        , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 7D /r /is4\", \"FMA4\"],\n    [\"vfnmsubpd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 7D /r /is4\", \"FMA4\"],\n    [\"vfnmsubpd\"        , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 7D /r /is4\", \"FMA4\"],\n    [\"vfnmsubpd\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 7D /r /is4\", \"FMA4\"],\n    [\"vfnmsubps\"        , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"VEX.128.66.0F3A.W1 7C /r /is4\", \"FMA4\"],\n    [\"vfnmsubps\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"VEX.128.66.0F3A.W0 7C /r /is4\", \"FMA4\"],\n    [\"vfnmsubps\"        , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"VEX.256.66.0F3A.W1 7C /r /is4\", \"FMA4\"],\n    [\"vfnmsubps\"        , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"VEX.256.66.0F3A.W0 7C /r /is4\", \"FMA4\"],\n    [\"vfnmsubsd\"        , \"W:xmm[63:0], xmm[63:0], xmm[63:0], xmm[63:0]/m64\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 7F /r /is4\", \"FMA4\"],\n    [\"vfnmsubsd\"        , \"W:xmm[63:0], xmm[63:0], xmm[63:0]/m64, xmm[63:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 7F /r /is4\", \"FMA4\"],\n    [\"vfnmsubss\"        , \"W:xmm[31:0], xmm[31:0], xmm[31:0], xmm[31:0]/m32\", \"RVSM\"    , \"VEX.128.66.0F3A.W1 7E /r /is4\", \"FMA4\"],\n    [\"vfnmsubss\"        , \"W:xmm[31:0], xmm[31:0], xmm[31:0]/m32, xmm[31:0]\", \"RVMS\"    , \"VEX.128.66.0F3A.W0 7E /r /is4\", \"FMA4\"],\n\n    [\"vfrczpd\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 81 /r\"       , \"XOP\"],\n    [\"vfrczpd\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"XOP.L1.P0.M09.W0 81 /r\"       , \"XOP\"],\n    [\"vfrczps\"          , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 80 /r\"       , \"XOP\"],\n    [\"vfrczps\"          , \"W:ymm, ymm/m256\"                                 , \"RM\"      , \"XOP.L1.P0.M09.W0 80 /r\"       , \"XOP\"],\n    [\"vfrczsd\"          , \"W:xmm[63:0], xmm[63:0]/m64\"                      , \"RM\"      , \"XOP.L0.P0.M09.W0 83 /r\"       , \"XOP\"],\n    [\"vfrczss\"          , \"W:xmm[31:0], xmm[31:0]/m32\"                      , \"RM\"      , \"XOP.L0.P0.M09.W0 82 /r\"       , \"XOP\"],\n    [\"vpcmov\"           , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"XOP.L0.P0.M08.W1 A2 /r /is4\"  , \"XOP\"],\n    [\"vpcmov\"           , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 A2 /r /is4\"  , \"XOP\"],\n    [\"vpcmov\"           , \"W:ymm, ymm, ymm, ymm/m256\"                       , \"RVSM\"    , \"XOP.L1.P0.M08.W1 A2 /r /is4\"  , \"XOP\"],\n    [\"vpcmov\"           , \"W:ymm, ymm, ymm/m256, ymm\"                       , \"RVMS\"    , \"XOP.L1.P0.M08.W0 A2 /r /is4\"  , \"XOP\"],\n    [\"vpcomb\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 CC /r ib\"    , \"XOP\"],\n    [\"vpcomd\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 CE /r ib\"    , \"XOP\"],\n    [\"vpcomq\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 CF /r ib\"    , \"XOP\"],\n    [\"vpcomub\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 EC /r ib\"    , \"XOP\"],\n    [\"vpcomud\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 EE /r ib\"    , \"XOP\"],\n    [\"vpcomuq\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 EF /r ib\"    , \"XOP\"],\n    [\"vpcomuw\"          , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 ED /r ib\"    , \"XOP\"],\n    [\"vpcomw\"           , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI\"    , \"XOP.L0.P0.M08.W0 CD /r ib\"    , \"XOP\"],\n    [\"vpermil2pd\"       , \"W:xmm, xmm, xmm/m128, xmm, i4/u4\"                , \"RVMSI\"   , \"VEX.L0.66.0F3A.W0 49 /r /is4\" , \"XOP\"],\n    [\"vpermil2pd\"       , \"W:xmm, xmm, xmm, xmm/m128, i4/u4\"                , \"RVSMI\"   , \"VEX.L0.66.0F3A.W1 49 /r /is4\" , \"XOP\"],\n    [\"vpermil2pd\"       , \"W:ymm, ymm, ymm/m256, ymm, i4/u4\"                , \"RVMSI\"   , \"VEX.L1.66.0F3A.W0 49 /r /is4\" , \"XOP\"],\n    [\"vpermil2pd\"       , \"W:ymm, ymm, ymm, ymm/m256, i4/u4\"                , \"RVSMI\"   , \"VEX.L1.66.0F3A.W1 49 /r /is4\" , \"XOP\"],\n    [\"vpermil2ps\"       , \"W:xmm, xmm, xmm/m128, xmm, i4/u4\"                , \"RVMSI\"   , \"VEX.L0.66.0F3A.W0 48 /r /is4\" , \"XOP\"],\n    [\"vpermil2ps\"       , \"W:xmm, xmm, xmm, xmm/m128, i4/u4\"                , \"RVSMI\"   , \"VEX.L0.66.0F3A.W1 48 /r /is4\" , \"XOP\"],\n    [\"vpermil2ps\"       , \"W:ymm, ymm, ymm/m256, ymm, i4/u4\"                , \"RVMSI\"   , \"VEX.L1.66.0F3A.W0 48 /r /is4\" , \"XOP\"],\n    [\"vpermil2ps\"       , \"W:ymm, ymm, ymm, ymm/m256, i4/u4\"                , \"RVSMI\"   , \"VEX.L1.66.0F3A.W1 48 /r /is4\" , \"XOP\"],\n    [\"vphaddbd\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 C2 /r\"       , \"XOP\"],\n    [\"vphaddbq\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 C3 /r\"       , \"XOP\"],\n    [\"vphaddbw\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 C1 /r\"       , \"XOP\"],\n    [\"vphadddq\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 CB /r\"       , \"XOP\"],\n    [\"vphaddubd\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 D2 /r\"       , \"XOP\"],\n    [\"vphaddubq\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 D3 /r\"       , \"XOP\"],\n    [\"vphaddubw\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 D1 /r\"       , \"XOP\"],\n    [\"vphaddudq\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 DB /r\"       , \"XOP\"],\n    [\"vphadduwd\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 D6 /r\"       , \"XOP\"],\n    [\"vphadduwq\"        , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 D7 /r\"       , \"XOP\"],\n    [\"vphaddwd\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 C6 /r\"       , \"XOP\"],\n    [\"vphaddwq\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 C7 /r\"       , \"XOP\"],\n    [\"vphsubbw\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 E1 /r\"       , \"XOP\"],\n    [\"vphsubdq\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 E3 /r\"       , \"XOP\"],\n    [\"vphsubwd\"         , \"W:xmm, xmm/m128\"                                 , \"RM\"      , \"XOP.L0.P0.M09.W0 E2 /r\"       , \"XOP\"],\n    [\"vpmacsdd\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 9E /r /is4\"  , \"XOP\"],\n    [\"vpmacsdqh\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 9F /r /is4\"  , \"XOP\"],\n    [\"vpmacsdql\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 97 /r /is4\"  , \"XOP\"],\n    [\"vpmacssdd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 8E /r /is4\"  , \"XOP\"],\n    [\"vpmacssdqh\"       , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 8F /r /is4\"  , \"XOP\"],\n    [\"vpmacssdql\"       , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 87 /r /is4\"  , \"XOP\"],\n    [\"vpmacsswd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 86 /r /is4\"  , \"XOP\"],\n    [\"vpmacssww\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 85 /r /is4\"  , \"XOP\"],\n    [\"vpmacswd\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 96 /r /is4\"  , \"XOP\"],\n    [\"vpmacsww\"         , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 95 /r /is4\"  , \"XOP\"],\n    [\"vpmadcsswd\"       , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 A6 /r /is4\"  , \"XOP\"],\n    [\"vpmadcswd\"        , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 B6 /r /is4\"  , \"XOP\"],\n    [\"vpperm\"           , \"W:xmm, xmm, xmm, xmm/m128\"                       , \"RVSM\"    , \"XOP.L0.P0.M08.W1 A3 /r /is4\"  , \"XOP\"],\n    [\"vpperm\"           , \"W:xmm, xmm, xmm/m128, xmm\"                       , \"RVMS\"    , \"XOP.L0.P0.M08.W0 A3 /r /is4\"  , \"XOP\"],\n    [\"vprotb\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 90 /r\"       , \"XOP\"],\n    [\"vprotb\"           , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"XOP.L0.P0.M08.W0 C0 /r ib\"    , \"XOP\"],\n    [\"vprotb\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 90 /r\"       , \"XOP\"],\n    [\"vprotd\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 92 /r\"       , \"XOP\"],\n    [\"vprotd\"           , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"XOP.L0.P0.M08.W0 C2 /r ib\"    , \"XOP\"],\n    [\"vprotd\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 92 /r\"       , \"XOP\"],\n    [\"vprotq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 93 /r\"       , \"XOP\"],\n    [\"vprotq\"           , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"XOP.L0.P0.M08.W0 C3 /r ib\"    , \"XOP\"],\n    [\"vprotq\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 93 /r\"       , \"XOP\"],\n    [\"vprotw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 91 /r\"       , \"XOP\"],\n    [\"vprotw\"           , \"W:xmm, xmm/m128, ib/ub\"                          , \"RMI\"     , \"XOP.L0.P0.M08.W0 C1 /r ib\"    , \"XOP\"],\n    [\"vprotw\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 91 /r\"       , \"XOP\"],\n    [\"vpshab\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 98 /r\"       , \"XOP\"],\n    [\"vpshab\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 98 /r\"       , \"XOP\"],\n    [\"vpshad\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 9A /r\"       , \"XOP\"],\n    [\"vpshad\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 9A /r\"       , \"XOP\"],\n    [\"vpshaq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 9B /r\"       , \"XOP\"],\n    [\"vpshaq\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 9B /r\"       , \"XOP\"],\n    [\"vpshaw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 99 /r\"       , \"XOP\"],\n    [\"vpshaw\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 99 /r\"       , \"XOP\"],\n    [\"vpshlb\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 94 /r\"       , \"XOP\"],\n    [\"vpshlb\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 94 /r\"       , \"XOP\"],\n    [\"vpshld\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 96 /r\"       , \"XOP\"],\n    [\"vpshld\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 96 /r\"       , \"XOP\"],\n    [\"vpshlq\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 97 /r\"       , \"XOP\"],\n    [\"vpshlq\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 97 /r\"       , \"XOP\"],\n    [\"vpshlw\"           , \"W:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"XOP.L0.P0.M09.W1 95 /r\"       , \"XOP\"],\n    [\"vpshlw\"           , \"W:xmm, xmm/m128, xmm\"                            , \"RMV\"     , \"XOP.L0.P0.M09.W0 95 /r\"       , \"XOP\"],\n\n    [\"vpdpbusd\"         , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 50 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpbusd\"         , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 50 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpbusds\"        , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 51 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpbusds\"        , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 51 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpwssd\"         , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 52 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpwssd\"         , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 52 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpwssds\"        , \"X:xmm, xmm, xmm/m128\"                            , \"RVM\"     , \"VEX.128.66.0F38.W0 53 /r\"     , \"AVX_VNNI\"],\n    [\"vpdpwssds\"        , \"X:ymm, ymm, ymm/m256\"                            , \"RVM\"     , \"VEX.256.66.0F38.W0 53 /r\"     , \"AVX_VNNI\"],\n\n    [\"kaddb\"            , \"W:k[7:0] ,~k[7:0] ,~k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 4A /r\"        , \"AVX512_DQ\"],\n    [\"kaddd\"            , \"W:k[31:0],~k[31:0],~k[31:0]\"                     , \"RVM\"     , \"VEX.L1.66.0F.W1 4A /r\"        , \"AVX512_BW\"],\n    [\"kaddq\"            , \"W:k[63:0],~k[63:0],~k[63:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 4A /r\"           , \"AVX512_BW\"],\n    [\"kaddw\"            , \"W:k[15:0],~k[15:0],~k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 4A /r\"           , \"AVX512_DQ\"],\n    [\"kandb\"            , \"W:k[7:0] ,~k[7:0] ,~k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 41 /r\"        , \"AVX512_DQ\"],\n    [\"kandd\"            , \"W:k[31:0],~k[31:0],~k[31:0]\"                     , \"RVM\"     , \"VEX.L1.66.0F.W1 41 /r\"        , \"AVX512_BW\"],\n    [\"kandnb\"           , \"W:k[7:0] , k[7:0] , k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 42 /r\"        , \"AVX512_DQ\"],\n    [\"kandnd\"           , \"W:k[31:0], k[31:0], k[31:0]\"                     , \"RVM\"     , \"VEX.L1.66.0F.W1 42 /r\"        , \"AVX512_BW\"],\n    [\"kandnq\"           , \"W:k[63:0], k[63:0], k[63:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 42 /r\"           , \"AVX512_BW\"],\n    [\"kandnw\"           , \"W:k[15:0], k[15:0], k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 42 /r\"           , \"AVX512_F\"],\n    [\"kandq\"            , \"W:k[63:0],~k[63:0],~k[63:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 41 /r\"           , \"AVX512_BW\"],\n    [\"kandw\"            , \"W:k[15:0],~k[15:0],~k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 41 /r\"           , \"AVX512_F\"],\n    [\"kmovb\"            , \"W:k[7:0], k[7:0]/m8\"                             , \"RM\"      , \"VEX.L0.66.0F.W0 90 /r\"        , \"AVX512_DQ\"],\n    [\"kmovb\"            , \"W:k[7:0], r32[7:0]\"                              , \"RM\"      , \"VEX.L0.66.0F.W0 92 /r\"        , \"AVX512_DQ\"],\n    [\"kmovb\"            , \"W:m8, k[7:0]\"                                    , \"MR\"      , \"VEX.L0.66.0F.W0 91 /r\"        , \"AVX512_DQ\"],\n    [\"kmovb\"            , \"W:r32[7:0], k[7:0]\"                              , \"RM\"      , \"VEX.L0.66.0F.W0 93 /r\"        , \"AVX512_DQ\"],\n    [\"kmovd\"            , \"W:k[31:0], k[31:0]/m32\"                          , \"RM\"      , \"VEX.L0.66.0F.W1 90 /r\"        , \"AVX512_BW\"],\n    [\"kmovd\"            , \"W:k[31:0], r32[31:0]\"                            , \"RM\"      , \"VEX.L0.F2.0F.W0 92 /r\"        , \"AVX512_BW\"],\n    [\"kmovd\"            , \"W:m32, k[31:0]\"                                  , \"MR\"      , \"VEX.L0.66.0F.W1 91 /r\"        , \"AVX512_BW\"],\n    [\"kmovd\"            , \"W:r32[31:0], k[31:0]\"                            , \"RM\"      , \"VEX.L0.F2.0F.W0 93 /r\"        , \"AVX512_BW\"],\n    [\"kmovq\"            , \"W:k[63:0], k[63:0]/m64\"                          , \"RM\"      , \"VEX.L0.0F.W1 90 /r\"           , \"AVX512_BW\"],\n    [\"kmovq\"            , \"W:k[63:0], r64\"                                  , \"RM\"      , \"VEX.L0.F2.0F.W1 92 /r\"        , \"AVX512_BW X64\"],\n    [\"kmovq\"            , \"W:m64, k[63:0]\"                                  , \"MR\"      , \"VEX.L0.0F.W1 91 /r\"           , \"AVX512_BW\"],\n    [\"kmovq\"            , \"W:r64, k[63:0]\"                                  , \"RM\"      , \"VEX.L0.F2.0F.W1 93 /r\"        , \"AVX512_BW X64\"],\n    [\"kmovw\"            , \"W:k[15:0], k[15:0]/m16\"                          , \"RM\"      , \"VEX.L0.0F.W0 90 /r\"           , \"AVX512_F\"],\n    [\"kmovw\"            , \"W:k[15:0], r32[15:0]\"                            , \"RM\"      , \"VEX.L0.0F.W0 92 /r\"           , \"AVX512_F\"],\n    [\"kmovw\"            , \"W:m16, k[15:0]\"                                  , \"MR\"      , \"VEX.L0.0F.W0 91 /r\"           , \"AVX512_F\"],\n    [\"kmovw\"            , \"W:r32[15:0], k[15:0]\"                            , \"RM\"      , \"VEX.L0.0F.W0 93 /r\"           , \"AVX512_F\"],\n    [\"knotb\"            , \"W:k[7:0] , k[7:0]\"                               , \"RM\"      , \"VEX.L0.66.0F.W0 44 /r\"        , \"AVX512_DQ\"],\n    [\"knotd\"            , \"W:k[31:0], k[31:0]\"                              , \"RM\"      , \"VEX.L0.66.0F.W1 44 /r\"        , \"AVX512_BW\"],\n    [\"knotq\"            , \"W:k[63:0] , k[63:0]\"                             , \"RM\"      , \"VEX.L0.0F.W1 44 /r\"           , \"AVX512_BW\"],\n    [\"knotw\"            , \"W:k[15:0], k[15:0]\"                              , \"RM\"      , \"VEX.L0.0F.W0 44 /r\"           , \"AVX512_F\"],\n    [\"korb\"             , \"W:k[7:0] , ~k[7:0] , ~k[7:0]\"                    , \"RVM\"     , \"VEX.L1.66.0F.W0 45 /r\"        , \"AVX512_DQ\"],\n    [\"kord\"             , \"W:k[31:0], ~k[31:0], ~k[31:0]\"                   , \"RVM\"     , \"VEX.L1.66.0F.W1 45 /r\"        , \"AVX512_BW\"],\n    [\"korq\"             , \"W:k[63:0], ~k[63:0], ~k[63:0]\"                   , \"RVM\"     , \"VEX.L1.0F.W1 45 /r\"           , \"AVX512_BW\"],\n    [\"kortestb\"         , \"R:~k[7:0] , ~k[7:0]\"                             , \"RM\"      , \"VEX.L0.66.0F.W0 98 /r\"        , \"AVX512_DQ OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"kortestd\"         , \"R:~k[31:0], ~k[31:0]\"                            , \"RM\"      , \"VEX.L0.66.0F.W1 98 /r\"        , \"AVX512_BW OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"kortestq\"         , \"R:~k[63:0], ~k[63:0]\"                            , \"RM\"      , \"VEX.L0.0F.W1 98 /r\"           , \"AVX512_BW OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"kortestw\"         , \"R:~k[15:0], ~k[15:0]\"                            , \"RM\"      , \"VEX.L0.0F.W0 98 /r\"           , \"AVX512_F  OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"korw\"             , \"W:k[15:0], ~k[15:0], ~k[15:0]\"                   , \"RVM\"     , \"VEX.L1.0F.W0 45 /r\"           , \"AVX512_F\"],\n    [\"kshiftlb\"         , \"W:k[7:0] , k[7:0] , ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W0 32 /r ib\"   , \"AVX512_DQ\"],\n    [\"kshiftld\"         , \"W:k[31:0], k[31:0], ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W0 33 /r ib\"   , \"AVX512_BW\"],\n    [\"kshiftlq\"         , \"W:k[63:0], k[63:0] , ib/ub\"                      , \"RMI\"     , \"VEX.L0.66.0F3A.W1 33 /r ib\"   , \"AVX512_BW\"],\n    [\"kshiftlw\"         , \"W:k[15:0], k[15:0], ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W1 32 /r ib\"   , \"AVX512_F\"],\n    [\"kshiftrb\"         , \"W:k[7:0] , k[7:0] , ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W0 30 /r ib\"   , \"AVX512_DQ\"],\n    [\"kshiftrd\"         , \"W:k[31:0], k[31:0], ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W0 31 /r ib\"   , \"AVX512_BW\"],\n    [\"kshiftrq\"         , \"W:k[63:0], k[63:0], ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W1 31 /r ib\"   , \"AVX512_BW\"],\n    [\"kshiftrw\"         , \"W:k[15:0], k[15:0], ib/ub\"                       , \"RMI\"     , \"VEX.L0.66.0F3A.W1 30 /r ib\"   , \"AVX512_F\"],\n    [\"ktestb\"           , \"R:~k[7:0] , ~k[7:0]\"                             , \"RM\"      , \"VEX.L0.66.0F.W0 99 /r\"        , \"AVX512_DQ OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"ktestd\"           , \"R:~k[31:0], ~k[31:0]\"                            , \"RM\"      , \"VEX.L0.66.0F.W1 99 /r\"        , \"AVX512_BW OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"ktestq\"           , \"R:~k[63:0] , ~k[63:0]\"                           , \"RM\"      , \"VEX.L0.0F.W1 99 /r\"           , \"AVX512_BW OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"ktestw\"           , \"R:~k[15:0], ~k[15:0]\"                            , \"RM\"      , \"VEX.L0.0F.W0 99 /r\"           , \"AVX512_DQ OF=0 SF=0 ZF=W AF=0 PF=0 CF=W\"],\n    [\"kunpckbw\"         , \"W:k[15:0], k[7:0] , k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 4B /r\"        , \"AVX512_F\"],\n    [\"kunpckdq\"         , \"W:k[63:0], k[31:0], k[31:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 4B /r\"           , \"AVX512_BW\"],\n    [\"kunpckwd\"         , \"W:k[31:0], k[15:0], k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 4B /r\"           , \"AVX512_BW\"],\n    [\"kxnorb\"           , \"W:k[7:0] , k[7:0] , k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 46 /r\"        , \"AVX512_DQ\"],\n    [\"kxnord\"           , \"W:k[31:0], k[31:0], k[31:0]\"                     , \"RVM\"     , \"VEX.L1.66.0F.W1 46 /r\"        , \"AVX512_BW\"],\n    [\"kxnorq\"           , \"W:k[63:0], k[63:0], k[63:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 46 /r\"           , \"AVX512_BW\"],\n    [\"kxnorw\"           , \"W:k[15:0], k[15:0], k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 46 /r\"           , \"AVX512_F\"],\n    [\"kxorb\"            , \"W:k[7:0] ,~k[7:0] ,~k[7:0]\"                      , \"RVM\"     , \"VEX.L1.66.0F.W0 47 /r\"        , \"AVX512_DQ\"],\n    [\"kxord\"            , \"W:k[31:0],~k[31:0],~k[31:0]\"                     , \"RVM\"     , \"VEX.L1.66.0F.W1 47 /r\"        , \"AVX512_BW\"],\n    [\"kxorq\"            , \"W:k[63:0],~k[63:0],~k[63:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W1 47 /r\"           , \"AVX512_BW\"],\n    [\"kxorw\"            , \"W:k[15:0],~k[15:0],~k[15:0]\"                     , \"RVM\"     , \"VEX.L1.0F.W0 47 /r\"           , \"AVX512_F\"],\n\n    [\"v4fmaddps\"        , \"X:zmm {kz}, zmm, zmm+1, zmm+2, zmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.512.F2.0F38.W0 9A /r\"    , \"AVX512_4FMAPS\"],\n    [\"v4fmaddss\"        , \"X:xmm {kz}, xmm, xmm+1, xmm+2, xmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.LIG.F2.0F38.W0 9B /r\"    , \"AVX512_4FMAPS\"],\n    [\"v4fnmaddps\"       , \"X:zmm {kz}, zmm, zmm+1, zmm+2, zmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.512.F2.0F38.W0 AA /r\"    , \"AVX512_4FMAPS\"],\n    [\"v4fnmaddss\"       , \"X:xmm {kz}, xmm, xmm+1, xmm+2, xmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.LIG.F2.0F38.W0 AB /r\"    , \"AVX512_4FMAPS\"],\n    [\"vaddpd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 58 /r\"      , \"AVX512_F-VL\"],\n    [\"vaddpd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 58 /r\"      , \"AVX512_F-VL\"],\n    [\"vaddpd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 58 /r\"      , \"AVX512_F\"],\n    [\"vaddps\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 58 /r\"         , \"AVX512_F-VL\"],\n    [\"vaddps\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 58 /r\"         , \"AVX512_F-VL\"],\n    [\"vaddps\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.0F.W0 58 /r\"         , \"AVX512_F\"],\n    [\"vaddsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 58 /r\"      , \"AVX512_F\"],\n    [\"vaddss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 58 /r\"      , \"AVX512_F\"],\n    [\"vaesdec\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG DE /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesdec\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG DE /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesdec\"          , \"W:zmm, zmm, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG DE /r\"   , \"AVX512_F    VAES\"],\n    [\"vaesdeclast\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG DF /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesdeclast\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG DF /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesdeclast\"      , \"W:zmm, zmm, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG DF /r\"   , \"AVX512_F    VAES\"],\n    [\"vaesenc\"          , \"W:xmm, xmm, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG DC /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesenc\"          , \"W:ymm, ymm, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG DC /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesenc\"          , \"W:zmm, zmm, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG DC /r\"   , \"AVX512_F    VAES\"],\n    [\"vaesenclast\"      , \"W:xmm, xmm, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG DD /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesenclast\"      , \"W:ymm, ymm, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG DD /r\"   , \"AVX512_F-VL VAES\"],\n    [\"vaesenclast\"      , \"W:zmm, zmm, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG DD /r\"   , \"AVX512_F    VAES\"],\n    [\"valignd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 03 /r ib\" , \"AVX512_F-VL\"],\n    [\"valignd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 03 /r ib\" , \"AVX512_F-VL\"],\n    [\"valignd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 03 /r ib\" , \"AVX512_F\"],\n    [\"valignq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 03 /r ib\" , \"AVX512_F-VL\"],\n    [\"valignq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 03 /r ib\" , \"AVX512_F-VL\"],\n    [\"valignq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 03 /r ib\" , \"AVX512_F\"],\n    [\"vandnpd\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 55 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vandnpd\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 55 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vandnpd\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 55 /r\"      , \"AVX512_DQ\"],\n    [\"vandnps\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.W0 55 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vandnps\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.W0 55 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vandnps\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.W0 55 /r\"         , \"AVX512_DQ\"],\n    [\"vandpd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 54 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vandpd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 54 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vandpd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 54 /r\"      , \"AVX512_DQ\"],\n    [\"vandps\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 54 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vandps\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 54 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vandps\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.0F.W0 54 /r\"         , \"AVX512_DQ\"],\n    [\"vblendmpd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 65 /r\"    , \"AVX512_F-VL\"],\n    [\"vblendmpd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 65 /r\"    , \"AVX512_F-VL\"],\n    [\"vblendmpd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 65 /r\"    , \"AVX512_F\"],\n    [\"vblendmps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 65 /r\"    , \"AVX512_F-VL\"],\n    [\"vblendmps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 65 /r\"    , \"AVX512_F-VL\"],\n    [\"vblendmps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 65 /r\"    , \"AVX512_F\"],\n    [\"vbroadcastf32x2\"  , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-T2\"   , \"EVEX.256.66.0F38.W0 19 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vbroadcastf32x2\"  , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-T2\"   , \"EVEX.512.66.0F38.W0 19 /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcastf32x4\"  , \"W:ymm {kz}, m128\"                                , \"RM-T4\"   , \"EVEX.256.66.0F38.W0 1A /r\"    , \"AVX512_F\"],\n    [\"vbroadcastf32x4\"  , \"W:zmm {kz}, m128\"                                , \"RM-T4\"   , \"EVEX.512.66.0F38.W0 1A /r\"    , \"AVX512_F\"],\n    [\"vbroadcastf32x8\"  , \"W:zmm {kz}, m256\"                                , \"RM-T8\"   , \"EVEX.512.66.0F38.W0 1B /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcastf64x2\"  , \"W:ymm {kz}, m128\"                                , \"RM-T2\"   , \"EVEX.256.66.0F38.W1 1A /r\"    , \"AVX512_DQ-VL\"],\n    [\"vbroadcastf64x2\"  , \"W:zmm {kz}, m128\"                                , \"RM-T2\"   , \"EVEX.512.66.0F38.W1 1A /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcastf64x4\"  , \"W:zmm {kz}, m256\"                                , \"RM-T4\"   , \"EVEX.512.66.0F38.W1 1B /r\"    , \"AVX512_F\"],\n    [\"vbroadcasti32x2\"  , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-T2\"   , \"EVEX.128.66.0F38.W0 59 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vbroadcasti32x2\"  , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-T2\"   , \"EVEX.256.66.0F38.W0 59 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vbroadcasti32x2\"  , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-T2\"   , \"EVEX.512.66.0F38.W0 59 /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcasti32x4\"  , \"W:ymm {kz}, m128\"                                , \"RM-T4\"   , \"EVEX.256.66.0F38.W0 5A /r\"    , \"AVX512_F-VL\"],\n    [\"vbroadcasti32x4\"  , \"W:zmm {kz}, m128\"                                , \"RM-T4\"   , \"EVEX.512.66.0F38.W0 5A /r\"    , \"AVX512_F\"],\n    [\"vbroadcasti32x8\"  , \"W:zmm {kz}, m256\"                                , \"RM-T8\"   , \"EVEX.512.66.0F38.W0 5B /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcasti64x2\"  , \"W:ymm {kz}, m128\"                                , \"RM-T2\"   , \"EVEX.256.66.0F38.W1 5A /r\"    , \"AVX512_DQ-VL\"],\n    [\"vbroadcasti64x2\"  , \"W:zmm {kz}, m128\"                                , \"RM-T2\"   , \"EVEX.512.66.0F38.W1 5A /r\"    , \"AVX512_DQ\"],\n    [\"vbroadcasti64x4\"  , \"W:zmm {kz}, m256\"                                , \"RM-T4\"   , \"EVEX.512.66.0F38.W1 5B /r\"    , \"AVX512_F\"],\n    [\"vbroadcastsd\"     , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 19 /r\"    , \"AVX512_F-VL\"],\n    [\"vbroadcastsd\"     , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 19 /r\"    , \"AVX512_F\"],\n    [\"vbroadcastss\"     , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 18 /r\"    , \"AVX512_F-VL\"],\n    [\"vbroadcastss\"     , \"W:ymm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 18 /r\"    , \"AVX512_F-VL\"],\n    [\"vbroadcastss\"     , \"W:zmm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 18 /r\"    , \"AVX512_F\"],\n    [\"vcmppd\"           , \"W:k {kz}, xmm, xmm/m128/b64, ib/ub\"              , \"RVMI-FV\" , \"EVEX.128.66.0F.W1 C2 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vcmppd\"           , \"W:k {kz}, ymm, ymm/m256/b64, ib/ub\"              , \"RVMI-FV\" , \"EVEX.256.66.0F.W1 C2 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vcmppd\"           , \"W:k {kz}, zmm, zmm/m512/b64, ib/ub {sae}\"        , \"RVMI-FV\" , \"EVEX.512.66.0F.W1 C2 /r ib\"   , \"AVX512_F\"],\n    [\"vcmpps\"           , \"W:k {kz}, xmm, xmm/m128/b32, ib/ub\"              , \"RVMI-FV\" , \"EVEX.128.0F.W0 C2 /r ib\"      , \"AVX512_F-VL\"],\n    [\"vcmpps\"           , \"W:k {kz}, ymm, ymm/m256/b32, ib/ub\"              , \"RVMI-FV\" , \"EVEX.256.0F.W0 C2 /r ib\"      , \"AVX512_F-VL\"],\n    [\"vcmpps\"           , \"W:k {kz}, zmm, zmm/m512/b32, ib/ub {sae}\"        , \"RVMI-FV\" , \"EVEX.512.0F.W0 C2 /r ib\"      , \"AVX512_F\"],\n    [\"vcmpsd\"           , \"W:k {kz}, xmm, xmm[63:0]/m64, ib/ub {sae}\"       , \"RVMI-T1S\", \"EVEX.LIG.F2.0F.W1 C2 /r ib\"   , \"AVX512_F\"],\n    [\"vcmpss\"           , \"W:k {kz}, xmm, xmm[31:0]/m32, ib/ub {sae}\"       , \"RVMI-T1S\", \"EVEX.LIG.F3.0F.W0 C2 /r ib\"   , \"AVX512_F\"],\n    [\"vcomisd\"          , \"R:xmm[63:0], xmm[63:0]/m64 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.66.0F.W1 2F /r\"      , \"AVX512_F OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vcomiss\"          , \"R:xmm[31:0], xmm[31:0]/m32 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.0F.W0 2F /r\"         , \"AVX512_F OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vcompresspd\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 8A /r\"    , \"AVX512_F-VL\"],\n    [\"vcompresspd\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 8A /r\"    , \"AVX512_F-VL\"],\n    [\"vcompresspd\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 8A /r\"    , \"AVX512_F\"],\n    [\"vcompressps\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 8A /r\"    , \"AVX512_F-VL\"],\n    [\"vcompressps\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 8A /r\"    , \"AVX512_F-VL\"],\n    [\"vcompressps\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 8A /r\"    , \"AVX512_F\"],\n    [\"vcvtdq2pd\"        , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.F3.0F.W0 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtdq2pd\"        , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.F3.0F.W0 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtdq2pd\"        , \"W:zmm {kz}, ymm/m256/b32\"                        , \"RM-HV\"   , \"EVEX.512.F3.0F.W0 E6 /r\"      , \"AVX512_F\"],\n    [\"vcvtdq2ps\"        , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.0F.W0 5B /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtdq2ps\"        , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.0F.W0 5B /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtdq2ps\"        , \"W:zmm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.0F.W0 5B /r\"         , \"AVX512_F\"],\n    [\"vcvtne2ps2bf16\"   , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F2.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtne2ps2bf16\"   , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F2.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtne2ps2bf16\"   , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.F2.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtneps2bf16\"    , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.F3.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtneps2bf16\"    , \"W:xmm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.F3.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtneps2bf16\"    , \"W:ymm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.F3.0F38.W0 72 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vcvtpd2ps\"        , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.66.0F.W1 5A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtpd2ps\"        , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 5A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtpd2ps\"        , \"W:ymm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.0F.W1 5A /r\"      , \"AVX512_F\"],\n    [\"vcvtpd2dq\"        , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.F2.0F.W1 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtpd2dq\"        , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.F2.0F.W1 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtpd2dq\"        , \"W:ymm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.0F.W1 E6 /r\"      , \"AVX512_F\"],\n    [\"vcvtpd2qq\"        , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W1 7B /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtpd2qq\"        , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 7B /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtpd2qq\"        , \"W:zmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.0F.W1 7B /r\"      , \"AVX512_DQ\"],\n    [\"vcvtpd2udq\"       , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.0F.W1 79 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtpd2udq\"       , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.0F.W1 79 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtpd2udq\"       , \"W:ymm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.0F.W1 79 /r\"         , \"AVX512_F\"],\n    [\"vcvtpd2uqq\"       , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W1 79 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtpd2uqq\"       , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 79 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtpd2uqq\"       , \"W:zmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.0F.W1 79 /r\"      , \"AVX512_DQ\"],\n    [\"vcvtph2ps\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.W0 13 /r\"    , \"AVX512_F-VL\"],\n    [\"vcvtph2ps\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.W0 13 /r\"    , \"AVX512_F-VL\"],\n    [\"vcvtph2ps\"        , \"W:zmm {kz}, ymm/m256 {sae}\"                      , \"RM-HVM\"  , \"EVEX.512.66.0F38.W0 13 /r\"    , \"AVX512_F\"],\n    [\"vcvtps2dq\"        , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W0 5B /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtps2dq\"        , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W0 5B /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtps2dq\"        , \"W:zmm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.0F.W0 5B /r\"      , \"AVX512_F\"],\n    [\"vcvtps2pd\"        , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.0F.W0 5A /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtps2pd\"        , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.0F.W0 5A /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtps2pd\"        , \"W:zmm {kz}, ymm/m256/b32 {er}\"                   , \"RM-HV\"   , \"EVEX.512.0F.W0 5A /r\"         , \"AVX512_F\"],\n    [\"vcvtps2ph\"        , \"W:xmm[63:0]/m64  {kz}, xmm, ib/ub\"               , \"MRI-HVM\" , \"EVEX.128.66.0F3A.W0 1D /r ib\" , \"AVX512_F-VL\"],\n    [\"vcvtps2ph\"        , \"W:xmm/m128 {kz}, ymm, ib/ub\"                     , \"MRI-HVM\" , \"EVEX.256.66.0F3A.W0 1D /r ib\" , \"AVX512_F-VL\"],\n    [\"vcvtps2ph\"        , \"W:ymm/m256 {kz}, zmm, ib/ub {sae}\"               , \"MRI-HVM\" , \"EVEX.512.66.0F3A.W0 1D /r ib\" , \"AVX512_F\"],\n    [\"vcvtps2qq\"        , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.66.0F.W0 7B /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtps2qq\"        , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.66.0F.W0 7B /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtps2qq\"        , \"W:zmm {kz}, ymm/m256/b32 {er}\"                   , \"RM-HV\"   , \"EVEX.512.66.0F.W0 7B /r\"      , \"AVX512_DQ\"],\n    [\"vcvtps2udq\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.0F.W0 79 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtps2udq\"       , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.0F.W0 79 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvtps2udq\"       , \"W:zmm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.0F.W0 79 /r\"         , \"AVX512_F\"],\n    [\"vcvtps2uqq\"       , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.66.0F.W0 79 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtps2uqq\"       , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.66.0F.W0 79 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtps2uqq\"       , \"W:zmm {kz}, ymm/m256/b32 {er}\"                   , \"RM-HV\"   , \"EVEX.512.66.0F.W0 79 /r\"      , \"AVX512_DQ\"],\n    [\"vcvtqq2pd\"        , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.F3.0F.W1 E6 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtqq2pd\"        , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.F3.0F.W1 E6 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtqq2pd\"        , \"W:zmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F3.0F.W1 E6 /r\"      , \"AVX512_DQ\"],\n    [\"vcvtqq2ps\"        , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.0F.W1 5B /r\"         , \"AVX512_DQ-VL\"],\n    [\"vcvtqq2ps\"        , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.0F.W1 5B /r\"         , \"AVX512_DQ-VL\"],\n    [\"vcvtqq2ps\"        , \"W:ymm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.0F.W1 5B /r\"         , \"AVX512_DQ\"],\n    [\"vcvtsd2si\"        , \"W:r32, xmm[63:0]/m64 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W0 2D /r\"      , \"AVX512_F\"],\n    [\"vcvtsd2si\"        , \"W:r64, xmm[63:0]/m64 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W1 2D /r\"      , \"AVX512_F X64\"],\n    [\"vcvtsd2ss\"        , \"W:xmm {kz}, xmm[127:32], xmm[63:0]/m64 {er}\"     , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 5A /r\"      , \"AVX512_F\"],\n    [\"vcvtsd2usi\"       , \"W:r32, xmm[63:0]/m64 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W0 79 /r\"      , \"AVX512_F\"],\n    [\"vcvtsd2usi\"       , \"W:r64, xmm[63:0]/m64 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W1 79 /r\"      , \"AVX512_F X64\"],\n    [\"vcvtsi2sd\"        , \"W:xmm, xmm[127:64], r32/m32 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W0 2A /r\"      , \"AVX512_F\"],\n    [\"vcvtsi2sd\"        , \"W:xmm, xmm[127:64], r64/m64 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 2A /r\"      , \"AVX512_F X64\"],\n    [\"vcvtsi2ss\"        , \"W:xmm, xmm[127:32], r32/m32 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 2A /r\"      , \"AVX512_F\"],\n    [\"vcvtsi2ss\"        , \"W:xmm, xmm[127:32], r64/m64 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W1 2A /r\"      , \"AVX512_F X64\"],\n    [\"vcvtss2sd\"        , \"W:xmm {kz}, xmm[127:64], xmm[31:0]/m32 {sae}\"    , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 5A /r\"      , \"AVX512_F\"],\n    [\"vcvtss2si\"        , \"W:r32, xmm[31:0]/m32 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W0 2D /r\"      , \"AVX512_F\"],\n    [\"vcvtss2si\"        , \"W:r64, xmm[31:0]/m32 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W1 2D /r\"      , \"AVX512_F X64\"],\n    [\"vcvtss2usi\"       , \"W:r32, xmm[31:0]/m32 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W0 79 /r\"      , \"AVX512_F\"],\n    [\"vcvtss2usi\"       , \"W:r64, xmm[31:0]/m32 {er}\"                       , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W1 79 /r\"      , \"AVX512_F X64\"],\n    [\"vcvttpd2dq\"       , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.66.0F.W1 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttpd2dq\"       , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 E6 /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttpd2dq\"       , \"W:ymm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F.W1 E6 /r\"      , \"AVX512_F\"],\n    [\"vcvttpd2qq\"       , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W1 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttpd2qq\"       , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttpd2qq\"       , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F.W1 7A /r\"      , \"AVX512_F\"],\n    [\"vcvttpd2udq\"      , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.0F.W1 78 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvttpd2udq\"      , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.0F.W1 78 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvttpd2udq\"      , \"W:ymm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.0F.W1 78 /r\"         , \"AVX512_F\"],\n    [\"vcvttpd2uqq\"      , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W1 78 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttpd2uqq\"      , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 78 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttpd2uqq\"      , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F.W1 78 /r\"      , \"AVX512_DQ\"],\n    [\"vcvttps2dq\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.F3.0F.W0 5B /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttps2dq\"       , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.F3.0F.W0 5B /r\"      , \"AVX512_F-VL\"],\n    [\"vcvttps2dq\"       , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.F3.0F.W0 5B /r\"      , \"AVX512_F\"],\n    [\"vcvttps2qq\"       , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.66.0F.W0 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttps2qq\"       , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.66.0F.W0 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttps2qq\"       , \"W:zmm {kz}, ymm/m256/b32 {sae}\"                  , \"RM-HV\"   , \"EVEX.512.66.0F.W0 7A /r\"      , \"AVX512_DQ\"],\n    [\"vcvttps2udq\"      , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.0F.W0 78 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvttps2udq\"      , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.0F.W0 78 /r\"         , \"AVX512_F-VL\"],\n    [\"vcvttps2udq\"      , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.0F.W0 78 /r\"         , \"AVX512_F\"],\n    [\"vcvttps2uqq\"      , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.66.0F.W0 78 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttps2uqq\"      , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.66.0F.W0 78 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvttps2uqq\"      , \"W:zmm {kz}, ymm/m256/b32 {sae}\"                  , \"RM-HV\"   , \"EVEX.512.66.0F.W0 78 /r\"      , \"AVX512_DQ\"],\n    [\"vcvttsd2si\"       , \"W:r32, xmm[63:0]/m64 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W0 2C /r\"      , \"AVX512_F\"],\n    [\"vcvttsd2si\"       , \"W:r64, xmm[63:0]/m64 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W1 2C /r\"      , \"AVX512_F X64\"],\n    [\"vcvttsd2usi\"      , \"W:r32, xmm[63:0]/m64 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W0 78 /r\"      , \"AVX512_F\"],\n    [\"vcvttsd2usi\"      , \"W:r64, xmm[63:0]/m64 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F2.0F.W1 78 /r\"      , \"AVX512_F X64\"],\n    [\"vcvttss2si\"       , \"W:r32, xmm[31:0]/m32 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W0 2C /r\"      , \"AVX512_F\"],\n    [\"vcvttss2si\"       , \"W:r64, xmm[31:0]/m32 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W1 2C /r\"      , \"AVX512_F X64\"],\n    [\"vcvttss2usi\"      , \"W:r32, xmm[31:0]/m32 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W0 78 /r\"      , \"AVX512_F\"],\n    [\"vcvttss2usi\"      , \"W:r64, xmm[31:0]/m32 {sae}\"                      , \"RM-T1F\"  , \"EVEX.LIG.F3.0F.W1 78 /r\"      , \"AVX512_F X64\"],\n    [\"vcvtudq2pd\"       , \"W:xmm {kz}, xmm[63:0]/m64/b32\"                   , \"RM-HV\"   , \"EVEX.128.F3.0F.W0 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtudq2pd\"       , \"W:ymm {kz}, xmm/m128/b32\"                        , \"RM-HV\"   , \"EVEX.256.F3.0F.W0 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtudq2pd\"       , \"W:zmm {kz}, ymm/m256/b32\"                        , \"RM-HV\"   , \"EVEX.512.F3.0F.W0 7A /r\"      , \"AVX512_F\"],\n    [\"vcvtudq2ps\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.F2.0F.W0 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtudq2ps\"       , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.F2.0F.W0 7A /r\"      , \"AVX512_F-VL\"],\n    [\"vcvtudq2ps\"       , \"W:zmm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.0F.W0 7A /r\"      , \"AVX512_F\"],\n    [\"vcvtuqq2pd\"       , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.F3.0F.W1 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtuqq2pd\"       , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.F3.0F.W1 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtuqq2pd\"       , \"W:zmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F3.0F.W1 7A /r\"      , \"AVX512_DQ\"],\n    [\"vcvtuqq2ps\"       , \"W:xmm[63:0] {kz}, xmm/m128/b64\"                  , \"RM-FV\"   , \"EVEX.128.F2.0F.W1 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtuqq2ps\"       , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.F2.0F.W1 7A /r\"      , \"AVX512_DQ-VL\"],\n    [\"vcvtuqq2ps\"       , \"W:ymm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.0F.W1 7A /r\"      , \"AVX512_DQ\"],\n    [\"vcvtusi2sd\"       , \"W:xmm, xmm[127:64], r32/m32 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W0 7B /r\"      , \"AVX512_F\"],\n    [\"vcvtusi2sd\"       , \"W:xmm, xmm[127:64], r64/m64 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 7B /r\"      , \"AVX512_F X64\"],\n    [\"vcvtusi2ss\"       , \"W:xmm, xmm[127:32], r32/m32 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 7B /r\"      , \"AVX512_F\"],\n    [\"vcvtusi2ss\"       , \"W:xmm, xmm[127:32], r64/m64 {er}\"                , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W1 7B /r\"      , \"AVX512_F X64\"],\n    [\"vdbpsadbw\"        , \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W0 42 /r ib\" , \"AVX512_BW-VL\"],\n    [\"vdbpsadbw\"        , \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W0 42 /r ib\" , \"AVX512_BW-VL\"],\n    [\"vdbpsadbw\"        , \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W0 42 /r ib\" , \"AVX512_BW\"],\n    [\"vdivpd\"           , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 5E /r\"      , \"AVX512_F-VL\"],\n    [\"vdivpd\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 5E /r\"      , \"AVX512_F-VL\"],\n    [\"vdivpd\"           , \"W:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 5E /r\"      , \"AVX512_F\"],\n    [\"vdivps\"           , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 5E /r\"         , \"AVX512_F-VL\"],\n    [\"vdivps\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 5E /r\"         , \"AVX512_F-VL\"],\n    [\"vdivps\"           , \"W:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.0F.W0 5E /r\"         , \"AVX512_F\"],\n    [\"vdivsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 5E /r\"      , \"AVX512_F\"],\n    [\"vdivss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 5E /r\"      , \"AVX512_F\"],\n    [\"vdpbf16ps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F3.0F38.W0 52 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vdpbf16ps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F3.0F38.W0 52 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vdpbf16ps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.F3.0F38.W0 52 /r\"    , \"AVX512_BF16-VL\"],\n    [\"vexp2pd\"          , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 C8 /r\"    , \"AVX512_ERI\"],\n    [\"vexp2ps\"          , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 C8 /r\"    , \"AVX512_ERI\"],\n    [\"vexpandpd\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 88 /r\"    , \"AVX512_F-VL\"],\n    [\"vexpandpd\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 88 /r\"    , \"AVX512_F-VL\"],\n    [\"vexpandpd\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 88 /r\"    , \"AVX512_F\"],\n    [\"vexpandps\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 88 /r\"    , \"AVX512_F-VL\"],\n    [\"vexpandps\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 88 /r\"    , \"AVX512_F-VL\"],\n    [\"vexpandps\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 88 /r\"    , \"AVX512_F\"],\n    [\"vextractf32x4\"    , \"W:xmm/m128 {kz}, ymm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.256.66.0F3A.W0 19 /r ib\" , \"AVX512_F-VL\"],\n    [\"vextractf32x4\"    , \"W:xmm/m128 {kz}, zmm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.512.66.0F3A.W0 19 /r ib\" , \"AVX512_F\"],\n    [\"vextractf32x8\"    , \"W:ymm/m256 {kz}, zmm, ib/ub\"                     , \"MRI-T8\"  , \"EVEX.512.66.0F3A.W0 1B /r ib\" , \"AVX512_DQ\"],\n    [\"vextractf64x2\"    , \"W:xmm/m128 {kz}, ymm, ib/ub\"                     , \"MRI-T2\"  , \"EVEX.256.66.0F3A.W1 19 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vextractf64x2\"    , \"W:xmm/m128 {kz}, zmm, ib/ub\"                     , \"MRI-T2\"  , \"EVEX.512.66.0F3A.W1 19 /r ib\" , \"AVX512_DQ\"],\n    [\"vextractf64x4\"    , \"W:ymm/m256 {kz}, zmm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.512.66.0F3A.W1 1B /r ib\" , \"AVX512_F\"],\n    [\"vextracti32x4\"    , \"W:xmm/m128 {kz}, ymm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.256.66.0F3A.W0 39 /r ib\" , \"AVX512_F-VL\"],\n    [\"vextracti32x4\"    , \"W:xmm/m128 {kz}, zmm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.512.66.0F3A.W0 39 /r ib\" , \"AVX512_F\"],\n    [\"vextracti32x8\"    , \"W:ymm/m256 {kz}, zmm, ib/ub\"                     , \"MRI-T8\"  , \"EVEX.512.66.0F3A.W0 3B /r ib\" , \"AVX512_DQ\"],\n    [\"vextracti64x2\"    , \"W:xmm/m128 {kz}, ymm, ib/ub\"                     , \"MRI-T2\"  , \"EVEX.256.66.0F3A.W1 39 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vextracti64x2\"    , \"W:xmm/m128 {kz}, zmm, ib/ub\"                     , \"MRI-T2\"  , \"EVEX.512.66.0F3A.W1 39 /r ib\" , \"AVX512_DQ\"],\n    [\"vextracti64x4\"    , \"W:ymm/m256 {kz}, zmm, ib/ub\"                     , \"MRI-T4\"  , \"EVEX.512.66.0F3A.W1 3B /r ib\" , \"AVX512_F\"],\n    [\"vextractps\"       , \"W:r32[31:0]/m32, xmm, ib/ub\"                     , \"MRI-T1S\" , \"EVEX.128.66.0F3A.WIG 17 /r ib\", \"AVX512_F\"],\n    [\"vfixupimmpd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 54 /r ib\" , \"AVX512_F-VL\"],\n    [\"vfixupimmpd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 54 /r ib\" , \"AVX512_F-VL\"],\n    [\"vfixupimmpd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64, ib/ub {sae}\"      , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 54 /r ib\" , \"AVX512_F\"],\n    [\"vfixupimmps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 54 /r ib\" , \"AVX512_F-VL\"],\n    [\"vfixupimmps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 54 /r ib\" , \"AVX512_F-VL\"],\n    [\"vfixupimmps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32, ib/ub {sae}\"      , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 54 /r ib\" , \"AVX512_F\"],\n    [\"vfixupimmsd\"      , \"X:xmm {kz},xmm[127:64],xmm[63:0]/m64,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W1 55 /r ib\" , \"AVX512_F\"],\n    [\"vfixupimmss\"      , \"X:xmm {kz},xmm[127:32],xmm[31:0]/m32,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W0 55 /r ib\" , \"AVX512_F\"],\n    [\"vfmadd132pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 98 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd132pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 98 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd132pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 98 /r\"    , \"AVX512_F\"],\n    [\"vfmadd132ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 98 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd132ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 98 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd132ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 98 /r\"    , \"AVX512_F\"],\n    [\"vfmadd132sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 99 /r\"    , \"AVX512_F\"],\n    [\"vfmadd132ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 99 /r\"    , \"AVX512_F\"],\n    [\"vfmadd213pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 A8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd213pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 A8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd213pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 A8 /r\"    , \"AVX512_F\"],\n    [\"vfmadd213ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 A8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd213ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 A8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd213ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 A8 /r\"    , \"AVX512_F\"],\n    [\"vfmadd213sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 A9 /r\"    , \"AVX512_F\"],\n    [\"vfmadd213ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 A9 /r\"    , \"AVX512_F\"],\n    [\"vfmadd231pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 B8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd231pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 B8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd231pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 B8 /r\"    , \"AVX512_F\"],\n    [\"vfmadd231ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 B8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd231ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 B8 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmadd231ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 B8 /r\"    , \"AVX512_F\"],\n    [\"vfmadd231sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 B9 /r\"    , \"AVX512_F\"],\n    [\"vfmadd231ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 B9 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub132pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 96 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub132pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 96 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub132pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 96 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub132ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 96 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub132ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 96 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub132ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 96 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub213pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 A6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub213pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 A6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub213pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 A6 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub213ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 A6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub213ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 A6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub213ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 A6 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub231pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 B6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub231pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 B6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub231pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 B6 /r\"    , \"AVX512_F\"],\n    [\"vfmaddsub231ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 B6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub231ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 B6 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmaddsub231ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 B6 /r\"    , \"AVX512_F\"],\n    [\"vfmsub132pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 9A /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub132pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 9A /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub132pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 9A /r\"    , \"AVX512_F\"],\n    [\"vfmsub132ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 9A /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub132ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 9A /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub132ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 9A /r\"    , \"AVX512_F\"],\n    [\"vfmsub132sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 9B /r\"    , \"AVX512_F\"],\n    [\"vfmsub132ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 9B /r\"    , \"AVX512_F\"],\n    [\"vfmsub213pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 AA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub213pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 AA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub213pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 AA /r\"    , \"AVX512_F\"],\n    [\"vfmsub213ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 AA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub213ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 AA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub213ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 AA /r\"    , \"AVX512_F\"],\n    [\"vfmsub213sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 AB /r\"    , \"AVX512_F\"],\n    [\"vfmsub213ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 AB /r\"    , \"AVX512_F\"],\n    [\"vfmsub231pd\"      , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 BA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub231pd\"      , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 BA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub231pd\"      , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 BA /r\"    , \"AVX512_F\"],\n    [\"vfmsub231ps\"      , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 BA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub231ps\"      , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 BA /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsub231ps\"      , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 BA /r\"    , \"AVX512_F\"],\n    [\"vfmsub231sd\"      , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 BB /r\"    , \"AVX512_F\"],\n    [\"vfmsub231ss\"      , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 BB /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd132pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 97 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd132pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 97 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd132pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 97 /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd132ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 97 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd132ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 97 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd132ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 97 /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd213pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 A7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd213pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 A7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd213pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 A7 /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd213ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 A7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd213ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 A7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd213ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 A7 /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd231pd\"   , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 B7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd231pd\"   , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 B7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd231pd\"   , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 B7 /r\"    , \"AVX512_F\"],\n    [\"vfmsubadd231ps\"   , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 B7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd231ps\"   , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 B7 /r\"    , \"AVX512_F-VL\"],\n    [\"vfmsubadd231ps\"   , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 B7 /r\"    , \"AVX512_F\"],\n    [\"vfnmadd132pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 9C /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd132pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 9C /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd132pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 9C /r\"    , \"AVX512_F\"],\n    [\"vfnmadd132ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 9C /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd132ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 9C /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd132ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 9C /r\"    , \"AVX512_F\"],\n    [\"vfnmadd132sd\"     , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 9D /r\"    , \"AVX512_F\"],\n    [\"vfnmadd132ss\"     , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 9D /r\"    , \"AVX512_F\"],\n    [\"vfnmadd213pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 AC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd213pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 AC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd213pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 AC /r\"    , \"AVX512_F\"],\n    [\"vfnmadd213ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 AC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd213ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 AC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd213ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 AC /r\"    , \"AVX512_F\"],\n    [\"vfnmadd213sd\"     , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 AD /r\"    , \"AVX512_F\"],\n    [\"vfnmadd213ss\"     , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 AD /r\"    , \"AVX512_F\"],\n    [\"vfnmadd231pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 BC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd231pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 BC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd231pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 BC /r\"    , \"AVX512_F\"],\n    [\"vfnmadd231ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 BC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd231ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 BC /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmadd231ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 BC /r\"    , \"AVX512_F\"],\n    [\"vfnmadd231sd\"     , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 BD /r\"    , \"AVX512_F\"],\n    [\"vfnmadd231ss\"     , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 BD /r\"    , \"AVX512_F\"],\n    [\"vfnmsub132pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 9E /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub132pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 9E /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub132pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 9E /r\"    , \"AVX512_F\"],\n    [\"vfnmsub132ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 9E /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub132ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 9E /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub132ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 9E /r\"    , \"AVX512_F\"],\n    [\"vfnmsub132sd\"     , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 9F /r\"    , \"AVX512_F\"],\n    [\"vfnmsub132ss\"     , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 9F /r\"    , \"AVX512_F\"],\n    [\"vfnmsub213pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 AE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub213pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 AE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub213pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 AE /r\"    , \"AVX512_F\"],\n    [\"vfnmsub213ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 AE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub213ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 AE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub213ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 AE /r\"    , \"AVX512_F\"],\n    [\"vfnmsub213sd\"     , \"x:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 AF /r\"    , \"AVX512_F\"],\n    [\"vfnmsub213ss\"     , \"x:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 AF /r\"    , \"AVX512_F\"],\n    [\"vfnmsub231pd\"     , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 BE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub231pd\"     , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 BE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub231pd\"     , \"X:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 BE /r\"    , \"AVX512_F\"],\n    [\"vfnmsub231ps\"     , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 BE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub231ps\"     , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 BE /r\"    , \"AVX512_F-VL\"],\n    [\"vfnmsub231ps\"     , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 BE /r\"    , \"AVX512_F\"],\n    [\"vfnmsub231sd\"     , \"X:xmm[63:0] {kz}, xmm[63:0], xmm[63:0]/m64 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 BF /r\"    , \"AVX512_F\"],\n    [\"vfnmsub231ss\"     , \"X:xmm[31:0] {kz}, xmm[31:0], xmm[31:0]/m32 {er}\" , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 BF /r\"    , \"AVX512_F\"],\n    [\"vfpclasspd\"       , \"W:k {k}, xmm/m128/b64, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W1 66 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vfpclasspd\"       , \"W:k {k}, ymm/m256/b64, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 66 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vfpclasspd\"       , \"W:k {k}, zmm/m512/b64, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 66 /r ib\" , \"AVX512_DQ\"],\n    [\"vfpclassps\"       , \"W:k {k}, xmm/m128/b32, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W0 66 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vfpclassps\"       , \"W:k {k}, ymm/m256/b32, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W0 66 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vfpclassps\"       , \"W:k {k}, zmm/m512/b32, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W0 66 /r ib\" , \"AVX512_DQ\"],\n    [\"vfpclasssd\"       , \"W:k {k}, xmm[63:0]/m64, ib/ub\"                   , \"RMI-T1S\" , \"EVEX.LIG.66.0F3A.W1 67 /r ib\" , \"AVX512_DQ\"],\n    [\"vfpclassss\"       , \"W:k {k}, xmm[31:0]/m32, ib/ub\"                   , \"RMI-T1S\" , \"EVEX.LIG.66.0F3A.W0 67 /r ib\" , \"AVX512_DQ\"],\n    [\"vgatherdpd\"       , \"X:xmm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 92 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherdpd\"       , \"X:ymm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 92 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherdpd\"       , \"X:zmm {k}, vm32y\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 92 /r\"    , \"AVX512_F\"],\n    [\"vgatherdps\"       , \"X:xmm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 92 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherdps\"       , \"X:ymm {k}, vm32y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 92 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherdps\"       , \"X:zmm {k}, vm32z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 92 /r\"    , \"AVX512_F\"],\n    [\"vgatherpf0dpd\"    , \"R:vm32y {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C6 /1\"    , \"AVX512_PFI\"],\n    [\"vgatherpf0dps\"    , \"R:vm32z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C6 /1\"    , \"AVX512_PFI\"],\n    [\"vgatherpf0qpd\"    , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C7 /1\"    , \"AVX512_PFI\"],\n    [\"vgatherpf0qps\"    , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C7 /1\"    , \"AVX512_PFI\"],\n    [\"vgatherpf1dpd\"    , \"R:vm32y {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C6 /2\"    , \"AVX512_PFI\"],\n    [\"vgatherpf1dps\"    , \"R:vm32z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C6 /2\"    , \"AVX512_PFI\"],\n    [\"vgatherpf1qpd\"    , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C7 /2\"    , \"AVX512_PFI\"],\n    [\"vgatherpf1qps\"    , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C7 /2\"    , \"AVX512_PFI\"],\n    [\"vgatherqpd\"       , \"X:xmm {k}, vm64x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 93 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherqpd\"       , \"X:ymm {k}, vm64y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 93 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherqpd\"       , \"X:zmm {k}, vm64z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 93 /r\"    , \"AVX512_F\"],\n    [\"vgatherqps\"       , \"X:xmm {k}, vm64x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 93 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherqps\"       , \"X:xmm {k}, vm64y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 93 /r\"    , \"AVX512_F-VL\"],\n    [\"vgatherqps\"       , \"X:ymm {k}, vm64z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 93 /r\"    , \"AVX512_F\"],\n    [\"vgetexppd\"        , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 42 /r\"    , \"AVX512_F-VL\"],\n    [\"vgetexppd\"        , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 42 /r\"    , \"AVX512_F-VL\"],\n    [\"vgetexppd\"        , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 42 /r\"    , \"AVX512_F\"],\n    [\"vgetexpps\"        , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 42 /r\"    , \"AVX512_F-VL\"],\n    [\"vgetexpps\"        , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 42 /r\"    , \"AVX512_F-VL\"],\n    [\"vgetexpps\"        , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 42 /r\"    , \"AVX512_F\"],\n    [\"vgetexpsd\"        , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64 {sae}\"    , \"RM-T1S\"  , \"EVEX.LIG.66.0F38.W1 43 /r\"    , \"AVX512_F\"],\n    [\"vgetexpss\"        , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32 {sae}\"    , \"RM-T1S\"  , \"EVEX.LIG.66.0F38.W0 43 /r\"    , \"AVX512_F\"],\n    [\"vgetmantpd\"       , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W1 26 /r ib\" , \"AVX512_F-VL\"],\n    [\"vgetmantpd\"       , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 26 /r ib\" , \"AVX512_F-VL\"],\n    [\"vgetmantpd\"       , \"W:zmm {kz}, zmm/m512/b64, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 26 /r ib\" , \"AVX512_F\"],\n    [\"vgetmantps\"       , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W0 26 /r ib\" , \"AVX512_F-VL\"],\n    [\"vgetmantps\"       , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W0 26 /r ib\" , \"AVX512_F-VL\"],\n    [\"vgetmantps\"       , \"W:zmm {kz}, zmm/m512/b32, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W0 26 /r ib\" , \"AVX512_F\"],\n    [\"vgetmantsd\"       , \"W:xmm {kz},xmm[127:64],xmm[63:0]/m64,ib/ub {sae}\", \"RMI-T1S\" , \"EVEX.LIG.66.0F3A.W1 27 /r ib\" , \"AVX512_F\"],\n    [\"vgetmantss\"       , \"W:xmm {kz},xmm[127:32],xmm[31:0]/m32,ib/ub {sae}\", \"RMI-T1S\" , \"EVEX.LIG.66.0F3A.W0 27 /r ib\" , \"AVX512_F\"],\n    [\"vgf2p8affineinvqb\", \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 CF /r ib\" , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8affineinvqb\", \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 CF /r ib\" , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8affineinvqb\", \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 CF /r ib\" , \"AVX512_F    GFNI\"],\n    [\"vgf2p8affineqb\"   , \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 CE /r ib\" , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8affineqb\"   , \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 CE /r ib\" , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8affineqb\"   , \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 CE /r ib\" , \"AVX512_F    GFNI\"],\n    [\"vgf2p8mulb\"       , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 CF /r\"    , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8mulb\"       , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 CF /r\"    , \"AVX512_F-VL GFNI\"],\n    [\"vgf2p8mulb\"       , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 CF /r\"    , \"AVX512_F    GFNI\"],\n    [\"vinsertf32x4\"     , \"W:ymm {kz}, ymm, xmm/m128, ib/ub\"                , \"RVMI-T4\" , \"EVEX.256.66.0F3A.W0 18 /r ib\" , \"AVX512_F-VL\"],\n    [\"vinsertf32x4\"     , \"W:zmm {kz}, zmm, xmm/m128, ib/ub\"                , \"RVMI-T4\" , \"EVEX.512.66.0F3A.W0 18 /r ib\" , \"AVX512_F\"],\n    [\"vinsertf32x8\"     , \"W:zmm {kz}, zmm, ymm/m256, ib/ub\"                , \"RVMI-T8\" , \"EVEX.512.66.0F3A.W0 1A /r ib\" , \"AVX512_DQ\"],\n    [\"vinsertf64x2\"     , \"W:ymm {kz}, ymm, xmm/m128, ib/ub\"                , \"RVMI-T2\" , \"EVEX.256.66.0F3A.W1 18 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vinsertf64x2\"     , \"W:zmm {kz}, zmm, xmm/m128, ib/ub\"                , \"RVMI-T2\" , \"EVEX.512.66.0F3A.W1 18 /r ib\" , \"AVX512_DQ\"],\n    [\"vinsertf64x4\"     , \"W:zmm {kz}, zmm, ymm/m256, ib/ub\"                , \"RVMI-T4\" , \"EVEX.512.66.0F3A.W1 1A /r ib\" , \"AVX512_F\"],\n    [\"vinserti32x4\"     , \"W:ymm {kz}, ymm, xmm/m128, ib/ub\"                , \"RVMI-T4\" , \"EVEX.256.66.0F3A.W0 38 /r ib\" , \"AVX512_F-VL\"],\n    [\"vinserti32x4\"     , \"W:zmm {kz}, zmm, xmm/m128, ib/ub\"                , \"RVMI-T4\" , \"EVEX.512.66.0F3A.W0 38 /r ib\" , \"AVX512_F\"],\n    [\"vinserti32x8\"     , \"W:zmm {kz}, zmm, ymm/m256, ib/ub\"                , \"RVMI-T8\" , \"EVEX.512.66.0F3A.W0 3A /r ib\" , \"AVX512_DQ\"],\n    [\"vinserti64x2\"     , \"W:ymm {kz}, ymm, xmm/m128, ib/ub\"                , \"RVMI-T2\" , \"EVEX.256.66.0F3A.W1 38 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vinserti64x2\"     , \"W:zmm {kz}, zmm, xmm/m128, ib/ub\"                , \"RVMI-T2\" , \"EVEX.512.66.0F3A.W1 38 /r ib\" , \"AVX512_DQ\"],\n    [\"vinserti64x4\"     , \"W:zmm {kz}, zmm, ymm/m256, ib/ub\"                , \"RVMI-T4\" , \"EVEX.512.66.0F3A.W1 3A /r ib\" , \"AVX512_F\"],\n    [\"vinsertps\"        , \"W:xmm, xmm, xmm[31:0]/m32, ib/ub\"                , \"RVMI-T1S\", \"EVEX.128.66.0F3A.W0 21 /r ib\" , \"AVX512_F\"],\n    [\"vmaxpd\"           , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 5F /r\"      , \"AVX512_F-VL\"],\n    [\"vmaxpd\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 5F /r\"      , \"AVX512_F-VL\"],\n    [\"vmaxpd\"           , \"W:zmm {kz}, zmm, zmm/m512/b64 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 5F /r\"      , \"AVX512_F\"],\n    [\"vmaxps\"           , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 5F /r\"         , \"AVX512_F-VL\"],\n    [\"vmaxps\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 5F /r\"         , \"AVX512_F-VL\"],\n    [\"vmaxps\"           , \"W:zmm {kz}, zmm, zmm/m512/b32 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.0F.W0 5F /r\"         , \"AVX512_F\"],\n    [\"vmaxsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 5F /r\"      , \"AVX512_F-VL\"],\n    [\"vmaxss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 5F /r\"      , \"AVX512_F-VL\"],\n    [\"vminpd\"           , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 5D /r\"      , \"AVX512_F-VL\"],\n    [\"vminpd\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 5D /r\"      , \"AVX512_F-VL\"],\n    [\"vminpd\"           , \"W:zmm {kz}, zmm, zmm/m512/b64 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 5D /r\"      , \"AVX512_F\"],\n    [\"vminps\"           , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 5D /r\"         , \"AVX512_F-VL\"],\n    [\"vminps\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 5D /r\"         , \"AVX512_F-VL\"],\n    [\"vminps\"           , \"W:zmm {kz}, zmm, zmm/m512/b32 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.0F.W0 5D /r\"         , \"AVX512_F\"],\n    [\"vminsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 5D /r\"      , \"AVX512_F-VL\"],\n    [\"vminss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 5D /r\"      , \"AVX512_F-VL\"],\n    [\"vmovapd\"          , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F.W1 28 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovapd\"          , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.66.0F.W1 29 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovapd\"          , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F.W1 28 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovapd\"          , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.66.0F.W1 29 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovapd\"          , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F.W1 28 /r\"      , \"AVX512_F\"],\n    [\"vmovapd\"          , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.66.0F.W1 29 /r\"      , \"AVX512_F\"],\n    [\"vmovaps\"          , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.0F.W0 28 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovaps\"          , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.0F.W0 29 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovaps\"          , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.0F.W0 28 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovaps\"          , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.0F.W0 29 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovaps\"          , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.0F.W0 28 /r\"         , \"AVX512_F\"],\n    [\"vmovaps\"          , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.0F.W0 29 /r\"         , \"AVX512_F\"],\n    [\"vmovd\"            , \"W:r32/m32, xmm[31:0]\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F.W0 7E /r\"      , \"AVX512_F\"],\n    [\"vmovd\"            , \"W:xmm[31:0], r32/m32\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F.W0 6E /r\"      , \"AVX512_F\"],\n    [\"vmovddup\"         , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-DUP\"  , \"EVEX.128.F2.0F.W1 12 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovddup\"         , \"W:ymm {kz}, ymm/m256\"                            , \"RM-DUP\"  , \"EVEX.256.F2.0F.W1 12 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovddup\"         , \"W:zmm {kz}, zmm/m512\"                            , \"RM-DUP\"  , \"EVEX.512.F2.0F.W1 12 /r\"      , \"AVX512_F\"],\n    [\"vmovdqa32\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F.W0 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa32\"        , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.66.0F.W0 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa32\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F.W0 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa32\"        , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.66.0F.W0 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa32\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F.W0 6F /r\"      , \"AVX512_F\"],\n    [\"vmovdqa32\"        , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.66.0F.W0 7F /r\"      , \"AVX512_F\"],\n    [\"vmovdqa64\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F.W1 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa64\"        , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.66.0F.W1 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa64\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F.W1 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa64\"        , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.66.0F.W1 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqa64\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F.W1 6F /r\"      , \"AVX512_F\"],\n    [\"vmovdqa64\"        , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.66.0F.W1 7F /r\"      , \"AVX512_F\"],\n    [\"vmovdqu16\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.F2.0F.W1 6F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu16\"        , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.F2.0F.W1 7F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu16\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.F2.0F.W1 6F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu16\"        , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.F2.0F.W1 7F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu16\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.F2.0F.W1 6F /r\"      , \"AVX512_BW\"],\n    [\"vmovdqu16\"        , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.F2.0F.W1 7F /r\"      , \"AVX512_BW\"],\n    [\"vmovdqu32\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.F3.0F.W0 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu32\"        , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.F3.0F.W0 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu32\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.F3.0F.W0 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu32\"        , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.F3.0F.W0 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu32\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.F3.0F.W0 6F /r\"      , \"AVX512_F\"],\n    [\"vmovdqu32\"        , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.F3.0F.W0 7F /r\"      , \"AVX512_F\"],\n    [\"vmovdqu64\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.F3.0F.W1 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu64\"        , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.F3.0F.W1 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu64\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.F3.0F.W1 6F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu64\"        , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.F3.0F.W1 7F /r\"      , \"AVX512_F-VL\"],\n    [\"vmovdqu64\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.F3.0F.W1 6F /r\"      , \"AVX512_F\"],\n    [\"vmovdqu64\"        , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.F3.0F.W1 7F /r\"      , \"AVX512_F\"],\n    [\"vmovdqu8\"         , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.F2.0F.W0 6F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu8\"         , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.F2.0F.W0 7F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu8\"         , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.F2.0F.W0 6F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu8\"         , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.F2.0F.W0 7F /r\"      , \"AVX512_BW-VL\"],\n    [\"vmovdqu8\"         , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.F2.0F.W0 6F /r\"      , \"AVX512_BW\"],\n    [\"vmovdqu8\"         , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.F2.0F.W0 7F /r\"      , \"AVX512_BW\"],\n    [\"vmovhlps\"         , \"W:xmm, xmm[127:64], xmm[127:64]\"                 , \"RVM\"     , \"EVEX.128.0F.W0 12 /r\"         , \"AVX512_F\"],\n    [\"vmovhpd\"          , \"W:m64, xmm[127:64]\"                              , \"MR-T1S\"  , \"EVEX.128.66.0F.W1 17 /r\"      , \"AVX512_F\"],\n    [\"vmovhpd\"          , \"W:xmm, xmm[63:0], m64\"                           , \"RVM-T1S\" , \"EVEX.128.66.0F.W1 16 /r\"      , \"AVX512_F\"],\n    [\"vmovhps\"          , \"W:m64, xmm[127:64]\"                              , \"MR-T2\"   , \"EVEX.128.0F.W0 17 /r\"         , \"AVX512_F\"],\n    [\"vmovhps\"          , \"W:xmm, xmm[63:0], m64\"                           , \"RVM-T2\"  , \"EVEX.128.0F.W0 16 /r\"         , \"AVX512_F\"],\n    [\"vmovlhps\"         , \"W:xmm, xmm[63:0], xmm[63:0]\"                     , \"RVM\"     , \"EVEX.128.0F.W0 16 /r\"         , \"AVX512_F\"],\n    [\"vmovlpd\"          , \"W:m64, xmm[63:0]\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F.W1 13 /r\"      , \"AVX512_F\"],\n    [\"vmovlpd\"          , \"W:xmm, xmm[127:64], m64\"                         , \"RVM-T1S\" , \"EVEX.128.66.0F.W1 12 /r\"      , \"AVX512_F\"],\n    [\"vmovlps\"          , \"W:m64, xmm[63:0]\"                                , \"MR-T2\"   , \"EVEX.128.0F.W0 13 /r\"         , \"AVX512_F\"],\n    [\"vmovlps\"          , \"W:xmm, xmm[127:64], m64\"                         , \"RVM-T2\"  , \"EVEX.128.0F.W0 12 /r\"         , \"AVX512_F\"],\n    [\"vmovntdq\"         , \"W:m128, xmm\"                                     , \"MR-FVM\"  , \"EVEX.128.66.0F.W0 E7 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntdq\"         , \"W:m256, ymm\"                                     , \"MR-FVM\"  , \"EVEX.256.66.0F.W0 E7 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntdq\"         , \"W:m512, zmm\"                                     , \"MR-FVM\"  , \"EVEX.512.66.0F.W0 E7 /r\"      , \"AVX512_F\"],\n    [\"vmovntdqa\"        , \"W:xmm, m128\"                                     , \"RM-FVM\"  , \"EVEX.128.66.0F38.W0 2A /r\"    , \"AVX512_F-VL\"],\n    [\"vmovntdqa\"        , \"W:ymm, m256\"                                     , \"RM-FVM\"  , \"EVEX.256.66.0F38.W0 2A /r\"    , \"AVX512_F-VL\"],\n    [\"vmovntdqa\"        , \"W:zmm, m512\"                                     , \"RM-FVM\"  , \"EVEX.512.66.0F38.W0 2A /r\"    , \"AVX512_F\"],\n    [\"vmovntpd\"         , \"W:m128, xmm\"                                     , \"MR-FVM\"  , \"EVEX.128.66.0F.W1 2B /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntpd\"         , \"W:m256, ymm\"                                     , \"MR-FVM\"  , \"EVEX.256.66.0F.W1 2B /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntpd\"         , \"W:m512, zmm\"                                     , \"MR-FVM\"  , \"EVEX.512.66.0F.W1 2B /r\"      , \"AVX512_F\"],\n    [\"vmovntps\"         , \"W:m128, xmm\"                                     , \"MR-FVM\"  , \"EVEX.128.66.0F.W0 2B /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntps\"         , \"W:m256, ymm\"                                     , \"MR-FVM\"  , \"EVEX.256.66.0F.W0 2B /r\"      , \"AVX512_F-VL\"],\n    [\"vmovntps\"         , \"W:m512, zmm\"                                     , \"MR-FVM\"  , \"EVEX.512.0F.W0 2B /r\"         , \"AVX512_F\"],\n    [\"vmovq\"            , \"W:r64/m64, xmm[63:0]\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F.W1 7E /r\"      , \"AVX512_F X64\"],\n    [\"vmovq\"            , \"W:xmm[63:0], r64/m64\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F.W1 6E /r\"      , \"AVX512_F X64\"],\n    [\"vmovq\"            , \"W:xmm[63:0], xmm[63:0]/m64\"                      , \"RM-T1S\"  , \"EVEX.128.F3.0F.W1 7E /r\"      , \"AVX512_F\"],\n    [\"vmovq\"            , \"W:xmm[63:0]/m64, xmm[63:0]\"                      , \"MR-T1S\"  , \"EVEX.128.66.0F.W1 D6 /r\"      , \"AVX512_F\"],\n    [\"vmovsd\"           , \"W:m64, xmm[63:0]\"                                , \"MR-T1S\"  , \"EVEX.LIG.F2.0F.W1 11 /r\"      , \"AVX512_F\"],\n    [\"vmovsd\"           , \"W:xmm[63:0] {kz}, m64\"                           , \"MR-T1S\"  , \"EVEX.LIG.F2.0F.W1 10 /r\"      , \"AVX512_F\"],\n    [\"vmovsd\"           , \"W:xmm {kz}, xmm[127:64], xmm[63:0]\"              , \"MVR\"     , \"EVEX.LIG.F2.0F.W1 11 /r\"      , \"AVX512_F\"],\n    [\"vmovsd\"           , \"W:xmm {kz}, xmm[127:64], xmm[63:0]\"              , \"RVM\"     , \"EVEX.LIG.F2.0F.W1 10 /r\"      , \"AVX512_F\"],\n    [\"vmovshdup\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.F3.0F.W0 16 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovshdup\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.F3.0F.W0 16 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovshdup\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.F3.0F.W0 16 /r\"      , \"AVX512_F\"],\n    [\"vmovsldup\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.F3.0F.W0 12 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovsldup\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.F3.0F.W0 12 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovsldup\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.F3.0F.W0 12 /r\"      , \"AVX512_F\"],\n    [\"vmovss\"           , \"W:m32, xmm[31:0]\"                                , \"MR-T1S\"  , \"EVEX.LIG.F3.0F.W0 11 /r\"      , \"AVX512_F\"],\n    [\"vmovss\"           , \"W:xmm[31:0] {kz}, m32\"                           , \"MR-T1S\"  , \"EVEX.LIG.F3.0F.W0 10 /r\"      , \"AVX512_F\"],\n    [\"vmovss\"           , \"W:xmm {kz}, xmm[127:32], xmm[31:0]\"              , \"MVR\"     , \"EVEX.LIG.F3.0F.W0 11 /r\"      , \"AVX512_F\"],\n    [\"vmovss\"           , \"W:xmm {kz}, xmm[127:32], xmm[31:0]\"              , \"RVM\"     , \"EVEX.LIG.F3.0F.W0 10 /r\"      , \"AVX512_F\"],\n    [\"vmovupd\"          , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F.W1 10 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovupd\"          , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.66.0F.W1 11 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovupd\"          , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F.W1 11 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovupd\"          , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.66.0F.W1 10 /r\"      , \"AVX512_F-VL\"],\n    [\"vmovupd\"          , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F.W1 10 /r\"      , \"AVX512_F\"],\n    [\"vmovupd\"          , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.66.0F.W1 11 /r\"      , \"AVX512_F\"],\n    [\"vmovups\"          , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.0F.W0 10 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovups\"          , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-FVM\"  , \"EVEX.128.0F.W0 11 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovups\"          , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.0F.W0 10 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovups\"          , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-FVM\"  , \"EVEX.256.0F.W0 11 /r\"         , \"AVX512_F-VL\"],\n    [\"vmovups\"          , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.0F.W0 10 /r\"         , \"AVX512_F\"],\n    [\"vmovups\"          , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-FVM\"  , \"EVEX.512.0F.W0 11 /r\"         , \"AVX512_F\"],\n    [\"vmulpd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 59 /r\"      , \"AVX512_F-VL\"],\n    [\"vmulpd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 59 /r\"      , \"AVX512_F-VL\"],\n    [\"vmulpd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 59 /r\"      , \"AVX512_F\"],\n    [\"vmulps\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 59 /r\"         , \"AVX512_F-VL\"],\n    [\"vmulps\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 59 /r\"         , \"AVX512_F-VL\"],\n    [\"vmulps\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.0F.W0 59 /r\"         , \"AVX512_F\"],\n    [\"vmulsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 59 /r\"      , \"AVX512_F\"],\n    [\"vmulss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 59 /r\"      , \"AVX512_F\"],\n    [\"vorpd\"            , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 56 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vorpd\"            , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 56 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vorpd\"            , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 56 /r\"      , \"AVX512_DQ\"],\n    [\"vorps\"            , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 56 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vorps\"            , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 56 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vorps\"            , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.0F.W0 56 /r\"         , \"AVX512_DQ\"],\n    [\"vp2intersectd\"    , \"W:k, W:k+1, xmm, xmm/m128/b32\"                   , \"RVM\"     , \"EVEX.128.F2.0F38.W0 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp2intersectd\"    , \"W:k, W:k+1, ymm, ymm/m256/b32\"                   , \"RVM\"     , \"EVEX.256.F2.0F38.W0 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp2intersectd\"    , \"W:k, W:k+1, zmm, zmm/m512/b32\"                   , \"RVM\"     , \"EVEX.512.F2.0F38.W0 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp2intersectq\"    , \"W:k, W:k+1, xmm, xmm/m128/b64\"                   , \"RVM\"     , \"EVEX.128.F2.0F38.W1 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp2intersectq\"    , \"W:k, W:k+1, ymm, ymm/m256/b64\"                   , \"RVM\"     , \"EVEX.256.F2.0F38.W1 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp2intersectq\"    , \"W:k, W:k+1, zmm, zmm/m512/b64\"                   , \"RVM\"     , \"EVEX.512.F2.0F38.W1 68 /r\"    , \"AVX512_VP2INTERSECT\"],\n    [\"vp4dpwssd\"        , \"W:zmm {kz}, zmm, zmm+1, zmm+2, zmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.512.F2.0F38.W0 52 /r\"    , \"AVX512_4VNNIW\"],\n    [\"vp4dpwssds\"       , \"W:zmm {kz}, zmm, zmm+1, zmm+2, zmm+3, m128\"      , \"RM-T1_4X\", \"EVEX.512.F2.0F38.W0 53 /r\"    , \"AVX512_4VNNIW\"],\n    [\"vpabsb\"           , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38 1C /r\"       , \"AVX512_BW-VL\"],\n    [\"vpabsb\"           , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38 1C /r\"       , \"AVX512_BW-VL\"],\n    [\"vpabsb\"           , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38 1C /r\"       , \"AVX512_BW\"],\n    [\"vpabsd\"           , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 1E /r\"    , \"AVX512_F-VL\"],\n    [\"vpabsd\"           , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 1E /r\"    , \"AVX512_F-VL\"],\n    [\"vpabsd\"           , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 1E /r\"    , \"AVX512_F\"],\n    [\"vpabsq\"           , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 1F /r\"    , \"AVX512_F-VL\"],\n    [\"vpabsq\"           , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 1F /r\"    , \"AVX512_F-VL\"],\n    [\"vpabsq\"           , \"W:zmm {kz}, zmm/m512/b64\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 1F /r\"    , \"AVX512_F\"],\n    [\"vpabsw\"           , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38 1D /r\"       , \"AVX512_BW-VL\"],\n    [\"vpabsw\"           , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38 1D /r\"       , \"AVX512_BW-VL\"],\n    [\"vpabsw\"           , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38 1D /r\"       , \"AVX512_BW\"],\n    [\"vpackssdw\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 6B /r\"      , \"AVX512_BW-VL\"],\n    [\"vpackssdw\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 6B /r\"      , \"AVX512_BW-VL\"],\n    [\"vpackssdw\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 6B /r\"      , \"AVX512_BW\"],\n    [\"vpacksswb\"        , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 63 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpacksswb\"        , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 63 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpacksswb\"        , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 63 /r\"     , \"AVX512_BW\"],\n    [\"vpackusdw\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 2B /r\"    , \"AVX512_BW-VL\"],\n    [\"vpackusdw\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 2B /r\"    , \"AVX512_BW-VL\"],\n    [\"vpackusdw\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 2B /r\"    , \"AVX512_BW\"],\n    [\"vpackuswb\"        , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 67 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpackuswb\"        , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 67 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpackuswb\"        , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 67 /r\"     , \"AVX512_BW\"],\n    [\"vpaddb\"           , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG FC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddb\"           , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG FC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddb\"           , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG FC /r\"     , \"AVX512_BW\"],\n    [\"vpaddd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 FE /r\"      , \"AVX512_F-VL\"],\n    [\"vpaddd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 FE /r\"      , \"AVX512_F-VL\"],\n    [\"vpaddd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 FE /r\"      , \"AVX512_F\"],\n    [\"vpaddq\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 D4 /r\"      , \"AVX512_F-VL\"],\n    [\"vpaddq\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 D4 /r\"      , \"AVX512_F-VL\"],\n    [\"vpaddq\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 D4 /r\"      , \"AVX512_F\"],\n    [\"vpaddsb\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG EC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddsb\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG EC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddsb\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG EC /r\"     , \"AVX512_BW\"],\n    [\"vpaddsw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG ED /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddsw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG ED /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddsw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG ED /r\"     , \"AVX512_BW\"],\n    [\"vpaddusb\"         , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG DC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddusb\"         , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG DC /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddusb\"         , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG DC /r\"     , \"AVX512_BW\"],\n    [\"vpaddusw\"         , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG DD /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddusw\"         , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG DD /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddusw\"         , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG DD /r\"     , \"AVX512_BW\"],\n    [\"vpaddw\"           , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG FD /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddw\"           , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG FD /r\"     , \"AVX512_BW-VL\"],\n    [\"vpaddw\"           , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG FD /r\"     , \"AVX512_BW\"],\n    [\"vpalignr\"         , \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FVM\", \"EVEX.128.66.0F3A.WIG 0F /r ib\", \"AVX512_BW-VL\"],\n    [\"vpalignr\"         , \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FVM\", \"EVEX.256.66.0F3A.WIG 0F /r ib\", \"AVX512_BW-VL\"],\n    [\"vpalignr\"         , \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FVM\", \"EVEX.512.66.0F3A.WIG 0F /r ib\", \"AVX512_BW\"],\n    [\"vpandd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 DB /r\"      , \"AVX512_F-VL\"],\n    [\"vpandd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 DB /r\"      , \"AVX512_F-VL\"],\n    [\"vpandd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 DB /r\"      , \"AVX512_F\"],\n    [\"vpandnd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 DF /r\"      , \"AVX512_F-VL\"],\n    [\"vpandnd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 DF /r\"      , \"AVX512_F-VL\"],\n    [\"vpandnd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 DF /r\"      , \"AVX512_F\"],\n    [\"vpandnq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 DF /r\"      , \"AVX512_F-VL\"],\n    [\"vpandnq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 DF /r\"      , \"AVX512_F-VL\"],\n    [\"vpandnq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 DF /r\"      , \"AVX512_F\"],\n    [\"vpandq\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 DB /r\"      , \"AVX512_F-VL\"],\n    [\"vpandq\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 DB /r\"      , \"AVX512_F-VL\"],\n    [\"vpandq\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 DB /r\"      , \"AVX512_F\"],\n    [\"vpavgb\"           , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E0 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpavgb\"           , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E0 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpavgb\"           , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E0 /r\"     , \"AVX512_BW\"],\n    [\"vpavgw\"           , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E3 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpavgw\"           , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E3 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpavgw\"           , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E3 /r\"     , \"AVX512_BW\"],\n    [\"vpblendmb\"        , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 66 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpblendmb\"        , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 66 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpblendmb\"        , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 66 /r\"    , \"AVX512_BW\"],\n    [\"vpblendmd\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 64 /r\"    , \"AVX512_F-VL\"],\n    [\"vpblendmd\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 64 /r\"    , \"AVX512_F-VL\"],\n    [\"vpblendmd\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 64 /r\"    , \"AVX512_F\"],\n    [\"vpblendmq\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 64 /r\"    , \"AVX512_F-VL\"],\n    [\"vpblendmq\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 64 /r\"    , \"AVX512_F-VL\"],\n    [\"vpblendmq\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 64 /r\"    , \"AVX512_F\"],\n    [\"vpblendmw\"        , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 66 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpblendmw\"        , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 66 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpblendmw\"        , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 66 /r\"    , \"AVX512_BW\"],\n    [\"vpbroadcastb\"     , \"W:xmm {kz}, r32[7:0]\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 7A /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastb\"     , \"W:xmm {kz}, xmm[7:0]/m8\"                         , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 78 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastb\"     , \"W:ymm {kz}, r32[7:0]\"                            , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 7A /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastb\"     , \"W:ymm {kz}, xmm[7:0]/m8\"                         , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 78 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastb\"     , \"W:zmm {kz}, r32[7:0]\"                            , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 7A /r\"    , \"AVX512_BW\"],\n    [\"vpbroadcastb\"     , \"W:zmm {kz}, xmm[7:0]/m8\"                         , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 78 /r\"    , \"AVX512_BW\"],\n    [\"vpbroadcastd\"     , \"W:xmm {kz}, r32[31:0]\"                           , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 7C /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastd\"     , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 58 /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastd\"     , \"W:ymm {kz}, r32[31:0]\"                           , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 7C /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastd\"     , \"W:ymm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 58 /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastd\"     , \"W:zmm {kz}, r32[31:0]\"                           , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 7C /r\"    , \"AVX512_F\"],\n    [\"vpbroadcastd\"     , \"W:zmm {kz}, xmm[31:0]/m32\"                       , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 58 /r\"    , \"AVX512_F\"],\n    [\"vpbroadcastmb2q\"  , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W1 2A /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpbroadcastmb2q\"  , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W1 2A /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpbroadcastmb2q\"  , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W1 2A /r\"    , \"AVX512_CDI\"],\n    [\"vpbroadcastmw2d\"  , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W0 3A /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpbroadcastmw2d\"  , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W0 3A /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpbroadcastmw2d\"  , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W0 3A /r\"    , \"AVX512_CDI\"],\n    [\"vpbroadcastq\"     , \"W:xmm {kz}, r64\"                                 , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 7C /r\"    , \"AVX512_F-VL X64\"],\n    [\"vpbroadcastq\"     , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 59 /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastq\"     , \"W:ymm {kz}, r64\"                                 , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 7C /r\"    , \"AVX512_F-VL X64\"],\n    [\"vpbroadcastq\"     , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 59 /r\"    , \"AVX512_F-VL\"],\n    [\"vpbroadcastq\"     , \"W:zmm {kz}, r64\"                                 , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 7C /r\"    , \"AVX512_F X64\"],\n    [\"vpbroadcastq\"     , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 59 /r\"    , \"AVX512_F\"],\n    [\"vpbroadcastw\"     , \"W:xmm {kz}, r32[15:0]\"                           , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 7B /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastw\"     , \"W:xmm {kz}, xmm[15:0]/m16\"                       , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 79 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastw\"     , \"W:ymm {kz}, r32[15:0]\"                           , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 7B /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastw\"     , \"W:ymm {kz}, xmm[15:0]/m16\"                       , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 79 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpbroadcastw\"     , \"W:zmm {kz}, r32[15:0]\"                           , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 7B /r\"    , \"AVX512_BW\"],\n    [\"vpbroadcastw\"     , \"W:zmm {kz}, xmm[15:0]/m16\"                       , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 79 /r\"    , \"AVX512_BW\"],\n    [\"vpclmulqdq\"       , \"W:xmm, xmm, xmm/m128, ib/ub\"                     , \"RVMI-FVM\", \"EVEX.128.66.0F3A.WIG 44 /r ib\", \"AVX512_F-VL VPCLMULQDQ\"],\n    [\"vpclmulqdq\"       , \"W:ymm, ymm, ymm/m256, ib/ub\"                     , \"RVMI-FVM\", \"EVEX.256.66.0F3A.WIG 44 /r ib\", \"AVX512_F-VL VPCLMULQDQ\"],\n    [\"vpclmulqdq\"       , \"W:zmm, zmm, zmm/m512, ib/ub\"                     , \"RVMI-FVM\", \"EVEX.512.66.0F3A.WIG 44 /r ib\", \"AVX512_F    VPCLMULQDQ\"],\n    [\"vpcmpb\"           , \"W:k {k}, xmm, xmm/m128, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W0 3F /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpb\"           , \"W:k {k}, ymm, ymm/m256, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W0 3F /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpb\"           , \"W:k {k}, zmm, zmm/m512, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W0 3F /r ib\" , \"AVX512_BW\"],\n    [\"vpcmpd\"           , \"W:k {k}, xmm, xmm/m128/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 1F /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpd\"           , \"W:k {k}, ymm, ymm/m256/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 1F /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpd\"           , \"W:k {k}, zmm, zmm/m512/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 1F /r ib\" , \"AVX512_F\"],\n    [\"vpcmpeqb\"         , \"W:k {k},~xmm,~xmm/m128\"                          , \"RVM-FV\"  , \"EVEX.128.66.0F.WIG 74 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpeqb\"         , \"W:k {k},~ymm,~ymm/m256\"                          , \"RVM-FV\"  , \"EVEX.256.66.0F.WIG 74 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpeqb\"         , \"W:k {k},~zmm,~zmm/m512\"                          , \"RVM-FV\"  , \"EVEX.512.66.0F.WIG 74 /r\"     , \"AVX512_BW\"],\n    [\"vpcmpeqd\"         , \"W:k {k},~xmm,~xmm/m128/b32\"                      , \"RVM-FVM\" , \"EVEX.128.66.0F.W0 76 /r\"      , \"AVX512_F-VL\"],\n    [\"vpcmpeqd\"         , \"W:k {k},~ymm,~ymm/m256/b32\"                      , \"RVM-FVM\" , \"EVEX.256.66.0F.W0 76 /r\"      , \"AVX512_F-VL\"],\n    [\"vpcmpeqd\"         , \"W:k {k},~zmm,~zmm/m512/b32\"                      , \"RVM-FVM\" , \"EVEX.512.66.0F.W0 76 /r\"      , \"AVX512_F\"],\n    [\"vpcmpeqq\"         , \"W:k {k},~xmm,~xmm/m128/b64\"                      , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 29 /r\"    , \"AVX512_F-VL\"],\n    [\"vpcmpeqq\"         , \"W:k {k},~ymm,~ymm/m256/b64\"                      , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 29 /r\"    , \"AVX512_F-VL\"],\n    [\"vpcmpeqq\"         , \"W:k {k},~zmm,~zmm/m512/b64\"                      , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 29 /r\"    , \"AVX512_F\"],\n    [\"vpcmpeqw\"         , \"W:k {k},~xmm,~xmm/m128\"                          , \"RVM-FV\"  , \"EVEX.128.66.0F.WIG 75 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpeqw\"         , \"W:k {k},~ymm,~ymm/m256\"                          , \"RVM-FV\"  , \"EVEX.256.66.0F.WIG 75 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpeqw\"         , \"W:k {k},~zmm,~zmm/m512\"                          , \"RVM-FV\"  , \"EVEX.512.66.0F.WIG 75 /r\"     , \"AVX512_BW\"],\n    [\"vpcmpgtb\"         , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FV\"  , \"EVEX.128.66.0F.WIG 64 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpgtb\"         , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FV\"  , \"EVEX.256.66.0F.WIG 64 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpgtb\"         , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FV\"  , \"EVEX.512.66.0F.WIG 64 /r\"     , \"AVX512_BW\"],\n    [\"vpcmpgtd\"         , \"W:k {k}, xmm, xmm/m128/b32\"                      , \"RVM-FVM\" , \"EVEX.128.66.0F.W0 66 /r\"      , \"AVX512_F-VL\"],\n    [\"vpcmpgtd\"         , \"W:k {k}, ymm, ymm/m256/b32\"                      , \"RVM-FVM\" , \"EVEX.256.66.0F.W0 66 /r\"      , \"AVX512_F-VL\"],\n    [\"vpcmpgtd\"         , \"W:k {k}, zmm, zmm/m512/b32\"                      , \"RVM-FVM\" , \"EVEX.512.66.0F.W0 66 /r\"      , \"AVX512_F\"],\n    [\"vpcmpgtq\"         , \"W:k {k}, xmm, xmm/m128/b64\"                      , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 37 /r\"    , \"AVX512_F-VL\"],\n    [\"vpcmpgtq\"         , \"W:k {k}, ymm, ymm/m256/b64\"                      , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 37 /r\"    , \"AVX512_F-VL\"],\n    [\"vpcmpgtq\"         , \"W:k {k}, zmm, zmm/m512/b64\"                      , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 37 /r\"    , \"AVX512_F\"],\n    [\"vpcmpgtw\"         , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FV\"  , \"EVEX.128.66.0F.WIG 65 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpgtw\"         , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FV\"  , \"EVEX.256.66.0F.WIG 65 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpcmpgtw\"         , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FV\"  , \"EVEX.512.66.0F.WIG 65 /r\"     , \"AVX512_BW\"],\n    [\"vpcmpq\"           , \"W:k {k}, xmm, xmm/m128/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 1F /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpq\"           , \"W:k {k}, ymm, ymm/m256/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 1F /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpq\"           , \"W:k {k}, zmm, zmm/m512/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 1F /r ib\" , \"AVX512_F\"],\n    [\"vpcmpub\"          , \"W:k {k}, xmm, xmm/m128, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W0 3E /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpub\"          , \"W:k {k}, ymm, ymm/m256, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W0 3E /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpub\"          , \"W:k {k}, zmm, zmm/m512, ib/ub\"                   , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W0 3E /r ib\" , \"AVX512_BW\"],\n    [\"vpcmpud\"          , \"W:k {k}, xmm, xmm/m128/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 1E /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpud\"          , \"W:k {k}, ymm, ymm/m256/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 1E /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpud\"          , \"W:k {k}, zmm, zmm/m512/b32, ib/ub\"               , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 1E /r ib\" , \"AVX512_F\"],\n    [\"vpcmpuq\"          , \"W:k {k}, xmm, xmm/m128/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 1E /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpuq\"          , \"W:k {k}, ymm, ymm/m256/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 1E /r ib\" , \"AVX512_F-VL\"],\n    [\"vpcmpuq\"          , \"W:k {k}, zmm, zmm/m512/b64, ib/ub\"               , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 1E /r ib\" , \"AVX512_F\"],\n    [\"vpcmpuw\"          , \"W:k {k}, xmm, xmm/m128/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 3E /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpuw\"          , \"W:k {k}, ymm, ymm/m256/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 3E /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpuw\"          , \"W:k {k}, zmm, zmm/m512/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 3E /r ib\" , \"AVX512_BW\"],\n    [\"vpcmpw\"           , \"W:k {k}, xmm, xmm/m128/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 3F /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpw\"           , \"W:k {k}, ymm, ymm/m256/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 3F /r ib\" , \"AVX512_BW-VL\"],\n    [\"vpcmpw\"           , \"W:k {k}, zmm, zmm/m512/b64, ib/ub\"               , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 3F /r ib\" , \"AVX512_BW\"],\n    [\"vpcompressb\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"RVM-T1S\" , \"EVEX.128.66.0F38.W0 63 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpcompressb\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"RVM-T1S\" , \"EVEX.256.66.0F38.W0 63 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpcompressb\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"RVM-T1S\" , \"EVEX.512.66.0F38.W0 63 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpcompressw\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"RVM-T1S\" , \"EVEX.128.66.0F38.W1 63 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpcompressw\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"RVM-T1S\" , \"EVEX.256.66.0F38.W1 63 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpcompressw\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"RVM-T1S\" , \"EVEX.512.66.0F38.W1 63 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpcompressd\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 8B /r\"    , \"AVX512_F-VL\"],\n    [\"vpcompressd\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 8B /r\"    , \"AVX512_F-VL\"],\n    [\"vpcompressd\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 8B /r\"    , \"AVX512_F\"],\n    [\"vpcompressq\"      , \"W:xmm/m128 {kz}, xmm\"                            , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 8B /r\"    , \"AVX512_F-VL\"],\n    [\"vpcompressq\"      , \"W:ymm/m256 {kz}, ymm\"                            , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 8B /r\"    , \"AVX512_F-VL\"],\n    [\"vpcompressq\"      , \"W:zmm/m512 {kz}, zmm\"                            , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 8B /r\"    , \"AVX512_F\"],\n    [\"vpconflictd\"      , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 C4 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpconflictd\"      , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 C4 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpconflictd\"      , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 C4 /r\"    , \"AVX512_CDI\"],\n    [\"vpconflictq\"      , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 C4 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpconflictq\"      , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 C4 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vpconflictq\"      , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 C4 /r\"    , \"AVX512_CDI\"],\n    [\"vpdpbusd\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 50 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpbusd\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 50 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpbusd\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 50 /r\"    , \"AVX512_VNNI\"],\n    [\"vpdpbusds\"        , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 51 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpbusds\"        , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 51 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpbusds\"        , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 51 /r\"    , \"AVX512_VNNI\"],\n    [\"vpdpwssd\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 52 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpwssd\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 52 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpwssd\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 52 /r\"    , \"AVX512_VNNI\"],\n    [\"vpdpwssds\"        , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 53 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpwssds\"        , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 53 /r\"    , \"AVX512_VNNI-VL\"],\n    [\"vpdpwssds\"        , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 53 /r\"    , \"AVX512_VNNI\"],\n    [\"vpexpandb\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38.W0 62 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpexpandb\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38.W0 62 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpexpandb\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38.W0 62 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpexpandw\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38.W1 62 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpexpandw\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38.W1 62 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpexpandw\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38.W1 62 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpermb\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 8D /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermb\"           , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 8D /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermb\"           , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 8D /r\"    , \"AVX512_VBMI\"],\n    [\"vpermd\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 36 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermd\"           , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 36 /r\"    , \"AVX512_F\"],\n    [\"vpermi2b\"         , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 75 /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermi2b\"         , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 75 /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermi2b\"         , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 75 /r\"    , \"AVX512_VBMI\"],\n    [\"vpermi2d\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 76 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2d\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 76 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2d\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 76 /r\"    , \"AVX512_F\"],\n    [\"vpermi2pd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 77 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2pd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 77 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2pd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 77 /r\"    , \"AVX512_F\"],\n    [\"vpermi2ps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 77 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2ps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 77 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2ps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 77 /r\"    , \"AVX512_F\"],\n    [\"vpermi2q\"         , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 76 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2q\"         , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 76 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermi2q\"         , \"X:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 76 /r\"    , \"AVX512_F\"],\n    [\"vpermi2w\"         , \"X:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 75 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermi2w\"         , \"X:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 75 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermi2w\"         , \"X:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 75 /r\"    , \"AVX512_BW\"],\n    [\"vpermilpd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 0D /r\"    , \"AVX512_F-VL\"],\n    [\"vpermilpd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 0D /r\"    , \"AVX512_F-VL\"],\n    [\"vpermilpd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 0D /r\"    , \"AVX512_F\"],\n    [\"vpermilpd\"        , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W1 05 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermilpd\"        , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 05 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermilpd\"        , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 05 /r ib\" , \"AVX512_F\"],\n    [\"vpermilps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 0C /r\"    , \"AVX512_F-VL\"],\n    [\"vpermilps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 0C /r\"    , \"AVX512_F-VL\"],\n    [\"vpermilps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 0C /r\"    , \"AVX512_F\"],\n    [\"vpermilps\"        , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W0 04 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermilps\"        , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W0 04 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermilps\"        , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W0 04 /r ib\" , \"AVX512_F\"],\n    [\"vpermpd\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 16 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermpd\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 16 /r\"    , \"AVX512_F\"],\n    [\"vpermpd\"          , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 01 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermpd\"          , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 01 /r ib\" , \"AVX512_F\"],\n    [\"vpermps\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 16 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermps\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 16 /r\"    , \"AVX512_F\"],\n    [\"vpermq\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 36 /r\"    , \"AVX512_F-VL\"],\n    [\"vpermq\"           , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 36 /r\"    , \"AVX512_F\"],\n    [\"vpermq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 00 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpermq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 00 /r ib\" , \"AVX512_F\"],\n    [\"vpermt2b\"         , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 7D /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermt2b\"         , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 7D /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpermt2b\"         , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 7D /r\"    , \"AVX512_VBMI\"],\n    [\"vpermt2d\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 7E /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2d\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 7E /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2d\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 7E /r\"    , \"AVX512_F\"],\n    [\"vpermt2pd\"        , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 7F /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2pd\"        , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 7F /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2pd\"        , \"X:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 7F /r\"    , \"AVX512_F\"],\n    [\"vpermt2ps\"        , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 7F /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2ps\"        , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 7F /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2ps\"        , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 7F /r\"    , \"AVX512_F\"],\n    [\"vpermt2q\"         , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 7E /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2q\"         , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 7E /r\"    , \"AVX512_F-VL\"],\n    [\"vpermt2q\"         , \"X:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 7E /r\"    , \"AVX512_F\"],\n    [\"vpermt2w\"         , \"X:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 7D /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermt2w\"         , \"X:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 7D /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermt2w\"         , \"X:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 7D /r\"    , \"AVX512_BW\"],\n    [\"vpermw\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 8D /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermw\"           , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 8D /r\"    , \"AVX512_BW-VL\"],\n    [\"vpermw\"           , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 8D /r\"    , \"AVX512_BW\"],\n    [\"vpexpandd\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 89 /r\"    , \"AVX512_F-VL\"],\n    [\"vpexpandd\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 89 /r\"    , \"AVX512_F-VL\"],\n    [\"vpexpandd\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 89 /r\"    , \"AVX512_F\"],\n    [\"vpexpandq\"        , \"W:xmm {kz}, xmm/m128\"                            , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 89 /r\"    , \"AVX512_F-VL\"],\n    [\"vpexpandq\"        , \"W:ymm {kz}, ymm/m256\"                            , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 89 /r\"    , \"AVX512_F-VL\"],\n    [\"vpexpandq\"        , \"W:zmm {kz}, zmm/m512\"                            , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 89 /r\"    , \"AVX512_F\"],\n    [\"vpextrb\"          , \"W:r32[7:0]/m8 , xmm, ib/ub\"                      , \"MRI-T1S\" , \"EVEX.128.66.0F3A.WIG 14 /r ib\", \"AVX512_BW\"],\n    [\"vpextrd\"          , \"W:r32/m32, xmm, ib/ub\"                           , \"MRI-T1S\" , \"EVEX.128.66.0F3A.W0 16 /r ib\" , \"AVX512_DQ\"],\n    [\"vpextrq\"          , \"W:r64/m64, xmm, ib/ub\"                           , \"MRI-T1S\" , \"EVEX.128.66.0F3A.W1 16 /r ib\" , \"AVX512_DQ X64\"],\n    [\"vpextrw\"          , \"W:r32[15:0], xmm, ib/ub\"                         , \"RMI\"     , \"EVEX.128.66.0F.WIG C5 /r ib\"  , \"AVX512_BW\"],\n    [\"vpextrw\"          , \"W:r32[15:0]/m16, xmm, ib/ub\"                     , \"MRI-T1S\" , \"EVEX.128.66.0F3A.WIG 15 /r ib\", \"AVX512_BW\"],\n    [\"vpgatherdd\"       , \"X:xmm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 90\"       , \"AVX512_F-VL\"],\n    [\"vpgatherdd\"       , \"X:ymm {k}, vm32y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 90\"       , \"AVX512_F-VL\"],\n    [\"vpgatherdd\"       , \"X:zmm {k}, vm32z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 90\"       , \"AVX512_F\"],\n    [\"vpgatherdq\"       , \"X:xmm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 90\"       , \"AVX512_F-VL\"],\n    [\"vpgatherdq\"       , \"X:ymm {k}, vm32x\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 90\"       , \"AVX512_F-VL\"],\n    [\"vpgatherdq\"       , \"X:zmm {k}, vm32y\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 90\"       , \"AVX512_F\"],\n    [\"vpgatherqd\"       , \"X:xmm {k}, vm64x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W0 91\"       , \"AVX512_F-VL\"],\n    [\"vpgatherqd\"       , \"X:xmm {k}, vm64y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W0 91\"       , \"AVX512_F-VL\"],\n    [\"vpgatherqd\"       , \"X:ymm {k}, vm64z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W0 91\"       , \"AVX512_F\"],\n    [\"vpgatherqq\"       , \"X:xmm {k}, vm64x\"                                , \"RM-T1S\"  , \"EVEX.128.66.0F38.W1 91\"       , \"AVX512_F-VL\"],\n    [\"vpgatherqq\"       , \"X:ymm {k}, vm64y\"                                , \"RM-T1S\"  , \"EVEX.256.66.0F38.W1 91\"       , \"AVX512_F-VL\"],\n    [\"vpgatherqq\"       , \"X:zmm {k}, vm64z\"                                , \"RM-T1S\"  , \"EVEX.512.66.0F38.W1 91\"       , \"AVX512_F\"],\n    [\"vpinsrb\"          , \"W:xmm {kz}, xmm, r32[7:0]/m8, ib/ub\"             , \"RVMI-T1S\", \"EVEX.128.66.0F3A.WIG 20 /r ib\", \"AVX512_BW\"],\n    [\"vpinsrd\"          , \"W:xmm {kz}, xmm, r32/m32, ib/ub\"                 , \"RVMI-T1S\", \"EVEX.128.66.0F3A.W0 22 /r ib\" , \"AVX512_DQ\"],\n    [\"vpinsrq\"          , \"W:xmm {kz}, xmm, r64/m64, ib/ub\"                 , \"RVMI-T1S\", \"EVEX.128.66.0F3A.W1 22 /r ib\" , \"AVX512_DQ X64\"],\n    [\"vpinsrw\"          , \"W:xmm {kz}, xmm, r32[15:0]/m16, ib/ub\"           , \"RVMI-T1S\", \"EVEX.128.66.0F.WIG C4 /r ib\"  , \"AVX512_BW\"],\n    [\"vplzcntd\"         , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 44 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vplzcntd\"         , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 44 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vplzcntd\"         , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 44 /r\"    , \"AVX512_CDI\"],\n    [\"vplzcntq\"         , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 44 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vplzcntq\"         , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 44 /r\"    , \"AVX512_CDI-VL\"],\n    [\"vplzcntq\"         , \"W:zmm {kz}, zmm/m512/b64\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 44 /r\"    , \"AVX512_CDI\"],\n    [\"vpmadd52luq\"      , \"X:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 B4 /r\"    , \"AVX512_IFMA-VL\"],\n    [\"vpmadd52luq\"      , \"X:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 B4 /r\"    , \"AVX512_IFMA-VL\"],\n    [\"vpmadd52luq\"      , \"X:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 B4 /r\"    , \"AVX512_IFMA\"],\n    [\"vpmadd52huq\"      , \"X:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 B5 /r\"    , \"AVX512_IFMA-VL\"],\n    [\"vpmadd52huq\"      , \"X:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 B5 /r\"    , \"AVX512_IFMA-VL\"],\n    [\"vpmadd52huq\"      , \"X:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 B5 /r\"    , \"AVX512_IFMA\"],\n    [\"vpmaddubsw\"       , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 04 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaddubsw\"       , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 04 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaddubsw\"       , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 04 /r\"   , \"AVX512_BW\"],\n    [\"vpmaddwd\"         , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG F5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaddwd\"         , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG F5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaddwd\"         , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG F5 /r\"     , \"AVX512_BW\"],\n    [\"vpmaxsb\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 3C /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaxsb\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 3C /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaxsb\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 3C /r\"   , \"AVX512_BW\"],\n    [\"vpmaxsd\"          , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 3D /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxsd\"          , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 3D /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxsd\"          , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 3D /r\"    , \"AVX512_F\"],\n    [\"vpmaxsq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 3D /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxsq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 3D /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxsq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 3D /r\"    , \"AVX512_F\"],\n    [\"vpmaxsw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG EE /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaxsw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG EE /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaxsw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG EE /r\"     , \"AVX512_BW\"],\n    [\"vpmaxub\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG DE /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaxub\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG DE /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmaxub\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG DE /r\"     , \"AVX512_BW\"],\n    [\"vpmaxud\"          , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 3F /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxud\"          , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 3F /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxud\"          , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 3F /r\"    , \"AVX512_F\"],\n    [\"vpmaxuq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 3F /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxuq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 3F /r\"    , \"AVX512_F-VL\"],\n    [\"vpmaxuq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 3F /r\"    , \"AVX512_F\"],\n    [\"vpmaxuw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 3E /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaxuw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 3E /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmaxuw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 3E /r\"   , \"AVX512_BW\"],\n    [\"vpminsb\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 38 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpminsb\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 38 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpminsb\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 38 /r\"   , \"AVX512_BW\"],\n    [\"vpminsd\"          , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 39 /r\"    , \"AVX512_F-VL\"],\n    [\"vpminsd\"          , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 39 /r\"    , \"AVX512_F-VL\"],\n    [\"vpminsd\"          , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 39 /r\"    , \"AVX512_F\"],\n    [\"vpminsq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 39 /r\"    , \"AVX512_F-VL\"],\n    [\"vpminsq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 39 /r\"    , \"AVX512_F-VL\"],\n    [\"vpminsq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 39 /r\"    , \"AVX512_F\"],\n    [\"vpminsw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG EA /r\"     , \"AVX512_BW-VL\"],\n    [\"vpminsw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG EA /r\"     , \"AVX512_BW-VL\"],\n    [\"vpminsw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG EA /r\"     , \"AVX512_BW\"],\n    [\"vpminub\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F DA /r\"         , \"AVX512_BW-VL\"],\n    [\"vpminub\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F DA /r\"         , \"AVX512_BW-VL\"],\n    [\"vpminub\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F DA /r\"         , \"AVX512_BW\"],\n    [\"vpminud\"          , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 3B /r\"    , \"AVX512_F-VL\"],\n    [\"vpminud\"          , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 3B /r\"    , \"AVX512_F-VL\"],\n    [\"vpminud\"          , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 3B /r\"    , \"AVX512_F\"],\n    [\"vpminuq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 3B /r\"    , \"AVX512_F-VL\"],\n    [\"vpminuq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 3B /r\"    , \"AVX512_F-VL\"],\n    [\"vpminuq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 3B /r\"    , \"AVX512_F\"],\n    [\"vpminuw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38 3A /r\"       , \"AVX512_BW-VL\"],\n    [\"vpminuw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38 3A /r\"       , \"AVX512_BW-VL\"],\n    [\"vpminuw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38 3A /r\"       , \"AVX512_BW\"],\n    [\"vpmovb2m\"         , \"W:k, xmm\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W0 29 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovb2m\"         , \"W:k, ymm\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W0 29 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovb2m\"         , \"W:k, zmm\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W0 29 /r\"    , \"AVX512_BW\"],\n    [\"vpmovd2m\"         , \"W:k, xmm\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W0 39 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovd2m\"         , \"W:k, ymm\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W0 39 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovd2m\"         , \"W:k, zmm\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W0 39 /r\"    , \"AVX512_DQ\"],\n    [\"vpmovdb\"          , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 31 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovdb\"          , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 31 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovdb\"          , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 31 /r\"    , \"AVX512_F\"],\n    [\"vpmovdw\"          , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 33 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovdw\"          , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 33 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovdw\"          , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 33 /r\"    , \"AVX512_F\"],\n    [\"vpmovm2b\"         , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W0 28 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovm2b\"         , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W0 28 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovm2b\"         , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W0 28 /r\"    , \"AVX512_BW\"],\n    [\"vpmovm2d\"         , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W0 38 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovm2d\"         , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W0 38 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovm2d\"         , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W0 38 /r\"    , \"AVX512_DQ\"],\n    [\"vpmovm2q\"         , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W1 38 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovm2q\"         , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W1 38 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovm2q\"         , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W1 38 /r\"    , \"AVX512_DQ\"],\n    [\"vpmovm2w\"         , \"W:xmm, k\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W1 28 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovm2w\"         , \"W:ymm, k\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W1 28 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovm2w\"         , \"W:zmm, k\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W1 28 /r\"    , \"AVX512_BW\"],\n    [\"vpmovq2m\"         , \"W:k, xmm\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W1 39 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovq2m\"         , \"W:k, ymm\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W1 39 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmovq2m\"         , \"W:k, zmm\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W1 39 /r\"    , \"AVX512_DQ\"],\n    [\"vpmovqb\"          , \"W:xmm[15:0]/m16 {kz}, xmm\"                       , \"MR-OVM\"  , \"EVEX.128.F3.0F38.W0 32 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqb\"          , \"W:xmm[31:0]/m32 {kz}, ymm\"                       , \"MR-OVM\"  , \"EVEX.256.F3.0F38.W0 32 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqb\"          , \"W:xmm[63:0]/m64 {kz}, zmm\"                       , \"MR-OVM\"  , \"EVEX.512.F3.0F38.W0 32 /r\"    , \"AVX512_F\"],\n    [\"vpmovqd\"          , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 35 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqd\"          , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 35 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqd\"          , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 35 /r\"    , \"AVX512_F\"],\n    [\"vpmovqw\"          , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 34 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqw\"          , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 34 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovqw\"          , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 34 /r\"    , \"AVX512_F\"],\n    [\"vpmovsdb\"         , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 21 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsdb\"         , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 21 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsdb\"         , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 21 /r\"    , \"AVX512_F\"],\n    [\"vpmovsdw\"         , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 23 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsdw\"         , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 23 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsdw\"         , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 23 /r\"    , \"AVX512_F\"],\n    [\"vpmovsqb\"         , \"W:xmm[15:0]/m16 {kz}, xmm\"                       , \"MR-OVM\"  , \"EVEX.128.F3.0F38.W0 22 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqb\"         , \"W:xmm[31:0]/m32 {kz}, ymm\"                       , \"MR-OVM\"  , \"EVEX.256.F3.0F38.W0 22 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqb\"         , \"W:xmm[63:0]/m64 {kz}, zmm\"                       , \"MR-OVM\"  , \"EVEX.512.F3.0F38.W0 22 /r\"    , \"AVX512_F\"],\n    [\"vpmovsqd\"         , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 25 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqd\"         , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 25 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqd\"         , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 25 /r\"    , \"AVX512_F\"],\n    [\"vpmovsqw\"         , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 24 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqw\"         , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 24 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsqw\"         , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 24 /r\"    , \"AVX512_F\"],\n    [\"vpmovswb\"         , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 20 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovswb\"         , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 20 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovswb\"         , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 20 /r\"    , \"AVX512_BW\"],\n    [\"vpmovsxbd\"        , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-QVM\"  , \"EVEX.128.66.0F38.WIG 21 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxbd\"        , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-QVM\"  , \"EVEX.256.66.0F38.WIG 21 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxbd\"        , \"W:zmm {kz}, xmm/m128\"                            , \"RM-QVM\"  , \"EVEX.512.66.0F38.WIG 21 /r\"   , \"AVX512_F\"],\n    [\"vpmovsxbq\"        , \"W:xmm {kz}, xmm[15:0]/m16\"                       , \"RM-OVM\"  , \"EVEX.128.66.0F38.WIG 22 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxbq\"        , \"W:ymm {kz}, xmm[31:0]/m32\"                       , \"RM-OVM\"  , \"EVEX.256.66.0F38.WIG 22 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxbq\"        , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-OVM\"  , \"EVEX.512.66.0F38.WIG 22 /r\"   , \"AVX512_F\"],\n    [\"vpmovsxbw\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.WIG 20 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmovsxbw\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.WIG 20 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmovsxbw\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.WIG 20 /r\"   , \"AVX512_BW\"],\n    [\"vpmovsxdq\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.W0 25 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsxdq\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.W0 25 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovsxdq\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.W0 25 /r\"    , \"AVX512_F\"],\n    [\"vpmovsxwd\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.WIG 23 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxwd\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.WIG 23 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxwd\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.WIG 23 /r\"   , \"AVX512_F\"],\n    [\"vpmovsxwq\"        , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-QVM\"  , \"EVEX.128.66.0F38.WIG 24 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxwq\"        , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-QVM\"  , \"EVEX.256.66.0F38.WIG 24 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovsxwq\"        , \"W:zmm {kz}, xmm/m128\"                            , \"RM-QVM\"  , \"EVEX.512.66.0F38.WIG 24 /r\"   , \"AVX512_F\"],\n    [\"vpmovusdb\"        , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 11 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusdb\"        , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 11 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusdb\"        , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 11 /r\"    , \"AVX512_F\"],\n    [\"vpmovusdw\"        , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 13 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusdw\"        , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 13 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusdw\"        , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 13 /r\"    , \"AVX512_F\"],\n    [\"vpmovusqb\"        , \"W:xmm[15:0]/m16 {kz}, xmm\"                       , \"MR-OVM\"  , \"EVEX.128.F3.0F38.W0 12 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqb\"        , \"W:xmm[31:0]/m32 {kz}, ymm\"                       , \"MR-OVM\"  , \"EVEX.256.F3.0F38.W0 12 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqb\"        , \"W:xmm[63:0]/m64 {kz}, zmm\"                       , \"MR-OVM\"  , \"EVEX.512.F3.0F38.W0 12 /r\"    , \"AVX512_F\"],\n    [\"vpmovusqd\"        , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqd\"        , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqd\"        , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 15 /r\"    , \"AVX512_F\"],\n    [\"vpmovusqw\"        , \"W:xmm[31:0]/m32 {kz}, xmm\"                       , \"MR-QVM\"  , \"EVEX.128.F3.0F38.W0 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqw\"        , \"W:xmm[63:0]/m64 {kz}, ymm\"                       , \"MR-QVM\"  , \"EVEX.256.F3.0F38.W0 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovusqw\"        , \"W:xmm/m128 {kz}, zmm\"                            , \"MR-QVM\"  , \"EVEX.512.F3.0F38.W0 14 /r\"    , \"AVX512_F\"],\n    [\"vpmovuswb\"        , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 10 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovuswb\"        , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 10 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovuswb\"        , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 10 /r\"    , \"AVX512_BW\"],\n    [\"vpmovw2m\"         , \"W:k, xmm\"                                        , \"RM\"      , \"EVEX.128.F3.0F38.W1 29 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovw2m\"         , \"W:k, ymm\"                                        , \"RM\"      , \"EVEX.256.F3.0F38.W1 29 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovw2m\"         , \"W:k, zmm\"                                        , \"RM\"      , \"EVEX.512.F3.0F38.W1 29 /r\"    , \"AVX512_BW\"],\n    [\"vpmovwb\"          , \"W:xmm[63:0]/m64 {kz}, xmm\"                       , \"MR-HVM\"  , \"EVEX.128.F3.0F38.W0 30 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovwb\"          , \"W:xmm/m128 {kz}, ymm\"                            , \"MR-HVM\"  , \"EVEX.256.F3.0F38.W0 30 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpmovwb\"          , \"W:ymm/m256 {kz}, zmm\"                            , \"MR-HVM\"  , \"EVEX.512.F3.0F38.W0 30 /r\"    , \"AVX512_BW\"],\n    [\"vpmovzxbd\"        , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-QVM\"  , \"EVEX.128.66.0F38.WIG 31 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxbd\"        , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-QVM\"  , \"EVEX.256.66.0F38.WIG 31 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxbd\"        , \"W:zmm {kz}, xmm/m128\"                            , \"RM-QVM\"  , \"EVEX.512.66.0F38.WIG 31 /r\"   , \"AVX512_F\"],\n    [\"vpmovzxbq\"        , \"W:xmm {kz}, xmm[15:0]/m16\"                       , \"RM-OVM\"  , \"EVEX.128.66.0F38.WIG 32 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxbq\"        , \"W:ymm {kz}, xmm[31:0]/m32\"                       , \"RM-OVM\"  , \"EVEX.256.66.0F38.WIG 32 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxbq\"        , \"W:zmm {kz}, xmm[63:0]/m64\"                       , \"RM-OVM\"  , \"EVEX.512.66.0F38.WIG 32 /r\"   , \"AVX512_F\"],\n    [\"vpmovzxbw\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.WIG 30 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmovzxbw\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.WIG 30 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmovzxbw\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.WIG 30 /r\"   , \"AVX512_BW\"],\n    [\"vpmovzxdq\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.W0 35 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovzxdq\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.W0 35 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmovzxdq\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.W0 35 /r\"    , \"AVX512_F\"],\n    [\"vpmovzxwd\"        , \"W:xmm {kz}, xmm[63:0]/m64\"                       , \"RM-HVM\"  , \"EVEX.128.66.0F38.WIG 33 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxwd\"        , \"W:ymm {kz}, xmm/m128\"                            , \"RM-HVM\"  , \"EVEX.256.66.0F38.WIG 33 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxwd\"        , \"W:zmm {kz}, ymm/m256\"                            , \"RM-HVM\"  , \"EVEX.512.66.0F38.WIG 33 /r\"   , \"AVX512_F\"],\n    [\"vpmovzxwq\"        , \"W:xmm {kz}, xmm[31:0]/m32\"                       , \"RM-QVM\"  , \"EVEX.128.66.0F38.WIG 34 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxwq\"        , \"W:ymm {kz}, xmm[63:0]/m64\"                       , \"RM-QVM\"  , \"EVEX.256.66.0F38.WIG 34 /r\"   , \"AVX512_F-VL\"],\n    [\"vpmovzxwq\"        , \"W:zmm {kz}, xmm/m128\"                            , \"RM-QVM\"  , \"EVEX.512.66.0F38.WIG 34 /r\"   , \"AVX512_F\"],\n    [\"vpmuldq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 28 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmuldq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 28 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmuldq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 28 /r\"    , \"AVX512_F\"],\n    [\"vpmulhrsw\"        , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 0B /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmulhrsw\"        , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 0B /r\"   , \"AVX512_BW-VL\"],\n    [\"vpmulhrsw\"        , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 0B /r\"   , \"AVX512_BW\"],\n    [\"vpmulhuw\"         , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E4 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmulhuw\"         , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E4 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmulhuw\"         , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E4 /r\"     , \"AVX512_BW\"],\n    [\"vpmulhw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmulhw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmulhw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E5 /r\"     , \"AVX512_BW\"],\n    [\"vpmulld\"          , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 40 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmulld\"          , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 40 /r\"    , \"AVX512_F-VL\"],\n    [\"vpmulld\"          , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 40 /r\"    , \"AVX512_F\"],\n    [\"vpmullq\"          , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 40 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmullq\"          , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 40 /r\"    , \"AVX512_DQ-VL\"],\n    [\"vpmullq\"          , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 40 /r\"    , \"AVX512_DQ\"],\n    [\"vpmullw\"          , \"W:xmm {kz},~xmm,~xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG D5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmullw\"          , \"W:ymm {kz},~ymm,~ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG D5 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpmullw\"          , \"W:zmm {kz},~zmm,~zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG D5 /r\"     , \"AVX512_BW\"],\n    [\"vpmultishiftqb\"   , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 83 /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpmultishiftqb\"   , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 83 /r\"    , \"AVX512_VBMI-VL\"],\n    [\"vpmultishiftqb\"   , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 83 /r\"    , \"AVX512_VBMI\"],\n    [\"vpmuludq\"         , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 F4 /r\"      , \"AVX512_F-VL\"],\n    [\"vpmuludq\"         , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 F4 /r\"      , \"AVX512_F-VL\"],\n    [\"vpmuludq\"         , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 F4 /r\"      , \"AVX512_F\"],\n    [\"vpopcntb\"         , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38.W0 54 /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpopcntb\"         , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38.W0 54 /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpopcntb\"         , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38.W0 54 /r\"    , \"AVX512_BITALG\"],\n    [\"vpopcntd\"         , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FVM\"  , \"EVEX.128.66.0F38.W0 55 /r\"    , \"AVX512_VPOPCNTDQ-VL\"],\n    [\"vpopcntd\"         , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FVM\"  , \"EVEX.256.66.0F38.W0 55 /r\"    , \"AVX512_VPOPCNTDQ-VL\"],\n    [\"vpopcntd\"         , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FVM\"  , \"EVEX.512.66.0F38.W0 55 /r\"    , \"AVX512_VPOPCNTDQ\"],\n    [\"vpopcntq\"         , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FVM\"  , \"EVEX.128.66.0F38.W1 55 /r\"    , \"AVX512_VPOPCNTDQ-VL\"],\n    [\"vpopcntq\"         , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FVM\"  , \"EVEX.256.66.0F38.W1 55 /r\"    , \"AVX512_VPOPCNTDQ-VL\"],\n    [\"vpopcntq\"         , \"W:zmm {kz}, zmm/m512/b64\"                        , \"RM-FVM\"  , \"EVEX.512.66.0F38.W1 55 /r\"    , \"AVX512_VPOPCNTDQ\"],\n    [\"vpopcntw\"         , \"W:xmm {kz}, xmm/m128\"                            , \"RM-FVM\"  , \"EVEX.128.66.0F38.W1 54 /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpopcntw\"         , \"W:ymm {kz}, ymm/m256\"                            , \"RM-FVM\"  , \"EVEX.256.66.0F38.W1 54 /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpopcntw\"         , \"W:zmm {kz}, zmm/m512\"                            , \"RM-FVM\"  , \"EVEX.512.66.0F38.W1 54 /r\"    , \"AVX512_BITALG\"],\n    [\"vpord\"            , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 EB /r\"      , \"AVX512_F-VL\"],\n    [\"vpord\"            , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 EB /r\"      , \"AVX512_F-VL\"],\n    [\"vpord\"            , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 EB /r\"      , \"AVX512_F\"],\n    [\"vporq\"            , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 EB /r\"      , \"AVX512_F-VL\"],\n    [\"vporq\"            , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 EB /r\"      , \"AVX512_F-VL\"],\n    [\"vporq\"            , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 EB /r\"      , \"AVX512_F\"],\n    [\"vprold\"           , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W0 72 /1 ib\"   , \"AVX512_F-VL\"],\n    [\"vprold\"           , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W0 72 /1 ib\"   , \"AVX512_F-VL\"],\n    [\"vprold\"           , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W0 72 /1 ib\"   , \"AVX512_F\"],\n    [\"vprolq\"           , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W1 72 /1 ib\"   , \"AVX512_F-VL\"],\n    [\"vprolq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W1 72 /1 ib\"   , \"AVX512_F-VL\"],\n    [\"vprolq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W1 72 /1 ib\"   , \"AVX512_F\"],\n    [\"vprolvd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vprolvd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vprolvd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 15 /r\"    , \"AVX512_F\"],\n    [\"vprolvq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vprolvq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 15 /r\"    , \"AVX512_F-VL\"],\n    [\"vprolvq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 15 /r\"    , \"AVX512_F\"],\n    [\"vprord\"           , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W0 72 /0 ib\"   , \"AVX512_F-VL\"],\n    [\"vprord\"           , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W0 72 /0 ib\"   , \"AVX512_F-VL\"],\n    [\"vprord\"           , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W0 72 /0 ib\"   , \"AVX512_F\"],\n    [\"vprorq\"           , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W1 72 /0 ib\"   , \"AVX512_F-VL\"],\n    [\"vprorq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W1 72 /0 ib\"   , \"AVX512_F-VL\"],\n    [\"vprorq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W1 72 /0 ib\"   , \"AVX512_F\"],\n    [\"vprorvd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vprorvd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vprorvd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 14 /r\"    , \"AVX512_F\"],\n    [\"vprorvq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vprorvq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 14 /r\"    , \"AVX512_F-VL\"],\n    [\"vprorvq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 14 /r\"    , \"AVX512_F\"],\n    [\"vpsadbw\"          , \"W:xmm,~xmm,~xmm/m128\"                            , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG F6 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsadbw\"          , \"W:ymm,~ymm,~ymm/m256\"                            , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG F6 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsadbw\"          , \"W:zmm,~zmm,~zmm/m512\"                            , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG F6 /r\"     , \"AVX512_BW\"],\n    [\"vpscatterdd\"      , \"W:vm32x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 A0 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterdd\"      , \"W:vm32y {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 A0 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterdd\"      , \"W:vm32z {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 A0 /r\"    , \"AVX512_F\"],\n    [\"vpscatterdq\"      , \"W:vm32x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 A0 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterdq\"      , \"W:vm32x {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 A0 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterdq\"      , \"W:vm32y {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 A0 /r\"    , \"AVX512_F\"],\n    [\"vpscatterqd\"      , \"W:vm64x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 A1 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterqd\"      , \"W:vm64y {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 A1 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterqd\"      , \"W:vm64z {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 A1 /r\"    , \"AVX512_F\"],\n    [\"vpscatterqq\"      , \"W:vm64x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 A1 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterqq\"      , \"W:vm64y {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 A1 /r\"    , \"AVX512_F-VL\"],\n    [\"vpscatterqq\"      , \"W:vm64z {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 A1 /r\"    , \"AVX512_F\"],\n    [\"vpshldd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W0 71 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W0 71 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W0 71 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshldq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 71 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 71 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 71 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshldvd\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 71 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvd\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 71 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvd\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 71 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshldvq\"         , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 71 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvq\"         , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 71 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvq\"         , \"X:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 71 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshldvw\"         , \"X:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 70 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvw\"         , \"X:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 70 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshldvw\"         , \"X:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 70 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshldw\"          , \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 70 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldw\"          , \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 70 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshldw\"          , \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 70 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshrdd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W0 73 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W0 73 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W0 73 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshrdq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.128.66.0F3A.W1 73 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.256.66.0F3A.W1 73 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FVM\", \"EVEX.512.66.0F3A.W1 73 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshrdvd\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 73 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvd\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 73 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvd\"         , \"X:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 73 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshrdvq\"         , \"X:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 73 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvq\"         , \"X:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 73 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvq\"         , \"X:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 73 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshrdvw\"         , \"X:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 72 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvw\"         , \"X:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 72 /r\"    , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdvw\"         , \"X:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 72 /r\"    , \"AVX512_VBMI2\"],\n    [\"vpshrdw\"          , \"W:xmm {kz}, xmm, xmm/m128, ib/ub\"                , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 72 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdw\"          , \"W:ymm {kz}, ymm, ymm/m256, ib/ub\"                , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 72 /r ib\" , \"AVX512_VBMI2-VL\"],\n    [\"vpshrdw\"          , \"W:zmm {kz}, zmm, zmm/m512, ib/ub\"                , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 72 /r ib\" , \"AVX512_VBMI2\"],\n    [\"vpshufb\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.WIG 00 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpshufb\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.WIG 00 /r\"   , \"AVX512_BW-VL\"],\n    [\"vpshufb\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.WIG 00 /r\"   , \"AVX512_BW\"],\n    [\"vpshufbitqmb\"     , \"W:k {k}, xmm, xmm/m128\"                          , \"RM-FVM\"  , \"EVEX.128.66.0F38.W0 8F /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpshufbitqmb\"     , \"W:k {k}, ymm, ymm/m256\"                          , \"RM-FVM\"  , \"EVEX.256.66.0F38.W0 8F /r\"    , \"AVX512_BITALG-VL\"],\n    [\"vpshufbitqmb\"     , \"W:k {k}, zmm, zmm/m512\"                          , \"RM-FVM\"  , \"EVEX.512.66.0F38.W0 8F /r\"    , \"AVX512_BITALG\"],\n    [\"vpshufd\"          , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F.W0 70 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vpshufd\"          , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F.W0 70 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vpshufd\"          , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F.W0 70 /r ib\"   , \"AVX512_F\"],\n    [\"vpshufhw\"         , \"W:xmm {kz}, xmm/m128, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.128.F3.0F.WIG 70 /r ib\"  , \"AVX512_BW-VL\"],\n    [\"vpshufhw\"         , \"W:ymm {kz}, ymm/m256, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.256.F3.0F.WIG 70 /r ib\"  , \"AVX512_BW-VL\"],\n    [\"vpshufhw\"         , \"W:zmm {kz}, zmm/m512, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.512.F3.0F.WIG 70 /r ib\"  , \"AVX512_BW\"],\n    [\"vpshuflw\"         , \"W:xmm {kz}, xmm/m128, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.128.F2.0F.WIG 70 /r ib\"  , \"AVX512_BW-VL\"],\n    [\"vpshuflw\"         , \"W:ymm {kz}, ymm/m256, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.256.F2.0F.WIG 70 /r ib\"  , \"AVX512_BW-VL\"],\n    [\"vpshuflw\"         , \"W:zmm {kz}, zmm/m512, ib/ub\"                     , \"RMI-FVM\" , \"EVEX.512.F2.0F.WIG 70 /r ib\"  , \"AVX512_BW\"],\n    [\"vpslld\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W0 F2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpslld\"           , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W0 72 /6 ib\"   , \"AVX512_F-VL\"],\n    [\"vpslld\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W0 F2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpslld\"           , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W0 72 /6 ib\"   , \"AVX512_F-VL\"],\n    [\"vpslld\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W0 F2 /r\"      , \"AVX512_F\"],\n    [\"vpslld\"           , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W0 72 /6 ib\"   , \"AVX512_F\"],\n    [\"vpslldq\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.128.66.0F.WIG 73 /7 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpslldq\"          , \"W:ymm, ymm/m256, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.256.66.0F.WIG 73 /7 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpslldq\"          , \"W:zmm, zmm/m512, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.512.66.0F.WIG 73 /7 ib\"  , \"AVX512_BW\"],\n    [\"vpsllq\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W1 F3 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsllq\"           , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W1 73 /6 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsllq\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W1 F3 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsllq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W1 73 /6 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsllq\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W1 F3 /r\"      , \"AVX512_F\"],\n    [\"vpsllq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W1 73 /6 ib\"   , \"AVX512_F\"],\n    [\"vpsllvd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 47 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsllvd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 47 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsllvd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 47 /r\"    , \"AVX512_F\"],\n    [\"vpsllvq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 47 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsllvq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 47 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsllvq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 47 /r\"    , \"AVX512_F\"],\n    [\"vpsllvw\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 12 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsllvw\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 12 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsllvw\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 12 /r\"    , \"AVX512_BW\"],\n    [\"vpsllw\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.WIG F1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsllw\"           , \"W:xmm {kz}, xmm/m128, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.128.66.0F.WIG 71 /6 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsllw\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.WIG F1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsllw\"           , \"W:ymm {kz}, ymm/m256, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.256.66.0F.WIG 71 /6 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsllw\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.WIG F1 /r\"     , \"AVX512_BW\"],\n    [\"vpsllw\"           , \"W:zmm {kz}, zmm/m512, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.512.66.0F.WIG 71 /6 ib\"  , \"AVX512_BW\"],\n    [\"vpsrad\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W0 E2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrad\"           , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W0 72 /4 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrad\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W0 E2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrad\"           , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W0 72 /4 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrad\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W0 E2 /r\"      , \"AVX512_F\"],\n    [\"vpsrad\"           , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W0 72 /4 ib\"   , \"AVX512_F\"],\n    [\"vpsraq\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W1 E2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsraq\"           , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W1 72 /4 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsraq\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W1 E2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsraq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W1 72 /4 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsraq\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W1 E2 /r\"      , \"AVX512_F\"],\n    [\"vpsraq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W1 72 /4 ib\"   , \"AVX512_F\"],\n    [\"vpsravd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 46 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsravd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 46 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsravd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 46 /r\"    , \"AVX512_F\"],\n    [\"vpsravq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 46 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsravq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 46 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsravq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 46 /r\"    , \"AVX512_F\"],\n    [\"vpsravw\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 11 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsravw\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 11 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsravw\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 11 /r\"    , \"AVX512_BW\"],\n    [\"vpsraw\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.WIG E1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsraw\"           , \"W:xmm {kz}, xmm/m128, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.128.66.0F.WIG 71 /4 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsraw\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.WIG E1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsraw\"           , \"W:ymm {kz}, ymm/m256, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.256.66.0F.WIG 71 /4 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsraw\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.WIG E1 /r\"     , \"AVX512_BW\"],\n    [\"vpsraw\"           , \"W:zmm {kz}, zmm/m512, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.512.66.0F.WIG 71 /4 ib\"  , \"AVX512_BW\"],\n    [\"vpsrld\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W0 D2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrld\"           , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W0 72 /2 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrld\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W0 D2 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrld\"           , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W0 72 /2 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrld\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W0 D2 /r\"      , \"AVX512_F\"],\n    [\"vpsrld\"           , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W0 72 /2 ib\"   , \"AVX512_F\"],\n    [\"vpsrldq\"          , \"W:xmm, xmm/m128, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.128.66.0F.WIG 73 /3 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsrldq\"          , \"W:ymm, ymm/m256, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.256.66.0F.WIG 73 /3 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsrldq\"          , \"W:zmm, zmm/m512, ib/ub\"                          , \"VMI-FVM\" , \"EVEX.512.66.0F.WIG 73 /3 ib\"  , \"AVX512_BW\"],\n    [\"vpsrlq\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.W1 D3 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrlq\"           , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.128.66.0F.W1 73 /2 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrlq\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.W1 D3 /r\"      , \"AVX512_F-VL\"],\n    [\"vpsrlq\"           , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.256.66.0F.W1 73 /2 ib\"   , \"AVX512_F-VL\"],\n    [\"vpsrlq\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.W1 D3 /r\"      , \"AVX512_F\"],\n    [\"vpsrlq\"           , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"VMI-FV\"  , \"EVEX.512.66.0F.W1 73 /2 ib\"   , \"AVX512_F\"],\n    [\"vpsrlvd\"          , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 45 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsrlvd\"          , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 45 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsrlvd\"          , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 45 /r\"    , \"AVX512_F\"],\n    [\"vpsrlvq\"          , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 45 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsrlvq\"          , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 45 /r\"    , \"AVX512_F-VL\"],\n    [\"vpsrlvq\"          , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 45 /r\"    , \"AVX512_F\"],\n    [\"vpsrlvw\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 10 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsrlvw\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 10 /r\"    , \"AVX512_BW-VL\"],\n    [\"vpsrlvw\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 10 /r\"    , \"AVX512_BW\"],\n    [\"vpsrlw\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.128.66.0F.WIG D1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsrlw\"           , \"W:xmm {kz}, xmm/m128, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.128.66.0F.WIG 71 /2 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsrlw\"           , \"W:ymm {kz}, ymm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.256.66.0F.WIG D1 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsrlw\"           , \"W:ymm {kz}, ymm/m256, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.256.66.0F.WIG 71 /2 ib\"  , \"AVX512_BW-VL\"],\n    [\"vpsrlw\"           , \"W:zmm {kz}, zmm, xmm/m128\"                       , \"RVM-M128\", \"EVEX.512.66.0F.WIG D1 /r\"     , \"AVX512_BW\"],\n    [\"vpsrlw\"           , \"W:zmm {kz}, zmm/m512, ib/ub\"                     , \"VMI-FVM\" , \"EVEX.512.66.0F.WIG 71 /2 ib\"  , \"AVX512_BW\"],\n    [\"vpsubb\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG F8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubb\"           , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG F8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubb\"           , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG F8 /r\"     , \"AVX512_BW\"],\n    [\"vpsubd\"           , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 FA /r\"      , \"AVX512_F-VL\"],\n    [\"vpsubd\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 FA /r\"      , \"AVX512_F-VL\"],\n    [\"vpsubd\"           , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 FA /r\"      , \"AVX512_F\"],\n    [\"vpsubq\"           , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 FB /r\"      , \"AVX512_F-VL\"],\n    [\"vpsubq\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 FB /r\"      , \"AVX512_F-VL\"],\n    [\"vpsubq\"           , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 FB /r\"      , \"AVX512_F\"],\n    [\"vpsubsb\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubsb\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubsb\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E8 /r\"     , \"AVX512_BW\"],\n    [\"vpsubsw\"          , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG E9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubsw\"          , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG E9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubsw\"          , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG E9 /r\"     , \"AVX512_BW\"],\n    [\"vpsubusb\"         , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG D8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubusb\"         , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG D8 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubusb\"         , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG D8 /r\"     , \"AVX512_BW\"],\n    [\"vpsubusw\"         , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG D9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubusw\"         , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG D9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubusw\"         , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG D9 /r\"     , \"AVX512_BW\"],\n    [\"vpsubw\"           , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG F9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubw\"           , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG F9 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpsubw\"           , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG F9 /r\"     , \"AVX512_BW\"],\n    [\"vpternlogd\"       , \"X:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 25 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpternlogd\"       , \"X:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 25 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpternlogd\"       , \"X:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 25 /r ib\" , \"AVX512_F\"],\n    [\"vpternlogq\"       , \"X:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 25 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpternlogq\"       , \"X:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 25 /r ib\" , \"AVX512_F-VL\"],\n    [\"vpternlogq\"       , \"X:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 25 /r ib\" , \"AVX512_F\"],\n    [\"vptestmb\"         , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FVM\" , \"EVEX.128.66.0F38.W0 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestmb\"         , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FVM\" , \"EVEX.256.66.0F38.W0 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestmb\"         , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FVM\" , \"EVEX.512.66.0F38.W0 26 /r\"    , \"AVX512_BW\"],\n    [\"vptestmd\"         , \"W:k {k}, xmm, xmm/m128/b32\"                      , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestmd\"         , \"W:k {k}, ymm, ymm/m256/b32\"                      , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestmd\"         , \"W:k {k}, zmm, zmm/m512/b32\"                      , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 27 /r\"    , \"AVX512_F\"],\n    [\"vptestmq\"         , \"W:k {k}, xmm, xmm/m128/b64\"                      , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestmq\"         , \"W:k {k}, ymm, ymm/m256/b64\"                      , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestmq\"         , \"W:k {k}, zmm, zmm/m512/b64\"                      , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 27 /r\"    , \"AVX512_F\"],\n    [\"vptestmw\"         , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FVM\" , \"EVEX.128.66.0F38.W1 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestmw\"         , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FVM\" , \"EVEX.256.66.0F38.W1 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestmw\"         , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FVM\" , \"EVEX.512.66.0F38.W1 26 /r\"    , \"AVX512_BW\"],\n    [\"vptestnmb\"        , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FVM\" , \"EVEX.128.F3.0F38.W0 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestnmb\"        , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FVM\" , \"EVEX.256.F3.0F38.W0 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestnmb\"        , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FVM\" , \"EVEX.512.F3.0F38.W0 26 /r\"    , \"AVX512_BW\"],\n    [\"vptestnmd\"        , \"W:k {k}, xmm, xmm/m128/b32\"                      , \"RVM-FV\"  , \"EVEX.128.F3.0F38.W0 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestnmd\"        , \"W:k {k}, ymm, ymm/m256/b32\"                      , \"RVM-FV\"  , \"EVEX.256.F3.0F38.W0 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestnmd\"        , \"W:k {k}, zmm, zmm/m512/b32\"                      , \"RVM-FV\"  , \"EVEX.512.F3.0F38.W0 27 /r\"    , \"AVX512_F\"],\n    [\"vptestnmq\"        , \"W:k {k}, xmm, xmm/m128/b64\"                      , \"RVM-FV\"  , \"EVEX.128.F3.0F38.W1 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestnmq\"        , \"W:k {k}, ymm, ymm/m256/b64\"                      , \"RVM-FV\"  , \"EVEX.256.F3.0F38.W1 27 /r\"    , \"AVX512_F-VL\"],\n    [\"vptestnmq\"        , \"W:k {k}, zmm, zmm/m512/b64\"                      , \"RVM-FV\"  , \"EVEX.512.F3.0F38.W1 27 /r\"    , \"AVX512_F\"],\n    [\"vptestnmw\"        , \"W:k {k}, xmm, xmm/m128\"                          , \"RVM-FVM\" , \"EVEX.128.F3.0F38.W1 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestnmw\"        , \"W:k {k}, ymm, ymm/m256\"                          , \"RVM-FVM\" , \"EVEX.256.F3.0F38.W1 26 /r\"    , \"AVX512_BW-VL\"],\n    [\"vptestnmw\"        , \"W:k {k}, zmm, zmm/m512\"                          , \"RVM-FVM\" , \"EVEX.512.F3.0F38.W1 26 /r\"    , \"AVX512_BW\"],\n    [\"vpunpckhbw\"       , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 68 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpckhbw\"       , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 68 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpckhbw\"       , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 68 /r\"     , \"AVX512_BW\"],\n    [\"vpunpckhdq\"       , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 6A /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckhdq\"       , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 6A /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckhdq\"       , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 6A /r\"      , \"AVX512_F\"],\n    [\"vpunpckhqdq\"      , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 6D /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckhqdq\"      , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 6D /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckhqdq\"      , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 6D /r\"      , \"AVX512_F\"],\n    [\"vpunpckhwd\"       , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 69 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpckhwd\"       , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 69 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpckhwd\"       , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 69 /r\"     , \"AVX512_BW\"],\n    [\"vpunpcklbw\"       , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 60 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpcklbw\"       , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 60 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpcklbw\"       , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 60 /r\"     , \"AVX512_BW\"],\n    [\"vpunpckldq\"       , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 62 /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckldq\"       , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 62 /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpckldq\"       , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 62 /r\"      , \"AVX512_F\"],\n    [\"vpunpcklqdq\"      , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 6C /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpcklqdq\"      , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 6C /r\"      , \"AVX512_F-VL\"],\n    [\"vpunpcklqdq\"      , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 6C /r\"      , \"AVX512_F\"],\n    [\"vpunpcklwd\"       , \"W:xmm {kz}, xmm, xmm/m128\"                       , \"RVM-FVM\" , \"EVEX.128.66.0F.WIG 61 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpcklwd\"       , \"W:ymm {kz}, ymm, ymm/m256\"                       , \"RVM-FVM\" , \"EVEX.256.66.0F.WIG 61 /r\"     , \"AVX512_BW-VL\"],\n    [\"vpunpcklwd\"       , \"W:zmm {kz}, zmm, zmm/m512\"                       , \"RVM-FVM\" , \"EVEX.512.66.0F.WIG 61 /r\"     , \"AVX512_BW\"],\n    [\"vpxord\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W0 EF /r\"      , \"AVX512_F-VL\"],\n    [\"vpxord\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W0 EF /r\"      , \"AVX512_F-VL\"],\n    [\"vpxord\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W0 EF /r\"      , \"AVX512_F\"],\n    [\"vpxorq\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 EF /r\"      , \"AVX512_F-VL\"],\n    [\"vpxorq\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 EF /r\"      , \"AVX512_F-VL\"],\n    [\"vpxorq\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 EF /r\"      , \"AVX512_F\"],\n    [\"vrangepd\"         , \"W:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W1 50 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vrangepd\"         , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 50 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vrangepd\"         , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub {sae}\"      , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 50 /r ib\" , \"AVX512_DQ\"],\n    [\"vrangeps\"         , \"W:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F3A.W0 50 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vrangeps\"         , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 50 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vrangeps\"         , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub {sae}\"      , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 50 /r ib\" , \"AVX512_DQ\"],\n    [\"vrangesd\"         , \"W:xmm {kz},xmm[127:64],xmm[63:0]/m64,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W1 51 /r ib\" , \"AVX512_DQ\"],\n    [\"vrangess\"         , \"W:xmm {kz},xmm[127:32],xmm[31:0]/m32,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W0 51 /r ib\" , \"AVX512_DQ\"],\n    [\"vrcp14pd\"         , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 4C /r\"    , \"AVX512_F-VL\"],\n    [\"vrcp14pd\"         , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 4C /r\"    , \"AVX512_F-VL\"],\n    [\"vrcp14pd\"         , \"W:zmm {kz}, zmm/m512/b64\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 4C /r\"    , \"AVX512_F\"],\n    [\"vrcp14ps\"         , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 4C /r\"    , \"AVX512_F-VL\"],\n    [\"vrcp14ps\"         , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 4C /r\"    , \"AVX512_F-VL\"],\n    [\"vrcp14ps\"         , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 4C /r\"    , \"AVX512_F\"],\n    [\"vrcp14sd\"         , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64\"          , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 4D /r\"    , \"AVX512_F\"],\n    [\"vrcp14ss\"         , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32\"          , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 4D /r\"    , \"AVX512_F\"],\n    [\"vrcp28pd\"         , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 CA /r\"    , \"AVX512_ERI\"],\n    [\"vrcp28ps\"         , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 CA /r\"    , \"AVX512_ERI\"],\n    [\"vrcp28sd\"         , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64 {sae}\"    , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 CB /r\"    , \"AVX512_ERI\"],\n    [\"vrcp28ss\"         , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32 {sae}\"    , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 CB /r\"    , \"AVX512_ERI\"],\n    [\"vreducepd\"        , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W1 56 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vreducepd\"        , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 56 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vreducepd\"        , \"W:zmm {kz}, zmm/m512/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 56 /r ib\" , \"AVX512_DQ\"],\n    [\"vreduceps\"        , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W0 56 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vreduceps\"        , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W0 56 /r ib\" , \"AVX512_DQ-VL\"],\n    [\"vreduceps\"        , \"W:zmm {kz}, zmm/m512/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W0 56 /r ib\" , \"AVX512_DQ\"],\n    [\"vreducesd\"        , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64, ib/ub\"   , \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W1 57 /r ib\" , \"AVX512_DQ\"],\n    [\"vreducess\"        , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32, ib/ub\"   , \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W0 57 /r ib\" , \"AVX512_DQ\"],\n    [\"vrndscalepd\"      , \"W:xmm {kz}, xmm/m128/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W1 09 /r ib\" , \"AVX512_F-VL\"],\n    [\"vrndscalepd\"      , \"W:ymm {kz}, ymm/m256/b64, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W1 09 /r ib\" , \"AVX512_F-VL\"],\n    [\"vrndscalepd\"      , \"W:zmm {kz}, zmm/m512/b64, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W1 09 /r ib\" , \"AVX512_F\"],\n    [\"vrndscaleps\"      , \"W:xmm {kz}, xmm/m128/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.66.0F3A.W0 08 /r ib\" , \"AVX512_F-VL\"],\n    [\"vrndscaleps\"      , \"W:ymm {kz}, ymm/m256/b32, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.66.0F3A.W0 08 /r ib\" , \"AVX512_F-VL\"],\n    [\"vrndscaleps\"      , \"W:zmm {kz}, zmm/m512/b32, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.66.0F3A.W0 08 /r ib\" , \"AVX512_F\"],\n    [\"vrndscalesd\"      , \"W:xmm {kz},xmm[127:64],xmm[63:0]/m64,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W1 0B /r ib\" , \"AVX512_F\"],\n    [\"vrndscaless\"      , \"W:xmm {kz},xmm[127:32],xmm[31:0]/m32,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.66.0F3A.W0 0A /r ib\" , \"AVX512_F\"],\n    [\"vrsqrt14pd\"       , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W1 4E /r\"    , \"AVX512_F-VL\"],\n    [\"vrsqrt14pd\"       , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W1 4E /r\"    , \"AVX512_F-VL\"],\n    [\"vrsqrt14pd\"       , \"W:zmm {kz}, zmm/m512/b64\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 4E /r\"    , \"AVX512_F\"],\n    [\"vrsqrt14ps\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.0F38.W0 4E /r\"    , \"AVX512_F-VL\"],\n    [\"vrsqrt14ps\"       , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.0F38.W0 4E /r\"    , \"AVX512_F-VL\"],\n    [\"vrsqrt14ps\"       , \"W:zmm {kz}, zmm/m512/b32\"                        , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 4E /r\"    , \"AVX512_F\"],\n    [\"vrsqrt14sd\"       , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64\"          , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 4F /r\"    , \"AVX512_F\"],\n    [\"vrsqrt14ss\"       , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32\"          , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 4F /r\"    , \"AVX512_F\"],\n    [\"vrsqrt28pd\"       , \"W:zmm {kz}, zmm/m512/b64 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W1 CC /r\"    , \"AVX512_ERI\"],\n    [\"vrsqrt28ps\"       , \"W:zmm {kz}, zmm/m512/b32 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.0F38.W0 CC /r\"    , \"AVX512_ERI\"],\n    [\"vrsqrt28sd\"       , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64 {sae}\"    , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 CD /r\"    , \"AVX512_ERI\"],\n    [\"vrsqrt28ss\"       , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32 {sae}\"    , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 CD /r\"    , \"AVX512_ERI\"],\n    [\"vscalefpd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W1 2C /r\"    , \"AVX512_F-VL\"],\n    [\"vscalefpd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W1 2C /r\"    , \"AVX512_F-VL\"],\n    [\"vscalefpd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W1 2C /r\"    , \"AVX512_F\"],\n    [\"vscalefps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F38.W0 2C /r\"    , \"AVX512_F-VL\"],\n    [\"vscalefps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F38.W0 2C /r\"    , \"AVX512_F-VL\"],\n    [\"vscalefps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F38.W0 2C /r\"    , \"AVX512_F\"],\n    [\"vscalefsd\"        , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W1 2D /r\"    , \"AVX512_F\"],\n    [\"vscalefss\"        , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.0F38.W0 2D /r\"    , \"AVX512_F\"],\n    [\"vscatterdpd\"      , \"W:vm32x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 A2 /r\"    , \"AVX512_F-VL\"],\n    [\"vscatterdpd\"      , \"W:vm32x {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 A2 /r\"    , \"AVX512_F-VL\"],\n    [\"vscatterdpd\"      , \"W:vm32y {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 A2 /r\"    , \"AVX512_F\"],\n    [\"vscatterdps\"      , \"W:vm32x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 A2 /r\"    , \"AVX512_F-VL\"],\n    [\"vscatterdps\"      , \"W:vm32y {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 A2 /r\"    , \"AVX512_F-VL\"],\n    [\"vscatterdps\"      , \"W:vm32z {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 A2 /r\"    , \"AVX512_F\"],\n    [\"vscatterpf0dpd\"   , \"R:vm32y {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C6 /5\"    , \"AVX512_PFI\"],\n    [\"vscatterpf0dps\"   , \"R:vm32z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C6 /5\"    , \"AVX512_PFI\"],\n    [\"vscatterpf0qpd\"   , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C7 /5\"    , \"AVX512_PFI\"],\n    [\"vscatterpf0qps\"   , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C7 /5\"    , \"AVX512_PFI\"],\n    [\"vscatterpf1dpd\"   , \"R:vm32y {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C6 /6\"    , \"AVX512_PFI\"],\n    [\"vscatterpf1dps\"   , \"R:vm32z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C6 /6\"    , \"AVX512_PFI\"],\n    [\"vscatterpf1qpd\"   , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W1 C7 /6\"    , \"AVX512_PFI\"],\n    [\"vscatterpf1qps\"   , \"R:vm64z {k}\"                                     , \"M-T1S\"   , \"EVEX.512.66.0F38.W0 C7 /6\"    , \"AVX512_PFI\"],\n    [\"vscatterqpd\"      , \"W:vm64x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W1 A3\"       , \"AVX512_F-VL\"],\n    [\"vscatterqpd\"      , \"W:vm64y {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W1 A3\"       , \"AVX512_F-VL\"],\n    [\"vscatterqpd\"      , \"W:vm64z {k}, zmm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W1 A3\"       , \"AVX512_F\"],\n    [\"vscatterqps\"      , \"W:vm64x {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.128.66.0F38.W0 A3\"       , \"AVX512_F-VL\"],\n    [\"vscatterqps\"      , \"W:vm64y {k}, xmm\"                                , \"MR-T1S\"  , \"EVEX.256.66.0F38.W0 A3\"       , \"AVX512_F-VL\"],\n    [\"vscatterqps\"      , \"W:vm64z {k}, ymm\"                                , \"MR-T1S\"  , \"EVEX.512.66.0F38.W0 A3\"       , \"AVX512_F\"],\n    [\"vshuff32x4\"       , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 23 /r ib\" , \"AVX512_F-VL\"],\n    [\"vshuff32x4\"       , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 23 /r ib\" , \"AVX512_F\"],\n    [\"vshuff64x2\"       , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 23 /r ib\" , \"AVX512_F-VL\"],\n    [\"vshuff64x2\"       , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 23 /r ib\" , \"AVX512_F\"],\n    [\"vshufi32x4\"       , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W0 43 /r ib\" , \"AVX512_F-VL\"],\n    [\"vshufi32x4\"       , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W0 43 /r ib\" , \"AVX512_F\"],\n    [\"vshufi64x2\"       , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F3A.W1 43 /r ib\" , \"AVX512_F-VL\"],\n    [\"vshufi64x2\"       , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F3A.W1 43 /r ib\" , \"AVX512_F\"],\n    [\"vshufpd\"          , \"W:xmm {kz}, xmm, xmm/m128/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.66.0F.W1 C6 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vshufpd\"          , \"W:ymm {kz}, ymm, ymm/m256/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.66.0F.W1 C6 /r ib\"   , \"AVX512_F-VL\"],\n    [\"vshufpd\"          , \"W:zmm {kz}, zmm, zmm/m512/b64, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.66.0F.W1 C6 /r ib\"   , \"AVX512_F\"],\n    [\"vshufps\"          , \"W:xmm {kz}, xmm, xmm/m128/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.128.0F.W0 C6 /r ib\"      , \"AVX512_F-VL\"],\n    [\"vshufps\"          , \"W:ymm {kz}, ymm, ymm/m256/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.256.0F.W0 C6 /r ib\"      , \"AVX512_F-VL\"],\n    [\"vshufps\"          , \"W:zmm {kz}, zmm, zmm/m512/b32, ib/ub\"            , \"RVMI-FV\" , \"EVEX.512.0F.W0 C6 /r ib\"      , \"AVX512_F\"],\n    [\"vsqrtpd\"          , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.0F.W1 51 /r\"      , \"AVX512_F-VL\"],\n    [\"vsqrtpd\"          , \"W:ymm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.0F.W1 51 /r\"      , \"AVX512_F-VL\"],\n    [\"vsqrtpd\"          , \"W:zmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.0F.W1 51 /r\"      , \"AVX512_F\"],\n    [\"vsqrtps\"          , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.0F.W0 51 /r\"         , \"AVX512_F-VL\"],\n    [\"vsqrtps\"          , \"W:ymm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.0F.W0 51 /r\"         , \"AVX512_F-VL\"],\n    [\"vsqrtps\"          , \"W:zmm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.0F.W0 51 /r\"         , \"AVX512_F\"],\n    [\"vsqrtsd\"          , \"W:xmm {kz}, xmm[127:64], xmm[63:0]/m64 {er}\"     , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 51 /r\"      , \"AVX512_F\"],\n    [\"vsqrtss\"          , \"W:xmm {kz}, xmm[127:32], xmm[31:0]/m32 {er}\"     , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 51 /r\"      , \"AVX512_F\"],\n    [\"vsubpd\"           , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 5C /r\"      , \"AVX512_F-VL\"],\n    [\"vsubpd\"           , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 5C /r\"      , \"AVX512_F-VL\"],\n    [\"vsubpd\"           , \"W:zmm {kz}, zmm, zmm/m512/b64 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 5C /r\"      , \"AVX512_F\"],\n    [\"vsubps\"           , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 5C /r\"         , \"AVX512_F-VL\"],\n    [\"vsubps\"           , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 5C /r\"         , \"AVX512_F-VL\"],\n    [\"vsubps\"           , \"W:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.0F.W0 5C /r\"         , \"AVX512_F\"],\n    [\"vsubsd\"           , \"W:xmm {kz}, xmm, xmm[63:0]/m64 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F2.0F.W1 5C /r\"      , \"AVX512_F\"],\n    [\"vsubss\"           , \"W:xmm {kz}, xmm, xmm[31:0]/m32 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.0F.W0 5C /r\"      , \"AVX512_F\"],\n    [\"vucomisd\"         , \"R:xmm[63:0], xmm[63:0]/m64 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.66.0F.W1 2E /r\"      , \"AVX512_F OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vucomiss\"         , \"R:xmm[31:0], xmm[31:0]/m32 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.0F.W0 2E /r\"         , \"AVX512_F OF=0 SF=0 ZF=W AF=0 PF=W CF=W\"],\n    [\"vunpckhpd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 15 /r\"      , \"AVX512_F-VL\"],\n    [\"vunpckhpd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 15 /r\"      , \"AVX512_F-VL\"],\n    [\"vunpckhpd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 15 /r\"      , \"AVX512_F\"],\n    [\"vunpckhps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 15 /r\"         , \"AVX512_F-VL\"],\n    [\"vunpckhps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 15 /r\"         , \"AVX512_F-VL\"],\n    [\"vunpckhps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.0F.W0 15 /r\"         , \"AVX512_F\"],\n    [\"vunpcklpd\"        , \"W:xmm {kz}, xmm, xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 14 /r\"      , \"AVX512_F-VL\"],\n    [\"vunpcklpd\"        , \"W:ymm {kz}, ymm, ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 14 /r\"      , \"AVX512_F-VL\"],\n    [\"vunpcklpd\"        , \"W:zmm {kz}, zmm, zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 14 /r\"      , \"AVX512_F\"],\n    [\"vunpcklps\"        , \"W:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 14 /r\"         , \"AVX512_F-VL\"],\n    [\"vunpcklps\"        , \"W:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 14 /r\"         , \"AVX512_F-VL\"],\n    [\"vunpcklps\"        , \"W:zmm {kz}, zmm, zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.0F.W0 14 /r\"         , \"AVX512_F\"],\n    [\"vxorpd\"           , \"W:xmm {kz},~xmm,~xmm/m128/b64\"                   , \"RVM-FV\"  , \"EVEX.128.66.0F.W1 57 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vxorpd\"           , \"W:ymm {kz},~ymm,~ymm/m256/b64\"                   , \"RVM-FV\"  , \"EVEX.256.66.0F.W1 57 /r\"      , \"AVX512_DQ-VL\"],\n    [\"vxorpd\"           , \"W:zmm {kz},~zmm,~zmm/m512/b64\"                   , \"RVM-FV\"  , \"EVEX.512.66.0F.W1 57 /r\"      , \"AVX512_DQ\"],\n    [\"vxorps\"           , \"W:xmm {kz},~xmm,~xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.0F.W0 57 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vxorps\"           , \"W:ymm {kz},~ymm,~ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.0F.W0 57 /r\"         , \"AVX512_DQ-VL\"],\n    [\"vxorps\"           , \"W:zmm {kz},~zmm,~zmm/m512/b32\"                   , \"RVM-FV\"  , \"EVEX.512.0F.W0 57 /r\"         , \"AVX512_DQ\"],\n\n    [\"vaddph\"           , \"W:xmm {kz},~xmm,~xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 58 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vaddph\"           , \"W:ymm {kz},~ymm,~ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 58 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vaddph\"           , \"W:zmm {kz},~zmm,~zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 58 /r\"    , \"AVX512_FP16\"],\n    [\"vaddsh\"           , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 58 /r\"    , \"AVX512_FP16\"],\n    [\"vcmpph\"           , \"W:k {k}, xmm, xmm/m128/b16, ib/ub\"               , \"RVMI-FV\" , \"EVEX.128.NP.0F3A.W0 C2 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vcmpph\"           , \"W:k {k}, ymm, ymm/m256/b16, ib/ub\"               , \"RVMI-FV\" , \"EVEX.256.NP.0F3A.W0 C2 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vcmpph\"           , \"W:k {k}, zmm, zmm/m512/b16, ib/ub {sae}\"         , \"RVMI-FV\" , \"EVEX.512.NP.0F3A.W0 C2 /r ib\" , \"AVX512_FP16\"],\n    [\"vcmpsh\"           , \"W:k {k}, xmm[15:0], xmm[15:0]/m16, ib/ub {sae}\"  , \"RVMI-T1S\", \"EVEX.LIG.F3.0F3A.W0 C2 /r ib\" , \"AVX512_FP16\"],\n    [\"vcomish\"          , \"R:xmm[15:0], xmm[15:0]/m16 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.NP.MAP5.W0 2F /r\"    , \"AVX512_FP16\"],\n    [\"vcvtdq2ph\"        , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.NP.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtdq2ph\"        , \"W:xmm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.NP.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtdq2ph\"        , \"W:ymm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.NP.MAP5.W0 5B /r\"    , \"AVX512_FP16\"],\n    [\"vcvtpd2ph\"        , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP5.W1 5A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtpd2ph\"        , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP5.W1 5A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtpd2ph\"        , \"W:xmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.MAP5.W1 5A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2dq\"        , \"W:xmm {kz}, xmm/m64/b16\"                         , \"RM-HV\"   , \"EVEX.128.66.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2dq\"        , \"W:ymm {kz}, xmm/m128/b16\"                        , \"RM-HV\"   , \"EVEX.256.66.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2dq\"        , \"W:zmm {kz}, ymm/m256/b16 {er}\"                   , \"RM-HV\"   , \"EVEX.512.66.MAP5.W0 5B /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2pd\"        , \"W:xmm {kz}, xmm/m32/b16\"                         , \"RM-QV\"   , \"EVEX.128.NP.MAP5.W0 5A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2pd\"        , \"W:ymm {kz}, xmm/m64/b16\"                         , \"RM-QV\"   , \"EVEX.256.NP.MAP5.W0 5A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2pd\"        , \"W:zmm {kz}, xmm/m128/b16 {sae}\"                  , \"RM-QV\"   , \"EVEX.512.NP.MAP5.W0 5A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2psx\"       , \"W:xmm {kz}, xmm/m64/b16\"                         , \"RM-HV\"   , \"EVEX.128.66.MAP6.W0 13 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2psx\"       , \"W:ymm {kz}, xmm/m128/b16\"                        , \"RM-HV\"   , \"EVEX.256.66.MAP6.W0 13 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2psx\"       , \"W:zmm {kz}, ymm/m256/b16 {sae}\"                  , \"RM-HV\"   , \"EVEX.512.66.MAP6.W0 13 /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2qq\"        , \"W:xmm {kz}, xmm/m32/b16\"                         , \"RM-QV\"   , \"EVEX.128.66.MAP5.W0 7B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2qq\"        , \"W:ymm {kz}, xmm/m64/b16\"                         , \"RM-QV\"   , \"EVEX.256.66.MAP5.W0 7B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2qq\"        , \"W:zmm {kz}, xmm/m128/b16 {er}\"                   , \"RM-QV\"   , \"EVEX.512.66.MAP5.W0 7B /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2udq\"       , \"W:xmm {kz}, xmm/m64/b16\"                         , \"RM-HV\"   , \"EVEX.128.NP.MAP5.W0 79 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2udq\"       , \"W:ymm {kz}, xmm/m128/b16\"                        , \"RM-HV\"   , \"EVEX.256.NP.MAP5.W0 79 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2udq\"       , \"W:zmm {kz}, ymm/m256/b16 {er}\"                   , \"RM-HV\"   , \"EVEX.512.NP.MAP5.W0 79 /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2uqq\"       , \"W:xmm {kz}, xmm/m32/b16\"                         , \"RM-QV\"   , \"EVEX.128.66.MAP5.W0 79 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2uqq\"       , \"W:ymm {kz}, xmm/m64/b16\"                         , \"RM-QV\"   , \"EVEX.256.66.MAP5.W0 79 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2uqq\"       , \"W:zmm {kz}, xmm/m128/b16 {er}\"                   , \"RM-QV\"   , \"EVEX.512.66.MAP5.W0 79 /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2uw\"        , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.NP.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2uw\"        , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.NP.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2uw\"        , \"W:zmm {kz}, zmm/m512/b16 {er}\"                   , \"RM-FV\"   , \"EVEX.512.NP.MAP5.W0 7D /r\"    , \"AVX512_FP16\"],\n    [\"vcvtph2w\"         , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2w\"         , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtph2w\"         , \"W:zmm {kz}, zmm/m512/b16 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.MAP5.W0 7D /r\"    , \"AVX512_FP16\"],\n    [\"vcvtps2phx\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP5.W0 1D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtps2phx\"       , \"W:xmm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP5.W0 1D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtps2phx\"       , \"W:ymm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.66.MAP5.W0 1D /r\"    , \"AVX512_FP16\"],\n    [\"vcvtqq2ph\"        , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.NP.MAP5.W1 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtqq2ph\"        , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.NP.MAP5.W1 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtqq2ph\"        , \"W:xmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.NP.MAP5.W1 5B /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsd2sh\"        , \"W:xmm {kz}, xmm, xmm/m64 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F2.MAP5.W1 5A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsh2sd\"        , \"W:xmm {kz}, xmm, xmm/m16 {sae}\"                  , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 5A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsh2si\"        , \"W:r32, xmm/m16 {er}\"                             , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 2D /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsh2si\"        , \"W:r64, xmm/m16 {er}\"                             , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W1 2D /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvtsh2ss\"        , \"W:xmm {kz}, xmm, xmm/m16 {sae}\"                  , \"RVM-T1S\" , \"EVEX.LIG.NP.MAP6.W0 13 /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsh2usi\"       , \"W:r32, xmm/m16 {er}\"                             , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 79 /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsh2usi\"       , \"W:r64, xmm/m16 {er}\"                             , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W1 79 /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvtsi2sh\"        , \"W:xmm, xmm, r32/m32 {er}\"                        , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 2A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtsi2sh\"        , \"W:xmm, xmm, r64/m64 {er}\"                        , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W1 2A /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvtss2sh\"        , \"W:xmm {kz}, xmm, xmm/m32 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.NP.MAP5.W0 1D /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2dq\"       , \"W:xmm {kz}, xmm/m64/b16\"                         , \"RM-HV\"   , \"EVEX.128.F3.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2dq\"       , \"W:ymm {kz}, xmm/m128/b16\"                        , \"RM-HV\"   , \"EVEX.256.F3.MAP5.W0 5B /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2dq\"       , \"W:zmm {kz}, ymm/m256/b16 {sae}\"                  , \"RM-HV\"   , \"EVEX.512.F3.MAP5.W0 5B /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2qq\"       , \"W:xmm {kz}, xmm/m32/b16\"                         , \"RM-QV\"   , \"EVEX.128.66.MAP5.W0 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2qq\"       , \"W:ymm {kz}, xmm/m64/b16\"                         , \"RM-QV\"   , \"EVEX.256.66.MAP5.W0 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2qq\"       , \"W:zmm {kz}, xmm/m128/b16 {sae}\"                  , \"RM-QV\"   , \"EVEX.512.66.MAP5.W0 7A /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2udq\"      , \"W:xmm {kz}, xmm/m64/b16\"                         , \"RM-HV\"   , \"EVEX.128.NP.MAP5.W0 78 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2udq\"      , \"W:ymm {kz}, xmm/m128/b16\"                        , \"RM-HV\"   , \"EVEX.256.NP.MAP5.W0 78 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2udq\"      , \"W:zmm {kz}, ymm/m256/b16 {sae}\"                  , \"RM-HV\"   , \"EVEX.512.NP.MAP5.W0 78 /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2uqq\"      , \"W:xmm {kz}, xmm/m32/b16\"                         , \"RM-QV\"   , \"EVEX.128.66.MAP5.W0 78 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2uqq\"      , \"W:ymm {kz}, xmm/m64/b16\"                         , \"RM-QV\"   , \"EVEX.256.66.MAP5.W0 78 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2uqq\"      , \"W:zmm {kz}, xmm/m128/b16 {sae}\"                  , \"RM-QV\"   , \"EVEX.512.66.MAP5.W0 78 /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2uw\"       , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.NP.MAP5.W0 7C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2uw\"       , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.NP.MAP5.W0 7C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2uw\"       , \"W:zmm {kz}, zmm/m512/b16 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.NP.MAP5.W0 7C /r\"    , \"AVX512_FP16\"],\n    [\"vcvttph2w\"        , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP5.W0 7C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2w\"        , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP5.W0 7C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvttph2w\"        , \"W:zmm {kz}, zmm/m512/b16 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.MAP5.W0 7C /r\"    , \"AVX512_FP16\"],\n    [\"vcvttsh2si\"       , \"W:r32, xmm/m16 {sae}\"                            , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 2C /r\"    , \"AVX512_FP16\"],\n    [\"vcvttsh2si\"       , \"W:r64, xmm/m16 {sae}\"                            , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W1 2C /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvttsh2usi\"      , \"W:r32, xmm/m16 {sae}\"                            , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 78 /r\"    , \"AVX512_FP16\"],\n    [\"vcvttsh2usi\"      , \"W:r64, xmm/m16 {sae}\"                            , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W1 78 /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvtudq2ph\"       , \"W:xmm {kz}, xmm/m128/b32\"                        , \"RM-FV\"   , \"EVEX.128.F2.MAP5.W0 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtudq2ph\"       , \"W:xmm {kz}, ymm/m256/b32\"                        , \"RM-FV\"   , \"EVEX.256.F2.MAP5.W0 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtudq2ph\"       , \"W:ymm {kz}, zmm/m512/b32 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.MAP5.W0 7A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtuqq2ph\"       , \"W:xmm {kz}, xmm/m128/b64\"                        , \"RM-FV\"   , \"EVEX.128.F2.MAP5.W1 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtuqq2ph\"       , \"W:xmm {kz}, ymm/m256/b64\"                        , \"RM-FV\"   , \"EVEX.256.F2.MAP5.W1 7A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtuqq2ph\"       , \"W:xmm {kz}, zmm/m512/b64 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.MAP5.W1 7A /r\"    , \"AVX512_FP16\"],\n    [\"vcvtusi2sh\"       , \"W:xmm, xmm, r32/m32 {er}\"                        , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 7B /r\"    , \"AVX512_FP16\"],\n    [\"vcvtusi2sh\"       , \"W:xmm, xmm, r64/m64 {er}\"                        , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W1 7B /r\"    , \"AVX512_FP16 X64\"],\n    [\"vcvtuw2ph\"        , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.F2.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtuw2ph\"        , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.F2.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtuw2ph\"        , \"W:zmm {kz}, zmm/m512/b16 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F2.MAP5.W0 7D /r\"    , \"AVX512_FP16\"],\n    [\"vcvtw2ph\"         , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.F3.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtw2ph\"         , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.F3.MAP5.W0 7D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vcvtw2ph\"         , \"W:zmm {kz}, zmm/m512/b16 {er}\"                   , \"RM-FV\"   , \"EVEX.512.F3.MAP5.W0 7D /r\"    , \"AVX512_FP16\"],\n    [\"vdivph\"           , \"W:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 5E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vdivph\"           , \"W:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 5E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vdivph\"           , \"W:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 5E /r\"    , \"AVX512_FP16\"],\n    [\"vdivsh\"           , \"W:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 5E /r\"    , \"AVX512_FP16\"],\n    [\"vfcmaddcph\"       , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F2.MAP6.W0 56 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfcmaddcph\"       , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F2.MAP6.W0 56 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfcmaddcph\"       , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.F2.MAP6.W0 56 /r\"    , \"AVX512_FP16\"],\n    [\"vfcmaddcsh\"       , \"X:xmm {kz}, xmm, xmm/m32 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F2.MAP6.W0 57 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfcmulcph\"        , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F2.MAP6.W0 D6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfcmulcph\"        , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F2.MAP6.W0 D6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfcmulcph\"        , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.F2.MAP6.W0 D6 /r\"    , \"AVX512_FP16\"],\n    [\"vfcmulcsh\"        , \"X:xmm {kz}, xmm, xmm/m32 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F2.MAP6.W0 D7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd132ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 98 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd132ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 98 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd132ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 98 /r\"    , \"AVX512_FP16\"],\n    [\"vfmadd132sh\"      , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 99 /r\"    , \"AVX512_FP16\"],\n    [\"vfmadd213ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 A8 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd213ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 A8 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd213ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 A8 /r\"    , \"AVX512_FP16\"],\n    [\"vfmadd213sh\"      , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 A9 /r\"    , \"AVX512_FP16\"],\n    [\"vfmadd231ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 B8 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd231ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 B8 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmadd231ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 B8 /r\"    , \"AVX512_FP16\"],\n    [\"vfmadd231sh\"      , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 B9 /r\"    , \"AVX512_FP16\"],\n    [\"vfmaddcph\"        , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F3.MAP6.W0 56 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddcph\"        , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F3.MAP6.W0 56 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddcph\"        , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.F3.MAP6.W0 56 /r\"    , \"AVX512_FP16\"],\n    [\"vfmaddcsh\"        , \"X:xmm {kz}, xmm, xmm/m32 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP6.W0 57 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub132ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 96 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub132ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 96 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub132ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 96 /r\"    , \"AVX512_FP16\"],\n    [\"vfmaddsub213ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 A6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub213ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 A6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub213ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 A6 /r\"    , \"AVX512_FP16\"],\n    [\"vfmaddsub231ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 B6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub231ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 B6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmaddsub231ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 B6 /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub132ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 9A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub132ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 9A /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub132ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 9A /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub132sh\"      , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 9B /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub213ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 AA /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub213ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 AA /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub213ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 AA /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub213sh\"      , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 AB /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub231ph\"      , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 BA /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub231ph\"      , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 BA /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsub231ph\"      , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 BA /r\"    , \"AVX512_FP16\"],\n    [\"vfmsub231sh\"      , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 BB /r\"    , \"AVX512_FP16\"],\n    [\"vfmsubadd132ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 97 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd132ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 97 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd132ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 97 /r\"    , \"AVX512_FP16\"],\n    [\"vfmsubadd213ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 A7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd213ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 A7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd213ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 A7 /r\"    , \"AVX512_FP16\"],\n    [\"vfmsubadd231ph\"   , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 B7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd231ph\"   , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 B7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmsubadd231ph\"   , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 B7 /r\"    , \"AVX512_FP16\"],\n    [\"vfmulcph\"         , \"X:xmm {kz}, xmm, xmm/m128/b32\"                   , \"RVM-FV\"  , \"EVEX.128.F3.MAP6.W0 D6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmulcph\"         , \"X:ymm {kz}, ymm, ymm/m256/b32\"                   , \"RVM-FV\"  , \"EVEX.256.F3.MAP6.W0 D6 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfmulcph\"         , \"X:zmm {kz}, zmm, zmm/m512/b32 {er}\"              , \"RVM-FV\"  , \"EVEX.512.F3.MAP6.W0 D6 /r\"    , \"AVX512_FP16\"],\n    [\"vfmulcsh\"         , \"X:xmm {kz}, xmm, xmm/m32 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP6.W0 D7 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd132ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 9C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd132ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 9C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd132ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 9C /r\"    , \"AVX512_FP16\"],\n    [\"vfnmadd132sh\"     , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 9D /r\"    , \"AVX512_FP16\"],\n    [\"vfnmadd213ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 AC /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd213ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 AC /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd213ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 AC /r\"    , \"AVX512_FP16\"],\n    [\"vfnmadd213sh\"     , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 AD /r\"    , \"AVX512_FP16\"],\n    [\"vfnmadd231ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 BC /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd231ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 BC /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmadd231ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 BC /r\"    , \"AVX512_FP16\"],\n    [\"vfnmadd231sh\"     , \"X:xmm {kz}, xmm, xmm/m16 {er}\"                   , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 BD /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub132ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 9E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub132ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 9E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub132ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 9E /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub132sh\"     , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 9F /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub213ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 AE /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub213ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 AE /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub213ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 AE /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub213sh\"     , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 AF /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub231ph\"     , \"X:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 BE /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub231ph\"     , \"X:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 BE /r\"    , \"AVX512_FP16-VL\"],\n    [\"vfnmsub231ph\"     , \"X:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 BE /r\"    , \"AVX512_FP16\"],\n    [\"vfnmsub231sh\"     , \"X:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 BF /r\"    , \"AVX512_FP16\"],\n    [\"vfpclassph\"       , \"W:k {k}, xmm/m128/b16, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.128.NP.0F3A.W0 66 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vfpclassph\"       , \"W:k {k}, ymm/m256/b16, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.256.NP.0F3A.W0 66 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vfpclassph\"       , \"W:k {k}, zmm/m512/b16, ib/ub\"                    , \"RMI-FV\"  , \"EVEX.512.NP.0F3A.W0 66 /r ib\" , \"AVX512_FP16\"],\n    [\"vfpclasssh\"       , \"W:k {k}, xmm[15:0]/m16, ib/ub\"                   , \"RMI-T1S\" , \"EVEX.LIG.NP.0F3A.W0 67 /r ib\" , \"AVX512_FP16\"],\n    [\"vgetexpph\"        , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP6.W0 42 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vgetexpph\"        , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP6.W0 42 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vgetexpph\"        , \"W:zmm {kz}, zmm/m512/b16 {sae}\"                  , \"RM-FV\"   , \"EVEX.512.66.MAP6.W0 42 /r\"    , \"AVX512_FP16\"],\n    [\"vgetexpsh\"        , \"W:xmm {kz}, xmm[127:16], xmm[15:0]/m16 {sae}\"    , \"RM-T1S\"  , \"EVEX.LIG.66.MAP6.W0 43 /r\"    , \"AVX512_FP16\"],\n    [\"vgetmantph\"       , \"W:xmm {kz}, xmm/m128/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.NP.0F3A.W0 26 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vgetmantph\"       , \"W:ymm {kz}, ymm/m256/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.NP.0F3A.W0 26 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vgetmantph\"       , \"W:zmm {kz}, zmm/m512/b16, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.NP.0F3A.W0 26 /r ib\" , \"AVX512_FP16\"],\n    [\"vgetmantsh\"       , \"W:xmm {kz},xmm[127:16],xmm[15:0]/m16,ib/ub {sae}\", \"RMI-T1S\" , \"EVEX.LIG.NP.0F3A.W0 27 /r ib\" , \"AVX512_FP16\"],\n    [\"vmaxph\"           , \"W:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 5F /r\"    , \"AVX512_FP16-VL\"],\n    [\"vmaxph\"           , \"W:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 5F /r\"    , \"AVX512_FP16-VL\"],\n    [\"vmaxph\"           , \"W:zmm {kz}, zmm, zmm/m512/b16 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 5F /r\"    , \"AVX512_FP16\"],\n    [\"vmaxsh\"           , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 5F /r\"    , \"AVX512_FP16\"],\n    [\"vminph\"           , \"W:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 5D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vminph\"           , \"W:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 5D /r\"    , \"AVX512_FP16-VL\"],\n    [\"vminph\"           , \"W:zmm {kz}, zmm, zmm/m512/b16 {sae}\"             , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 5D /r\"    , \"AVX512_FP16\"],\n    [\"vminsh\"           , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {sae}\"            , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 5D /r\"    , \"AVX512_FP16\"],\n    [\"vmovsh\"           , \"W:m16, xmm[15:0]\"                                , \"MR-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 11 /r\"    , \"AVX512_FP16\"],\n    [\"vmovsh\"           , \"W:xmm[15:0] {kz}, m16\"                           , \"RM-T1S\"  , \"EVEX.LIG.F3.MAP5.W0 10 /r\"    , \"AVX512_FP16\"],\n    [\"vmovsh\"           , \"W:xmm {kz}, xmm[127:16], xmm[15:0]\"              , \"MVR\"     , \"EVEX.LIG.F3.MAP5.W0 11 /r\"    , \"AVX512_FP16\"],\n    [\"vmovsh\"           , \"W:xmm {kz}, xmm[127:16], xmm[15:0]\"              , \"RVM\"     , \"EVEX.LIG.F3.MAP5.W0 10 /r\"    , \"AVX512_FP16\"],\n    [\"vmovw\"            , \"W:r32[15:0]/m16, xmm[15:0]\"                      , \"MR-T1S\"  , \"EVEX.128.66.MAP5.WIG 7E /r\"   , \"AVX512_FP16\"],\n    [\"vmovw\"            , \"W:xmm[15:0] {kz}, r32[15:0]/m16\"                 , \"RM-T1S\"  , \"EVEX.128.66.MAP5.WIG 6E /r\"   , \"AVX512_FP16\"],\n    [\"vmulph\"           , \"W:xmm {kz},~xmm,~xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 59 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vmulph\"           , \"W:ymm {kz},~ymm,~ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 59 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vmulph\"           , \"W:zmm {kz},~zmm,~zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 59 /r\"    , \"AVX512_FP16\"],\n    [\"vmulsh\"           , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 59 /r\"    , \"AVX512_FP16\"],\n    [\"vrcpph\"           , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP6.W0 4C /r\"    , \"AVX512_FP16\"],\n    [\"vrcpph\"           , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP6.W0 4C /r\"    , \"AVX512_FP16\"],\n    [\"vrcpph\"           , \"W:zmm {kz}, zmm/m512/b16\"                        , \"RM-FV\"   , \"EVEX.512.66.MAP6.W0 4C /r\"    , \"AVX512_FP16\"],\n    [\"vrcpsh\"           , \"W:xmm {kz}, xmm[127:16], xmm[15:0]/m16\"          , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 4D /r\"    , \"AVX512_FP16\"],\n    [\"vreduceph\"        , \"W:xmm {kz}, xmm/m128/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.NP.0F3A.W0 56 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vreduceph\"        , \"W:ymm {kz}, ymm/m256/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.NP.0F3A.W0 56 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vreduceph\"        , \"W:zmm {kz}, zmm/m512/b16, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.NP.0F3A.W0 56 /r ib\" , \"AVX512_FP16\"],\n    [\"vreducesh\"        , \"W:xmm {kz},xmm[127:16],xmm[15:0]/m16,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.NP.0F3A.W0 57 /r ib\" , \"AVX512_FP16\"],\n    [\"vrndscaleph\"      , \"W:xmm {kz}, xmm/m128/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.128.NP.0F3A.W0 08 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vrndscaleph\"      , \"W:ymm {kz}, ymm/m256/b16, ib/ub\"                 , \"RMI-FV\"  , \"EVEX.256.NP.0F3A.W0 08 /r ib\" , \"AVX512_FP16-VL\"],\n    [\"vrndscaleph\"      , \"W:zmm {kz}, zmm/m512/b16, ib/ub {sae}\"           , \"RMI-FV\"  , \"EVEX.512.NP.0F3A.W0 08 /r ib\" , \"AVX512_FP16\"],\n    [\"vrndscalesh\"      , \"W:xmm {kz},xmm[127:16],xmm[15:0]/m16,ib/ub {sae}\", \"RVMI-T1S\", \"EVEX.LIG.NP.0F3A.W0 0A /r ib\" , \"AVX512_FP16\"],\n    [\"vrsqrtph\"         , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.66.MAP6.W0 4E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vrsqrtph\"         , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.66.MAP6.W0 4E /r\"    , \"AVX512_FP16-VL\"],\n    [\"vrsqrtph\"         , \"W:zmm {kz}, zmm/m512/b16\"                        , \"RM-FV\"   , \"EVEX.512.66.MAP6.W0 4E /r\"    , \"AVX512_FP16\"],\n    [\"vrsqrtsh\"         , \"W:xmm {kz}, xmm[127:16], xmm[15:0]/m16\"          , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 4F /r\"    , \"AVX512_FP16\"],\n    [\"vscalefph\"        , \"W:xmm {kz}, xmm, xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.66.MAP6.W0 2C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vscalefph\"        , \"W:ymm {kz}, ymm, ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.66.MAP6.W0 2C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vscalefph\"        , \"W:zmm {kz}, zmm, zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.66.MAP6.W0 2C /r\"    , \"AVX512_FP16\"],\n    [\"vscalefsh\"        , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.66.MAP6.W0 2D /r\"    , \"AVX512_FP16\"],\n    [\"vsqrtph\"          , \"W:xmm {kz}, xmm/m128/b16\"                        , \"RM-FV\"   , \"EVEX.128.NP.MAP5.W0 51 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vsqrtph\"          , \"W:ymm {kz}, ymm/m256/b16\"                        , \"RM-FV\"   , \"EVEX.256.NP.MAP5.W0 51 /r\"    , \"AVX512_FP16-VL\"],\n    [\"vsqrtph\"          , \"W:zmm {kz}, zmm/m512/b16 {er}\"                   , \"RM-FV\"   , \"EVEX.512.NP.MAP5.W0 51 /r\"    , \"AVX512_FP16\"],\n    [\"vsqrtsh\"          , \"W:xmm {kz}, xmm[127:16], xmm[15:0]/m16 {er}\"     , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 51 /r\"    , \"AVX512_FP16\"],\n    [\"vsubph\"           , \"W:xmm {kz},~xmm,~xmm/m128/b16\"                   , \"RVM-FV\"  , \"EVEX.128.NP.MAP5.W0 5C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vsubph\"           , \"W:ymm {kz},~ymm,~ymm/m256/b16\"                   , \"RVM-FV\"  , \"EVEX.256.NP.MAP5.W0 5C /r\"    , \"AVX512_FP16-VL\"],\n    [\"vsubph\"           , \"W:zmm {kz},~zmm,~zmm/m512/b16 {er}\"              , \"RVM-FV\"  , \"EVEX.512.NP.MAP5.W0 5C /r\"    , \"AVX512_FP16\"],\n    [\"vsubsh\"           , \"W:xmm {kz}, xmm, xmm[15:0]/m16 {er}\"             , \"RVM-T1S\" , \"EVEX.LIG.F3.MAP5.W0 5C /r\"    , \"AVX512_FP16\"],\n    [\"vucomish\"         , \"R:xmm[15:0], xmm[15:0]/m16 {sae}\"                , \"RM-T1S\"  , \"EVEX.LIG.NP.MAP5.W0 2E /r\"    , \"AVX512_FP16\"],\n\n    [\"ldtilecfg\"        , \"R:m512\"                                          , \"M\"       , \"VEX.128.0F38.W0 49 /0\"        , \"AMX_TILE X64\"],\n    [\"sttilecfg\"        , \"W:m512\"                                          , \"M\"       , \"VEX.128.66.0F38.W0 49 /0\"     , \"AMX_TILE X64\"],\n    [\"tdpbf16ps\"        , \"X:tmm, tmm, tmm\"                                 , \"RMV\"     , \"VEX.128.F3.0F38.W0 5C /r\"     , \"AMX_BF16 X64\"],\n    [\"tdpbssd\"          , \"X:tmm, tmm, tmm\"                                 , \"RMV\"     , \"VEX.128.F2.0F38.W0 5E /r\"     , \"AMX_INT8 X64\"],\n    [\"tdpbsud\"          , \"X:tmm, tmm, tmm\"                                 , \"RMV\"     , \"VEX.128.F3.0F38.W0 5E /r\"     , \"AMX_INT8 X64\"],\n    [\"tdpbusd\"          , \"X:tmm, tmm, tmm\"                                 , \"RMV\"     , \"VEX.128.66.0F38.W0 5E /r\"     , \"AMX_INT8 X64\"],\n    [\"tdpbuud\"          , \"X:tmm, tmm, tmm\"                                 , \"RMV\"     , \"VEX.128.0F38.W0 5E /r\"        , \"AMX_INT8 X64\"],\n    [\"tileloadd\"        , \"W:tmm, tmem\"                                     , \"RM\"      , \"VEX.128.F2.0F38.W0 4B /r\"     , \"AMX_TILE X64\"],\n    [\"tileloaddt1\"      , \"W:tmm, tmem\"                                     , \"RM\"      , \"VEX.128.66.0F38.W0 4B /r\"     , \"AMX_TILE X64\"],\n    [\"tilerelease\"      , \"\"                                                , \"NONE\"    , \"VEX.128.0F38.W0 49 /0\"        , \"AMX_TILE X64\"],\n    [\"tilestored\"       , \"W:tmem, tmm\"                                     , \"MR\"      , \"VEX.128.F3.0F38.W0 4B /r\"     , \"AMX_TILE X64\"],\n    [\"tilezero\"         , \"W:tmm\"                                           , \"R\"       , \"VEX.128.F2.0F38.W0 49 /r\"     , \"AMX_TILE X64\"]\n  ]\n}\n// ${JSON:END}\n;\n\n}).apply(this, typeof module === \"object\" && module && module.exports\n  ? [module, \"exports\"] : [this.asmdb || (this.asmdb = {}), \"x86data\"]);\n"
  },
  {
    "path": "dev/README.md",
    "content": "This directory contains scripts etc. used to develop GEF features.\nThese do not affect the operation of GEF.\n"
  },
  {
    "path": "dev/angr/test.c",
    "content": "#include <stdio.h>\n#include <string.h>\nint main(int argc, char* argv[]) {\n  if (argc != 2)\n    return 0;\n\n  if (memcmp(argv[1], \"hogehoge\", 8) == 0) {\n    puts(\"ok\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "dev/bpf/bpf_insn.h",
    "content": "/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */\n/* eBPF instruction mini library */\n#ifndef __BPF_INSN_H\n#define __BPF_INSN_H\n\nstruct bpf_insn;\n\n/* ArgX, context and stack frame pointer register positions. Note,\n * Arg1, Arg2, Arg3, etc are used as argument mappings of function\n * calls in BPF_CALL instruction.\n */\n#define BPF_REG_ARG1    BPF_REG_1\n#define BPF_REG_ARG2    BPF_REG_2\n#define BPF_REG_ARG3    BPF_REG_3\n#define BPF_REG_ARG4    BPF_REG_4\n#define BPF_REG_ARG5    BPF_REG_5\n#define BPF_REG_CTX     BPF_REG_6\n#define BPF_REG_FP      BPF_REG_10\n\n/* Additional register mappings for converted user programs. */\n#define BPF_REG_A       BPF_REG_0\n#define BPF_REG_X       BPF_REG_7\n#define BPF_REG_TMP     BPF_REG_8\n\n/* BPF program can access up to 512 bytes of stack space. */\n#define MAX_BPF_STACK   512\n\n/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */\n\n#define BPF_ALU64_REG(OP, DST, SRC)                             \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU64 | BPF_OP(OP) | BPF_X,        \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = 0,                                     \\\n                .imm   = 0 })\n\n#define BPF_ALU32_REG(OP, DST, SRC)                             \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU | BPF_OP(OP) | BPF_X,          \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = 0,                                     \\\n                .imm   = 0 })\n\n/* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */\n\n#define BPF_ALU64_IMM(OP, DST, IMM)                             \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU64 | BPF_OP(OP) | BPF_K,        \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = IMM })\n\n#define BPF_ALU32_IMM(OP, DST, IMM)                             \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU | BPF_OP(OP) | BPF_K,          \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = IMM })\n\n/* Short form of mov, dst_reg = src_reg */\n\n#define BPF_MOV64_REG(DST, SRC)                                 \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU64 | BPF_MOV | BPF_X,           \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = 0,                                     \\\n                .imm   = 0 })\n\n#define BPF_MOV32_REG(DST, SRC)                                 \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU | BPF_MOV | BPF_X,             \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = 0,                                     \\\n                .imm   = 0 })\n\n/* Short form of mov, dst_reg = imm32 */\n\n#define BPF_MOV64_IMM(DST, IMM)                                 \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU64 | BPF_MOV | BPF_K,           \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = IMM })\n\n#define BPF_MOV32_IMM(DST, IMM)                                 \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ALU | BPF_MOV | BPF_K,             \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = IMM })\n\n/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */\n#define BPF_LD_IMM64(DST, IMM)                                  \\\n        BPF_LD_IMM64_RAW(DST, 0, IMM)\n\n#define BPF_LD_IMM64_RAW(DST, SRC, IMM)                         \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_LD | BPF_DW | BPF_IMM,             \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = 0,                                     \\\n                .imm   = (__u32) (IMM) }),                      \\\n        ((struct bpf_insn) {                                    \\\n                .code  = 0, /* zero is reserved opcode */       \\\n                .dst_reg = 0,                                   \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = ((__u64) (IMM)) >> 32 })\n\n#ifndef BPF_PSEUDO_MAP_FD\n# define BPF_PSEUDO_MAP_FD        1\n#endif\n\n/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */\n#define BPF_LD_MAP_FD(DST, MAP_FD)                              \\\n        BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)\n\n\n/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */\n\n#define BPF_LD_ABS(SIZE, IMM)                                   \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS,     \\\n                .dst_reg = 0,                                   \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = IMM })\n\n/* Memory load, dst_reg = *(uint *) (src_reg + off16) */\n\n#define BPF_LDX_MEM(SIZE, DST, SRC, OFF)                        \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM,    \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = 0 })\n\n/* Memory store, *(uint *) (dst_reg + off16) = src_reg */\n\n#define BPF_STX_MEM(SIZE, DST, SRC, OFF)                        \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM,    \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = 0 })\n\n/*\n * Atomic operations:\n *\n *   BPF_ADD                  *(uint *) (dst_reg + off16) += src_reg\n *   BPF_AND                  *(uint *) (dst_reg + off16) &= src_reg\n *   BPF_OR                   *(uint *) (dst_reg + off16) |= src_reg\n *   BPF_XOR                  *(uint *) (dst_reg + off16) ^= src_reg\n *   BPF_ADD | BPF_FETCH      src_reg = atomic_fetch_add(dst_reg + off16, src_reg);\n *   BPF_AND | BPF_FETCH      src_reg = atomic_fetch_and(dst_reg + off16, src_reg);\n *   BPF_OR | BPF_FETCH       src_reg = atomic_fetch_or(dst_reg + off16, src_reg);\n *   BPF_XOR | BPF_FETCH      src_reg = atomic_fetch_xor(dst_reg + off16, src_reg);\n *   BPF_XCHG                 src_reg = atomic_xchg(dst_reg + off16, src_reg)\n *   BPF_CMPXCHG              r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg)\n */\n\n#define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF)                  \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_STX | BPF_SIZE(SIZE) | BPF_ATOMIC, \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = OP })\n\n/* Legacy alias */\n#define BPF_STX_XADD(SIZE, DST, SRC, OFF) BPF_ATOMIC_OP(SIZE, BPF_ADD, DST, SRC, OFF)\n\n/* Memory store, *(uint *) (dst_reg + off16) = imm32 */\n\n#define BPF_ST_MEM(SIZE, DST, OFF, IMM)                         \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM,     \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = OFF,                                   \\\n                .imm   = IMM })\n\n/* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */\n\n#define BPF_JMP_REG(OP, DST, SRC, OFF)                          \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP | BPF_OP(OP) | BPF_X,          \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = 0 })\n\n/* Like BPF_JMP_REG, but with 32-bit wide operands for comparison. */\n\n#define BPF_JMP32_REG(OP, DST, SRC, OFF)                        \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP32 | BPF_OP(OP) | BPF_X,        \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = 0 })\n\n/* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */\n\n#define BPF_JMP_IMM(OP, DST, IMM, OFF)                          \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP | BPF_OP(OP) | BPF_K,          \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = OFF,                                   \\\n                .imm   = IMM })\n\n/* Like BPF_JMP_IMM, but with 32-bit wide operands for comparison. */\n\n#define BPF_JMP32_IMM(OP, DST, IMM, OFF)                        \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP32 | BPF_OP(OP) | BPF_K,        \\\n                .dst_reg = DST,                                 \\\n                .src_reg = 0,                                   \\\n                .off   = OFF,                                   \\\n                .imm   = IMM })\n\n/* Function call */\n\n#define BPF_EMIT_CALL(FUNC)                                     \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP | BPF_CALL,                    \\\n                .dst_reg = 0,                                   \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = (FUNC) })\n\n/* Raw code statement block */\n\n#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM)                  \\\n        ((struct bpf_insn) {                                    \\\n                .code  = CODE,                                  \\\n                .dst_reg = DST,                                 \\\n                .src_reg = SRC,                                 \\\n                .off   = OFF,                                   \\\n                .imm   = IMM })\n\n/* Program exit */\n\n#define BPF_EXIT_INSN()                                         \\\n        ((struct bpf_insn) {                                    \\\n                .code  = BPF_JMP | BPF_EXIT,                    \\\n                .dst_reg = 0,                                   \\\n                .src_reg = 0,                                   \\\n                .off   = 0,                                     \\\n                .imm   = 0 })\n\n#endif\n"
  },
  {
    "path": "dev/bpf/test.c",
    "content": "#include <linux/bpf.h>\n#include <linux/filter.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/socket.h>\n#include <sys/syscall.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include \"bpf_insn.h\"\n\nvoid fatal(const char *msg) {\n  perror(msg);\n  exit(1);\n}\n\nint bpf(int cmd, union bpf_attr *attrs) {\n  return syscall(__NR_bpf, cmd, attrs, sizeof(*attrs));\n}\n\nint map_create(int val_size, int max_entries) {\n  union bpf_attr attr = {\n    .map_type = BPF_MAP_TYPE_ARRAY,\n    .key_size = sizeof(int),\n    .value_size = val_size,\n    .max_entries = max_entries\n  };\n  int mapfd = bpf(BPF_MAP_CREATE, &attr);\n  if (mapfd == -1) fatal(\"bpf(BPF_MAP_CREATE)\");\n  return mapfd;\n}\n\nint map_update(int mapfd, int key, void *pval) {\n  union bpf_attr attr = {\n    .map_fd = mapfd,\n    .key = (unsigned long)&key,\n    .value = (unsigned long)pval,\n    .flags = BPF_ANY\n  };\n  int res = bpf(BPF_MAP_UPDATE_ELEM, &attr);\n  if (res == -1) fatal(\"bpf(BPF_MAP_UPDATE_ELEM)\");\n  return res;\n}\n\nint map_lookup(int mapfd, int key, void *pval) {\n  union bpf_attr attr = {\n    .map_fd = mapfd,\n    .key = (unsigned long)&key,\n    .value = (unsigned long)pval,\n    .flags = BPF_ANY\n  };\n  return bpf(BPF_MAP_LOOKUP_ELEM, &attr); // -1 if not found\n}\n\nint main() {\n  char verifier_log[0x10000];\n\n  /* prepare the bpf map */\n  unsigned long val;\n  int mapfd = map_create(sizeof(val), 4);\n\n  val = 0xdeadbeef;\n  map_update(mapfd, 1, &val);\n  val = 0xcafebabe;\n  map_update(mapfd, 2, &val);\n\n  /* prepare the bpf program */\n  struct bpf_insn insns[] = {\n    BPF_ST_MEM(BPF_DW, BPF_REG_FP, -0x08, 1),      // key=1\n    BPF_ST_MEM(BPF_DW, BPF_REG_FP, -0x10, 0x1337), // val=0x1337\n    // arg1: mapfd\n    BPF_LD_MAP_FD(BPF_REG_ARG1, mapfd),\n    // arg2: key pointer\n    BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),\n    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),\n    // arg3: value pointer\n    BPF_MOV64_REG(BPF_REG_ARG3, BPF_REG_2),\n    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG3, -8),\n    // arg4: flags\n    BPF_MOV64_IMM(BPF_REG_ARG4, 0),\n    // store\n    BPF_EMIT_CALL(BPF_FUNC_map_update_elem), // map_update_elem(mapfd, &k, &v)\n\n    BPF_ST_MEM(BPF_DW, BPF_REG_FP, -0x08, 2),      // key=2\n    BPF_ST_MEM(BPF_DW, BPF_REG_FP, -0x10, 0x1338), // val=0x1338\n    // arg1: mapfd\n    BPF_LD_MAP_FD(BPF_REG_ARG1, mapfd),\n    // arg2: key pointer\n    BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),\n    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),\n    // arg3: value pointer\n    BPF_MOV64_REG(BPF_REG_ARG3, BPF_REG_2),\n    BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG3, -8),\n    // arg4: flags\n    BPF_MOV64_IMM(BPF_REG_ARG4, 0),\n    // store\n    BPF_EMIT_CALL(BPF_FUNC_map_update_elem), // map_update_elem(mapfd, &k, &v)\n\n    // socket filter; Cut off after the 4th bytes from the top\n    BPF_MOV64_IMM(BPF_REG_0, 4),\n    BPF_EXIT_INSN(),\n  };\n\n  /* setup as socket filter */\n  union bpf_attr prog_attr = {\n    .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,\n    .insn_cnt = sizeof(insns) / sizeof(insns[0]),\n    .insns = (unsigned long)insns,\n    .license = (unsigned long)\"GPL v2\",\n    .log_level = 2,\n    .log_size = sizeof(verifier_log),\n    .log_buf = (unsigned long)verifier_log\n  };\n\n  /* load the BPF program */\n  int progfd = bpf(BPF_PROG_LOAD, &prog_attr);\n  if (progfd == -1) {\n    fatal(\"bpf(BPF_PROG_LOAD)\");\n  }\n\n  /* make sockets */\n  int socks[2];\n  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks))\n    fatal(\"socketpair\");\n  if (setsockopt(socks[0], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(int)))\n    fatal(\"setsockopt\");\n\n  /* use the map */\n  map_lookup(mapfd, 1, &val);\n  printf(\"val (before): 0x%lx\\n\", val);\n  map_lookup(mapfd, 2, &val);\n  printf(\"val (before): 0x%lx\\n\", val);\n\n  /* use the socket */\n  write(socks[1], \"Hello\", 5);\n\n  /* use the map */\n  map_lookup(mapfd, 1, &val);\n  printf(\"val (after) : 0x%lx\\n\", val);\n  map_lookup(mapfd, 2, &val);\n  printf(\"val (after) : 0x%lx\\n\", val);\n\n  /* use the socket */\n  char buf[0x10] = {};\n  read(socks[0], buf, 0x10);\n  printf(\"Received: %s\\n\", buf);\n\n  char c[1];\n  scanf(\"%c%c\", c, c);\n  return 0;\n}\n"
  },
  {
    "path": "dev/dma-heap/test.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#define DMA_HEAP_IOCTL_ALLOC 0xc0184800\ntypedef unsigned long long u64;\ntypedef unsigned int u32;\nstruct dma_heap_allocation_data {\n  u64 len;\n  u32 fd;\n  u32 fd_flags;\n  u64 heap_flags;\n};\n\nvoid fatal(const char *msg) {\n    perror(msg);\n    exit(1);\n}\n\nint main(void) {\n    // Open DMA-BUF\n    int dma_fd = open(\"/dev/dma_heap/system\", O_RDWR);\n    if (dma_fd == -1)\n      fatal(\"/dev/dma_heap/system\");\n\n    // Allocate DMA-BUF heap\n    int dma_buf_fd = -1;\n    struct dma_heap_allocation_data data;\n    data.len = 0x400000;\n    data.fd_flags = O_RDWR;\n    data.heap_flags = 0;\n    data.fd = 0;\n    if (ioctl(dma_fd, DMA_HEAP_IOCTL_ALLOC, &data) < 0)\n      fatal(\"DMA_HEAP_IOCTL_ALLOC\");\n    printf(\"[+] dma_buf_fd: %d\\n\", dma_buf_fd = data.fd);\n    close(dma_fd);\n\n    // wait\n    puts(\"Press enter to mmap/write\");\n    scanf(\"%*[^\\n]\"); scanf(\"%*c\");\n\n    // Mmap DMA-BUF heap\n    void *dma_buf = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, dma_buf_fd, 0);\n    printf(\"[+] dma_buf: %p\\n\", dma_buf);\n\n    // write to DMA-BUF heap\n    memcpy(dma_buf, \"AAAABBBBCCCCDDDD\", 16);\n\n    // wait\n    puts(\"Press enter to close\");\n    scanf(\"%*[^\\n]\"); scanf(\"%*c\");\n\n    // close\n    close(dma_buf_fd);\n\n    return 0;\n}\n"
  },
  {
    "path": "dev/dtor/test.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\ntypedef void (*dtor_func) (void *);\nextern void *__dso_handle __attribute__ ((__visibility__ (\"hidden\")));\nextern int __cxa_thread_atexit_impl (dtor_func, void *, void *);\n\ntypedef struct {\n    void *val;\n} A;\n\nvoid A_dtor(void *obj) {\n}\n\nint main(int argc, char* argv[]) {\n    // tls_dtor_list\n    static __thread A b;\n    //__cxa_thread_atexit_impl((dtor_func)A_dtor, &b, __dso_handle);\n    __cxa_thread_atexit_impl((dtor_func)0x41414141, &b, __dso_handle);\n\n    // __exit_funcs\n    atexit((void (*)(void))0x42424242);\n    on_exit((void (*)(int, void*))0x43434343, NULL);\n\n    // __quick_exit_funcs\n    at_quick_exit((void (*)(void))0x44444444);\n\n    sleep(3);\n    return 0;\n}\n\n"
  },
  {
    "path": "dev/dtor/test2.c",
    "content": "// gcc test2.c -lpthread\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid cleanup_func(void *arg) {\n    printf(\"called: %s \\n\",(char *)arg);\n}\n\nvoid* func(void *arg) {\n    // It's actually a macro, which is stored on the stack, making it difficult to dump.\n    pthread_cleanup_push(cleanup_func, \"cleanup_func (1)\");\n    pthread_cleanup_push(cleanup_func, \"cleanup_func (2)\");\n    pthread_exit((void*)2);\n    // never reached\n    pthread_cleanup_pop(0);\n    pthread_cleanup_pop(0);\n}\n\nint main(int argc, char* argv[]) {\n    pthread_t tid;\n    void* tret;\n    pthread_create(&tid, NULL, func, (void*) 1);\n    pthread_join(tid, &tret);\n    return 0;\n}\n"
  },
  {
    "path": "dev/glibc-heap/test.c",
    "content": "// gcc test.c -lpthread\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n#include <pthread.h>\n\n#define COUNT 0x30\n\nvoid *func(void* arg) {\n    void* p[COUNT*2] = {};\n    void* dummy;\n\n    // allocate\n    for (int i=0; i<COUNT; i++) {\n        p[i*2] = malloc(0x10); // tcache, fastbin, small bin\n        dummy = malloc(0x20);\n        p[i*2+1] = malloc(0x1000); // unsorted, large bin\n        dummy = malloc(0x20);\n    }\n\n    // free\n    for (int i=0; i<COUNT / 3 * 2; i+=2) {\n        free(p[i*2]); // tcache, fastbin\n        if (i < COUNT / 3)\n            free(p[i*2+1]); // unsorted\n    }\n\n    // consolidate (fastbin -> small bin; unsorted -> large bin)\n    void *q = malloc(0x10000);\n\n    // free\n    for (int i=COUNT / 3 * 2; i<COUNT; i+=2) {\n        free(p[i*2]); // fastbin\n        free(p[i*2+1]); // unsorted\n    }\n\n    while(1) {};\n}\n\nint main(void) {\n    pthread_t th[2];\n    for (int i=0; i<2; i++) {\n        pthread_create(&th[i], NULL, func, NULL);\n    }\n    func(NULL);\n\n    return 0;\n}\n\n"
  },
  {
    "path": "dev/golang/gc.go",
    "content": "package main\nimport (\n  \"fmt\"\n  \"runtime\"\n)\n\ntype Person struct {\n  name string\n  age  int\n  x    int\n  y    int\n}\n\nvar persons [0x10]*Person;\n\nfunc create_persons() {\n  for i:=0; i<0x10; i++ {\n    var p *Person = &Person{fmt.Sprintf(\"Taro%d\", i), 20, 0xdead, 0xbeef};\n    if i % 2 == 0 {\n      persons[i] = p;\n    }\n  }\n}\n\nfunc main() {\n  create_persons();\n  runtime.GC();\n  for {} // infinity loop\n}\n"
  },
  {
    "path": "dev/iouring/test.c",
    "content": "// https://github.com/shuveb/io_uring-by-example\n// gcc test.c -luring\n\n#include <fcntl.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/ioctl.h>\n#include <liburing.h>\n#include <stdlib.h>\n#include <unistd.h>\n\n#define QUEUE_DEPTH 1\n#define BLOCK_SZ    1024\n\nstruct file_info {\n    off_t file_sz;\n    struct iovec iovecs[];      /* Referred by readv/writev */\n};\n\n/*\n* Returns the size of the file whose open file descriptor is passed in.\n* Properly handles regular file and block devices as well. Pretty.\n* */\n\noff_t get_file_size(int fd) {\n    struct stat st;\n\n    if(fstat(fd, &st) < 0) {\n        perror(\"fstat\");\n        return -1;\n    }\n    if (S_ISBLK(st.st_mode)) {\n        unsigned long long bytes;\n        if (ioctl(fd, BLKGETSIZE64, &bytes) != 0) {\n            perror(\"ioctl\");\n            return -1;\n        }\n        return bytes;\n    } else if (S_ISREG(st.st_mode))\n        return st.st_size;\n\n    return -1;\n}\n\n/*\n * Output a string of characters of len length to stdout.\n * We use buffered output here to be efficient,\n * since we need to output character-by-character.\n * */\nvoid output_to_console(char *buf, int len) {\n    while (len--) {\n        fputc(*buf++, stdout);\n    }\n}\n\n/*\n * Wait for a completion to be available, fetch the data from\n * the readv operation and print it to the console.\n * */\n\nint get_completion_and_print(struct io_uring *ring) {\n    struct io_uring_cqe *cqe;\n    int ret = io_uring_wait_cqe(ring, &cqe);\n    if (ret < 0) {\n        perror(\"io_uring_wait_cqe\");\n        return 1;\n    }\n    if (cqe->res < 0) {\n        fprintf(stderr, \"Async readv failed.\\n\");\n        return 1;\n    }\n    struct file_info *fi = io_uring_cqe_get_data(cqe);\n    int blocks = (int) fi->file_sz / BLOCK_SZ;\n    if (fi->file_sz % BLOCK_SZ) blocks++;\n    for (int i = 0; i < blocks; i ++)\n        output_to_console(fi->iovecs[i].iov_base, fi->iovecs[i].iov_len);\n\n    io_uring_cqe_seen(ring, cqe);\n    return 0;\n}\n\n/*\n * Submit the readv request via liburing\n * */\n\nint submit_read_request(char *file_path, struct io_uring *ring) {\n    int file_fd = open(file_path, O_RDONLY);\n    if (file_fd < 0) {\n        perror(\"open\");\n        return 1;\n    }\n    off_t file_sz = get_file_size(file_fd);\n    off_t bytes_remaining = file_sz;\n    off_t offset = 0;\n    int current_block = 0;\n    int blocks = (int) file_sz / BLOCK_SZ;\n    if (file_sz % BLOCK_SZ) blocks++;\n    struct file_info *fi = malloc(sizeof(*fi) + (sizeof(struct iovec) * blocks));\n\n    /*\n     * For each block of the file we need to read, we allocate an iovec struct\n     * which is indexed into the iovecs array. This array is passed in as part\n     * of the submission. If you don't understand this, then you need to look\n     * up how the readv() and writev() system calls work.\n     * */\n    while (bytes_remaining) {\n        off_t bytes_to_read = bytes_remaining;\n        if (bytes_to_read > BLOCK_SZ)\n            bytes_to_read = BLOCK_SZ;\n\n        offset += bytes_to_read;\n        fi->iovecs[current_block].iov_len = bytes_to_read;\n\n        void *buf;\n        if (posix_memalign(&buf, BLOCK_SZ, BLOCK_SZ)) {\n            perror(\"posix_memalign\");\n            return 1;\n        }\n        fi->iovecs[current_block].iov_base = buf;\n\n        current_block++;\n        bytes_remaining -= bytes_to_read;\n    }\n    fi->file_sz = file_sz;\n\n    /* Get an SQE */\n    struct io_uring_sqe *sqe = io_uring_get_sqe(ring);\n    /* Setup a readv operation */\n    io_uring_prep_readv(sqe, file_fd, fi->iovecs, blocks, 0);\n    /* Set user data */\n    io_uring_sqe_set_data(sqe, fi);\n    /* Finally, submit the request */\n    io_uring_submit(ring);\n\n    return 0;\n}\n\nint main(int argc, char *argv[]) {\n    struct io_uring ring;\n\n    if (argc < 2) {\n        fprintf(stderr, \"Usage: %s [file name] <[file name] ...>\\n\", argv[0]);\n        return 1;\n    }\n\n    /* Initialize io_uring */\n    io_uring_queue_init(QUEUE_DEPTH, &ring, 0);\n\n    for (int i = 1; i < argc; i++) {\n        int ret = submit_read_request(argv[i], &ring);\n        if (ret) {\n            fprintf(stderr, \"Error reading file: %s\\n\", argv[i]);\n            return 1;\n        }\n        get_completion_and_print(&ring);\n    }\n\n    /* Call the clean-up function. */\n    __asm__(\"int3\");\n    io_uring_queue_exit(&ring);\n    return 0;\n}\n"
  },
  {
    "path": "dev/iouring/test2.c",
    "content": "// https://github.com/shuveb/io_uring-by-example\n// gcc test2.c\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <sys/ioctl.h>\n#include <sys/syscall.h>\n#include <sys/mman.h>\n#include <sys/uio.h>\n#include <linux/fs.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <string.h>\n\n/* If your compilation fails because the header file below is missing,\n * your kernel is probably too old to support io_uring.\n * */\n#include <linux/io_uring.h>\n\n#define QUEUE_DEPTH 1\n#define BLOCK_SZ    1024\n\n/* This is x86 specific */\n#define read_barrier()  __asm__ __volatile__(\"\":::\"memory\")\n#define write_barrier() __asm__ __volatile__(\"\":::\"memory\")\n\nstruct app_io_sq_ring {\n    unsigned *head;\n    unsigned *tail;\n    unsigned *ring_mask;\n    unsigned *ring_entries;\n    unsigned *flags;\n    unsigned *array;\n};\n\nstruct app_io_cq_ring {\n    unsigned *head;\n    unsigned *tail;\n    unsigned *ring_mask;\n    unsigned *ring_entries;\n    struct io_uring_cqe *cqes;\n};\n\nstruct submitter {\n    int ring_fd;\n    struct app_io_sq_ring sq_ring;\n    struct io_uring_sqe *sqes;\n    struct app_io_cq_ring cq_ring;\n};\n\nstruct file_info {\n    off_t file_sz;\n    struct iovec iovecs[];      /* Referred by readv/writev */\n};\n\n/*\n * This code is written in the days when io_uring-related system calls are not\n * part of standard C libraries. So, we roll our own system call wrapper\n * functions.\n * */\n\nint io_uring_setup(unsigned entries, struct io_uring_params *p)\n{\n    return (int) syscall(__NR_io_uring_setup, entries, p);\n}\n\nint io_uring_enter(int ring_fd, unsigned int to_submit,\n                          unsigned int min_complete, unsigned int flags)\n{\n    return (int) syscall(__NR_io_uring_enter, ring_fd, to_submit, min_complete,\n                   flags, NULL, 0);\n}\n\n/*\n * Returns the size of the file whose open file descriptor is passed in.\n * Properly handles regular file and block devices as well. Pretty.\n * */\n\noff_t get_file_size(int fd) {\n    struct stat st;\n\n    if(fstat(fd, &st) < 0) {\n        perror(\"fstat\");\n        return -1;\n    }\n    if (S_ISBLK(st.st_mode)) {\n        unsigned long long bytes;\n        if (ioctl(fd, BLKGETSIZE64, &bytes) != 0) {\n            perror(\"ioctl\");\n            return -1;\n        }\n        return bytes;\n    } else if (S_ISREG(st.st_mode))\n        return st.st_size;\n\n    return -1;\n}\n\n/*\n * io_uring requires a lot of setup which looks pretty hairy, but isn't all\n * that difficult to understand. Because of all this boilerplate code,\n * io_uring's author has created liburing, which is relatively easy to use.\n * However, you should take your time and understand this code. It is always\n * good to know how it all works underneath. Apart from bragging rights,\n * it does offer you a certain strange geeky peace.\n * */\n\nint app_setup_uring(struct submitter *s) {\n    struct app_io_sq_ring *sring = &s->sq_ring;\n    struct app_io_cq_ring *cring = &s->cq_ring;\n    struct io_uring_params p;\n    void *sq_ptr, *cq_ptr;\n\n    /*\n     * We need to pass in the io_uring_params structure to the io_uring_setup()\n     * call zeroed out. We could set any flags if we need to, but for this\n     * example, we don't.\n     * */\n    memset(&p, 0, sizeof(p));\n    s->ring_fd = io_uring_setup(QUEUE_DEPTH, &p);\n    if (s->ring_fd < 0) {\n        perror(\"io_uring_setup\");\n        return 1;\n    }\n\n    /*\n     * io_uring communication happens via 2 shared kernel-user space ring buffers,\n     * which can be jointly mapped with a single mmap() call in recent kernels. \n     * While the completion queue is directly manipulated, the submission queue \n     * has an indirection array in between. We map that in as well.\n     * */\n\n    int sring_sz = p.sq_off.array + p.sq_entries * sizeof(unsigned);\n    int cring_sz = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe);\n\n    /* In kernel version 5.4 and above, it is possible to map the submission and \n     * completion buffers with a single mmap() call. Rather than check for kernel \n     * versions, the recommended way is to just check the features field of the \n     * io_uring_params structure, which is a bit mask. If the \n     * IORING_FEAT_SINGLE_MMAP is set, then we can do away with the second mmap()\n     * call to map the completion ring.\n     * */\n    if (p.features & IORING_FEAT_SINGLE_MMAP) {\n        if (cring_sz > sring_sz) {\n            sring_sz = cring_sz;\n        }\n        cring_sz = sring_sz;\n    }\n\n    /* Map in the submission and completion queue ring buffers.\n     * Older kernels only map in the submission queue, though.\n     * */\n    sq_ptr = mmap(0, sring_sz, PROT_READ | PROT_WRITE, \n            MAP_SHARED | MAP_POPULATE,\n            s->ring_fd, IORING_OFF_SQ_RING);\n    if (sq_ptr == MAP_FAILED) {\n        perror(\"mmap\");\n        return 1;\n    }\n\n    if (p.features & IORING_FEAT_SINGLE_MMAP) {\n        cq_ptr = sq_ptr;\n    } else {\n        /* Map in the completion queue ring buffer in older kernels separately */\n        cq_ptr = mmap(0, cring_sz, PROT_READ | PROT_WRITE, \n                MAP_SHARED | MAP_POPULATE,\n                s->ring_fd, IORING_OFF_CQ_RING);\n        if (cq_ptr == MAP_FAILED) {\n            perror(\"mmap\");\n            return 1;\n        }\n    }\n    /* Save useful fields in a global app_io_sq_ring struct for later\n     * easy reference */\n    sring->head = sq_ptr + p.sq_off.head;\n    sring->tail = sq_ptr + p.sq_off.tail;\n    sring->ring_mask = sq_ptr + p.sq_off.ring_mask;\n    sring->ring_entries = sq_ptr + p.sq_off.ring_entries;\n    sring->flags = sq_ptr + p.sq_off.flags;\n    sring->array = sq_ptr + p.sq_off.array;\n\n    /* Map in the submission queue entries array */\n    s->sqes = mmap(0, p.sq_entries * sizeof(struct io_uring_sqe),\n            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,\n            s->ring_fd, IORING_OFF_SQES);\n    if (s->sqes == MAP_FAILED) {\n        perror(\"mmap\");\n        return 1;\n    }\n\n    /* Save useful fields in a global app_io_cq_ring struct for later\n     * easy reference */\n    cring->head = cq_ptr + p.cq_off.head;\n    cring->tail = cq_ptr + p.cq_off.tail;\n    cring->ring_mask = cq_ptr + p.cq_off.ring_mask;\n    cring->ring_entries = cq_ptr + p.cq_off.ring_entries;\n    cring->cqes = cq_ptr + p.cq_off.cqes;\n\n    return 0;\n}\n\n/*\n * Output a string of characters of len length to stdout.\n * We use buffered output here to be efficient,\n * since we need to output character-by-character.\n * */\nvoid output_to_console(char *buf, int len) {\n    while (len--) {\n        fputc(*buf++, stdout);\n    }\n}\n\n/*\n * Read from completion queue.\n * In this function, we read completion events from the completion queue, get\n * the data buffer that will have the file data and print it to the console.\n * */\n\nvoid read_from_cq(struct submitter *s) {\n    struct file_info *fi;\n    struct app_io_cq_ring *cring = &s->cq_ring;\n    struct io_uring_cqe *cqe;\n    unsigned head, reaped = 0;\n\n    head = *cring->head;\n\n    do {\n        read_barrier();\n        /*\n         * Remember, this is a ring buffer. If head == tail, it means that the\n         * buffer is empty.\n         * */\n        if (head == *cring->tail)\n            break;\n\n        /* Get the entry */\n        cqe = &cring->cqes[head & *s->cq_ring.ring_mask];\n        fi = (struct file_info*) cqe->user_data;\n        if (cqe->res < 0)\n            fprintf(stderr, \"Error: %s\\n\", strerror(abs(cqe->res)));\n\n        int blocks = (int) fi->file_sz / BLOCK_SZ;\n        if (fi->file_sz % BLOCK_SZ) blocks++;\n\n        for (int i = 0; i < blocks; i++)\n            output_to_console(fi->iovecs[i].iov_base, fi->iovecs[i].iov_len);\n\n        head++;\n    } while (1);\n\n    *cring->head = head;\n    write_barrier();\n}\n/*\n * Submit to submission queue.\n * In this function, we submit requests to the submission queue. You can submit\n * many types of requests. Ours is going to be the readv() request, which we\n * specify via IORING_OP_READV.\n *\n * */\nint submit_to_sq(char *file_path, struct submitter *s) {\n    struct file_info *fi;\n\n    int file_fd = open(file_path, O_RDONLY);\n    if (file_fd < 0 ) {\n        perror(\"open\");\n        return 1;\n    }\n\n    struct app_io_sq_ring *sring = &s->sq_ring;\n    unsigned index = 0, current_block = 0, tail = 0, next_tail = 0;\n\n    off_t file_sz = get_file_size(file_fd);\n    if (file_sz < 0)\n        return 1;\n    off_t bytes_remaining = file_sz;\n    int blocks = (int) file_sz / BLOCK_SZ;\n    if (file_sz % BLOCK_SZ) blocks++;\n\n    fi = malloc(sizeof(*fi) + sizeof(struct iovec) * blocks);\n    if (!fi) {\n        fprintf(stderr, \"Unable to allocate memory\\n\");\n        return 1;\n    }\n    fi->file_sz = file_sz;\n\n    /*\n     * For each block of the file we need to read, we allocate an iovec struct\n     * which is indexed into the iovecs array. This array is passed in as part\n     * of the submission. If you don't understand this, then you need to look\n     * up how the readv() and writev() system calls work.\n     * */\n    while (bytes_remaining) {\n        off_t bytes_to_read = bytes_remaining;\n        if (bytes_to_read > BLOCK_SZ)\n            bytes_to_read = BLOCK_SZ;\n\n        fi->iovecs[current_block].iov_len = bytes_to_read;\n\n        void *buf;\n        if( posix_memalign(&buf, BLOCK_SZ, BLOCK_SZ)) {\n            perror(\"posix_memalign\");\n            return 1;\n        }\n        fi->iovecs[current_block].iov_base = buf;\n\n        current_block++;\n        bytes_remaining -= bytes_to_read;\n    }\n\n    /* Add our submission queue entry to the tail of the SQE ring buffer */\n    next_tail = tail = *sring->tail;\n    next_tail++;\n    read_barrier();\n    index = tail & *s->sq_ring.ring_mask;\n    struct io_uring_sqe *sqe = &s->sqes[index];\n    sqe->fd = file_fd;\n    sqe->flags = 0;\n    sqe->opcode = IORING_OP_READV;\n    sqe->addr = (unsigned long) fi->iovecs;\n    sqe->len = blocks;\n    sqe->off = 0;\n    sqe->user_data = (unsigned long long) fi;\n    sring->array[index] = index;\n    tail = next_tail;\n\n    /* Update the tail so the kernel can see it. */\n    if(*sring->tail != tail) {\n        *sring->tail = tail;\n        write_barrier();\n    }\n\n    /*\n     * Tell the kernel we have submitted events with the io_uring_enter() system\n     * call. We also pass in the IOURING_ENTER_GETEVENTS flag which causes the\n     * io_uring_enter() call to wait until min_complete events (the 3rd param)\n     * complete.\n     * */\n    int ret =  io_uring_enter(s->ring_fd, 1,1,\n            IORING_ENTER_GETEVENTS);\n    if(ret < 0) {\n        perror(\"io_uring_enter\");\n        return 1;\n    }\n\n    return 0;\n}\n\nint main(int argc, char *argv[]) {\n    struct submitter *s;\n\n    if (argc < 2) {\n        fprintf(stderr, \"Usage: %s <filename>\\n\", argv[0]);\n        return 1;\n    }\n\n    s = malloc(sizeof(*s));\n    if (!s) {\n        perror(\"malloc\");\n        return 1;\n    }\n    memset(s, 0, sizeof(*s));\n\n    if(app_setup_uring(s)) {\n        fprintf(stderr, \"Unable to setup uring!\\n\");\n        return 1;\n    }\n\n    for (int i = 1; i < argc; i++) {\n        if(submit_to_sq(argv[i], s)) {\n            fprintf(stderr, \"Error reading file\\n\");\n            return 1;\n        }\n        read_from_cq(s);\n    }\n\n    __asm__(\"int3\");\n    return 0;\n}\n"
  },
  {
    "path": "dev/ipcs/test_posix.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <malloc.h>\n#include <fcntl.h>\n#include <sys/types.h>\n#include <mqueue.h>\n#include <semaphore.h>\n#include <sys/mman.h>\n\nint main(int argc, char* argv[]) {\n    if (argc < 2) {\n        printf(\"%s s|r|d\\n\", argv[0]);\n        puts(\"* POSIX sem/shm can be accessed from under /dev/shm\");\n        puts(\"* POSIX mq can be accessed from under /dev/mqueue\");\n        exit(1);\n    }\n\n    if (argv[1][0] == 's') {\n        /* POSIX semaphore */\n        sem_t* semid = sem_open(\"/sample\", O_CREAT, 0666, 0);\n        printf(\"semid /sample: %lx\\n\", (unsigned long)semid);\n        sem_close(semid);\n\n        /* POSIX message queue */\n        mqd_t msqid = mq_open(\"/sample\", O_WRONLY | O_CREAT, 0666, NULL);\n        printf(\"msqid /sample: %d\\n\", msqid);\n        char buf[] = \"AAAA\";\n        mq_send(msqid, (char*)&buf, strlen(buf), 0);\n        mq_close(msqid);\n\n        /* POSIX shared memory */\n        int shmid = shm_open(\"/sample\", O_RDWR | O_CREAT, 0666);\n        printf(\"shmid /sample: %d\\n\", shmid);\n        close(shmid);\n\n    } else if (argv[1][0] == 'r') {\n        /* POSIX semaphore */\n        // do nothing\n\n        /* POSIX message queue */\n        mqd_t msqid = mq_open(\"/sample\", O_RDONLY);\n        struct mq_attr attr;\n        mq_getattr(msqid, &attr);\n        char *buf = malloc(attr.mq_msgsize);\n        mq_receive(msqid, (char*)buf, attr.mq_msgsize, NULL);\n        puts(\"mq /sample: receive\");\n        puts(buf);\n        free(buf);\n        mq_close(msqid);\n\n        /* POSIX shared memory */\n        // do nothing\n\n    } else if (argv[1][0] == 'd') {\n        /* POSIX semaphore */\n        puts(\"sem /sample: unlink\");\n        sem_unlink(\"/sample\");\n\n        /* POSIX message queue */\n        puts(\"mq /sample: unlink\");\n        mq_unlink(\"/sample\");\n\n        /* POSIX shared memory */\n        puts(\"shm /sample: unlink\");\n        shm_unlink(\"/sample\");\n    }\n    return 0;\n}\n"
  },
  {
    "path": "dev/ipcs/test_sysv.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <sys/ipc.h>\n#include <sys/sem.h>\n#include <sys/msg.h>\n#include <sys/shm.h>\n\n#define NSEMS 10\nunion semun {\n    int val;\n    struct semid_ds *buf;\n    unsigned short *array;\n};\n\n#define MSGTYPE 1\nstruct msgbuf {\n    long mtype;\n    char mtext[4];\n};\n\nint main(int argc, char* argv[]) {\n    if (argc < 3) {\n        printf(\"%s <PATH> s|r|d\\n\", argv[0]);\n        puts(\"* System-V IPCs can be dumped by `ipcs`\");\n        exit(1);\n    }\n\n    key_t key = ftok(argv[1], 'S');\n    if (key == -1) {\n        perror(\"ftok\");\n        exit(1);\n    }\n\n    if (argv[2][0] == 's') {\n        /* SystemV semaphore */\n        int semid = semget(key, NSEMS, IPC_CREAT | 0666);\n        printf(\"semid: %d\\n\", semid);\n        union semun arg = { .val = 1 };\n        semctl(semid, 0, SETVAL, arg);\n\n        /* SystemV message queue */\n        int msqid = msgget(key, IPC_CREAT | 0666);\n        printf(\"msqid: %d\\n\", msqid);\n        struct msgbuf message = { .mtype = MSGTYPE, .mtext = {'A', 'A', 'A', '\\0'} };\n        msgsnd(msqid, &message, sizeof(message.mtext), IPC_NOWAIT);\n\n        /* SystemV shared memory */\n        int shmid = shmget(key, 0x1000, IPC_CREAT | 0666);\n        printf(\"shmid: %d\\n\", shmid);\n\n    } else if (argv[2][0] == 'r') {\n        /* SystemV semaphore */\n        // do nothing\n\n        /* SystemV message queue */\n        int msqid = msgget(key, 0);\n        printf(\"msqid: %d\\n\", msqid);\n        struct msgbuf message = { .mtype = MSGTYPE };\n        msgrcv(msqid, &message, sizeof(message.mtext), MSGTYPE, IPC_NOWAIT);\n        puts(message.mtext);\n\n        /* SystemV shared memory */\n        // do nothing\n\n    } else if (argv[2][0] == 'd') {\n        /* SystemV semaphore */\n        int semid = semget(key, 0, 0);\n        printf(\"semid: %d\\n\", semid);\n        semctl(semid, 0, IPC_RMID);\n\n        /* SystemV message queue */\n        int msqid = msgget(key, 0);\n        printf(\"msqid: %d\\n\", msqid);\n        msgctl(msqid, IPC_RMID, NULL);\n\n        /* SystemV shared memory */\n        int shmid = shmget(key, 0, 0);\n        printf(\"shmid: %d\\n\", shmid);\n        shmctl(shmid, IPC_RMID, NULL);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "dev/js/test.js",
    "content": "// d8 --allow-natives-syntax test.js\n\n// ---- basic objects ----\nlet obj = { a: 1, b: 2 };\nlet arr = [1, 2, 3];\nlet str = \"hello\";\nlet num = 42;\nlet bool = true;\nlet date = new Date();\nlet map = new Map([[1, 'one'], [2, 'two']]);\nlet set = new Set([1, 2, 3]);\n\n// other\nlet weakMap = new WeakMap();\nlet weakSet = new WeakSet();\nlet tempObj = {};\nweakMap.set(tempObj, 'value');\nweakSet.add(tempObj);\n\nlet promise = Promise.resolve(123);\nlet symbol = Symbol(\"mysymbol\");\nlet bigInt = 1234567890123456789012345678901234567890n;\n\n// ---- buffer ----\nlet buffer = new ArrayBuffer(0x1000);\nlet view = new DataView(buffer);\nlet typedArray = new Uint8Array(buffer);\n\n// ---- functions ----\nfunction normalFunc(x) { return x + 1; }\nlet arrowFunc = (x) => x * 2;\nlet closureFunc = (function(y) {\n  return function(x) { return x + y; };\n})(10);\nclass MyClass {\n  constructor(value) { this.value = value; }\n  method() { return this.value; }\n}\nlet classInstance = new MyClass(123);\n\n// ---- Wasm Module ----\nlet wasmCode = new Uint8Array([\n  0x00,0x61,0x73,0x6D, // magic \"\\0asm\"\n  0x01,0x00,0x00,0x00, // version 1\n  // minimal empty wasm module\n]);\nlet wasmModule = new WebAssembly.Module(wasmCode);\nlet wasmInstance = new WebAssembly.Instance(wasmModule);\n\n// ---- Proxy ----\nlet target = { foo: \"bar\" };\nlet handler = {\n  get: function(obj, prop) {\n    return prop in obj ? obj[prop] : \"default\";\n  }\n};\nlet proxy = new Proxy(target, handler);\n\n// ---- Generator ----\nfunction* genFunc() {\n  yield 1;\n  yield 2;\n  return 3;\n}\nlet generator = genFunc();\n\n// ---- AsyncFunction ----\nasync function asyncFunc() {\n  return 42;\n}\n\n// ---- AsyncGenerator ----\nasync function* asyncGenFunc() {\n  yield 1;\n  yield 2;\n}\nlet asyncGenerator = asyncGenFunc();\n\n// ---- Reflect ----\nlet reflectObj = Reflect;\n\n// ---- Intl ----\nlet intlCollator = new Intl.Collator();\nlet intlNumberFormat = new Intl.NumberFormat();\nlet intlDateTimeFormat = new Intl.DateTimeFormat();\n\n// ---- SharedArrayBuffer ----\nlet sharedArrayBuffer = new SharedArrayBuffer(1024);\n\n// ---- Atomics ----\nlet sharedInt32Array = new Int32Array(sharedArrayBuffer);\nAtomics.store(sharedInt32Array, 0, 42);\n\n// ---- Error ----\nlet error = new Error(\"test error\");\nlet typeError = new TypeError(\"test type error\");\n\n// ---- RegExp ----\nlet re = /abc/;\n\n// ---- FinalizationRegistry / WeakRef ----\nlet registry = new FinalizationRegistry(() => {});\nlet weakRef = new WeakRef({});\n\n// ---------------------------------------------------\n\n// ---- dump ----\nfunction debug(name, obj) {\n  print(`=== ${name} ===`);\n  %DebugPrint(obj);\n}\n\ndebug(\"Object\", obj);\ndebug(\"Array\", arr);\ndebug(\"String\", str);\ndebug(\"Number\", num);\ndebug(\"Boolean\", bool);\ndebug(\"Date\", date);\ndebug(\"Map\", map);\ndebug(\"Set\", set);\ndebug(\"WeakMap\", weakMap);\ndebug(\"WeakSet\", weakSet);\ndebug(\"Promise\", promise);\ndebug(\"Symbol\", symbol);\ndebug(\"BigInt\", bigInt);\n\ndebug(\"ArrayBuffer\", buffer);\ndebug(\"DataView\", view);\ndebug(\"TypedArray\", typedArray);\n\ndebug(\"Normal Function\", normalFunc);\ndebug(\"Arrow Function\", arrowFunc);\ndebug(\"Closure Function\", closureFunc);\ndebug(\"Class\", MyClass);\ndebug(\"Class Instance\", classInstance);\n\ndebug(\"Wasm Module\", wasmModule);\ndebug(\"Wasm Instance\", wasmInstance);\n\ndebug(\"Proxy\", proxy);\ndebug(\"Generator\", generator);\ndebug(\"AsyncFunction\", asyncFunc);\n\ndebug(\"AsyncGenerator\", asyncGenerator);\ndebug(\"Reflect\", reflectObj);\ndebug(\"Intl.Collator\", intlCollator);\ndebug(\"Intl.NumberFormat\", intlNumberFormat);\ndebug(\"Intl.DateTimeFormat\", intlDateTimeFormat);\n\ndebug(\"SharedArrayBuffer\", sharedArrayBuffer);\ndebug(\"Shared Int32Array (Atomics target)\", sharedInt32Array);\n\ndebug(\"Error\", error);\ndebug(\"TypeError\", typeError);\n\ndebug(\"RegExp\", re);\n\ndebug(\"FinalizationRegistry\", registry);\ndebug(\"WeakRef\", weakRef);\n\ndebug(\"Math\", Math);\ndebug(\"JSON\", JSON);\n\nwhile (1) {}\n"
  },
  {
    "path": "dev/partition-alloc-dump/downloader.py",
    "content": "#!/usr/bin/python3\nimport sys\nimport os\nimport subprocess\nimport requests\nimport json\nimport functools\nimport bisect\n\n\n@functools.lru_cache\ndef get_chrome_info():\n    url = \"https://chromiumdash.appspot.com/fetch_releases?num=1\"\n    r = requests.get(url)\n    j = json.loads(r.text)\n    return j\n\n\n@functools.lru_cache\ndef get_channel_info(channel):\n    j = get_chrome_info()\n    for entry in j:\n        if entry[\"channel\"].lower() == channel and entry[\"platform\"] == \"Linux\":\n            return entry\n    raise\n\n\n@functools.lru_cache\ndef get_valid_pos(pos):\n    urlbase = \"https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64\"\n    while pos > 0:\n        print(f\"[!] checking {pos}...\")\n        url = urlbase + f\"%2F{pos}%2FREVISIONS?&alt=media\"\n        r = requests.get(url)\n        if \"chromium_revision\" in r.text:\n            return pos\n        pos -= 1\n    return pos\n\n\ndef download_binary(channel):\n    print(\"#\"*50)\n    print(f\"[*] channel: {channel}\")\n\n    # preparing\n    e = get_channel_info(channel)\n    current_version = e[\"version\"]\n    print(f\"[*] current_version: {current_version}\")\n    pos = e[\"chromium_main_branch_position\"]\n    print(f\"[*] position: {pos}\")\n    pos = get_valid_pos(pos)\n    print(f\"[*] position where snapshot exists: {pos}\")\n\n    # check exists\n    dirname = f\"./chrome_{channel}\"\n    os.makedirs(dirname, exist_ok=True)\n    if os.path.exists(f\"{dirname}/chrome-linux-{pos}.zip\"):\n        print(\"  Already exists, download is skipped\")\n        return\n\n    # download\n    # https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Linux_x64/\n    urlbase = \"https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Linux_x64\"\n    url = urlbase + f\"%2F{pos}%2Fchrome-linux.zip?&alt=media\"\n    cmd = f\"wget -O {dirname}/chrome-linux-{pos}.zip '{url}'\"\n    print(\"  Execute: {:s}\".format(cmd))\n    subprocess.getoutput(cmd)\n    return\n\n\ndef print_git_url(channel):\n    e = get_channel_info(channel)\n    current_version = e[\"version\"]\n    pos = get_valid_pos(e[\"chromium_main_branch_position\"])\n    url_base = \"https://source.chromium.org/chromium/chromium/src/+/main:base\"\n    dir_base = \"allocator/partition_allocator/src/partition_alloc\"\n    commit = e[\"hashes\"][\"chromium\"]\n\n    print(\"[*] commit hash: {:s}\".format(commit))\n    print(\"[*] struct base::PartitionRoot\")\n    print(\"    {:s}/{:s}/partition_root.h;drc={:s}\".format(url_base, dir_base, commit))\n    print(\"[*] struct base::internal::PartitionBucket:\")\n    print(\"    {:s}/{:s}/partition_bucket.h;drc={:s}\".format(url_base, dir_base, commit))\n    print(\"[*] struct PartitionSuperPageExtentEntry:\")\n    print(\"    {:s}/{:s}/partition_superpage_extent_entry.h;drc={:s}\".format(url_base, dir_base, commit))\n    print(\"[*] struct PartitionDirectMapExtent:\")\n    print(\"    {:s}/{:s}/partition_direct_map_extent.h;drc={:s}\".format(url_base, dir_base, commit))\n    print(\"[*] struct SlotSpanMetadata:\")\n    print(\"    {:s}/{:s}/partition_page.h;drc={:s}\".format(url_base, dir_base, commit))\n\n    print(\"[*] v{:s}.x / {:d} / {:s}\".format(current_version.split(\".\")[0], pos, commit))\n    print()\n    return\n\n\ndef memo():\n    print(\"#\"*50)\n    print(\"[*] memo\")\n    print(\"  [preparation]\")\n    print(\"    disable apparmor. I added `apparmor=0` to `GRUB_CMDLINE_LINUX` in `/etc/default/grub`, then `update-grub && reboot`\")\n    print(\"  [term1]\")\n    print(\"    cd www && python3 -m http.server 8080\")\n    print(\"  [term2]\")\n    print(\"    unzip -d /tmp chrome_dev/chrome-linux-*.zip && cd /tmp/chrome-linux\")\n    print(\"    rm -rf /tmp/u && sudo -u NON_ROOT_USER_NAME ./chrome --headless=new --disable-gpu \"\n          \"--remote-debugging-port=1338 --user-data-dir=/tmp/u --enable-logging=stderr http://localhost:8080/inf-loop.html\")\n    print(\"  [term3 (for renderer process)]\")\n    print(\"\"\"    gdb -q -p $(ps -ef | grep -- \"--[t]ype=renderer\" | awk '{pid=$2; for(i=1;i<=NF;i++) \"\"\"\n          \"\"\"if($i ~ /--renderer-client-id=/) {split($i,a,\"=\"); print a[2], pid}}' | sort -n | head -n 1 | awk '{print $2}')\"\"\")\n    print(\"  [term3 (for browser process)]\")\n    print(\"\"\"    gdb -q -p $(ps -ef | grep \"\\\\./[c]hrome\" | grep -v type | grep -v sudo | awk '{print $2}')\"\"\")\n    return\n\n\nif __name__ == '__main__':\n    if len(sys.argv) == 1:\n        channels = [\"stable\", \"beta\", \"dev\"]\n    elif sys.argv[1] in [\"-h\", \"--help\"]:\n        print(\"[*] usage\")\n        print(\"  python3 {:s}             # download all channels (stable, beta, dev)\".format(sys.argv[0]))\n        print(\"  python3 {:s} stable beta # download specific channel(s)\".format(sys.argv[0]))\n        print()\n        channels = []\n    else:\n        channels = sys.argv[1:]\n\n    if channels:\n        for chan in channels:\n            if chan in [\"stable\", \"beta\", \"dev\"]:\n                download_binary(chan)\n                print_git_url(chan)\n            else:\n                print(\"channel is stable, beta, or dev\")\n                exit()\n\n    memo()\n"
  },
  {
    "path": "dev/partition-alloc-dump/www/inf-loop.html",
    "content": "<!DOCTYPE html><html><head>\n<script type=\"text/javascript\">\n\nwait = async timeout => new Promise(resolve => setTimeout(resolve, timeout));\n\nasync function main() {\n  var i = 0;\n  while (1 == 1) {\n    console.log(i);\n    await wait(3000);\n    i += 1;\n  };\n}\n\nmain();\n\n</script></head></html>\n"
  },
  {
    "path": "dev/seccomp/test1.c",
    "content": "// gcc test1.c -lseccomp\n#include <stdio.h>\n#include <seccomp.h>\nint main() {\n    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);\n    if (ctx < 0)\n        perror(\"seccomp_init\");\n\n    if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0))\n        perror(\"seccomp_rule_add\");\n    if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0))\n        perror(\"seccomp_rule_add\");\n    if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0))\n        perror(\"seccomp_rule_add\");\n    if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0))\n        perror(\"seccomp_rule_add\");\n    if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0))\n        perror(\"seccomp_rule_add\");\n\n    if (seccomp_load(ctx))\n        perror(\"seccomp_load\");\n\n    seccomp_release(ctx);\n\n    return 0;\n}\n"
  },
  {
    "path": "dev/seccomp/test2.c",
    "content": "// gcc test2.c\n#include <stdio.h>\n#include <stddef.h>\n#include <linux/seccomp.h>\n#include <linux/filter.h>\n#include <linux/audit.h>\n#include <sys/prctl.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\nint main() {\n    struct sock_filter filter[] = {\n        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, arch))),\n\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),\n\n        BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),\n        BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, __X32_SYSCALL_BIT , 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),\n\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_read, 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_write, 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit, 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_exit_group, 0, 1),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n        BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n    };\n\n    struct sock_fprog prog = {\n        .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),\n        .filter = filter,\n    };\n\n    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))\n        perror(\"prctl(NO_NEW_PRIVS)\");\n\n    if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER,0, &prog))\n        perror(\"seccomp\");\n\n    return 0;\n}\n"
  },
  {
    "path": "dev/simple-heap/test.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n\n#define COUNT 0x10\n\nvoid *func(int sz) {\n    void* p[COUNT] = {};\n    void* dummy;\n\n    // allocate\n    for (int i=0; i<COUNT; i++) {\n        p[i] = malloc(sz);\n        printf(\"malloc %#x: %p\\n\", sz, p[i]);\n        memset(p[i], 'A' + i, sz);\n    }\n\n    // free\n    for (int i=0; i<COUNT; i+=2) {\n        memset(p[i], '\\0', sz);\n        printf(\"free   %#x: %p\\n\", sz, p[i]);\n        free(p[i]);\n    }\n\n    printf(\"malloc %#x: %p\\n\", sz, malloc(sz));\n}\n\nint main(void) {\n    func(0x80);\n    while(1) {};\n    return 0;\n}\n\n"
  },
  {
    "path": "dev/sock/test.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <pthread.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <sys/un.h>\n#include <errno.h>\n#include <netinet/ip.h>\n#include <netinet/ip_icmp.h>\n#include <netinet/icmp6.h>\n\n#define PORT_TCP4 5001\n#define PORT_TCP6 5002\n#define PORT_UDP4 5003\n#define PORT_UDP6 5004\n#define UNIX_SOCK_PATH \"/tmp/echo_unix.sock\"\n#define BUFFER_SIZE 1024\n\nchar* bytes_to_hex(const unsigned char* bytes, size_t len) {\n    if (bytes == NULL || len == 0) {\n        return NULL;\n    }\n    size_t hex_len = len * 2 + 1;\n    char* hex_str = (char*)malloc(hex_len);\n    if (hex_str == NULL) {\n        perror(\"malloc failed\");\n        return NULL;\n    }\n    for (size_t i = 0; i < len; ++i) {\n        sprintf(hex_str + (i * 2), \"%02X\", bytes[i]);\n    }\n    hex_str[hex_len - 1] = '\\0';\n    return hex_str;\n}\n\nvoid *tcp4_echo_server(void *arg) {\n    int server_fd, client_fd;\n    struct sockaddr_in addr;\n    server_fd = socket(AF_INET, SOCK_STREAM, 0);\n    printf(\"[DEBUG] tcp4_server socket: fd=%d\\n\", server_fd);\n    if (server_fd < 0) { perror(\"tcp4 socket\"); exit(1); }\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = INADDR_ANY;\n    addr.sin_port = htons(PORT_TCP4);\n    if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"tcp4 bind\"); exit(1);\n    }\n    if (listen(server_fd, 3) < 0) { perror(\"tcp4 listen\"); exit(1); }\n\n    while (1) {\n        struct sockaddr_in client_addr;\n        socklen_t addrlen = sizeof(client_addr);\n        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &addrlen);\n        printf(\"[DEBUG] tcp4_server accept: fd=%d\\n\", client_fd);\n        if (client_fd < 0) { perror(\"tcp4 accept\"); continue; }\n        char buffer[BUFFER_SIZE];\n        int valread;\n        while ((valread = read(client_fd, buffer, BUFFER_SIZE)) > 0) {\n            write(client_fd, buffer, valread);\n        }\n        close(client_fd);\n        printf(\"[DEBUG] tcp4_server close client: fd=%d\\n\", client_fd);\n    }\n    return NULL;\n}\n\nvoid *tcp6_echo_server(void *arg) {\n    int server_fd, client_fd;\n    struct sockaddr_in6 addr;\n    server_fd = socket(AF_INET6, SOCK_STREAM, 0);\n    printf(\"[DEBUG] tcp6_server socket: fd=%d\\n\", server_fd);\n    if (server_fd < 0) { perror(\"tcp6 socket\"); exit(1); }\n    addr.sin6_family = AF_INET6;\n    addr.sin6_addr = in6addr_any;\n    addr.sin6_port = htons(PORT_TCP6);\n    if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"tcp6 bind\"); exit(1);\n    }\n    if (listen(server_fd, 3) < 0) { perror(\"tcp6 listen\"); exit(1); }\n\n    while (1) {\n        struct sockaddr_in6 client_addr;\n        socklen_t addrlen = sizeof(client_addr);\n        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &addrlen);\n        printf(\"[DEBUG] tcp6_server accept: fd=%d\\n\", client_fd);\n        if (client_fd < 0) { perror(\"tcp6 accept\"); continue; }\n        char buffer[BUFFER_SIZE];\n        int valread;\n        while ((valread = read(client_fd, buffer, BUFFER_SIZE)) > 0) {\n            write(client_fd, buffer, valread);\n        }\n        close(client_fd);\n        printf(\"[DEBUG] tcp6_server close client: fd=%d\\n\", client_fd);\n    }\n    return NULL;\n}\n\nvoid *udp4_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in addr;\n    sockfd = socket(AF_INET, SOCK_DGRAM, 0);\n    printf(\"[DEBUG] udp4_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"udp4 socket\"); exit(1); }\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = INADDR_ANY;\n    addr.sin_port = htons(PORT_UDP4);\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"udp4 bind\"); exit(1);\n    }\n\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in client_addr;\n        socklen_t addrlen = sizeof(client_addr);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client_addr, &addrlen);\n        if (n < 0) { perror(\"udp4 recvfrom\"); continue; }\n        // 何もしない\n        printf(\"[udp4 srever] %s\", buffer);\n    }\n    return NULL;\n}\n\nvoid *udp6_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in6 addr;\n    sockfd = socket(AF_INET6, SOCK_DGRAM, 0);\n    printf(\"[DEBUG] udp6_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"udp6 socket\"); exit(1); }\n    addr.sin6_family = AF_INET6;\n    addr.sin6_addr = in6addr_any;\n    addr.sin6_port = htons(PORT_UDP6);\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"udp6 bind\"); exit(1);\n    }\n\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in6 client_addr;\n        socklen_t addrlen = sizeof(client_addr);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client_addr, &addrlen);\n        if (n < 0) { perror(\"udp6 recvfrom\"); continue; }\n        printf(\"[udp6 server] %s\", buffer);\n    }\n    return NULL;\n}\n\nvoid *unix_echo_server(void *arg) {\n    int server_fd, client_fd;\n    struct sockaddr_un addr;\n    unlink(UNIX_SOCK_PATH);\n    server_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n    printf(\"[DEBUG] unix_server socket: fd=%d\\n\", server_fd);\n    if (server_fd < 0) { perror(\"unix socket\"); exit(1); }\n    memset(&addr, 0, sizeof(addr));\n    addr.sun_family = AF_UNIX;\n    strncpy(addr.sun_path, UNIX_SOCK_PATH, sizeof(addr.sun_path)-1);\n    if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"unix bind\"); exit(1);\n    }\n    if (listen(server_fd, 3) < 0) { perror(\"unix listen\"); exit(1); }\n\n    while (1) {\n        client_fd = accept(server_fd, NULL, NULL);\n        printf(\"[DEBUG] unix_server accept: fd=%d\\n\", client_fd);\n        if (client_fd < 0) { perror(\"unix accept\"); continue; }\n        char buffer[BUFFER_SIZE];\n        int valread;\n        while ((valread = read(client_fd, buffer, BUFFER_SIZE)) > 0) {\n            write(client_fd, buffer, valread);\n        }\n        close(client_fd);\n        printf(\"[DEBUG] unix_server close client: fd=%d\\n\", client_fd);\n    }\n    return NULL;\n}\n\nvoid *icmp_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in addr;\n    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);\n    printf(\"[DEBUG] icmp_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"icmp socket (要root)\"); pthread_exit(NULL); }\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = INADDR_ANY;\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"icmp bind\"); pthread_exit(NULL);\n    }\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in from;\n        socklen_t fromlen = sizeof(from);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&from, &fromlen);\n        if (n < 0) { perror(\"icmp recvfrom\"); continue; }\n        printf(\"[icmp4 server] %s\\n\", bytes_to_hex(buffer, n));\n        fflush(stdout);\n    }\n    return NULL;\n}\n\nvoid *icmp6_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in6 addr;\n    sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);\n    printf(\"[DEBUG] icmp6_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"icmp6 socket (要root)\"); pthread_exit(NULL); }\n    addr.sin6_family = AF_INET6;\n    addr.sin6_addr = in6addr_any;\n    addr.sin6_port = 0;\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"icmp6 bind\"); pthread_exit(NULL);\n    }\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in6 from;\n        socklen_t fromlen = sizeof(from);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&from, &fromlen);\n        if (n < 0) { perror(\"icmp6 recvfrom\"); continue; }\n        printf(\"[icmp6 server] %s\\n\", bytes_to_hex(buffer, n));\n        fflush(stdout);\n    }\n    return NULL;\n}\n\nvoid *raw_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in addr;\n    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);\n    printf(\"[DEBUG] raw_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"raw socket (要root)\"); pthread_exit(NULL); }\n    addr.sin_family = AF_INET;\n    addr.sin_addr.s_addr = INADDR_ANY;\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"raw bind\"); pthread_exit(NULL);\n    }\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in from;\n        socklen_t fromlen = sizeof(from);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&from, &fromlen);\n        if (n < 0) { perror(\"raw recvfrom\"); continue; }\n        printf(\"[raw server] %s\", buffer);\n        fflush(stdout);\n    }\n    return NULL;\n}\n\nvoid *raw6_server(void *arg) {\n    int sockfd;\n    struct sockaddr_in6 addr;\n    sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);\n    printf(\"[DEBUG] raw6_server socket: fd=%d\\n\", sockfd);\n    if (sockfd < 0) { perror(\"raw6 socket (要root)\"); pthread_exit(NULL); }\n    addr.sin6_family = AF_INET6;\n    addr.sin6_addr = in6addr_any;\n    addr.sin6_port = 0;\n    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {\n        perror(\"raw6 bind\"); pthread_exit(NULL);\n    }\n    while (1) {\n        char buffer[BUFFER_SIZE];\n        struct sockaddr_in6 from;\n        socklen_t fromlen = sizeof(from);\n        ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&from, &fromlen);\n        if (n < 0) { perror(\"raw6 recvfrom\"); continue; }\n        printf(\"[raw6 server] %s\", buffer);\n        fflush(stdout);\n    }\n    return NULL;\n}\n\nvoid *client_thread(void *arg) {\n    int sock4 = socket(AF_INET, SOCK_STREAM, 0);\n    printf(\"[DEBUG] client tcp4 socket: fd=%d\\n\", sock4);\n    if (sock4 < 0) { perror(\"client tcp4 socket\"); exit(1); }\n    struct sockaddr_in addr4;\n    addr4.sin_family = AF_INET;\n    addr4.sin_port = htons(PORT_TCP4);\n    inet_pton(AF_INET, \"127.0.0.1\", &addr4.sin_addr);\n    if (connect(sock4, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {\n        perror(\"client tcp4 connect\"); exit(1);\n    }\n\n    int sock6 = socket(AF_INET6, SOCK_STREAM, 0);\n    printf(\"[DEBUG] client tcp6 socket: fd=%d\\n\", sock6);\n    if (sock6 < 0) { perror(\"client tcp6 socket\"); exit(1); }\n    struct sockaddr_in6 addr6;\n    addr6.sin6_family = AF_INET6;\n    addr6.sin6_port = htons(PORT_TCP6);\n    inet_pton(AF_INET6, \"::1\", &addr6.sin6_addr);\n    if (connect(sock6, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {\n        perror(\"client tcp6 connect\"); exit(1);\n    }\n\n    int usock4 = socket(AF_INET, SOCK_DGRAM, 0);\n    printf(\"[DEBUG] client udp4 socket: fd=%d\\n\", usock4);\n    if (usock4 < 0) { perror(\"client udp4 socket\"); exit(1); }\n    struct sockaddr_in uaddr4;\n    uaddr4.sin_family = AF_INET;\n    uaddr4.sin_port = htons(PORT_UDP4);\n    inet_pton(AF_INET, \"127.0.0.1\", &uaddr4.sin_addr);\n\n    int usock6 = socket(AF_INET6, SOCK_DGRAM, 0);\n    printf(\"[DEBUG] client udp6 socket: fd=%d\\n\", usock6);\n    if (usock6 < 0) { perror(\"client udp6 socket\"); exit(1); }\n    struct sockaddr_in6 uaddr6;\n    uaddr6.sin6_family = AF_INET6;\n    uaddr6.sin6_port = htons(PORT_UDP6);\n    inet_pton(AF_INET6, \"::1\", &uaddr6.sin6_addr);\n\n    int unix_sock = socket(AF_UNIX, SOCK_STREAM, 0);\n    printf(\"[DEBUG] client unix socket: fd=%d\\n\", unix_sock);\n    if (unix_sock < 0) { perror(\"client unix socket\"); exit(1); }\n    struct sockaddr_un unix_addr;\n    memset(&unix_addr, 0, sizeof(unix_addr));\n    unix_addr.sun_family = AF_UNIX;\n    strncpy(unix_addr.sun_path, UNIX_SOCK_PATH, sizeof(unix_addr.sun_path)-1);\n    while (connect(unix_sock, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {\n        if (errno == ENOENT) { usleep(100000); continue; }\n        perror(\"client unix connect\");\n        exit(1);\n    }\n\n    int icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);\n    printf(\"[DEBUG] client icmp socket: fd=%d\\n\", icmp_sock);\n    struct sockaddr_in icmp_addr;\n    icmp_addr.sin_family = AF_INET;\n    inet_pton(AF_INET, \"127.0.0.1\", &icmp_addr.sin_addr);\n\n    int icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);\n    printf(\"[DEBUG] client icmp6 socket: fd=%d\\n\", icmp6_sock);\n    struct sockaddr_in6 icmp6_addr;\n    icmp6_addr.sin6_family = AF_INET6;\n    inet_pton(AF_INET6, \"::1\", &icmp6_addr.sin6_addr);\n\n    int raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);\n    printf(\"[DEBUG] client raw socket: fd=%d\\n\", raw_sock);\n    struct sockaddr_in raw_addr;\n    raw_addr.sin_family = AF_INET;\n    inet_pton(AF_INET, \"127.0.0.1\", &raw_addr.sin_addr);\n\n    int raw6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);\n    printf(\"[DEBUG] client raw6 socket: fd=%d\\n\", raw6_sock);\n    struct sockaddr_in6 raw6_addr;\n    raw6_addr.sin6_family = AF_INET6;\n    inet_pton(AF_INET6, \"::1\", &raw6_addr.sin6_addr);\n\n    while (1) {\n        char input[BUFFER_SIZE];\n        sleep(0.1);\n        printf(\"Input: \");\n        if (!fgets(input, BUFFER_SIZE, stdin)) break;\n\n        send(sock4, input, strlen(input), 0);\n        char resp4[BUFFER_SIZE] = {0};\n        int r4 = read(sock4, resp4, BUFFER_SIZE-1);\n        if (r4 > 0) resp4[r4] = '\\0';\n        printf(\"[TCPv4 echo] %s\", resp4);\n\n        send(sock6, input, strlen(input), 0);\n        char resp6[BUFFER_SIZE] = {0};\n        int r6 = read(sock6, resp6, BUFFER_SIZE-1);\n        if (r6 > 0) resp6[r6] = '\\0';\n        printf(\"[TCPv6 echo] %s\", resp6);\n\n        sendto(usock4, input, strlen(input), 0, (struct sockaddr *)&uaddr4, sizeof(uaddr4));\n        sendto(usock6, input, strlen(input), 0, (struct sockaddr *)&uaddr6, sizeof(uaddr6));\n\n        send(unix_sock, input, strlen(input), 0);\n        char unix_resp[BUFFER_SIZE] = {0};\n        int ur = read(unix_sock, unix_resp, BUFFER_SIZE-1);\n        if (ur > 0) unix_resp[ur] = '\\0';\n        printf(\"[UNIX echo] %s\", unix_resp);\n\n        if (icmp_sock >= 0) {\n            char icmp_packet[8] = {8, 0, 0, 0, 0, 0, 0, 0};\n            sendto(icmp_sock, icmp_packet, sizeof(icmp_packet), 0, (struct sockaddr *)&icmp_addr, sizeof(icmp_addr));\n        }\n        if (icmp6_sock >= 0) {\n            char icmp6_packet[8] = {128, 0, 0, 0, 0, 0, 0, 0};\n            sendto(icmp6_sock, icmp6_packet, sizeof(icmp6_packet), 0, (struct sockaddr *)&icmp6_addr, sizeof(icmp6_addr));\n        }\n        if (raw_sock >= 0) {\n            char raw_data[BUFFER_SIZE] = \"RAW DATA\";\n            sendto(raw_sock, raw_data, strlen(raw_data), 0, (struct sockaddr *)&raw_addr, sizeof(raw_addr));\n        }\n        if (raw6_sock >= 0) {\n            char raw6_data[BUFFER_SIZE] = \"RAW6 DATA\";\n            sendto(raw6_sock, raw6_data, strlen(raw6_data), 0, (struct sockaddr *)&raw6_addr, sizeof(raw6_addr));\n        }\n    }\n\n    close(sock4);\n    close(sock6);\n    close(usock4);\n    close(usock6);\n    close(unix_sock);\n    if (icmp_sock >= 0) close(icmp_sock);\n    if (icmp6_sock >= 0) close(icmp6_sock);\n    if (raw_sock >= 0) close(raw_sock);\n    if (raw6_sock >= 0) close(raw6_sock);\n    return NULL;\n}\n\nint main() {\n    pthread_t threads[10];\n    pthread_create(&threads[0], NULL, tcp4_echo_server, NULL);\n    pthread_create(&threads[1], NULL, tcp6_echo_server, NULL);\n    pthread_create(&threads[2], NULL, udp4_server, NULL);\n    pthread_create(&threads[3], NULL, udp6_server, NULL);\n    pthread_create(&threads[4], NULL, unix_echo_server, NULL);\n    pthread_create(&threads[5], NULL, icmp_server, NULL);\n    pthread_create(&threads[6], NULL, icmp6_server, NULL);\n    pthread_create(&threads[7], NULL, raw_server, NULL);\n    pthread_create(&threads[8], NULL, raw6_server, NULL);\n    pthread_create(&threads[9], NULL, client_thread, NULL);\n\n    for (int i = 0; i < 10; ++i) {\n        pthread_join(threads[i], NULL);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "dev/split/de-split.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os\nimport re\nimport sys\n\ndef reconstruct():\n    base_dir = os.path.dirname(os.path.abspath(__file__))\n    save_dir = os.path.join(base_dir, \"save\")\n    splitted_path = os.path.join(save_dir, \"gef-splitted.py\")\n    output_path = os.path.join(base_dir, \"gef-reconstructed.py\")\n\n    if not os.path.exists(splitted_path):\n        print(f\"Error: {splitted_path} not found.\")\n        sys.exit(1)\n\n    with open(splitted_path, \"r\", encoding=\"utf-8\") as f:\n        lines = f.read().splitlines()\n\n    out_lines = []\n\n    import_re = re.compile(r\"^from\\s+(lib[a-zA-Z0-9_.]+)\\s+import\\s+([a-zA-Z0-9_]+)(?:\\s+as\\s+([a-zA-Z0-9_]+))?\")\n    sys_path_re = re.compile(r\"^sys\\.path\\.insert\\(0,\\s*[\\\"'].*?save.*?[\\\"']\\)$\")\n\n    in_hash = False\n\n    i = 0\n    while i < len(lines):\n        line = lines[i]\n\n        if sys_path_re.match(line):\n            i += 1\n            if i < len(lines) and lines[i] == \"\":\n                # Optional empty line skip if any\n                pass\n            continue\n\n        m = import_re.match(line)\n        if m:\n            module_path = m.group(1)\n            file_path = os.path.join(save_dir, *module_path.split(\".\")) + \".py\"\n\n            if os.path.exists(file_path):\n                with open(file_path, \"r\", encoding=\"utf-8\") as f:\n                    file_content = f.read()\n\n                if module_path.startswith(\"lib.hash.\"):\n                    if not in_hash:\n                        out_lines.append(\"class Hash:\")\n                        in_hash = True\n\n                    file_lines = file_content.splitlines()\n                    if file_lines and file_lines[0].strip() == \"class Hash:\":\n                        file_lines = file_lines[1:]\n\n                    out_lines.extend(file_lines)\n                else:\n                    in_hash = False\n                    out_lines.extend(file_content.splitlines())\n\n                # adding blank lines to restore what `collapse_blank_lines_between_from_imports` removed\n                if i + 1 < len(lines):\n                    next_m = import_re.match(lines[i+1])\n                    if next_m:\n                        next_is_hash = next_m.group(1).startswith(\"lib.hash.\")\n                        if in_hash and next_is_hash:\n                            out_lines.append(\"\")\n                        else:\n                            out_lines.append(\"\")\n                            out_lines.append(\"\")\n\n                i += 1\n                continue\n\n        in_hash = False\n        out_lines.append(line)\n        i += 1\n\n    with open(output_path, \"w\", encoding=\"utf-8\") as f:\n        f.write(\"\\n\".join(out_lines) + \"\\n\")\n\n    print(f\"[+] Reconstructed GEF saved to {output_path}\")\n\nif __name__ == \"__main__\":\n    reconstruct()\n"
  },
  {
    "path": "dev/split/split.py",
    "content": "#!/usr/bin/python3\n# This file simply splits each class into a separate file for AI code review.\n# Dependencies will not be resolved, so splitting GEF will not work correctly.\n\nimport os\nimport re\nimport ast\nimport shutil\n\n\ndef get_comment_start(lines, start_lineno):\n    start = start_lineno\n    idx = start_lineno - 2\n    while idx >= 0:\n        if not lines[idx].lstrip().startswith(\"#\"):\n            break\n        start = idx + 1\n        idx -= 1\n    return start\n\n\ndef class_ranges_from_file(path):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        src = f.read()\n\n    tree = ast.parse(src, filename=path)\n    result = {}\n\n    tops = [n for n in tree.body if hasattr(n, \"lineno\")]\n\n    for node in tops:\n        if not isinstance(node, ast.ClassDef):\n            continue\n\n        if node.decorator_list:\n            start = min(d.lineno for d in node.decorator_list)\n        else:\n            start = node.lineno\n\n        end = node.end_lineno\n        result[node.name] = (start - 1, end)\n\n    return result\n\n\ndef global_ranges_from_file(path):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        src = f.read()\n\n    tree = ast.parse(src, filename=path)\n    lines = src.splitlines()\n    result = {}\n\n    tops = [n for n in tree.body if hasattr(n, \"lineno\")]\n\n    for node in tops:\n        name = None\n\n        if isinstance(node, ast.Assign):\n            if len(node.targets) != 1:\n                continue\n            if not isinstance(node.targets[0], ast.Name):\n                continue\n            name = node.targets[0].id\n        elif isinstance(node, ast.AnnAssign):\n            if not isinstance(node.target, ast.Name):\n                continue\n            name = node.target.id\n        else:\n            continue\n\n        if (\"syscall_defs\" not in name) and (\"syscall_tbl\" not in name) and (\"syscall_list\" not in name):\n            continue\n\n        start = get_comment_start(lines, node.lineno)\n        end = node.end_lineno\n        result[name] = (start - 1, end)\n\n    return result\n\n\ndef top_level_function_ranges_from_file(path):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        src = f.read()\n\n    tree = ast.parse(src, filename=path)\n    lines = src.splitlines()\n\n    result = {}\n    for node in tree.body:\n        if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):\n            continue\n\n        if node.decorator_list:\n            start = min(d.lineno for d in node.decorator_list)\n        else:\n            start = node.lineno\n\n        start = get_comment_start(lines, start)\n        end = node.end_lineno\n        result[node.name] = (start - 1, end)\n\n    return result\n\n\ndef used_decorator_names_from_file(path):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        src = f.read()\n\n    tree = ast.parse(src, filename=path)\n    used_decorators = set()\n\n    def add_decorator_name(expr):\n        target = expr\n        if isinstance(target, ast.Call):\n            target = target.func\n\n        if isinstance(target, ast.Name):\n            used_decorators.add(target.id)\n            return\n\n        if isinstance(target, ast.Attribute):\n            used_decorators.add(target.attr)\n            return\n\n    for node in ast.walk(tree):\n        if not isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):\n            continue\n        for deco in node.decorator_list:\n            add_decorator_name(deco)\n\n    return used_decorators\n\n\ndef function_groups_from_file(path):\n    top_level_funcs = top_level_function_ranges_from_file(path)\n    used_decorators = used_decorator_names_from_file(path)\n\n    decorator_dic = {}\n    rw_dic = {}\n    checker_dic = {}\n\n    forced_decorators = {\"perf\", \"cperf\"}\n\n    for name, rng in top_level_funcs.items():\n        if name in used_decorators or name in forced_decorators:\n            decorator_dic[name] = rng\n            continue\n\n        if re.match(r\"^(read|write)_[A-Za-z0-9_]+$\", name):\n            rw_dic[name] = rng\n            continue\n\n        if re.match(r\"^is_[A-Za-z0-9_]+$\", name) or name in [\"kgdb_has_system_registers\"]:\n            checker_dic[name] = rng\n            continue\n\n    return {\n        \"decorator\": decorator_dic,\n        \"rw\": rw_dic,\n        \"checker\": checker_dic,\n    }\n\n\ndef hash_groups_from_file(path):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        src = f.read()\n\n    tree = ast.parse(src, filename=path)\n    lines = src.splitlines()\n\n    hash_node = None\n    for node in tree.body:\n        if isinstance(node, ast.ClassDef) and node.name == \"Hash\":\n            hash_node = node\n            break\n\n    if hash_node is None:\n        return None\n\n    nested_classes = []\n    nested_names = set()\n\n    for node in hash_node.body:\n        if not isinstance(node, ast.ClassDef):\n            continue\n        nested_classes.append(node)\n        nested_names.add(node.name)\n\n    ranges = {}\n    base_map = {}\n    order = []\n\n    for node in nested_classes:\n        if node.decorator_list:\n            start = min(d.lineno for d in node.decorator_list)\n        else:\n            start = node.lineno\n        start = get_comment_start(lines, start)\n        end = node.end_lineno\n\n        ranges[node.name] = (start - 1, end)\n        order.append(node.name)\n\n        base_name = None\n        if len(node.bases) > 1:\n            raise ValueError(f\"multiple inheritance is not supported: Hash.{node.name}\")\n\n        if node.bases:\n            base = node.bases[0]\n            if isinstance(base, ast.Name) and base.id in nested_names:\n                base_name = base.id\n            elif (\n                isinstance(base, ast.Attribute)\n                and isinstance(base.value, ast.Name)\n                and base.value.id == \"Hash\"\n                and base.attr in nested_names\n            ):\n                base_name = base.attr\n\n        base_map[node.name] = base_name\n\n    def root_of(name):\n        cur = name\n        seen = set()\n        while base_map[cur] is not None:\n            if cur in seen:\n                raise ValueError(f\"cyclic inheritance detected under Hash: {name}\")\n            seen.add(cur)\n            cur = base_map[cur]\n        return cur\n\n    groups = {}\n    for name in order:\n        root = root_of(name)\n        if root not in groups:\n            groups[root] = []\n        groups[root].append(name)\n\n    hash_start = min(d.lineno for d in hash_node.decorator_list) if hash_node.decorator_list else hash_node.lineno\n    hash_start = get_comment_start(lines, hash_start)\n    hash_end = hash_node.end_lineno\n\n    return {\n        \"hash_range\": (hash_start - 1, hash_end),\n        \"groups\": groups,\n        \"ranges\": ranges,\n        \"order\": order,\n    }\n\n\ndef write_hash_groups(path, save_dir, hash_info):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        lines = f.read().splitlines()\n\n    hash_dir = os.path.join(save_dir, \"lib\", \"hash\")\n    if not os.path.exists(hash_dir):\n        os.mkdir(hash_dir)\n\n    group_imports = []\n    order_index = {name: idx for idx, name in enumerate(hash_info[\"order\"])}\n\n    for root_name, class_names in sorted(\n        hash_info[\"groups\"].items(),\n        key=lambda item: order_index[item[0]],\n    ):\n        sorted_names = sorted(class_names, key=lambda name: order_index[name])\n        chunks = []\n\n        for class_name in sorted_names:\n            s, e = hash_info[\"ranges\"][class_name]\n            chunks.extend(lines[s:e])\n            chunks.append(\"\")\n\n        if chunks and chunks[-1] == \"\":\n            chunks.pop()\n\n        out_lines = [\"class Hash:\"]\n        out_lines.extend(chunks)\n\n        file_path = os.path.join(hash_dir, root_name + \".py\")\n        with open(file_path, \"w\", encoding=\"utf-8\") as f:\n            f.write(\"\\n\".join(out_lines) + \"\\n\")\n\n        alias = f\"Hash__{root_name}\"\n        group_imports.append(f\"from lib.hash.{root_name} import Hash as {alias}\")\n\n    return group_imports\n\n\ndef collapse_blank_lines_between_from_imports(lines):\n    result = []\n    i = 0\n\n    def is_from_import(line):\n        return line.startswith(\"from \") and \" import \" in line\n\n    while i < len(lines):\n        line = lines[i]\n        if is_from_import(line):\n            result.append(line)\n            j = i + 1\n            while j < len(lines) and lines[j] == \"\":\n                j += 1\n            if j < len(lines) and is_from_import(lines[j]):\n                i = j\n                continue\n            i += 1\n            continue\n\n        result.append(line)\n        i += 1\n\n    return result\n\n\ndef split_gef(path, class_dic, global_dic, function_groups, save_dir):\n    with open(path, \"r\", encoding=\"utf-8\") as f:\n        lines = f.read().splitlines()\n\n    hash_info = hash_groups_from_file(path)\n    hash_imports = []\n\n    new_gef = []\n    pos = 0\n\n    items = []\n    for class_name, (s, e) in class_dic.items():\n        items.append((\"class\", class_name, s, e))\n    for global_name, (s, e) in global_dic.items():\n        items.append((\"global\", global_name, s, e))\n    for decorator_name, (s, e) in function_groups[\"decorator\"].items():\n        items.append((\"decorator\", decorator_name, s, e))\n    for rw_name, (s, e) in function_groups[\"rw\"].items():\n        items.append((\"rw\", rw_name, s, e))\n    for checker_name, (s, e) in function_groups[\"checker\"].items():\n        items.append((\"checker\", checker_name, s, e))\n\n    if hash_info is not None:\n        hash_s, hash_e = hash_info[\"hash_range\"]\n        items = [item for item in items if not (item[0] == \"class\" and item[1] == \"Hash\")]\n        items.append((\"hash\", \"Hash\", hash_s, hash_e))\n        hash_imports = write_hash_groups(path, save_dir, hash_info)\n\n    items.sort(key=lambda x: x[2])\n\n    for item_type, name, s, e in items:\n        new_gef.extend(lines[pos:s])\n        code = lines[s:e]\n\n        if item_type == \"class\":\n            if name.endswith(\"Command\"):\n                file_path = os.path.join(save_dir, \"lib\", \"command\", name + \".py\")\n                new_gef.append(f\"from lib.command.{name} import {name}\")\n            elif (s + 1) < len(lines) and (\"GEF representation of \" in lines[s + 1]) and (\"architecture.\" in lines[s + 1]):\n                file_path = os.path.join(save_dir, \"lib\", \"arch\", name + \".py\")\n                new_gef.append(f\"from lib.arch.{name} import {name}\")\n            else:\n                file_path = os.path.join(save_dir, \"lib\", name + \".py\")\n                new_gef.append(f\"from lib.{name} import {name}\")\n\n            with open(file_path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(code))\n        elif item_type == \"global\":\n            file_path = os.path.join(save_dir, \"lib\", \"syscall\", name + \".py\")\n            new_gef.append(f\"from lib.syscall.{name} import {name}\")\n\n            with open(file_path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(code))\n        elif item_type == \"decorator\":\n            file_path = os.path.join(save_dir, \"lib\", \"decorator\", name + \".py\")\n            new_gef.append(f\"from lib.decorator.{name} import {name}\")\n\n            with open(file_path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(code))\n        elif item_type == \"rw\":\n            file_path = os.path.join(save_dir, \"lib\", \"rw\", name + \".py\")\n            new_gef.append(f\"from lib.rw.{name} import {name}\")\n\n            with open(file_path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(code))\n        elif item_type == \"checker\":\n            file_path = os.path.join(save_dir, \"lib\", \"checker\", name + \".py\")\n            new_gef.append(f\"from lib.checker.{name} import {name}\")\n\n            with open(file_path, \"w\", encoding=\"utf-8\") as f:\n                f.write(\"\\n\".join(code))\n        elif item_type == \"hash\":\n            new_gef.extend(hash_imports)\n        else:\n            raise ValueError(f\"unknown item type: {item_type}\")\n\n        pos = e\n\n    new_gef.extend(lines[pos:])\n\n    idx = new_gef.index(\"import traceback\") + 1\n    new_gef = (\n        new_gef[:idx]\n        + ['sys.path.insert(0, \"' + os.path.join(os.path.dirname(__file__), \"save\") + '\")']\n        + new_gef[idx:]\n    )\n\n    new_gef = collapse_blank_lines_between_from_imports(new_gef)\n\n    file_name = os.path.join(save_dir, \"gef-splitted.py\")\n    with open(file_name, \"w\", encoding=\"utf-8\") as f:\n        f.write(\"\\n\".join(new_gef))\n\n    return\n\n\nif __name__ == \"__main__\":\n    base_dir = os.path.dirname(__file__)\n    save_dir = os.path.join(base_dir, \"save\")\n    if os.path.exists(save_dir):\n        shutil.rmtree(save_dir)\n\n    if not os.path.exists(save_dir):\n        os.mkdir(save_dir)\n    if not os.path.exists(os.path.join(save_dir, \"lib\")):\n        os.mkdir(os.path.join(save_dir, \"lib\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"command\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"command\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"arch\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"arch\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"syscall\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"syscall\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"hash\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"hash\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"decorator\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"decorator\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"rw\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"rw\"))\n    if not os.path.exists(os.path.join(save_dir, \"lib\", \"checker\")):\n        os.mkdir(os.path.join(save_dir, \"lib\", \"checker\"))\n\n    gef_path = os.path.normpath(os.path.join(base_dir, \"../../gef.py\"))\n    class_dic = class_ranges_from_file(gef_path)\n    global_dic = global_ranges_from_file(gef_path)\n    function_groups = function_groups_from_file(gef_path)\n    split_gef(gef_path, class_dic, global_dic, function_groups, save_dir)\n"
  },
  {
    "path": "dev/tls/test.c",
    "content": "#include <stdio.h>\n_Thread_local unsigned int x = 0xdeadbeef;\n// __thread unsigned int x = 0xdeadbeef;\n\nint main(void) {\n    printf(\"%#x\\n\", x);\n    return 0;\n}\n"
  },
  {
    "path": "dev/tmux/tmux_setup.py",
    "content": "# How to use:\n# gef> source /path/to/tmux_setup.py\n\nimport os\nimport gdb\nimport atexit\n\ndef main():\n    # reset panes\n    try:\n        gdb.execute(\"pi GefTmuxSetupCommand.reset_panes()\", to_string=True)\n    except gdb.error:\n        print(\"GEF is not loaded\")\n        return\n\n    # split\n    \"\"\"\n    +--------+--------+--------+\n    |        | code   | legend |\n    |        | args   | regs   |\n    |        | source +--------+\n    |        |        | stack  |\n    |        +--------+ mem_acc|\n    |        | others |        |\n    | cmd    |        |        |\n    +--------+--------+--------+\n    \"\"\"\n    panes = {}\n    panes[\"legend\"] = os.popen('tmux split-window -P -F\"#{pane_tty}\" -h -l 30% -d \"cat -\"').read().strip()\n    panes[\"regs\"] = panes[\"legend\"]\n    panes[\"stack\"] = os.popen('tmux split-window -P -F\"#{pane_tty}\" -v -t {bottom-right} -l 66% -d \"cat -\"').read().strip()\n    panes[\"mem_access\"] = panes[\"stack\"]\n\n    panes[\"code\"] = os.popen('tmux split-window -P -F\"#{pane_tty}\" -h -l 50% -d \"cat -\"').read().strip()\n    panes[\"args\"] = panes[\"code\"]\n    panes[\"source\"] = panes[\"code\"]\n    panes[\"trace\"] = os.popen('tmux split-window -P -F\"#{pane_tty}\" -v -t {right-of} -l 33% -d \"cat -\"').read().strip()\n    panes[\"threads\"] = panes[\"trace\"]\n    panes[\"mem_watch\"] = panes[\"trace\"]\n    panes[\"extra\"] = panes[\"trace\"]\n\n    # set config\n    for section, pane_tty in panes.items():\n        if pane_tty:\n            gdb.execute(f\"gef config context_{section}.redirect {pane_tty}\", to_string=True)\n\n    # set more config\n    gdb.execute(f\"gef config context_code.nb_lines 16\", to_string=True)\n    gdb.execute(f\"gef config context_code.nb_lines_prev 8\", to_string=True)\n    gdb.execute(f\"gef config context_stack.nb_lines 16\", to_string=True)\n\n    # add atexit\n    gdb.execute(\"pi atexit.register(GefTmuxSetupCommand.reset_panes)\", to_string=True)\n\n    # clear cache\n    gdb.execute(\"gef reset-cache\", to_string=True)\n\n    return\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "dev/update-kmalloc-tracer/check.py",
    "content": "import argparse\nimport os\nimport subprocess\nimport re\n\nclass KernelVersion:\n    def __init__(self, version_string):\n        self.version_string = version_string\n        try:\n            major, minor, patch, rc = self.to_version_tuple(version_string)\n        except Exception as err:\n            raise argparse.ArgumentTypeError from err\n        self.major = major\n        self.minor = minor\n        self.patch = patch\n        self.rc = rc\n        self.version_tuple = (major, minor, patch, rc)\n        return\n\n    def to_version_tuple(self, v):\n        r = re.match(r\"(\\d+)\\.(\\d+)-rc(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), 0, int(r.group(3))\n\n        r = re.match(r\"(\\d+)\\.(\\d+)\\.(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), int(r.group(3)), 0\n\n        r = re.match(r\"(\\d+)\\.(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), 0, 0\n        raise\n\n    def __str__(self):\n        if self.rc > 0:\n            return \"{:d}.{:d}-rc{:d}\".format(self.major, self.minor, self.rc)\n        elif self.patch == 0:\n            return \"{:d}.{:d}\".format(self.major, self.minor)\n        else:\n            return \"{:d}.{:d}.{:d}\".format(self.major, self.minor, self.patch)\n        raise\n\n    @property\n    def dirname(self):\n        return \"linux-{:s}\".format(str(self))\n\n    @property\n    def filename(self):\n        if self.rc > 0:\n            return \"{:s}.tar.gz\".format(self.dirname)\n        return \"{:s}.tar.xz\".format(self.dirname)\n\n    @property\n    def url(self):\n        if self.rc > 0:\n            return \"https://git.kernel.org/torvalds/t/{:s}\".format(self.filename)\n        return \"https://cdn.kernel.org/pub/linux/kernel/v{:d}.x/{:s}\".format(self.major, self.filename)\n\ndef check_black_list(line):\n    black_list = [\n        \"kmalloc_caches\", # variable\n        \"random_kmalloc_seed\", # variable\n        \"kmalloc_dma_caches\", # variable\n        \"kfree_const\", # always calls kfree\n        \"kfree_sensitive\", # always calls kfree\n        \"mempool_kfree\", # always calls kfree\n        \"mempool_kmalloc\", # always calls kmalloc\n        \"kmem_cache_alloc_bulk_noprof\", # does not return ptr\n        \"kmem_cache_alloc_bulk\", # does not return ptr\n        \"kmalloc_size_roundup\", # does not return ptr\n        \"__kasan_kmalloc\", # does not get ptr\n        \"kasan_kmalloc\", # does not get ptr\n    ]\n    for f in black_list:\n        f = \"EXPORT_SYMBOL({:s})\".format(f)\n        if f in line:\n            return True\n    return False\n\ndef doit(args, version):\n    if not os.path.exists(version.filename):\n        os.system(\"wget {:s}\".format(version.url))\n\n    if not os.path.exists(version.dirname):\n        print(\"[+] Extracting...\")\n        os.system(\"tar xf {:s} '{:s}/mm/'\".format(version.filename, version.dirname))\n\n    os.chdir(os.path.join(version.dirname, \"mm\"))\n    ret = subprocess.getoutput(\"grep -r EXPORT_SYMBOL |egrep 'kmalloc|krealloc|kfree|kmem_cache_alloc'\")\n    os.chdir(\"../..\")\n\n    lines = []\n    for line in ret.splitlines():\n        if check_black_list(line):\n            continue\n        line = re.sub(r\"\\((.+?)\\)\", lambda x: \"(\" + '\\x1b[1;37m' + x.group(1) + '\\x1b[00m' + \")\", line)\n        if args.simple:\n            line = line.split(\":\")[1]\n        lines.append(line)\n    return sorted(set(lines))\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"version\", metavar=\"VERSION\", type=KernelVersion, help=\"target version\")\n    parser.add_argument(\"version2\", metavar=\"VERSION2\", nargs=\"?\", type=KernelVersion, help=\"target version for diff\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"omit source filename\")\n    args = parser.parse_args()\n\n    if not args.version2:\n        lines = doit(args, args.version)\n        for line in lines:\n            print(line)\n    else:\n        lines = doit(args, args.version)\n        lines2 = doit(args, args.version2)\n\n        print(\"#\" * 30 + args.version.dirname)\n\n        for line in lines:\n            if line in lines2:\n                continue\n            print(line)\n\n        print(\"#\" * 30 + args.version2.dirname)\n\n        for line in lines2:\n            if line in lines:\n                continue\n            print(line)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "dev/update-kops/check.py",
    "content": "import argparse\nimport os\nimport subprocess\nimport re\nimport tarfile\nimport difflib\n\nclass KernelVersion:\n    def __init__(self, version_string):\n        self.version_string = version_string\n        try:\n            major, minor, patch, rc = self.to_version_tuple(version_string)\n        except Exception as err:\n            raise argparse.ArgumentTypeError from err\n        self.major = major\n        self.minor = minor\n        self.patch = patch\n        self.rc = rc\n        self.version_tuple = (major, minor, patch, rc)\n        return\n\n    def to_version_tuple(self, v):\n        r = re.match(r\"(\\d+)\\.(\\d+)-rc(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), 0, int(r.group(3))\n\n        r = re.match(r\"(\\d+)\\.(\\d+)\\.(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), int(r.group(3)), 0\n\n        r = re.match(r\"(\\d+)\\.(\\d+)\", v)\n        if r:\n            return int(r.group(1)), int(r.group(2)), 0, 0\n        raise\n\n    def __str__(self):\n        if self.rc > 0:\n            return \"{:d}.{:d}-rc{:d}\".format(self.major, self.minor, self.rc)\n        elif self.patch == 0:\n            return \"{:d}.{:d}\".format(self.major, self.minor)\n        else:\n            return \"{:d}.{:d}.{:d}\".format(self.major, self.minor, self.patch)\n        raise\n\n    @property\n    def dirname(self):\n        return \"linux-{:s}\".format(str(self))\n\n    @property\n    def filename(self):\n        if self.rc > 0:\n            return \"{:s}.tar.gz\".format(self.dirname)\n        return \"{:s}.tar.xz\".format(self.dirname)\n\n    @property\n    def url(self):\n        if self.rc > 0:\n            return \"https://git.kernel.org/torvalds/t/{:s}\".format(self.filename)\n        return \"https://cdn.kernel.org/pub/linux/kernel/v{:d}.x/{:s}\".format(self.major, self.filename)\n\nEntries = {\n    \"address_space_operations\": [\"include/linux/fs.h\"],\n    \"ata_port_operations\": [\"include/linux/libata.h\"],\n    \"btf_kind_operations\": [\"kernel/bpf/btf.c\"],\n    \"block_device_operations\": [\"include/linux/blkdev.h\"],\n    \"clk_ops\": [\"include/linux/clk-provider.h\"],\n    \"configfs_item_operations\": [\"include/linux/configfs.h\"],\n    \"configfs_group_operations\": [\"include/linux/configfs.h\"],\n    \"damon_operations\": [\"include/linux/damon.h\"],\n    \"dentry_operations\": [\"include/linux/dcache.h\"],\n    \"dev_pm_ops\": [\"include/linux/pm.h\"],\n    \"dma_buf_ops\": [\"include/linux/dma-buf.h\"],\n    \"export_operations\": [\"include/linux/exportfs.h\"],\n    \"file_operations\": [\"include/linux/fs.h\"],\n    \"fs_context_operations\": [\"include/linux/fs_context.h\"],\n    \"inode_operations\": [\"include/linux/fs.h\"],\n    \"kobj_ns_type_operations\": [\"include/linux/kobject_ns.h\"],\n    \"media_entity_operations\": [\"include/media/media-entity.h\"],\n    \"movable_operations\": [\"include/linux/migrate.h\"],\n    \"net_device_ops\": [\"include/linux/netdevice.h\"],\n    \"page_ext_operations\": [\"include/linux/page_ext.h\"],\n    \"parport_operations\": [\"include/linux/parport.h\"],\n    \"pernet_operations\": [\"include/net/net_namespace.h\"],\n    \"pipe_buf_operations\": [\"include/linux/pipe_fs_i.h\"],\n    \"proc_ns_operations\": [\"include/linux/proc_ns.h\"],\n    \"proc_ops\": [\"include/linux/proc_fs.h\"],\n    \"regulator_ops\": [\"include/linux/regulator/driver.h\"],\n    \"seq_operations\": [\"include/linux/seq_file.h\"],\n    \"smp_operations\": [\"arch/arm/include/asm/smp.h\"],\n    \"super_operations\": [\"include/linux/fs.h\", \"include/linux/fs/super_types.h\"],\n    \"tty_ldisc_ops\": [\"include/linux/tty_ldisc.h\"],\n    \"tty_operations\": [\"include/linux/tty_driver.h\"],\n    \"tty_port_operations\": [\"include/linux/tty_port.h\"],\n    \"ucsi_operations\": [\"drivers/usb/typec/ucsi/ucsi.h\"],\n    \"vm_operations_struct\": [\"include/linux/mm.h\"],\n}\n\ndef doit(args, version):\n    if not os.path.exists(version.filename):\n        r = os.system(\"wget {:s}\".format(version.url))\n        if r != 0:\n            print(\"Failed to downloard\")\n            raise\n\n    ops = {}\n    for struct_name, filenames in Entries.items():\n        found = False\n        for filename in filenames:\n            filepath = os.path.join(version.dirname, filename)\n\n            if not os.path.exists(filepath):\n                print(\"[+] Extracting... {:s}\".format(filepath))\n                r = os.system(\"tar xf {:s} '{:s}'\".format(version.filename, filepath))\n                if r != 0:\n                    print(\"Failed to extract\")\n                    continue\n\n            content = open(filepath).read()\n\n            struct_name_ = \"struct {:s}\".format(struct_name)\n            struct_lines = []\n            inner = False\n            for line in content.splitlines():\n                if not inner:\n                    if line.startswith(struct_name_) and not line.endswith(\";\"):\n                        inner = True\n                        struct_lines.append(line)\n                    continue\n                else:\n                    struct_lines.append(line)\n                    if line.startswith(\"}\"):\n                        ops[struct_name] = [filepath, struct_lines]\n                        found = True\n                        break\n                    continue\n            if found:\n                break\n        else:\n            ops[struct_name] = [filepath, [\"Not found\"]]\n    return ops\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"version\", metavar=\"VERSION\", type=KernelVersion, help=\"target version\")\n    parser.add_argument(\"version2\", metavar=\"VERSION2\", nargs=\"?\", type=KernelVersion, help=\"target version for diff\")\n    args = parser.parse_args()\n\n    if not args.version2:\n        ops = doit(args, args.version)\n        assert len(ops) == len(Entries)\n\n        for struct_name, [filepath, lines] in ops.items():\n            print(\"\\x1b[1;37m{:s}:{:s}\\x1b[00m\".format(filepath, struct_name))\n            for line in lines:\n                print(line)\n    else:\n        ops1 = doit(args, args.version)\n        ops2 = doit(args, args.version2)\n        assert len(ops1) == len(ops2) == len(Entries)\n\n        for struct_name in Entries.keys():\n            print(\"\\x1b[1;37m{:s}\\x1b[00m\".format(struct_name))\n            path1, content1 = ops1[struct_name]\n            path2, content2 = ops2[struct_name]\n            for line in difflib.unified_diff(content1, content2, fromfile=path1, tofile=path2):\n                if line[0] == \"-\":\n                    print(\"\\x1b[1;31m{:s}\\x1b[00m\".format(line)) # Red\n                elif line[0] == \"+\":\n                    print(\"\\x1b[1;32m{:s}\\x1b[00m\".format(line)) # Green\n                else:\n                    print(line)\n    return\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "dev/update-syscalls/update-syscalls.py",
    "content": "#!/usr/bin/python\nimport sys\nimport os\nimport subprocess\nimport shutil\nimport hashlib\n\n################################################################################\n# init and arguments check\n\ndef init():\n    if len(sys.argv) != 3:\n        print(\"usage: {:s} KERNEL_SRC_DIR GEF_DIR\".format(sys.argv[0]))\n        print()\n        print(\"example: {:s} /tmp/work/linux-6.6-rc7 /tmp/work/gef\".format(sys.argv[0]))\n        exit()\n\n    which(\"clang-format\")\n\n    global K_DIR, GEF_DIR, GEF_PATH, GEF_TMP_PATH\n    K_DIR = sys.argv[1]\n    GEF_DIR = sys.argv[2]\n    GEF_PATH = os.path.join(sys.argv[2], \"gef.py\")\n    GEF_TMP_PATH = GEF_PATH + \".tmp\"\n\n    if not os.path.exists(K_DIR):\n        print(\"[-] Not found {:s}\".format(K_DIR))\n        exit()\n\n    if not os.path.exists(GEF_PATH):\n        print(\"[-] Not found {:s}\".format(GEF_PATH))\n        exit()\n\n    if os.path.exists(GEF_TMP_PATH):\n        print(\"[-] Found {:s} already.\".format(GEF_TMP_PATH))\n        exit()\n\n    if os.path.exists(\"/tmp/a\"):\n        print(\"[-] Found {:s} already.\".format(\"/tmp/a\"))\n        exit()\n\n    if os.path.exists(\"/tmp/b\"):\n        print(\"[-] Found {:s} already.\".format(\"/tmp/b\"))\n        exit()\n\n    shutil.copyfile(GEF_PATH, GEF_TMP_PATH)\n    return\n\ndef print_patch_result():\n    print(titlify(\"patch result\"))\n    h1 = hashlib.sha1(open(GEF_PATH, \"rb\").read()).hexdigest()\n    h2 = hashlib.sha1(open(GEF_TMP_PATH, \"rb\").read()).hexdigest()\n    if h1 != h2:\n        print(\"[+] patched gef.py is saved to {:s}\".format(GEF_TMP_PATH))\n    else:\n        print(\"[+] No diff\")\n        os.unlink(GEF_TMP_PATH)\n    return\n\ndef cleanup():\n    if os.path.exists(\"/tmp/a\"):\n        os.unlink(\"/tmp/a\")\n    if os.path.exists(\"/tmp/b\"):\n        os.unlink(\"/tmp/b\")\n    return\n\n################################################################################\n# utility\n\ndef get_terminal_size():\n    import termios\n    import struct\n    import fcntl\n    try:\n        tty_rows, tty_columns = struct.unpack(\"hh\", fcntl.ioctl(1, termios.TIOCGWINSZ, \"1234\"))\n        return tty_rows, tty_columns\n    except OSError:\n        return 600, 100\n\ndef titlify(text):\n    cols = get_terminal_size()[1]\n    cs = \"\\033[36m\" # cyan\n    ce = \"\\033[0m\" # normal\n\n    msg = []\n    if text:\n        nb = (cols - len(text) - 2) // 2\n        msg.append(cs + \"{} \".format(\"-\" * nb) + ce)\n        msg.append(cs + text + ce)\n        msg.append(cs + \" {}\".format(\"-\" * nb) + ce)\n    else:\n        msg.append(cs + \"{}\".format(\"-\" * cols) + ce)\n    return \"\".join(msg)\n\ndef which(command):\n    x = subprocess.getoutput(\"which {:s}\".format(command))\n    if not x:\n        print(\"[-] Not found {:s}\".format(command))\n        exit()\n    return x\n\ndef str2bytes(x):\n    if isinstance(x, bytes):\n        return x\n    if isinstance(x, str):\n        x = bytes(ord(xx) for xx in x)\n        return x\n    raise\n\ndef bytes2str(x):\n    if isinstance(x, str):\n        return x\n    if isinstance(x, bytes):\n        x = \"\".join(chr(xx) for xx in x)\n        return x\n    raise\n\n################################################################################\n# utility2\n\ndef print_diff(a, b):\n    import difflib\n    for i, line in enumerate(difflib.unified_diff(a, b, fromfile=\"before\", tofile=\"after\")):\n        if i < 2:\n            continue\n        print(line)\n    return\n\ndef write_back(lines, s, e):\n    gef = open(GEF_TMP_PATH, \"rb\").read().decode(\"ascii\").splitlines()\n    gef[s + 1:e] = lines\n    open(GEF_TMP_PATH, \"wb\").write((\"\\n\".join(gef) + \"\\n\").encode())\n    return\n\n################################################################################\n# update syscall interfaces\n\ndef get_new_defs(header_path):\n    clang = which(\"clang-format\")\n    header = os.path.join(K_DIR, header_path)\n    cmd = \"{:s} --style='{{BasedOnStyle: Google, ColumnLimit: 1000}}' {:s}\".format(clang, header)\n    syscall_defs = subprocess.getoutput(cmd)\n    syscall_defs = [line for line in syscall_defs.splitlines() if line.startswith(\"asmlinkage\")]\n    return syscall_defs\n\ndef get_gef_defs(start_kw, end_kw):\n    gef = open(GEF_TMP_PATH, \"rb\").read().decode(\"ascii\").splitlines()\n    start_kw_pos = gef.index(start_kw)\n    end_kw_pos = gef.index(end_kw, start_kw_pos)\n    return gef[start_kw_pos + 1:end_kw_pos], start_kw_pos, end_kw_pos\n\n# replace line and add \"!\"\ndef replace_lines1(replace_rules, lines):\n    for rule in replace_rules:\n        before, after = rule\n        if before not in lines:\n            continue\n        idx = lines.index(before)\n        lines[idx] = \"!\" + after\n    return lines\n\n# add \"#\"\ndef replace_lines2(replace_rules, lines):\n    for rule in replace_rules:\n        lines_tmp = []\n        for line in lines:\n            if line.startswith(rule):\n                line = \"#\" + line\n            lines_tmp.append(line)\n        lines = lines_tmp[::]\n    return lines\n\ndef syscall_defs_update():\n    print(titlify(\"syscall_defs\"))\n\n    new_syscall_defs = get_new_defs(\"include/linux/syscalls.h\")\n    old_syscall_defs, s, e = get_gef_defs('syscall_defs = \"\"\"', '\"\"\"')\n\n    # replace some defs\n    replace_rules1 = [\n        [\"asmlinkage long sys_io_submit(aio_context_t, long, struct iocb __user *__user *);\",\n         \"asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, struct iocb __user * __user *iocbpp);\",\n        ],\n        [\"asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, fd_set __user *, struct __kernel_timespec __user *, void __user *);\",\n         \"asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_timespec __user *tsp, void __user *sig);\",\n        ],\n        [\"asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *, fd_set __user *, struct old_timespec32 __user *, void __user *);\",\n         \"asmlinkage long sys_pselect6_time32(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct old_timespec32 __user *tsp, void __user *sig);\",\n        ],\n        [\"asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int, struct __kernel_timespec __user *, const sigset_t __user *, size_t);\",\n         \"asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, struct __kernel_timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize);\",\n        ],\n        [\"asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int, struct old_timespec32 __user *, const sigset_t __user *, size_t);\",\n         \"asmlinkage long sys_ppoll_time32(struct pollfd __user *ufds, unsigned int nfds, struct old_timespec32 __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize);\",\n        ],\n        [\"asmlinkage long sys_rt_sigaction(int, const struct sigaction __user *, struct sigaction __user *, size_t);\",\n         \"asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, size_t sigsetsize);\",\n        ],\n        [\"asmlinkage long sys_socket(int, int, int);\",\n         \"asmlinkage long sys_socket(int family, int type, int protocol);\",\n        ],\n        [\"asmlinkage long sys_socketpair(int, int, int, int __user *);\",\n         \"asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);\",\n        ],\n        [\"asmlinkage long sys_bind(int, struct sockaddr __user *, int);\",\n         \"asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);\",\n        ],\n        [\"asmlinkage long sys_listen(int, int);\",\n         \"asmlinkage long sys_listen(int fd, int backlog);\",\n        ],\n        [\"asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);\",\n         \"asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);\",\n        ],\n        [\"asmlinkage long sys_connect(int, struct sockaddr __user *, int);\",\n         \"asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);\",\n        ],\n        [\"asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);\",\n         \"asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);\",\n        ],\n        [\"asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);\",\n         \"asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);\",\n        ],\n        [\"asmlinkage long sys_sendto(int, void __user *, size_t, unsigned, struct sockaddr __user *, int);\",\n         \"asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, struct sockaddr __user *addr, int addr_len);\",\n        ],\n        [\"asmlinkage long sys_recvfrom(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *);\",\n         \"asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, struct sockaddr __user *addr, int __user *addr_len);\",\n        ],\n        [\"asmlinkage long sys_shutdown(int, int);\",\n         \"asmlinkage long sys_shutdown(int fd, int how);\",\n        ],\n        [\"asmlinkage long sys_accept4(int, struct sockaddr __user *, int __user *, int);\",\n         \"asmlinkage long sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen, int flags);\",\n        ],\n    ]\n\n    replace_rules2 = [\n        \"asmlinkage long sys_clone(\",\n        \"asmlinkage long sys_sigsuspend(int\",\n        \"asmlinkage long sys_ni_syscall(\",\n        \"asmlinkage long sys_fanotify_mark(\",\n    ]\n\n    new_syscall_defs = replace_lines1(replace_rules1, new_syscall_defs)\n    new_syscall_defs = replace_lines2(replace_rules2, new_syscall_defs)\n\n    print_diff(old_syscall_defs, new_syscall_defs)\n    write_back(new_syscall_defs, s, e)\n    return\n\ndef syscall_defs_compat_update():\n    print(titlify(\"syscall_defs_compat\"))\n\n    new_syscall_defs = get_new_defs(\"include/linux/compat.h\")\n    old_syscall_defs, s, e = get_gef_defs('syscall_defs_compat = \"\"\"', '\"\"\"')\n\n    replace_rules1 = [\n        [\"asmlinkage long compat_sys_waitid(int, compat_pid_t, struct compat_siginfo __user *, int, struct compat_rusage __user *);\",\n         \"asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, struct compat_siginfo __user *waitid, int options, struct compat_rusage __user *uru);\",\n        ],\n        [\"asmlinkage long compat_sys_kexec_load(compat_ulong_t entry, compat_ulong_t nr_segments, struct compat_kexec_segment __user *, compat_ulong_t flags);\",\n         \"asmlinkage long compat_sys_kexec_load(compat_ulong_t entry, compat_ulong_t nr_segments, struct compat_kexec_segment __user *segments, compat_ulong_t flags);\",\n        ],\n        [\"asmlinkage long compat_sys_rt_sigaction(int, const struct compat_sigaction __user *, struct compat_sigaction __user *, compat_size_t);\",\n         \"asmlinkage long compat_sys_rt_sigaction(int sig, const struct compat_sigaction __user *act, struct compat_sigaction __user *oact, compat_size_t sigsetsize);\",\n        ],\n        [\"asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32, int, const char __user *);\",\n         \"asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags, __u32 mask_1, __u32 mask_2, int dfd, const char __user *pathname);\",\n        ],\n        [\"asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct old_timespec32 __user *timeout, const struct __compat_aio_sigset __user *usig);\",\n         \"asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct old_timespec32 __user *timeout, const struct __compat_aio_sigset __user *usig); # codespell:ignore\",\n        ],\n        [\"asmlinkage long compat_sys_io_pgetevents_time64(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct __kernel_timespec __user *timeout, const struct __compat_aio_sigset __user *usig);\",\n         \"asmlinkage long compat_sys_io_pgetevents_time64(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct __kernel_timespec __user *timeout, const struct __compat_aio_sigset __user *usig); # codespell:ignore\",\n        ],\n    ]\n\n    replace_rules2 = [\n    ]\n\n    new_syscall_defs = replace_lines1(replace_rules1, new_syscall_defs)\n    new_syscall_defs = replace_lines2(replace_rules2, new_syscall_defs)\n\n    print_diff(old_syscall_defs, new_syscall_defs)\n    write_back(new_syscall_defs, s, e)\n    return\n\n################################################################################\n# update syscall table\n\ndef get_new_tbl(tbl_path):\n    path = os.path.join(K_DIR, tbl_path)\n    print(\"[+] path:\", path)\n    new_tbl = open(path, \"rb\").read().decode(\"ascii\").expandtabs(8).splitlines()\n    new_tbl = [l for l in new_tbl if l and not l.startswith(\"#\")]\n    return new_tbl\n\ndef get_new_tbl_by_cmds(cmds):\n    cmds = \"; \".join([cmd.lstrip() for cmd in cmds.splitlines() if cmd])\n    print(\"[+] cmds:\", cmds)\n    result = subprocess.getoutput(cmds)\n    return result.splitlines()\n\ndef x64_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/x86/entry/syscalls/syscall_64.tbl\")\n    old_tbl, s, e = get_gef_defs('x64_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef i386_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/x86/entry/syscalls/syscall_32.tbl\")\n    old_tbl, s, e = get_gef_defs('x86_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef arm64_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/arm64/tools/syscall_64.tbl\")\n    old_tbl, s, e = get_gef_defs('arm64_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef arm_compat_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/arm64/tools/syscall_32.tbl\")\n    old_tbl, s, e = get_gef_defs('arm_compat_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef arm_native_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/arm/tools/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('arm_native_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef mips_o32_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/mips/kernel/syscalls/syscall_o32.tbl\")\n    old_tbl, s, e = get_gef_defs('mips_o32_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef mips_n32_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/mips/kernel/syscalls/syscall_n32.tbl\")\n    old_tbl, s, e = get_gef_defs('mips_n32_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef mips_n64_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/mips/kernel/syscalls/syscall_n64.tbl\")\n    old_tbl, s, e = get_gef_defs('mips_n64_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef ppc_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/powerpc/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('ppc_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef sparc_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/sparc/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('sparc_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef riscv64_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\ndef riscv32_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\ndef s390x_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/s390/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('s390x_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef sh4_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/sh/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('sh4_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef m68k_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/m68k/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('m68k_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef alpha_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/alpha/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('alpha_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef hppa_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/parisc/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('hppa_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef or1k_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\ndef nios2_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\ndef microblaze_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/microblaze/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('microblaze_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef xtensa_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl(\"arch/xtensa/kernel/syscalls/syscall.tbl\")\n    old_tbl, s, e = get_gef_defs('xtensa_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef cris_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    new_tbl = get_new_tbl_by_cmds(\n        r\"\"\"\n        cd {:s}\n        awk '/sys_call_table:/,/^$/' arch/cris/arch-v10/kernel/entry.S | grep -o \"\\.long \\w*\" | nl -v0 | awk '{print $1\" cris \"substr($3,5)\" \"$3}' |column -t\n        \"\"\".format(K_DIR)\n    )\n    old_tbl, s, e = get_gef_defs('cris_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef loongarch_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] skip {:s}. need fix manually.\".format(sys._getframe().f_code.co_name[:-19]) + \"\\033[0m\")\n    return\n\n    new_tbl = get_new_tbl_by_cmds(\n        r\"\"\"\n        cd {:s}\n        gcc -I `pwd`/include/uapi/ -E -D__SYSCALL=SYSCALL arch/loongarch/include/uapi/asm/unistd.h | grep ^SYSCALL | sed -e 's/SYSCALL(//;s/[,)]//g' > /tmp/a\n        grep -oP \"__NR\\S+\\s+\\d+$\" include/uapi/asm-generic/unistd.h | grep -v __NR_sync_file_range2 > /tmp/b\n        join -2 2 -o 1.1,1.10,2.1,1.2 -e loongarch /tmp/a /tmp/b 2>/dev/null | sed -e 's/\\(__NR_\\|__NR3264_\\)//g' | column -t\n        \"\"\".format(K_DIR)\n    )\n    old_tbl, s, e = get_gef_defs('loongarch_syscall_tbl = \"\"\"', '\"\"\"')\n    print_diff(old_tbl, new_tbl)\n    write_back(new_tbl, s, e)\n    return\n\ndef arc_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\ndef csky_syscall_tbl_update():\n    print(titlify(sys._getframe().f_code.co_name[:-7]))\n    print(\"\\033[1m\" + \"[!] same with arm64 \\033[0m\")\n    return\n\n################################################################################\n# main\n\nif __name__ == \"__main__\":\n    init()\n\n    syscall_defs_update()\n    syscall_defs_compat_update()\n\n    x64_syscall_tbl_update()\n    i386_syscall_tbl_update()\n    arm64_syscall_tbl_update()\n    arm_compat_syscall_tbl_update()\n    arm_native_syscall_tbl_update()\n    mips_o32_syscall_tbl_update()\n    mips_n32_syscall_tbl_update()\n    mips_n64_syscall_tbl_update()\n    ppc_syscall_tbl_update()\n    sparc_syscall_tbl_update()\n    riscv64_syscall_tbl_update()\n    riscv32_syscall_tbl_update()\n    s390x_syscall_tbl_update()\n    sh4_syscall_tbl_update()\n    m68k_syscall_tbl_update()\n    alpha_syscall_tbl_update()\n    hppa_syscall_tbl_update()\n    or1k_syscall_tbl_update()\n    nios2_syscall_tbl_update()\n    microblaze_syscall_tbl_update()\n    xtensa_syscall_tbl_update()\n    #cris_syscall_tbl_update() # cris is removed at current linux\n    loongarch_syscall_tbl_update() # skip\n    arc_syscall_tbl_update()\n    csky_syscall_tbl_update()\n\n    print_patch_result()\n    cleanup()\n"
  },
  {
    "path": "dev/zellij/zellij-init.py",
    "content": "# GEF Zellij Initializer\n#\n# This script configures GEF to redirect its context output to the Zellij panes.\n# Place it in the same directory as `zellij-wrapper.py`.\n# This script is automatically called from `zellij-wrapper.py`.\n# Change `PANE_SECTIONS` to match the layout description in `zellij-wrapper.py`.\n\nimport os\nimport glob\nimport time\nimport signal\nimport subprocess\n\nimport gdb\nimport atexit\n\n\nPANE_SECTIONS = {\n    # pane_name: [gef_context_sections]\n    \"code_args_source\": [\"code\", \"args\", \"source\"],\n    \"trace_threads_memwatch_extra\": [\"trace\", \"threads\", \"mem_watch\", \"extra\"],\n    \"legend_regs\": [\"legend\", \"regs\"],\n    \"stack_memaccess\": [\"stack\", \"mem_access\"],\n}\n\nTTY_FILE_PREFIX = \"/tmp/gef/zellij-\"\nTTY_FILE_SUFFIX = \".tty\"\n\n# Timeout for waiting TTY files to appear (seconds)\nTTY_WAIT_TIMEOUT = 10\nTTY_WAIT_INTERVAL = 0.2\n\n\ndef wait_for_tty_files():\n    \"\"\"Wait for all pane TTY files to be written and return a dict of {pane_name: tty_path}.\"\"\"\n    expected_panes = set(PANE_SECTIONS.keys())\n    result = {}\n    deadline = time.time() + TTY_WAIT_TIMEOUT\n\n    while time.time() < deadline:\n        for pane_name in list(expected_panes):\n            tty_file = f\"{TTY_FILE_PREFIX}{pane_name}{TTY_FILE_SUFFIX}\"\n            if os.path.exists(tty_file):\n                try:\n                    with open(tty_file, \"r\") as f:\n                        tty_path = f.read().strip()\n                    if tty_path:\n                        result[pane_name] = tty_path\n                        expected_panes.discard(pane_name)\n                except (IOError, OSError):\n                    pass\n\n        if not expected_panes:\n            return result\n\n        time.sleep(TTY_WAIT_INTERVAL)\n\n    if expected_panes:\n        print(f\"[zellij_init] Warning: Timed out waiting for TTY files: {expected_panes}\")\n    return result\n\n\ndef get_redirect_configs():\n    \"\"\"Return a list of GEF redirect config keys.\"\"\"\n    return [\n        \"context.redirect\",\n        \"context_args.redirect\",\n        \"context_code.redirect\",\n        \"context_extra.redirect\",\n        \"context_legend.redirect\",\n        \"context_mem_access.redirect\",\n        \"context_mem_watch.redirect\",\n        \"context_regs.redirect\",\n        \"context_source.redirect\",\n        \"context_stack.redirect\",\n        \"context_threads.redirect\",\n        \"context_trace.redirect\",\n    ]\n\n\ndef configure_gef_redirects(tty_map):\n    \"\"\"Set GEF context section redirects based on the TTY map.\"\"\"\n    for pane_name, sections in PANE_SECTIONS.items():\n        tty_path = tty_map.get(pane_name)\n        if not tty_path:\n            continue\n        for section in sections:\n            try:\n                gdb.execute(\n                    f\"gef config context_{section}.redirect {tty_path}\", to_string=True\n                )\n            except gdb.error as e:\n                print(\n                    f\"[zellij_init] Warning: Failed to set redirect for {section}: {e}\"\n                )\n\n    # Additional GEF settings\n    try:\n        gdb.execute(\"gef config context_code.nb_lines 16\", to_string=True)\n        gdb.execute(\"gef config context_code.nb_lines_prev 8\", to_string=True)\n        gdb.execute(\"gef config context_stack.nb_lines 16\", to_string=True)\n    except gdb.error:\n        pass\n\n\ndef reset_gef_redirects():\n    \"\"\"Clear all GEF context redirect settings.\"\"\"\n    for config in get_redirect_configs():\n        try:\n            gdb.execute('gef config {:s} \"\"'.format(config), to_string=True)\n        except gdb.error:\n            pass\n\n\ncleanup_state = {\n    \"pane_pids\": [],\n    \"registered\": False,\n}\n\n\ndef find_cat_pids_for_ttys(tty_map):\n    \"\"\"Find PIDs of 'cat' processes running on the given TTYs.\"\"\"\n    pids = []\n    for pane_name, tty_path in tty_map.items():\n        try:\n            result = subprocess.run(\n                [\"ps\", \"-t\", tty_path.replace(\"/dev/\", \"\"), \"-o\", \"pid,comm\", \"--no-headers\"],\n                capture_output=True,\n                text=True,\n                timeout=3,\n            )\n            for line in result.stdout.strip().splitlines():\n                parts = line.strip().split()\n                if len(parts) >= 2 and parts[1] == \"cat\":\n                    pids.append(int(parts[0]))\n        except Exception:\n            pass\n    return pids\n\n\ndef reset_panes():\n    \"\"\"Reset GEF settings and kill display pane processes. Called on GDB exit.\"\"\"\n    reset_gef_redirects()\n\n    for pid in cleanup_state.get(\"pane_pids\", []):\n        try:\n            os.kill(pid, signal.SIGTERM)\n        except (ProcessLookupError, PermissionError, OSError):\n            pass\n\n    # Clean up TTY files\n    for f in glob.glob(f\"{TTY_FILE_PREFIX}*{TTY_FILE_SUFFIX}\"):\n        try:\n            os.remove(f)\n        except OSError:\n            pass\n\n    try:\n        atexit.unregister(reset_panes)\n    except Exception:\n        pass\n\n    cleanup_state[\"registered\"] = False\n\n\ndef main():\n    # Check if we're in a Zellij session\n    if not os.environ.get(\"ZELLIJ\"):\n        print(\"[zellij_init] Error: Not in a Zellij session.\")\n        return\n\n    # Reset any previous pane settings from GEF tmux-setup\n    try:\n        gdb.execute(\"pi GefTmuxSetupCommand.reset_panes()\", to_string=True)\n    except gdb.error:\n        pass\n\n    print(\"[zellij_init] Waiting for display panes to initialize...\")\n    tty_map = wait_for_tty_files()\n\n    if not tty_map:\n        print(\"[zellij_init] Error: No pane TTYs discovered. Setup failed.\")\n        return\n\n    # Find cat PIDs for cleanup\n    cleanup_state[\"pane_pids\"] = find_cat_pids_for_ttys(tty_map)\n\n    # Configure GEF redirects\n    configure_gef_redirects(tty_map)\n\n    # Register cleanup on exit\n    atexit.register(reset_panes)\n    cleanup_state[\"registered\"] = True\n\n    # Clear GEF cache\n    try:\n        gdb.execute(\"gef reset-cache\", to_string=True)\n    except gdb.error:\n        pass\n\n    # Report success\n    print(\"[zellij_init] Zellij panes configured successfully.\")\n    for pane_name, tty_path in sorted(tty_map.items()):\n        sections = \", \".join(PANE_SECTIONS[pane_name])\n        print(f\"  {pane_name}: {tty_path} -> [{sections}]\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "dev/zellij/zellij-wrapper.py",
    "content": "#!/usr/bin/env python3\n# GEF Zellij Wrapper\n#\n# This wrapper launches Zellij with a GEF-compatible layout and starts GDB\n# in the command pane. When GDB exits, the Zellij session is closed.\n#\n# Usage:\n#   ./zellij-wrapper.py [gdb_args...]\n#\n# Examples:\n#   ./zellij-wrapper.py             # Just start gdb\n#   ./zellij-wrapper.py ./a.out     # gdb ./a.out\n#   ./zellij-wrapper.py -q ./a.out  # gdb -q ./a.out\n#\n# NOTE: This script should be run OUTSIDE of Zellij.\n#       It will create a new Zellij session with the correct layout.\n\nimport os\nimport sys\nimport glob\nimport subprocess\n\ndef generate_layout_kdl(gdb_args, script_path):\n    \"\"\"Generate a KDL layout file for GEF panes.\n\n    Layout:\n    +--------+--------+--------+\n    |        | code   | legend |\n    |        | args   | regs   |\n    |        | source +--------+\n    |        |        | stack  |\n    |        +--------+ mem_acc|\n    |        | others |        |\n    | cmd    |        |        |\n    +--------+--------+--------+\n    \"\"\"\n    # Build the GDB command with auto-source of the setup script\n    # The setup script (zellij-init.py) will be sourced in GDB to configure redirects\n    init_script = os.path.join(os.path.dirname(script_path), \"zellij-init.py\")\n\n    # Build args string for GDB command pane\n    quoted_args = \" \".join(f'\"{a}\"' for a in gdb_args)\n\n    layout = \"\"\"\nlayout {\n    pane split_direction=\"vertical\" {\n        pane size=\"33%\" focus=true {\n            name \"command\"\n            command \"gdb\"\n            args \"-ex\" \"source INIT_SCRIPT\" GDB_ARGS\n            close_on_exit true\n        }\n        pane size=\"33%\" split_direction=\"horizontal\" {\n            pane size=\"67%\" {\n                name \"code/args/source\"\n                command \"bash\"\n                args \"-c\" \"tty > /tmp/gef/zellij-code_args_source.tty; exec cat\"\n                close_on_exit true\n            }\n            pane size=\"33%\" {\n                name \"trace/thread/mem-watch/extra\"\n                command \"bash\"\n                args \"-c\" \"tty > /tmp/gef/zellij-trace_threads_memwatch_extra.tty; exec cat\"\n                close_on_exit true\n            }\n        }\n        pane size=\"34%\" split_direction=\"horizontal\" {\n            pane size=\"33%\" {\n                name \"legend/regs\"\n                command \"bash\"\n                args \"-c\" \"tty > /tmp/gef/zellij-legend_regs.tty; exec cat\"\n                close_on_exit true\n            }\n            pane size=\"67%\" {\n                name \"stack/mem-access\"\n                command \"bash\"\n                args \"-c\" \"tty > /tmp/gef/zellij-stack_memaccess.tty; exec cat\"\n                close_on_exit true\n            }\n        }\n    }\n}\n\"\"\".replace(\"INIT_SCRIPT\", init_script).replace(\"GDB_ARGS\", quoted_args)\n    return layout\n\n\ndef cleanup_tty_files():\n    \"\"\"Remove any leftover TTY files from a previous session.\"\"\"\n    for f in glob.glob(\"/tmp/gef/zellij-*.tty\"):\n        try:\n            os.remove(f)\n        except OSError:\n            pass\n\n\ndef main():\n    # Clean up leftover TTY files\n    cleanup_tty_files()\n\n    # Generate layout\n    layout_content = generate_layout_kdl(sys.argv[1:], os.path.abspath(__file__))\n\n    # Write layout to temporary file\n    layout_file = \"/tmp/gef/zellij-wrapper-layout.kdl\"\n    with open(layout_file, \"w\") as f:\n        f.write(layout_content)\n    print(f\"[zellij-wrapper] Layout written to {layout_file}\")\n\n    try:\n        # Launch zellij with the layout\n        print(\"[zellij-wrapper] Starting Zellij with GDB...\")\n        subprocess.run([\"zellij\", \"--layout\", layout_file], check=False)\n    except KeyboardInterrupt:\n        pass\n    finally:\n        # Clean up\n        cleanup_tty_files()\n        try:\n            os.remove(layout_file)\n        except OSError:\n            pass\n    return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "docs/BUILDING-QEMU-SYSTEM-ENV.md",
    "content": "## Building Qemu\n\n```bash\napt install libslirp-dev\napt build-dep qemu ninja-build\n\nwget https://download.qemu.org/qemu-9.2.0.tar.xz\ntar xf qemu-9.2.0.tar.xz\ncd qemu-9.2.0\ncp -r pc-bios /usr/local/bin\n\n./configure --enable-slirp\nmake -j\nmake install\n```\n\n## buildroot x86-64\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_x86_64_defconfig\nmake\n\nqemu-system-x86_64 \\\n    -M pc \\\n    -m 512M \\\n    -cpu kvm64,+smep,+smap \\\n    -kernel output/images/bzImage \\\n    -drive file=output/images/rootfs.ext2,if=virtio,format=raw \\\n    -append \"rootwait root=/dev/vda console=tty1 console=ttyS0 noapic\" \\\n    -net nic,model=virtio \\\n    -net user \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n- Notes\n    - Various default build configs for buildroot are in `configs/`.\n        - When you run `make qemu_x86_64_defconfig`, it will be copied to `.config` in the top directory and used.\n    - The build configuration for the Linux kernel is in `board/qemu/*/linux.config`.\n        - Change this if you want to change the configuration.\n        - Or copy it to another location and specify the following in the build configuration (`.config`) of buildroot itself in the top directory.\n            - `BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y`\n            - `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=\"/path/to/config\"`\n    - The startup command is written in `board/qemu/*/readme.txt`.\n        - Modify it as appropriate, for example adding `-nographic` or removing `-serial`.\n    - If the Qemu download is too slow, abort the build, switch to the mirror site as follows, and make again.\n        ```\n        vi package/qemu/qemu.mk\n        -QEMU_SITE = http://download.qemu.org\n        +QEMU_SITE = https://mirror.koddos.net/blfs/conglomeration/qemu\n        ```\n    - If you want to replace the kernel with the latest version, just build the kernel, replace the `bzImage`, and start it.\n        ```\n        git clone https://github.com/torvalds/linux.git\n        cd linux/\n        make defconfig\n        make\n\n        # If you want to cross compile here,\n        #     For i386: make defconfig && make ARCH=i386\n        #     For AArch64: make ARCH=arm64 defconfig && make ARCH=arm64 CROSS_COMPILE=\"aarch64-linux-gnu-\"\n        #     For ARM: make ARCH=arm defconfig && make ARCH=arm CROSS_COMPILE=\"arm-linux-gnueabihf-\"\n\n        qemu-system-x86_64 \\\n            -M pc \\\n            -kernel kernel/linux/arch/x86_64/boot/bzImage \\\n            -drive file=buildroot-2024.11.1/output/images/rootfs.ext2,if=ide \\\n            -append \"root=/dev/sda console=ttyS0\" \\\n            -nographic \\\n            -netdev tap,id=tap0 \\\n            -device e1000,netdev=tap0 \\\n            -monitor telnet:127.0.0.1:9999,server,nowait \\\n            -s\n\n        # Note 1\n        # When I updated the kernel, eth0 was no longer recognized for some reason,\n        # so I recommend creating tap0 with the qemu command (-netdev tap,id=tap0 -device e1000,netdev=tap0) and attaching it.\n        # https://unix.stackexchange.com/questions/171874/no-network-interface-in-qemu\n\n        # Note 2\n        # For some reason, the new kernel no longer recognizes /dev/vda,\n        # so it is a good idea to change the type to ide and start it as /dev/sda\n        # (virtio: /dev/vda, ide connection: /dev/sda, SD card: /dev/mmcblk0).\n        ```\n\n## buildroot x86\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_x86_defconfig\nmake\n\nqemu-system-i386 \\\n    -M pc \\\n    -kernel output/images/bzImage \\\n    -drive file=output/images/rootfs.ext2,if=virtio,format=raw \\\n    -append \"rootwait root=/dev/vda console=tty1 console=ttyS0\" \\\n    -net nic,model=virtio \\\n    -net user \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## buildroot ARM\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_arm_vexpress_defconfig\nmake\n\nqemu-system-arm \\\n    -M vexpress-a9 \\\n    -m 256 \\\n    -kernel output/images/zImage \\\n    -dtb output/images/vexpress-v2p-ca9.dtb \\\n    -drive file=output/images/rootfs.ext2,if=sd,format=raw \\\n    -append \"console=ttyAMA0,115200 rootwait root=/dev/mmcblk0\" \\\n    -net nic,model=lan9118 \\\n    -net user \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n- Notes\n    - In the case of ARM (vexpress), there is no configuration in `board/qemu/arm-vexpress/linux.config`.\n    - The following steps are necessary (I think), but I'm not sure what the correct way is.\n        - Build once with buildroot\n        - Copy the generated `output/build/linux-XXX/.config` to another location and modify the contents\n        - Specify `.config` with `BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE`.\n\n## buildroot AArch64\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_aarch64_virt_defconfig\nmake\n\nqemu-system-aarch64 \\\n    -M virt \\\n    -cpu cortex-a53 \\\n    -smp 1 \\\n    -kernel output/images/Image \\\n    -append \"rootwait root=/dev/vda console=ttyAMA0\" \\\n    -netdev user,id=eth0 \\\n    -device virtio-net-device,netdev=eth0 \\\n    -drive file=output/images/rootfs.ext4,if=none,format=raw,id=hd0 \\\n    -device virtio-blk-device,drive=hd0 \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## buildroot mipsel\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_mips32r6el_malta_defconfig\nmake\n\nqemu-system-mipsel \\\n    -M malta \\\n    -cpu mips32r6-generic \\\n    -kernel output/images/vmlinux \\\n    -drive file=output/images/rootfs.ext2,format=raw \\\n    -append \"rootwait root=/dev/hda\" \\\n    -net nic,model=pcnet \\\n    -net user \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## buildroot mips\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_mips32r6_malta_defconfig\nmake\n\nqemu-system-mips \\\n    -M malta \\\n    -cpu mips32r6-generic \\\n    -kernel output/images/vmlinux \\\n    -drive file=output/images/rootfs.ext2,format=raw \\\n    -append \"rootwait root=/dev/hda\" \\\n    -net nic,model=pcnet \\\n    -net user \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## buildroot mips64el\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_mips64r6el_malta_defconfig\nmake\n\nqemu-system-mips64el \\\n    -M malta \\\n    -cpu I6400 \\\n    -kernel output/images/vmlinux \\\n    -drive file=output/images/rootfs.ext2,format=raw \\\n    -append \"rootwait root=/dev/hda\" \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## buildroot mips64\n```bash\ntar xf buildroot-2024.11.1.tar.xz\ncd buildroot-2024.11.1/\nmake qemu_mips64r6_malta_defconfig\nmake\n\nqemu-system-mips64el \\\n    -M malta \\\n    -cpu I6400 \\\n    -kernel output/images/vmlinux \\\n    -drive file=output/images/rootfs.ext2,format=raw \\\n    -append \"rootwait root=/dev/hda\" \\\n    -nographic \\\n    -monitor telnet:127.0.0.1:9999,server,nowait \\\n    -s\n```\n\n## debian x86-64\n```bash\nwget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.9.0-amd64-netinst.iso\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# For some reason, adding -nographic -serial mon:stdio did not work as the output was not displayed on the screen,\n# so I started it without those options and set it up in a GUI environment.\nqemu-system-x86_64 \\\n    -enable-kvm \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -net nic,model=virtio \\\n    -net user \\\n    -cdrom debian-12.9.0-amd64-netinst.iso \\\n    -boot d\n\n# Open disk.qcow2 with 7-zip file manager and extract the following two files:\n0.img/boot/initrd.img-6.1.123-amd64\n0.img/boot/vmlinuz-6.1.123-amd64\n\n# Run\nqemu-system-x86_64 \\\n    -enable-kvm \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -kernel vmlinuz-6.1.123-1-amd64 \\\n    -append 'root=/dev/sda1 console=ttyS0' \\\n    -initrd initrd.img-6.1.123-1-amd64 \\\n    -net nic,model=virtio \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22 \\\n    -nographic \\\n    -serial mon:stdio \\\n    -s\n```\n\n## debian x86\n```bash\nwget https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-12.9.0-i386-netinst.iso\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# For some reason, adding -nographic -serial mon:stdio did not work as the output was not displayed on the screen,\n# so I started it without those options and set it up in a GUI environment.\nqemu-system-i386 \\\n    -enable-kvm \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -net nic,model=virtio \\\n    -net user \\\n    -cdrom debian-12.9.0-i386-netinst.iso \\\n    -boot d\n\n# Open disk.qcow2 with 7-zip file manager and extract the following two files:\n0.img/boot/initrd.img-6.1.123-1-686-pae\n0.img/boot/vmlinuz-6.1.123-1-686-pae\n\n# Run\nqemu-system-i386 \\\n    -enable-kvm \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -kernel vmlinuz-6.1.123-1-686-pae \\\n    -append 'root=/dev/sda1 console=ttyS0' \\\n    -initrd initrd.img-6.1.123-1-686-pae \\\n    -net nic,model=virtio \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22 \\\n    -nographic \\\n    -serial mon:stdio \\\n    -s\n```\n\n## debian ARM\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-armhf/current/images/netboot/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-armhf/current/images/netboot/vmlinuz\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-arm \\\n    -smp 2 \\\n    -M virt \\\n    -cpu cortex-a15 \\\n    -m 1G \\\n    -initrd initrd.gz \\\n    -kernel vmlinuz \\\n    -append \"root=/dev/ram console=ttyAMA0\" \\\n    -global virtio-blk-device.scsi=off \\\n    -device virtio-scsi-device,id=scsi \\\n    -drive file=disk.qcow2,id=rootimg,cache=unsafe,if=none \\\n    -device scsi-hd,drive=rootimg \\\n    -netdev user,id=unet \\\n    -device virtio-net-device,netdev=unet \\\n    -net user \\\n    -nographic \\\n    -s\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/initrd.img-*-armmp-lpae mnt/vmlinuz-*-armmp-lpae . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz vmlinuz\n\n# Run\nqemu-system-arm \\\n    -smp 2 \\\n    -M virt \\\n    -cpu cortex-a15 \\\n    -m 1G \\\n    -initrd initrd.img-4.19.0-9-armmp-lpae \\\n    -kernel vmlinuz-4.19.0-9-armmp-lpae \\\n    -append \"root=/dev/sda2 console=ttyAMA0\" \\\n    -global virtio-blk-device.scsi=off \\\n    -device virtio-scsi-device,id=scsi \\\n    -drive file=disk.qcow2,id=rootimg,cache=unsafe,if=none \\\n    -device scsi-hd,drive=rootimg \\\n    -device virtio-net-device,netdev=net0 \\\n    -netdev user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic \\\n    -s\n```\n\n## debian AArch64\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-arm64/current/images/netboot/debian-installer/arm64/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-arm64/current/images/netboot/debian-installer/arm64/linux\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-aarch64 \\\n    -smp 2 \\\n    -M virt \\\n    -cpu cortex-a57 \\\n    -m 1G \\\n    -initrd initrd.gz \\\n    -kernel linux \\\n    -append \"root=/dev/ram console=ttyAMA0\" \\\n    -global virtio-blk-device.scsi=off \\\n    -device virtio-scsi-device,id=scsi \\\n    -drive file=disk.qcow2,id=rootimg,cache=unsafe,if=none \\\n    -device scsi-hd,drive=rootimg \\\n    -netdev user,id=unet \\\n    -device virtio-net-device,netdev=unet \\\n    -net user \\\n    -nographic \\\n    -s\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/initrd.img-*-arm64 mnt/vmlinuz-*-arm64 . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz linux\n\n# Run\nqemu-system-aarch64\n    -smp 2 \\\n    -M virt \\\n    -cpu cortex-a57 \\\n    -m 1G \\\n    -initrd initrd.img-4.19.0-9-arm64 \\\n    -kernel vmlinuz-4.19.0-9-arm64 \\\n    -append \"root=/dev/sda2 console=ttyAMA0\" \\\n    -global virtio-blk-device.scsi=off \\\n    -device virtio-scsi-device,id=scsi \\\n    -drive file=disk.qcow2,id=rootimg,cache=unsafe,if=none \\\n    -device scsi-hd,drive=rootimg \\\n    -device virtio-net-device,netdev=net0 \\\n    -netdev user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic \\\n    -s\n```\n\n## debian mipsel\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mipsel/current/images/malta/netboot/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mipsel/current/images/malta/netboot/vmlinux-4.19.0-9-4kc-malta\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-mipsel \\\n    -M malta \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.gz \\\n    -kernel ./vmlinux-4.19.0-9-4kc-malta \\\n    -append \"nokaslr\" \\\n    -nographic\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/boot/initrd.img-*-malta . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz\n\n# Run\nqemu-system-mipsel \\\n    -M malta \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.img-4.19.0-9-4kc-malta \\\n    -kernel ./vmlinux-4.19.0-9-4kc-malta \\\n    -append \"nokaslr root=/dev/sda1\" \\\n    -net nic,model=e1000 \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic\n```\n\n```bash\n# Execute in the guest\n\n# fix interface\ncat > /etc/network/interfaces << EOF\nauto lo\nauto enp0s18\niface lo inet loopback\niface enp0s18 inet dhcp\nEOF\nsystemctl restart networking\n```\n\n## debian mips\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mips/current/images/malta/netboot/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mips/current/images/malta/netboot/vmlinux-4.19.0-9-4kc-malta\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-mips \\\n    -M malta \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.gz \\\n    -kernel ./vmlinux-4.19.0-9-4kc-malta \\\n    -append \"nokaslr\" \\\n    -nographic\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/boot/initrd.img-*-malta . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz\n\n# Run\nqemu-system-mips \\\n    -M malta \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.img-4.19.0-9-4kc-malta \\\n    -kernel ./vmlinux-4.19.0-9-4kc-malta \\\n    -append \"nokaslr root=/dev/sda1\" \\\n    -net nic,model=e1000 \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic\n```\n\n```bash\n# Execute in the guest\n\n# fix interface\ncat > /etc/network/interfaces << EOF\nauto lo\nauto enp0s18\niface lo inet loopback\niface enp0s18 inet dhcp\nEOF\nsystemctl restart networking\n```\n\n## debian mips64el\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mips64el/current/images/malta/netboot/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-mips64el/current/images/malta/netboot/vmlinux-4.19.0-9-5kc-malta\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-mips64el \\\n    -M malta \\\n    -cpu MIPS64R2-generic \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.gz \\\n    -kernel ./vmlinux-4.19.0-9-5kc-malta \\\n    -append \"nokaslr\" \\\n    -nographic\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/boot/initrd.img-*-malta . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz\n\n# Run\nqemu-system-mips64el \\\n    -M malta \\\n    -cpu MIPS64R2-generic \\\n    -m 1G \\\n    -hda ./disk.qcow2 \\\n    -initrd ./initrd.img-4.19.0-9-5kc-malta \\\n    -kernel ./vmlinux-4.19.0-9-5kc-malta \\\n    -append \"nokaslr root=/dev/sda1\" \\\n    -net nic,model=e1000 \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic\n```\n\n```bash\n# Execute in the guest\n\n# fix interface\ncat > /etc/network/interfaces << EOF\nauto lo\nauto enp0s18\niface lo inet loopback\niface enp0s18 inet dhcp\nEOF\nsystemctl restart networking\n```\n\n## debian ppc64el\n```bash\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-ppc64el/current/images/netboot/debian-installer/ppc64el/initrd.gz\nwget http://ftp.debian.org/debian/dists/Debian10.4/main/installer-ppc64el/current/images/netboot/debian-installer/ppc64el/vmlinux\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-ppc64 \\\n    -M pseries-2.12 \\\n    -cpu power9 \\\n    -smp 2 \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -initrd ./initrd.gz \\\n    -kernel ./vmlinux \\\n    -append \"nokaslr\" \\\n    -net nic,macaddr=52:54:00:fa:ce:12,model=virtio \\\n    -net user \\\n    -nographic \\\n    -nodefaults \\\n    -serial stdio\n\n# Open disk.qcow2 with 7-zip file manager and extract the following two files:\n1.img/boot/initrd.img-4.19.0-9-powerpc64le\n1.img/boot/vmlinux-4.19.0-9-powerpc64le\n\n# Delete the kernel and ramdisk used during installation\nrm -f initrd.gz vmlinux\n\n# Run\nqemu-system-ppc64 \\\n    -M pseries-2.12 \\\n    -cpu power9 \\\n    -smp 2 \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -initrd ./initrd.img-4.19.0-9-powerpc64le \\\n    -kernel ./vmlinux-4.19.0-9-powerpc64le \\\n    -append \"nokaslr root=/dev/sda2\" \\\n    -net nic,macaddr=52:54:00:fa:ce:12,model=virtio \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic \\\n    -nodefaults \\\n    -serial stdio\n```\n\n## debian sparc64\n```bash\n# Versions later than 9.0 will not install properly.\nwget http://cdimage.debian.org/cdimage/ports/9.0/sparc64/iso-cd/debian-9.0-sparc64-NETINST-1.iso\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# Press Enter to start booting from the CD, select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# You will be told that there is no NIC, but this is what you intended so select \"no ethernet card\" and proceed.\n# When asked whether to scan another CD/DVD, select No and proceed.\n# When it comes to entering the mirror, press \"Go Back\" to skip the installation from the network and proceed.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-sparc64 \\\n    -m 2G \\\n    -hda disk.qcow2 \\\n    -cdrom debian-9.0-sparc64-NETINST-1.iso \\\n    -boot once=d \\\n    -serial stdio \\\n    -nographic \\\n    -nodefaults\n\n# Run\nqemu-system-sparc64 \\\n    -machine sun4u,accel=tcg,usb=off \\\n    -m 2G \\\n    -realtime mlock=off \\\n    -smp 1,sockets=1,cores=1,threads=1 \\\n    -uuid ccd8b5c2-b8e4-4d5e-af19-9322cd8e55bf \\\n    -rtc base=utc \\\n    -no-reboot \\\n    -no-shutdown \\\n    -boot strict=on \\\n    -drive file=disk.qcow2,if=none,id=hd,format=qcow2,cache=none,aio=native \\\n    -device ide-hd,bus=ide.0,unit=0,drive=hd \\\n    -net nic,model=e1000 \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -msg timestamp=on \\\n    -serial mon:stdio \\\n    -nographic \\\n    -nodefaults\n```\n\n```bash\n# Execute in the guest\n\n# fix interface\ncat > /etc/network/interfaces << EOF\nauto lo\nauto enp2s0\niface lo inet loopback\niface enp2s0 inet dhcp\nEOF\nsystemctl restart networking\n\n# Added blacklist module\ncat > /etc/modprobe.d/drm-blacklist.conf << EOF\n# blacklist of DRM modules that do not load on qemu-system-sparc64 sun4u\nblacklist drm\nblacklist bochs-drm\nblacklist ttm\nEOF\n\n# Add the apt repository and key that are missing.\necho 'deb http://ftp.ports.debian.org/debian-ports/ unstable main' > /etc/apt/sources.list\nbusybox wget http://ftp.ports.debian.org/debian-ports/pool/main/d/debian-ports-archive-keyring/debian-ports-archive-keyring_2019.11.05_all.deb\ndpkg -i debian-ports-archive-keyring_2019.11.05_all.deb && rm debian-ports-archive-keyring_2019.11.05_all.deb\n\n# Parallel disk writing occurs during apt, causing frequent I/O errors.\n# As a countermeasure, save the apt cache to tmpfs.\n# Of course, this will disappear when you restart the computer.\nmv /var/cache/apt/archives/* /tmp\nrmdir /var/cache/apt/archives\nln -s /tmp /var/cache/apt/archives\n```\n\n## debian s390x\n```bash\nwget https://cdimage.debian.org/pub/debian/dists/stretch/main/installer-s390x/current/images/generic/kernel.debian\nwget https://cdimage.debian.org/pub/debian/dists/stretch/main/installer-s390x/current/images/generic/initrd.debian\nqemu-img create -f qcow2 disk.qcow2 20G\n\n# You will first be asked for the NIC and IP, so enter the model as virtio, IP as 10.0.2.15, default as 10.0.2.2, and DNS as 10.0.2.3.\n# Select C for language and your country (e.g. Japan or Japanese, etc.) for others.\n# Please note that mirror download destinations may not work properly in some cases.\n# Installation takes about 2 hours.\n# You may get a grub installation error, but you can ignore it and proceed.\n# When it's time for the final reboot, use pkill -9 qemu from another terminal to force it to terminate.\nqemu-system-s390x \\\n    -M s390-ccw-virtio \\\n    -m 2G \\\n    -kernel kernel.debian \\\n    -initrd initrd.debian \\\n    -drive file=disk.qcow2,if=none,format=qcow2,id=hd0 \\\n    -device virtio-blk-ccw,drive=hd0,id=virtio-disk0 \\\n    -net nic,macaddr=52:54:00:fa:ce:18,model=virtio \\\n    -net user \\\n    -nographic\n\n# Copy kernel and ramdisk\napt install nbd-client && modprobe nbd max_part=8 && qemu-nbd --connect=/dev/nbd0 disk.qcow2\nmkdir mnt && mount /dev/nbd0p1 mnt && cp mnt/boot/initrd.img mnt/boot/vmlinuz . && sync\numount /dev/nbd0p1 && nbd-client -d /dev/nbd0 && rmdir mnt && rm -f initrd.gz\n\n# Run\nqemu-system-s390x \\\n    -M s390-ccw-virtio \\\n    -m 2G \\\n    -kernel vmlinuz \\\n    -append \"root=/dev/vda1\" \\\n    -initrd initrd.img \\\n    -drive file=disk.qcow2,if=none,format=qcow2,id=hd0 \\\n    -device virtio-blk-ccw,drive=hd0,id=virtio-disk0 \\\n    -net nic,macaddr=52:54:00:fa:ce:18,model=virtio \\\n    -net user,hostfwd=tcp:127.0.0.1:2222-:22,id=net0 \\\n    -nographic\n```\n"
  },
  {
    "path": "docs/FAQ.md",
    "content": "# FAQ\n\n## Table of Contents\n- [About GEF's Files or Directories](#about-gefs-files-or-directories)\n- [About the Installation](#about-the-installation)\n- [About the Host Environment](#about-the-host-environment)\n- [About the Guest (Debugged) Environment](#about-the-guest-debugged-environment)\n- [About GEF Settings](#about-gef-settings)\n- [About Commands](#about-commands)\n- [About the Internal Mechanism](#about-the-internal-mechanism)\n- [About the Python Interface](#about-the-python-interface)\n- [About the Development Schedule](#about-the-development-schedule)\n- [About Reporting, etc.](#about-reporting-etc)\n- [About Orynth](#about-orynth)\n\n\n# About GEF's Files or Directories\n\n## Where is `gef.py`?\nBy default, GEF (`gef.py`) is placed at `/root/.gef/gef.py`.\n\nGEF is primarily a single file (`gef.py`). Optional configuration and helper files may accompany it.\n\n## What is `~/.gef.rc`?\nThis is the GEF configuration file. It is not present by default.\n\nExecuting the `gef save` command saves the current settings to disk (`~/.gef.rc`).\nThe next time GEF starts, it will automatically load this file and apply the saved settings.\nThis includes the current values of items configurable with `gef config` and user-defined command aliases.\n\n## What is `~/.gdbinit`?\nThis is the command file that GDB will execute when it starts up.\n\nBy including the following command to load `gef.py`, GEF will be loaded automatically.\nThere are two ways to load GEF from `.gdbinit`; either one works.\n```\n# New style\npython sys.path.insert(0, \"/root/.gef\"); from gef import *; Gef.main()\n\n# Old style\nsource /root/.gef/gef.py\n\n# Another old style\nsource /root/.gdbinit-gef.py  # In the old installer, GEF was located here\n```\n\nNotes:\n- The former (new style) imports GEF using Python. Because a `*.pyc` file is generated and cached, subsequent startups are faster. This is the default setting in recent versions of GEF.\n- The latter (old style) is the traditional method, where GEF is loaded directly. It takes longer to load each time, but the command is simpler.\n\n## What is `/tmp/gef`?\nThis is the directory where GEF temporarily stores files.\n\nSince it is used for caching, deleting it does not cause any issues.\nIt will be created automatically the next time GEF starts.\n\nThe variable `GEF_TEMP_DIR` is defined in `gef.py` and can be changed if necessary.\n\n## What is `install-uv.sh`?\nThis is the new installer that creates and uses a Python virtual environment (`venv`) with `uv`.\n\nIt installs the same packages as `install-no-uv.sh` (previously named simply `install.sh`).\nThe key difference is that Python packages are installed into the virtual environment.\n\nBy default, it installs into `/root/.gef/.venv-gef`.\nExternal tools such as `rp++`(`rp-lin`), `seccomp-tools`, etc. are also installed under this directory (`/root/.gef/.venv-gef/bin`).\n\nUsage:\n```\n# Run the following commands as `root` or `sudo`\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/install-uv.sh -O- | sudo sh\n```\n\n## What is `install-no-uv.sh`?\nThis is the old installer that was used before the `uv`-based installation became available.\n\nThis installer is not currently recommended, but it still works.\n\nUsage:\n```\n# Run the following commands as `root` or `sudo`\n\n# On Ubuntu 23.04 or later, global Python package installation via pip3 is restricted.\n# Use the --break-system-packages option.\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/install-no-uv.sh -O- \\\n| sed -e 's/pip3 install/pip3 install --break-system-packages/g' | sudo sh\n\n# For Ubuntu 22.10 or earlier\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/install-no-uv.sh -O- | sudo sh\n```\n\n## What is `install-minimal.sh`?\nThis is an installer for running GEF in restricted environments where required packages cannot be installed due to various limitations.\n\nMost core features work, but commands that depend on extra Python packages or external tools will be unavailable.\n\nUsage:\n```\n# Run the following commands as `root` or `sudo`\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/install-minimal.sh -O- | sudo sh\n```\n\nNotes:\n- The process is straightforward: download `gef.py`, place it in the appropriate location, and add a line to `.gdbinit` to load it. You can also do the same thing manually.\n- Because it does not install any Python packages, it does not create a `venv`.\n\n## What is `gef.venv.conf`?\nThis is the path information file required by GEF that is automatically generated when you install GEF using `install-uv.sh`.\nIt is not generated if you use `install-no-uv.sh` or `install-minimal.sh`.\nPlace this file in the same directory as `gef.py`.\n\nIt contains three pieces of path information:\n- `GEF_VENV_GEM_HOME`\n    - Sets `GEM_HOME` so Ruby `gem`-installed tools can be discovered and used by GEF.\n- `GEF_VENV_SYS_PATH`\n    - By default, GEF searches globally installed Python packages.\n    - Prepend this path to `sys.path` so that packages inside the `venv` take precedence.\n- `GEF_VENV_BIN_PATH`\n    - By default, GEF searches for executables using the `$PATH` environment variable (the actual process is a bit more complicated).\n    - GEF will prepend the specified path to the search directories before searching.\n\n\n# About the Installation\n\n## How many ways are there to install GEF?\nThere are three installers.\n\n- `uv`-based install\n    - This is the installation method provided by `install-uv.sh`.\n    - This uses `uv` to install Python packages into an isolated environment.\n    - This is a full installation, so you can use almost all the features that GEF provides.\n    - This is the currently recommended installer for GEF.\n- Minimal install\n    - This is the installation method provided by `install-minimal.sh`.\n    - Simply download `gef.py` and place it in the appropriate location.\n    - Because this method is very simple, it can also be performed manually.\n- Normal install\n    - This is the installation method provided by `install-no-uv.sh`.\n    - This uses `python3-pip` to install Python packages globally.\n    - This is a full installation, so you can use almost all the features that GEF provides.\n    - This installer is not currently recommended, but it still works.\n    - This method was used before the `uv`-based installation became available.\n\nFor an explanation of each installer, see [About GEF's Files or Directories](#about-gefs-files-or-directories).\n\n## Why does GEF need to run as `root`?\nSome GDB stubs require GEF to gather information and to read or write process memory through `/proc`, which typically needs root privileges.\n\nExamples:\n- Resolving the real PID during remote debugging (e.g., when connecting to `localhost`):\n    - GEF may search across `/proc` to identify the target process and determine details about the remote network endpoint.\n- Gathering attachment details for a process running in a container (e.g., namespaces, real file paths).\n- Intel Pin / SDE: Reads memory via `/proc/<PID>/mem` for performance.\n- qemu-user etc.: Applies patches at addresses that are not writable.\n- qemu-system: Reads physical memory via `/proc/<PID>/mem` for performance.\n    - If this is unavailable, GEF falls back to slower memory access through `gdb`.\n- qemu-system (ARM32/ARM64): Reads and writes secure-world memory.\n\nAs a result, running GEF as an unprivileged user is not currently tested.\n\nIf you prefer not to run GEF as `root`, you have two options:\n- Install and run it inside a container (e.g., Docker).\n- Install it as a normal user using the steps below.\n\n## How to change the location of GEF? / How can I run GEF as a non-`root` user?\nThis is NOT officially supported; proceed at your own risk. Future updates may break this workflow.\n\n```\n# First, download GEF install script\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/install-uv.sh -P /tmp\n\n# apt-get install as root\nsudo apt-get update\nsudo apt-get install <needed-package>   # see /tmp/install-uv.sh\n\n# 1. replace GDBINIT_PATH and GEF_DIR as you wanted\n# 2. remove root user check\n# 3. remove apt-get install\nvim /tmp/install-uv.sh\n\n# install\nsh /tmp/install-uv.sh\n\n# Delete /tmp/gef directory (if it exists)\nsudo rm -rf /tmp/gef\n```\n\nAlternative simple method (no external tools; simple loading):\n\n```\n# Download\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/gef.py -O ~/.gdbinit-gef.py\n\n# Add path to .gdbinit\necho \"source $HOME/.gdbinit-gef.py\" >> ~/.gdbinit\n```\n\nNotes:\n- GEF is designed to have as few dependencies as possible. Many commands should work with just `gef.py` without any additional external tools.\n- If you do not install external tools, the features that will not be available are listed below.\n\n## If I do not install external tools, which commands will no longer be available?\nThe following is a breakdown. It may not be comprehensive.\n\nTo use these commands fully, you need to manually install the necessary packages and tools.\n\n|GEF command/feature|Required apt package|Required python3 package|Required other tools|\n|:---|:---|:---|:---|\n|(`gef`)|`gdb` or `gdb-multiarch`|-|-|\n|`got`|`binutils` (`objdump`, `readelf`)|-|-|\n|`got --cppfilt`|`binutils` (`c++filt`)|-|-|\n|`add-symbol-temporary`|`binutils` (`objcopy`)|-|-|\n|`ksymaddr-remote-apply`|`binutils` (`objcopy`)|-|-|\n|`kmod -a`|`binutils` (`objcopy`)|-|-|\n|`ksymaddr-remote --vmlinux-file`|`binutils` (`nm`)|-|-|\n|`ktypes`|`bpftool`|-|-|\n|`ktypes-load`|`bpftool`,`gcc`|-|-|\n|`qemu-device-info`|`binutils` (`nm`)|-|-|\n|`rp`|-|-|`rp++`|\n|`rp --kernel`|`binutils` (`nm`), `grep`|-|`rp++`|\n|`binwalk-memory`|`binwalk`|-|-|\n|`diffo colordiff`|`colordiff`|-|-|\n|`diffo git-diff`|`git`|-|-|\n|`tmux-setup`|`tmux`|-|-|\n|`ps`|`procps`|-|-|\n|`proc-info`|`procps`|-|-|\n|`proc-dump`|`bsdextrautils` (`hexdump`, `column`)|-|-|\n|`heap dump-image`|`imagemagick`|-|-|\n|`vdump`|`imagemagick`|-|-|\n|`sixel-memory`|`imagemagick`|-|-|\n|`sixel-memory -b`|-|`pillow`, `pyzbar`|-|\n|`ktask -S`|-|-|`ceccomp` or `seccomp-tools`|\n|`seccomp-tools`|-|-|`ceccomp` or `seccomp-tools`|\n|`onegadget`|-|-|`one_gadget`|\n|Progress Indicator|-|`tqdm`|-|\n|`angr`|-|`angr`|-|\n|`asm-list`|-|`capstone`|-|\n|`capstone-disassemble`|-|`capstone`|-|\n|`dasm`|-|`capstone`|-|\n|`i8086` mode|-|`capstone`|-|\n|`unicorn-emulate`|-|`capstone`, `unicorn`, `setuptools`(python 3.12+)|-|\n|`heap try-free`|-|`capstone`, `unicorn`, `setuptools`(python 3.12+)|-|\n|`heap try-malloc`|-|`capstone`, `unicorn`, `setuptools`(python 3.12+)|-|\n|`heap try-realloc`|-|`capstone`, `unicorn`, `setuptools`(python 3.12+)|-|\n|`heap try-calloc`|-|`capstone`, `unicorn`, `setuptools`(python 3.12+)|-|\n|`asm`|-|`keystone-engine`|-|\n|`base-n-decode`|-|`codext`|-|\n|`base-n-encode`|-|`codext`|-|\n|`crc`|-|`crccheck`|-|\n|`hash`(FSB hash) |-|`gmpy2`|-|\n|`uefi-ovmf-info`|-|`crccheck`|-|\n|`filetype-memory`|`file`|`magika`|-|\n|`ropper`|-|`ropper`|-|\n|`vmlinux-to-elf-apply`|-|`vmlinux-to-elf`|-|\n\nNotes:\n- To save installation time, the GEF installer does not install `binwalk` by default. This is because it has many package dependencies.\n- The GEF installer does no longer install `bpftool` when run inside a Docker container because `bpftool` is intended to run in the host.\n- The GEF installer installs `seccomp-tools` if neither `ceccomp` nor `seccomp-tools` is found. I recommend `ceccomp`, but its build is not simple. Install it manually if needed.\n- The GEF installer does no longer install `vmlinux-to-elf` because in many cases you can use `ks-apply` instead.\n\n## Is there a lighter version with fewer features?\nThere is no such version. But you can adjust it yourself.\n\n1. Split into classes using `dev/split/split.py`\n2. Edit `dev/split/save/gef-splitted.py` and remove unnecessary commands and architectures\n3. Recombine with `dev/split/de-split.py`\n4. `dev/split/gef-reconstructed.py` is generated\n\n\n# About the Host Environment\n\n## Does GEF work properly on operating systems other than Ubuntu?\nYes, it generally works on most standard Linux distributions; however, not every command is validated on every distribution.\n\nI have used it on Debian, and some users are running it on Arch Linux.\nIt also seems to be working fine on WSL2 (Ubuntu) so far.\nHowever, I have not confirmed that all commands work correctly.\n\n## Will this GEF work as a plugin for `hugsy/gef`?\nNo, it does not work as a plugin. It replaces `hugsy/gef`.\n\nCompatibility with `hugsy/gef` has already been lost, as well as with `hugsy/gef-extras`.\nIt should be considered an entirely separate product.\n\nSimilarly, this GEF cannot be used at the same time as `peda` or `pwndbg`.\nMake sure you only load one of them.\n\n## GDB will not load GEF.\nStart GDB as the `root` user or with `sudo`.\nBy default, GEF is installed under `/root/.gef`, so non-`root` sessions will not find it unless you change the install paths or update your `.gdbinit` to point to the actual location.\n\n## GDB still does not load GEF, even as the `root` user.\nIt is likely that your GDB does not support integration with `python3`.\n\nThis can happen if you are not using the GDB provided by Ubuntu's `apt` package manager. For example:\n- You built it yourself from source code\n- You are using a version that someone else prepared for a specific architecture\n\nConsider rebuilding GDB from the latest tarball or from the Git repository.\n\n## How to build GDB?\n- From the latest tarball:\n    - Download latest tarball from https://ftp.gnu.org/gnu/gdb/\n    ```\n    tar xf gdb-16.3.tar.xz && cd gdb-16.3\n    ./configure --enable-targets=all --with-python=/usr/bin/python3\n    make && make install\n    ```\n- From Git:\n    ```\n    apt install -y libdebuginfod-dev libreadline-dev\n    git clone --depth 1 https://gnu.googlesource.com/binutils-gdb && cd binutils-gdb\n    ./configure --disable-{binutils,ld,gold,gas,sim,gprof,gprofng} --enable-targets=all \\\n    --with-python=/usr/bin/python3 --with-debuginfod --with-system-{zlib,readline} \\\n    --disable-{dependency-tracking,gdbtk,unit-tests} --without-{tcl,tk,x,guile,babeltrace,intel-pt,xx-hash}\n    make && make install\n    ```\n\n## When debugging with GDB, how can I display the source code of preinstalled libraries and commands?\nFor Ubuntu 22.10 and later, it is recommended to use `debuginfod`.\n\n- Enable `debuginfod` (Ubuntu 22.10 and later)\n    ```\n    export DEBUGINFOD_URLS=\"https://debuginfod.ubuntu.com\"\n    echo \"set debuginfod enabled on\" >> ~/.gdbinit\n    ```\n\n- If you are unable to use `debuginfod`, please set up the symbols manually.\n    ```\n    # Not necessary if debuginfod is enabled\n    apt install libc6-dbg\n    echo \"set debug-file-directory /usr/lib/debug\" >> ~/.gdbinit\n    ```\n\nHowever, `debuginfod` often does not provide `glibc` source files.\nFetch and place the `glibc` sources locally as shown below.\n\n- Get the `glibc` source\n    ```\n    # Ubuntu 24.04 or later\n    sed -i -e 's/^Types: deb$/Types: deb deb-src/g' /etc/apt/sources.list.d/ubuntu.sources\n\n    # Ubuntu 23.10 or before\n    sed -i -e 's/^# deb-src/deb-src/g' /etc/apt/sources.list\n\n    # common\n    cd /usr/lib/debug && apt update && apt source libc6\n    echo \"directory /usr/lib/debug/glibc-2.39\" >> ~/.gdbinit\n    # You need to adjust the version for your environment.\n    ```\n\n\n# About the Guest (Debugged) Environment\n\n## What Linux kernel versions does GEF support as guests in qemu-system?\nMost commands have been validated on kernels from 3.x up to 6.19.x. Newer kernels may work but are not fully validated.\n\nHowever, I have not verified every kernel version.\nFor example, certain symbols in some versions may not be supported by heuristic symbol detection.\nAlso, the structure may differ depending on the build configuration and the compiler used to build the kernel.\nTherefore, there may be environments where GEF does not work.\nIf you encounter any issues, please report them on the issue page.\n\n## Is there a way to get a prebuilt kernel for each version?\nI use [https://kernel.ubuntu.com/](https://kernel.ubuntu.com/mainline).\n\nDownload the desired `linux-image-unsigned-*_amd64.deb` and extract `/boot/vmlinuz-*` from it (e.g., with `dpkg-deb -x`).\nNo filesystem image is provided. Please use one created with `buildroot` or one provided in past CTF challenges.\n\nDownload the `linux-modules-*_amd64.deb` package for `System.map` and `config`.\n\nAnother option is [COPR of Fedora](https://download.copr.fedorainfracloud.org/results/%40kernel-vanilla/fedora/fedora-rawhide-x86_64/).\n\n## Will each GEF command be more accurate if I have `vmlinux` with debug symbols?\nLet's consider debug information and debug symbols separately.\n\n- Debug information\n    - Partially yes, partially no.\n        - Some commands (e.g.; `slub-dump`, `buddy-dump`, `ktask`, `kmod`, etc.) use type information, if available, to speed up offset calculation.\n        - However, there are still not many commands that implement this kind of optimization.\n- Debug symbols\n    - Yes.\n        - If the symbols are already loaded:\n            - The `ksymaddr-remtote` command will automatically use offsets read from the `vmlinux` file (with rebasing).\n        - If the symbols are not loaded yet:\n            - First, load the `vmlinux` symbols using the `file` command.\n    - Note:\n        - GEF internally uses the addresses resolved with `ksymaddr-remote`, and these results are cached.\n        - If `vmlinux` file is already loaded, the results of `ksymaddr-remote` can be replaced with accurate values (with rebasing) and cached.\n\n## Does GEF support i386 16-bit mode (real mode)?\nYes, GEF supports real mode experimentally.\n\nUse `qemu-system-i386`, and do NOT use `qemu-system-x86_64`.\nExplicitly specify the i8086 architecture before connecting: `gdb -ex 'set architecture i8086' -ex 'target remote localhost:1234'`.\n\nGEF automatically handles transitions between 16-bit real mode and 32-bit protected mode, but expect limitations compared to 32/64-bit workflows.\n\n## Does GEF support ARM Cortex-M?\nYes, GEF supports ARM Cortex-M.\n\nYou can debug microcontrollers, but the memory map cannot be enumerated via GDB; consult vendor documentation or SVD files for layout details.\n\n## Is it possible to debug userland with GEF when using qemu-system?\nPartially, yes.\n\nI think it can be useful when you want to trace before and after a system call.\nHowever, of course, I do not recommend continually debugging userland with qemu-system.\nThis is because many commands are restricted for various reasons.\nConsider setting up `gdbserver` in the guest and connecting from the outside.\n\nNote:\n- If KPTI is enabled, many kernel-related commands cannot be used in userland. This is because most memory access to kernel space is unavailable if KPTI is enabled.\n\n## How do I break in userland when using qemu-system?\nUse a hardware breakpoint.\n\nWhen execution is stopped in the kernel, first ensure you are in the intended process context. If so, you can set a `break *ADDRESS` as usual.\nIf execution stopped in the kernel context of a different user process than you expected, or in a kernel thread like `swapper/0`, the virtual address of the process you want is not mapped.\nFor this reason, software breakpoints that embed `0xcc` in virtual memory cannot be used in some situations.\nHowever, hardware breakpoints can be used without any problems.\n\n## Does GEF support debugging the Android kernel?\nYes, it is supported, but not fully.\n\nWhen I tried using `Android Studio`, most commands seemed to work.\n- I used `Android Studio` on Windows and connected from Linux.\n- Refer to [docs/SUPPORTED-MODE.md](SUPPORTED-MODE.md) for the commands I used.\n\nHowever, the QEMU in `Android Studio` is based on an older version, 2.12.0, and seems to have compatibility issues with recent GDB versions (16.x and later).\nSpecifically, repeated memory reads may cause QEMU's GDB stub to return incorrect results.\nThis is especially noticeable for commands that perform repeated memory access, such as `ktask` and `kchecksec`.\n\n## Does GEF support debugging Android userland binaries?\nYes, it is supported, but not fully.\n\nWhen I tried using `Android Studio`, most commands seemed to work.\n- I used `Android Studio` on Windows and connected from Linux.\n- Refer to [docs/SUPPORTED-MODE.md](SUPPORTED-MODE.md) for the commands I used.\n\nHowever, Android does not use glibc (it uses the Bionic C library).\nTherefore, be aware that all `glibc`-specific commands, such as the `heap` command, cannot be used.\n\n## Does GEF support TEE OSs other than OP-TEE?\nNo, GEF does not support them.\n\n\n# About GEF Settings\n\n## I prefer the AT&T syntax.\nYou can set the AT&T syntax for each session using the `set disassembly-flavor att` command.\n\nAlternatively, since the `set disassembly-flavor intel` command is executed in the main function of GEF, you may want to comment it out.\nHowever, as GEF is not optimized for AT&T syntax parsing, some commands may not function correctly.\nIf you find a case where it does not work, please report it on the issue page.\n\n## I don't like the color scheme.\nCustomize it using the `theme` command, then run `gef save`.\nThis will save the configuration to `~/.gef.rc`.\n\nAnother option is to disable colors. Try `gef config gef.disable_color True`.\n\n## I don't want to add `-n` to every command to disable pager.\nTo permanently disable the pager, use the command `gef config gef.always_no_pager True` followed by `gef save`.\n\n\n# About Commands\n\n## Which command should I start with when debugging the kernel?\nTry `pagewalk` , `ks-apply`, and `kchecksec`.\nAfter that, try `slub-dump`, `ktask` and `ksysctl` as well.\n\nOther commands are less important, so check them with `gef help` if necessary.\n\n## Is it possible for GEF to re-display the results of a command (for using the `less` pager)?\nIn general, no.\n\nIf you need to keep output while the `less` pager is active, use `|$cat > /tmp/foo.txt`.\n\nAlternatively, set `gef config gef.keep_pager_result True` and then `gef save`.\nFrom the next time onwards, temporary files will no longer be deleted.\n\n## Is it possible for GEF to pass the result of a command to a shell command?\nYes, you can use the built-in `pipe` command.\n\nFor example, `pipe elf-info -n | grep .data` or `|pdisas | grep call`.\n\n## `ktask` (or other kernel-related commands) does not work.\nThe kernel you are debugging may have been built with `CONFIG_RANDSTRUCT=y`.\n\nIn this case, except for a few commands, most will not work correctly.\nCurrently, at least the following commands do not work:\n- `ktask`\n- `kmod`\n- `kbdev`\n- `kcdev`\n- `kops`\n- `kpipe`\n- `ksysctl`\n- `kmalloc-tracer`\n- `kmalloc-allocated-by`\n- `kfiles`\n- `kregs`\n- `ksighands`\n- `kpcidev`\n- `knamespaces`\n- `kipcs`\n- `kfilesystems`\n\nIf it does not work properly even though `CONFIG_RANDSTRUCT=n`, GEF may be failing to parse due to a change in `struct task_struct` or similar.\nIf you think there is a problem with GEF, please report it on the issues page.\n\n## The `vmlinux-to-elf-apply` command causes an error when creating an ELF file.\nPlease update `vmlinux-to-elf` to the latest version.\n\nIf the problem persists, try using the `ks-apply` command.\nThe logic is slightly different, so it might work.\nIf it still does not work, please report it on the issue page.\n\n## If I have a `vmlinux` with debuginfo, how can I use `ks-apply`?\nThe `ks-apply` command is unnecessary. Run `kload <vmlinux_path>`.\n\nBelow is a summary of each.\n|Component|How GDB uses it|How GEF uses it|\n|:---|:---|:---|\n|`vmlinux` debuginfo|- Loaded via `add-symbol-file`<br>- Or `kload` (easy wrapper with `kbase`)<br>- Essential for source-level debugging|- Used by some commands if available<br>- Can be viewed with `dt`|\n|`vmlinux` symbols|- Loaded via `add-symbol-file`<br>- Or `kload` (easy wrapper with `kbase`)<br>- Provides kernel symbol resolution|- Accessible after `ksymaddr-remote`<br>- Addresses will be automatically rebased|\n|Memory-resident `debuginfo`<br>(if `CONFIG_DEBUG_INFO_BTF=y`)|- Not available by default<br>- Accessible via `ktypes-load`|- Used by some commands if available after `ktypes-load`<br>- Can be viewed with `dt`|\n|Memory-resident `kallsyms`<br>(if `CONFIG_KALLSYMS=y`)|- Not available by default<br>- Accessible via `ks-apply`|- Accessible after `ksymaddr-remote`<br>- Used by various GEF commands internally|\n\n## The kernel-related commands are unstable; sometimes they work fine, sometimes they don't. / The output of `ksymaddr-remote` seems odd.\nThis may be due to the GEF's caching mechanism.\n\nGEF resolves kernel symbols using the `ksymaddr-remote` command.\nThis command caches the offsets (needed for parsing) under the `/tmp/gef` directory.\nAt that time, it uses the kernel version string (its hash) as the cache key.\n\nBecause of this, in a situation like following, you may encounter an issue where the wrong cache is used.\n- You have built and debug multiple kernels with slightly different build configs (same kernel version)\n\nTo resolve this, after attaching with GDB, execute either of the following:\n- `gef reset-cache --hard` (clears the cache)\n- `ks -rv` (resolves symbols ignoring the cache)\n    - Once symbols are resolved, it remains in effect for the duration of that GDB (GEF) debug session.\n\n## The `got` command does not display PLT addresses.\nThis problem is probably caused by an outdated version of `binutils`.\n\nThe `got` command uses `objdump` internally to obtain the PLT addresses.\nHowever, with certain combinations of `binutils` and `glibc` versions, `objdump` does not display the PLT addresses.\n\nThe currently known combinations are as follows:\n- `binutils 2.38` (Ubuntu 22.04 default) + `glibc 2.37 or later`\n\nThis problem occurs when you try to use a newer `glibc` in an Ubuntu 22.04 environment using `patchelf` etc.\nThe workaround is to build and install a newer version of `binutils` from source code.\n\n## Can I switch to a mode that references physical memory?\nYes, when using qemu-system. Switch with `pi enable_phys()` and revert with `pi disable_phys()`.\nGEF uses this internally; if a command is interrupted mid-execution, you may need to revert manually.\n\n## The `magic` command produces few valid results.\nThis is because libc symbols are not loaded.\n\nUnlike kernel symbols, userland symbols do not undergo heuristic detection (with some special exceptions).\nTherefore, missing symbols may not be detected by the `magic` command.\n\nIf you are referring to system-wide `glibc`, you can resolve this with the following steps:\n1. Install the symbols with `apt install libc6-dbg`.\n2. Add `set debug-file-directory /usr/lib/debug` to `~/.gdbinit`.\n\n## The command to get the source (e.g., `ptr-mangle --source`) does not work.\nDo not use `~` in paths that point to the `gef.py` directory in `.gdbinit`.\n\nPython's `inspect` may not expand tildes reliably; use absolute paths instead.\nI encountered this behavior in Python 3.9.2 on Debian 11.\n\n## When using qemu-user, an error occurs when continuing execution.\nIs the error something like this?\n```\n...\ndwarf2/dwz.c:188: internal-error: dwarf2_read_dwz_file: Assertion `is_main_thread ()' failed.\nA problem internal to GDB has been detected,\nfurther debugging may prove unreliable.\n----- Backtrace -----\n...\n```\nIf so, this is caused by the `continue-for-qemu-user` command.\nThis problem occurs only when the configuration option `continue_for_qemu_user.use_fork` is set to `False`.\n\n`continue-for-qemu-user` is a wrapper for the `c`(`continue`) command that allows `Ctrl+C` to be accepted even during `continue` under `qemu-user`.\nOn some architectures, this wrapper may not work properly when running dynamically linked binaries with `qemu-user`.\n\nThere are two ways to work around this:\n- Use the `main-break` command to reach `main` once; after that, this error will no longer occur.\n- Use the `continue` command instead of the `c` command (but `Ctrl+C` will not work).\n\n\n# About the Internal Mechanism\n\n## How does GEF implement kernel analysis-related commands without symbols?\nInternally, this process consists of several steps:\n1. Enumerate memory map information from the page table structure.\n2. Detect the `.rodata` area of the kernel from the memory map information.\n3. Scan `.rodata` to identify the kernel version.\n4. Parse the structure of `kallsyms` in `.rodata` and obtain all \"symbol and address\" pairs.\n5. If global variable symbols are available at this point, use them (= `CONFIG_KALLSYMS_ALL=y`).\n    - If not, GEF disassembles the function that uses the specified global variable.\n    - By parsing the result, GEF obtains the address of the required global variable.\n    - This is implemented in `KernelAddressHeuristicFinder` and `KernelAddressHeuristicFinderUtil` classes.\n6. Detect the offset of the structure member, if necessary.\n    - To identify it heuristically, GEF uses facts such as whether a value in memory is an address or whether a structure in memory has a specific layout.\n    - At this time, GEF takes into account the presence or absence of members and changes in their order due to differences in kernel versions.\n7. Parse and display the value in memory using all the information detected so far.\n\nAs you can see, this does not work well if structure members are arranged randomly (`CONFIG_RANDSTRUCT=y`).\nAlso, depending on the assembly output by the compiler, it may not be possible to parse correctly.\n\n## How does GEF achieve the conversion from `page` to `virt` (or `phys`)?\nGEF achieves this by using the parsed results of the SLUB free list.\n\nIf you are interested in this question, you probably know how difficult this conversion formula is.\nAs you can see, this conversion (`page <-> virt`) is very difficult.\n\nThis is because several values are needed to convert `page` to `virt` (or vice versa), two of which are hard to obtain without symbols and type information:\n- `vmemmap`\n- `sizeof(struct page)`\n\nI concluded that the only way to get these is to calculate them backwards from valid `page` and `virt` pairs.\n\nThese pairs can be found with a very high probability while parsing the SLUB structure.\nTherefore, GEF calls the `slub-dump` command internally and temporarily, then calculates these values from the result.\n\nThis is the reason why the first time the `page2virt` command runs, it takes a long time: it parses the page tables, identifies function symbols, and internally calls `slub-dump` twice.\n\nNote:\n- The `slub-dump` command itself uses the `page` to `virt` conversion function as well, resulting in a circular reference. GEF avoid this problem by adding an option to skip this (`--skip-page2virt`).\n\n\n# About the Python Interface\n\n## Can I access each GEF command or alias instance from `python-interactive`?\nYes, you can access them via `GCI` or `GAI`.\n\nFor example, `pi GCI[\"vmmap\"]` or `pi GAI[\"us\"]`.\n- `GCI` stands for Gef Command Instances.\n- `GAI` stands for Gef Alias Instances.\n\n## The class name `KernelAddressHeuristicFinder` is too long.\nYou can access it using `KF`.\n\nFor example, use `pi KF.get_slab_caches()` instead of `pi KernelAddressHeuristicFinder.get_slab_caches()`.\n\n## Can I revert the output of `python-interactive` back to decimal from hex?\nYes, you can do so by executing `pi hexoff()`.\n\n## How can I get the instruction object?\nYou can get the instruction object with `pi get_insn(addr=None)`.\n\nThere are also similar functions. Here is the list:\n- `get_insn(addr=None)`\n- `get_insn_next(addr=None)`\n- `get_insn_prev(addr=None)`\n\n## Are there any other globally accessible functions that are useful?\n- Memory access\n    - `write_memory(addr, data)`, `read_memory(addr, length)`\n    - `read_int_from_memory(addr)` # Sizes are estimated\n        - `read_int8_from_memory(addr)`\n        - `read_int16_from_memory(addr)`\n        - `read_int32_from_memory(addr)`\n        - `read_int64_from_memory(addr)`\n    - `read_cstring_from_memory(addr, max_length=None)`\n    - `read_physmem(paddr, size)`, `write_physmem(paddr, data)`\n    - `is_valid_addr(addr)`\n    - `is_single_link_list(addr)`, `is_double_link_list(addr, min_len=0)`\n    - `is_ascii_string(addr)`\n- Register access\n    - `get_register(regname, use_mbed_exec=False, use_monitor=False)`\n- Calculating a minor hash function (100+ variants)\n    - `Hash.SHA0`, `Hash.Whirlpool`, etc.\n- Value manipulation\n    - `String.str2bytes(x)`, `String.bytes2str(x)`\n    - `slicer(data, n)`, `slice_unpack(data, n)`\n    - `p8`, `p16`, `p32`, `p64`\n    - `u8`, `u16`, `u32`, `u64`, `u128`\n    - `byteswap(x, byte_size=None)`, `xor(a, b=None)`,\n    - `ror(val, bits, arch_bits=64)`, `rol(val, bits, arch_bits=64)`,\n    - `align(value, align)`, `align_to_ptrsize(addr)`, `align_to_pagesize(addr)`,\n- Other\n    - `get_pagesize()`, `get_pagesize_mask_low()`, `get_pagesize_mask_high()`\n    - `get_syscall_table(arch=None, mode=None)`\n\nIf you want the complete list, run `gef pyobj-list`.\n\n## I want to add a command. How do I get started?\nCopy and paste the `TemplateCommand` class and edit it as you like.\n\nHere are some notes:\n- Class name\n    - Rename the newly added command class to any name you like.\n    - Make sure it ends with `...Command`.\n- Inheritance\n    - Make sure you inherit from the `GenericCommand` class.\n    - This is required for the command to be registered.\n- Important attributes\n    - `_cmdline_`: used to invoke the command.\n    - `_aliases_`: used to create command aliases.\n    - `_category_`, `_syntax_`, `_example_` and `_note_`: used by `gef help`.\n    - `_repeat_`: enables command repetition.\n- `__init__()`\n    - This method is executed only once, when GEF starts.\n    - There is usually no need to override this method.\n    - Delete it if you do not need to do anything special.\n- `do_invoke()`\n    - It is important to override this method.\n    - When a command is executed, it starts from this method.\n- Command arguments\n    - They should be handled with the `argparse` module.\n    - They are managed by the `parse_args` decorator of the `do_invoke()` method.\n- Command execution conditions\n    - Add decorators to the `do_invoke()` method as needed.\n    - You can check the list of available decorators with `gef pyobj-list`.\n- Other\n    - Use the `gef_print()` function instead of the `print()` function whenever possible.\n    - The function named `complete()` is reserved.\n\n## `pi current_arch` is always `None`.\nUse `pi get_current_arch()`.\n\n## Is there an easy way to get an overview of the code?\nTry splitting it by class with `dev/split/split.py`.\n\n`dev/split/save/gef-splitted.py` is broken and doesn't work as a python script, but it is very useful for getting an overview of the code.\n\n\n# About the Development Schedule\n\n## Are there any plans to support kernels for other architectures?\nThere are no plans.\n\n## Are there any plans to support more architectures with qemu-user?\nYes. However, it is becoming difficult to find new targets to support.\n\nThis is because three things are required:\n1. Toolchain\n    - `linux-headers`, `binutils`, `gcc`, `glibc` (or `uClibc`) are needed.\n    - A prebuilt tarball is preferred.\n2. Qemu-user\n    - It needs an implementation of GDB stub.\n3. GDB\n    - It needs `python3` support.\n\n\n# About Reporting, etc.\n\n## After upgrading GEF, it stopped working.\nThe configuration file format may have changed. Try renaming `~/.gef.rc` (for the `root` user this is `/root/.gef.rc`).\n\n## I found a bug.\nPlease feel free to report it on the issue page. I will respond as soon as possible.\n\n## Can you please add this feature? / I don't like a certain feature, so please fix it.\nI will consider it, so please report it on the issue page.\n\nHowever, this is a personal project, so I have the final decision. I appreciate your understanding.\n\n## What information should I provide when reporting an issue?\nPlease provide a screenshot or a copy of the terminal output when the issue occurred.\n\n- Additionally, include the results of the `gef version` and `gef status` commands.\n- If the issue is related to kernel debugging, please also provide your environment files (such as `run.sh`, `bzImage`, etc.) or information on where they can be obtained.\n\n## Is it okay to fork and modify?\nYes, please follow the license terms and preserve copyright and attribution notices.\n\n\n# About Orynth\n\n## Is this project listed on Orynth?\nYes. This project is listed on Orynth for discovery: https://www.orynth.dev/projects/bata24-gef-8901\n\n## What is `B24G`?\n`B24G` is the market token symbol shown on the Orynth project page.\n- Using this project does NOT require token.\n- This is just fan token and no utility.\n- Orynth markets are optional and do not represent equity/ownership/rights.\n\n## Official token address\n- Symbol: B24G\n- Address: cox9QpSKymFq1oQc8Pm1KZpAcK82RMQNvu846WSYory\n"
  },
  {
    "path": "docs/HOW-TO-DEBUG-AARCH64-MTE.md",
    "content": "## Build static gdbserver\nI used debian-arm64 environment. See https://hackmd.io/lDob-hTUTfqIJyj0ahYY3A\n\n```\nwget https://ftp.gnu.org/gnu/gdb/gdb-14.1.tar.xz\ntar xf gdb-14.1.tar.xz && cd gdb-14.1\napt install libgmp-dev libmpfr-dev\nLDFLAGS=-static ./configure && make\nscp -P 2222 root@localhost:/root/gdb-14.1/gdbserver/gdbserver .\n```\n\n## Build aarch64 buildroot\n```\nwget https://buildroot.org/downloads/buildroot-2023.11.tar.xz\ntar xf buildroot-2023.11.tar.xz\ncd buildroot-2023.11\ncat << EOF >> board/qemu/aarch64-virt/linux.config\nCONFIG_ARM64_HW_AFDBM=y\nCONFIG_ARM64_PAN=y\nCONFIG_AS_HAS_LDAPR=y\nCONFIG_AS_HAS_LSE_ATOMICS=y\nCONFIG_ARM64_LSE_ATOMICS=y\nCONFIG_ARM64_USE_LSE_ATOMICS=y\n\nCONFIG_AS_HAS_ARMV8_2=y\nCONFIG_AS_HAS_SHA3=y\nCONFIG_ARM64_RAS_EXTN=y\nCONFIG_ARM64_CNP=y\n\nCONFIG_ARM64_PTR_AUTH=y\nCONFIG_ARM64_PTR_AUTH_KERNEL=y\nCONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y\nCONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y\nCONFIG_AS_HAS_PAC=y\nCONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y\n\nCONFIG_ARM64_AMU_EXTN=y\nCONFIG_AS_HAS_ARMV8_4=y\nCONFIG_ARM64_TLB_RANGE=y\n\nCONFIG_AS_HAS_ARMV8_5=y\nCONFIG_ARM64_BTI=y\nCONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y\nCONFIG_ARM64_E0PD=y\nCONFIG_ARM64_AS_HAS_MTE=y\nCONFIG_ARM64_MTE=y\n\nCONFIG_ARM64_EPAN=y\nEOF\n\nmake qemu_aarch64_virt_defconfig\nmake\nmkdir ~/qemu-aarch64-buildroot\ncp output/images/{Image,rootfs.ext2} ~/qemu-aarch64-buildroot\n```\n\n## Start qemu-system\nAdd `mte=on`, `-cpu max` and `hostfwd` settings.\n\n```\n(host) cd ~/qemu-aarch64-buildroot\n\n(host) qemu-system-aarch64 \\\n-machine virt,mte=on \\\n-cpu max \\\n-smp 1 \\\n-kernel Image \\\n-append \"rootwait root=/dev/vda console=ttyAMA0\" \\\n-netdev user,id=eth0,hostfwd=tcp:127.0.0.1:1234-:1234,hostfwd=tcp:127.0.0.1:1235-:1235 \\\n-device virtio-net-device,netdev=eth0 \\\n-drive file=rootfs.ext2,if=none,format=raw,id=hd0 \\\n-device virtio-blk-device,drive=hd0 \\\n-nographic\n```\n\n## Send the target binary and gdbserver\n```\n(host) python -m http.server 8080\n(guest) wget http://HOST_IP:8080/main\n(guest) wget http://HOST_IP:8080/gdbserver\n(guest) chmod +x main gdbserver\n```\n\n## Start debugging\n```\n(guest) ./gdbserver 0.0.0.0:1234 ./main\n(host) gdb-multiarch -q ./main -ex 'target remote :1234'\n```\n\n## Note\nGDB (aarch64-linux) already supports tagged pointers, treating the top byte as non-address data.\nIn practice, this means tagged-pointer chasing (e.g., `telescope`) is generally usable for userland debugging without manually stripping tags.\n\nHere is a sample (see `0x007ffa47e858`).\n```\ngef> telescope -n $sp 8\n $x29+ 0x007ffa47e830|+0x0000|+000: 0x0000007ffa47e8c0  ->  0x0000007ffa47e8d0  ->  0x0000007ffa47e9e0  ->  ...\n       0x007ffa47e838|+0x0008|+001: 0x0000000000401128 <main+0x14>  ->  0x5280000097ffff52  <-  retaddr[1]\n       0x007ffa47e840|+0x0010|+002: 0x0000007ffa47e850  ->  0x0000007ffa47e8b0  ->  0x0000007ffa47e000  ->  ...\n       0x007ffa47e848|+0x0018|+003: 0x0000007ffa47e870  ->  0x0000000a41414141 ('AAAA\\n'?)\n       0x007ffa47e850|+0x0020|+004: 0x0000007ffa47e8b0  ->  0x0000007ffa47e000  ->  0x0000000000000000\n       0x007ffa47e858|+0x0028|+005: 0x4100007ffa47e870  ->  0x0000000a41414141 ('AAAA\\n'?)  <-  $x0\n       0x007ffa47e860|+0x0030|+006: 0x0000000000000000\n       0x007ffa47e868|+0x0038|+007: 0x0000000000000000\ngef>\n```\n"
  },
  {
    "path": "docs/QEMU-USER-SUPPORTED-ARCH.md",
    "content": "# Qemu-user supported architectures\nI also list the tools I used in my Ubuntu 25.10 environment.\n\n## x86\n- toolchain: `gcc` via apt with `-m32` option.\n- qemu: `qemu-i386` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## x64\n- toolchain: `gcc` via apt.\n- qemu: `qemu-x86_64` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## arm (Cortex-A)\n- toolchain: `gcc-arm-linux-gnueabihf` via apt.\n- qemu: `qemu-arm` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## aarch64 (Cortex-A)\n- toolchain: `gcc-aarch64-linux-gnu` via apt.\n- qemu: `qemu-aarch64` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## ppc32\n- toolchain: `gcc-powerpc-linux-gnu` via apt.\n- qemu: `qemu-ppc` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## ppc64\n- toolchain: `gcc-powerpc64{,le}-linux-gnu` via apt.\n- qemu: `qemu-ppc64{,le}` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## mips32\n- toolchain: `gcc-mips{,el}-linux-gnu` via apt.\n- toolchain (Ubuntu 25.10): `mips32{,el}--glibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-mips{,el}` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## mips64\n- toolchain: `gcc-mips64{,el}-linux-gnuabi64` via apt.\n- toolchain (Ubuntu 25.10): not found.\n- qemu: `qemu-mips64{,el}` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## mipsn32\n- toolchain: `gcc-multilib-mips{,el}-linux-gnu` or `gcc-multilib-mips64{,el}-linux-gnuabi64` via apt with `-mabi=n32` option.\n- toolchain (Ubuntu 25.10): `mips64{,el}-n32--glibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-mipsn32{,el}` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## sparc32\n- toolchain: `sparcv8--uclibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-sparc` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## sparc32plus\n- toolchain: `gcc-multilib-sparc64-linux-gnu` via apt with `-m32` option.\n- qemu: `qemu-sparc32plus` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## sparc64\n- toolchain: `gcc-sparc64-linux-gnu` via apt.\n- qemu: `qemu-sparc64` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## riscv32\n- toolchain: `riscv32-ilp32d--glibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-riscv32` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## riscv64\n- toolchain: `gcc-riscv64-linux-gnu` via apt.\n- qemu: `qemu-riscv64` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## s390x\n- toolchain: `gcc-s390x-linux-gnu` via apt.\n- qemu: `qemu-s390x` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## sh4\n- toolchain: `gcc-sh4-linux-gnu` via apt.\n- qemu: `qemu-sh4` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## m68k\n- toolchain: `gcc-m68k-linux-gnu` via apt.\n- qemu: `qemu-m68k` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## alpha\n- toolchain: `gcc-alpha-linux-gnu` via apt.\n- qemu: `qemu-alpha` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## hppa32 (PA-RISC)\n- toolchain: `gcc-hppa-linux-gnu` via apt.\n- qemu: `qemu-hppa` via apt.\n- gdb: `gdb-multiarch` via apt.\n\n## or1k (OpenRISC 1000)\n- toolchain: `openrisc--glibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-or1k` via apt.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## nios2\n- toolchain: `nios2--glibc--bleeding-edge-2024.05-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-nios2` via apt.\n- qemu (Ubuntu 25.04): not found.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## microblaze\n- toolchain: `microblazebe--glibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n- qemu: `qemu-microblaze` via apt.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## xtensa (lx60)\n- toolchain: `xtensa-lx60--uclibc--stable-2025.08-1` from https://toolchains.bootlin.com/\n    - Because the toolchain obtained with apt seems to be broken since the C header is unavailable.\n- qemu: `qemu-xtensa` via apt.\n- gdb: `xtensa-lx60--uclibc--bleeding-edge-2023.08-1` from https://toolchains.bootlin.com/\n    - Because `gdb` built from latest source will not work with `set architecture xtensa`.\n    - But old toolchain (not 2025, but 2023) includes `xtensa-linux-gdb` that works fine.\n\n## cris\n- lib: [cris-dist_1.64-1_i386.deb](https://www.axis.com/ftp/pub/axis/tools/cris/compiler-kit/cris-dist_1.64-1_i386.deb)\n- toolchain: [x86_64-gcc-7.3.0-nolibc_cris-linux.tar.xz](https://ftp.iij.ad.jp/pub/linux/kernel/tools/crosstool/files/bin/x86_64/7.3.0/x86_64-gcc-7.3.0-nolibc_cris-linux.tar.xz) from http://ftp.iij.ad.jp/pub/linux/kernel/tools/crosstool/\n    - `mkdir cris-gcc-7.3.0-glibc && tar xf x86_64-gcc-7.3.0-nolibc_cris-linux.tar.xz -C cris-gcc-7.3.0-glibc --strip-components 1`\n    - `cd cris-gcc-7.3.0-glibc && mkdir rootfs && dpkg-deb -x ../cris-dist_1.64-1_i386.deb rootfs`\n    - `export CRIS=$(pwd)/rootfs/usr/local/cris/cris-axis-linux-gnu`\n    - `cd /lib/x86_64-linux-gnu && ln -s libisl.so.{23,15} && ln -s libmpfr.so.{6,4}`\n    - `cris-linux-gcc -B $CRIS/lib -I $CRIS/sys-include -static ./test.c`\n- qemu: `qemu-cris` via apt.\n    - It needs `-cpu` option like `qemu-cris -cpu crisv17 -g 1234 ./a.out`.\n    - Could not use `-cpu crisv32` because gdb does not support it.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## loongarch64\n- toolchain: [x86_64-cross-t    ools-loongarch64-binutils_2.45-gcc_15.1.0-glibc_2.42.tar.xz](https://github.com/loongson/build-tools/releases/download/2025.08.08/x86_64-cross-tools-loongarch64-binutils_2.45-gcc_15.1.0-glibc_2.42.tar.xz)\n- qemu: `qemu-loongarch64` via apt.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## arc32 (HS38; ARCv2)\n- toolchain: `gcc-arc-linux-gnu` via apt.\n- qemu: https://github.com/foss-for-synopsys-dwc-arc-processors/qemu\n    - Add `#ifndef` and `#endif` like following to `linux-user/syscall.c`.\n        - ```\n          341 #ifndef SCHED_ATTR_SIZE_VER0\n          342 struct sched_attr {\n          343     uint32_t size;\n          344     uint32_t sched_policy;\n          345     uint64_t sched_flags;\n          346     int32_t sched_nice;\n          347     uint32_t sched_priority;\n          348     uint64_t sched_runtime;\n          349     uint64_t sched_deadline;\n          350     uint64_t sched_period;\n          351     uint32_t sched_util_min;\n          352     uint32_t sched_util_max;\n          353 };\n          354 #endif\n          ```\n    - `./configure --target-list=arc-linux-user --disable-werror && make && cp build/qemu-arc /usr/local/bin`\n    - It needs `-cpu` option like `qemu-arc -cpu hs5x -g 1234 ./a.out`.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## arc32 (HS58; ARCv3)\n- toolchain: [arc_gnu_2025.09_prebuilt_arc32_glibc_linux_install.tar.bz2](https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases/download/arc-2025.09-release/arc_gnu_2025.09_prebuilt_arc32_glibc_linux_install.tar.xz)\n    - `gdb` is included, but it does not support `python3`.\n- qemu: https://github.com/foss-for-synopsys-dwc-arc-processors/qemu\n    - Add `#ifndef` and `#endif` like following to `linux-user/syscall.c`.\n        - ```\n          341 #ifndef SCHED_ATTR_SIZE_VER0\n          342 struct sched_attr {\n          343     uint32_t size;\n          344     uint32_t sched_policy;\n          345     uint64_t sched_flags;\n          346     int32_t sched_nice;\n          347     uint32_t sched_priority;\n          348     uint64_t sched_runtime;\n          349     uint64_t sched_deadline;\n          350     uint64_t sched_period;\n          351     uint32_t sched_util_min;\n          352     uint32_t sched_util_max;\n          353 };\n          354 #endif\n          ```\n    - `./configure --target-list=arc-linux-user --disable-werror && make && cp build/qemu-arc /usr/local/bin`\n    - It needs `-cpu` option like `qemu-arc -cpu hs5x -g 1234 ./a.out`.\n- gdb: https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb\n    - `./configure --disable-{binutils,ld,gold,gas,sim,gprof,gprofng} --target=arc64-snps-linux-gnu --with-python=/usr/bin/python3 && make && cp gdb/gdb /usr/local/bin/gdb-arc`\n\n## arc64 (HS68; ARCv3)\n- toolchain: [arc_gnu_2025.09_prebuilt_arc64_glibc_linux_install.tar.bz2](https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases/download/arc-2025.09-release/arc_gnu_2025.09_prebuilt_arc64_glibc_linux_install.tar.xz)\n    - `gdb` is included, but it does not support `python3`.\n- qemu: https://github.com/foss-for-synopsys-dwc-arc-processors/qemu\n    - Add `#ifndef` and `#endif` like following to `linux-user/syscall.c`.\n        - ```\n          341 #ifndef SCHED_ATTR_SIZE_VER0\n          342 struct sched_attr {\n          343     uint32_t size;\n          344     uint32_t sched_policy;\n          345     uint64_t sched_flags;\n          346     int32_t sched_nice;\n          347     uint32_t sched_priority;\n          348     uint64_t sched_runtime;\n          349     uint64_t sched_deadline;\n          350     uint64_t sched_period;\n          351     uint32_t sched_util_min;\n          352     uint32_t sched_util_max;\n          353 };\n          354 #endif\n          ```\n    - `./configure --target-list=arc64-linux-user --disable-werror && make && cp build/qemu-arc64 /usr/local/bin`\n    - It needs `-cpu` option like `qemu-arc64 -cpu hs6x -g 1234 ./a.out`.\n- gdb: https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb\n    - `./configure --disable-{binutils,ld,gold,gas,sim,gprof,gprofng} --target=arc64-snps-linux-gnu --with-python=/usr/bin/python3 && make && cp gdb/gdb /usr/local/bin/gdb-arc`\n\n## csky\n- toolchain: https://github.com/c-sky/toolchain-build\n    - `apt -y install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev`\n    - `git submodule update --init && python3 build-csky-gcc.py csky-gcc --src ./ --triple csky-unknown-linux-gnu --disable-gdb`\n    - `build-gcc-csky-unknown-linux-gnu/Xuantie-800-gcc-linux-5.10.4-glibc-x86_64` is result toolchains.\n- qemu: https://github.com/XUANTIE-RV/qemu\n    - Add `#ifndef` and `#endif` like following to `linux-user/syscall.c`.\n        - ```\n          364 #ifndef SCHED_ATTR_SIZE_VER0\n          365 struct sched_attr {\n          366     uint32_t size;\n          367     uint32_t sched_policy;\n          368     uint64_t sched_flags;\n          369     int32_t sched_nice;\n          370     uint32_t sched_priority;\n          371     uint64_t sched_runtime;\n          372     uint64_t sched_deadline;\n          373     uint64_t sched_period;\n          374     uint32_t sched_util_min;\n          375     uint32_t sched_util_max;\n          376 };\n          377 #endif\n          ```\n    - `./configure --target-list=cskyv1-linux-user,cskyv1eb-linux-user,cskyv2-linux-user,cskyv2eb-linux-user --disable-{bpf,werror} && make && cp build/qemu-cskyv{1,2}{,eb} /usr/local/bin`\n    - It needs `-cpu` option like `qemu-cskyv2 -cpu ck810 -g 1234 ./a.out`.\n- gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n\n# Qemu-user UNSUPPORTED architectures\nThese will be added if I find a combination that works.\nIf you find it, please let me know in the issue page.\n\n## bfin:\n- [x] toolchain: `bfin--uclibc--bleeding-edge-2018.02-1` from https://toolchains.bootlin.com/\n- [ ] qemu: https://github.com/vapier/qemu\n    - gdb stub is broken.\n- [x] gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## hexagon:\n- [x] toolchain: https://github.com/quic/toolchain_for_hexagon\n- [x] qemu: `qemu-hexagon` via apt.\n- [ ] gdb: not found.\n\n## tilegx:\n- [x] toolchain: https://ftp.riken.jp/Linux/kernel.org/tools/crosstool/files/bin/x86_64/7.3.0/\n- [x] lib: http://www.voidrouter.net/archives/211\n- [ ] qemu: https://github.com/qemu/qemu/releases/tag/v5.2.0\n    - the breakpoint is broken.\n- [x] gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## s390\n- [x] toolchain: `gcc-multilib-s390x-linux-gnu` via apt with `-m31` option.\n- [ ] toolchain (Ubuntu 25.04): not found.\n- [ ] qemu: not found.\n- [x] gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## hppa64\n- [x] toolchain: `gcc-hppa64-linux` via apt.\n- [ ] lib: not found.\n- [ ] qemu: not found.\n- [ ] gdb: not found.\n\n## loongarch32\n- [x] toolchain: [loongson-gnu-toolchain-8.3-x86_64-loongarch32r-linux-gnusf-v2.0.tar.xz](https://gitee.com/loongson-edu/la32r-toolchains/releases/download/v0.0.3/loongson-gnu-toolchain-8.3-x86_64-loongarch32r-linux-gnusf-v2.0.tar.xz)\n- [ ] qemu: https://gitee.com/loongson-edu/la32r-QEMU\n    - `./configure --target-list=loongarch32-linux-user --disable-werror && make && cp build/qemu-loongarch32 /usr/local/bin`\n    - It says `Architecture rejected` when connecting from gdb.\n- [x] gdb: build from latest. See [docs/FAQ](FAQ.md#how-to-build-gdb).\n\n## e2k\n- [ ] toolchain: not found.\n- [x] qemu: https://github.com/OpenE2K/qemu-e2k\n    - `./configure --target-list=e2k-linux-user --disable-werror && make && cp build/qemu-e2k /usr/local/bin`\n- [ ] gdb: https://github.com/OpenE2K/binutils-gdb\n    - `git switch gdb-9.1-mcst`\n    - `mkdir build && cd build && ../configure --disable-{binutils,ld,gold,gas,sim,gprof,gprofng,nls,bpf} --target=e2k-linux-gnu --with-python=/usr/bin/python3 && make`\n    - Crash when it executes. It seems that binding python3 failed.\n\n## nds32\n- [x] toolchain: https://github.com/VincentZWC/prebuilt-nds32-v3f-toolchain\n- [ ] qemu: not found.\n- [ ] gdb: not found.\n"
  },
  {
    "path": "docs/SUPPORTED-MODE.md",
    "content": "# Supported mode\n\n## Standard debugging\n- Usage\n    - Run `gdb-multiarch` or `gdb` as `root` user.\n        - e.g., `gdb-multiarch /PATH/TO/BINARY`, then `run [ARGS]`.\n    - Alternatively, `sudo gdb-multiarch /PATH/TO/BINARY`, then `run [ARGS]`.\n- Supported architectures\n    - Debugger (GDB) host (= Debuggee (ELF) host)\n        - x86 and x64\n        - Possibly ARM and ARM64\n- Notes\n    - The following instructions assume that you are the `root` user. Add `sudo` commands as needed.\n    - The instructions also assume that you use `gdb-multiarch`. Of course, you can use `gdb`.\n\n## Attaching to a running process\n- Usage\n    - Run `gdb-multiarch /PATH/TO/BINARY -p PID`.\n- Supported architectures\n    - Debugger (GDB) host (= Debuggee (ELF) host)\n        - x86 and x64\n        - Possibly ARM and ARM64\n\n## With Docker\n- Usage\n    - Attach from outside of Docker using `gdb-multiarch /PATH/TO/BINARY -p PID`.\n        - The `PID` refers to the process ID visible to the host.\n- Supported architectures\n    - Debugger (GDB) host (= Debuggee (Docker, ELF) host)\n        - x86 and x64\n        - Possibly ARM and ARM64\n- Notes\n    - You can also install and use GEF inside Docker.\n    - However, the `--privileged` option is required when running `docker run` or `docker exec`.\n\n## With Gdbserver\n- Usage\n    - Start `gdbserver localhost:1234 /PATH/TO/BINARY [ARGS]` to listen on port `0.0.0.0:1234`.\n    - Attach using `gdb-multiarch -ex 'target remote <IP address>:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x86 and x64\n        - Possibly ARM and ARM64\n    - Debugger stub (Gdbserver) host (= Debuggee (ELF) host)\n        - x86 and x64\n        - Possibly ARM and ARM64\n\n## With Qemu-system\n- Usage\n    - Start `qemu-system` with the `-s` option to listen on `localhost:1234`.\n        - If you want to change the listening port, use the `-gdb tcp::9876` option.\n    - Attach using `gdb-multiarch -ex 'target remote localhost:1234'`.\n        - Alternatively, use `gdb-multiarch -ex 'set architecture TARGET_ARCH' -ex 'target remote localhost:1234'` (for old versions of QEMU).\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Qemu-system) host\n        - x64\n    - Debuggee (Qemu-system guest)\n        - x86, x64, ARM and ARM64\n        - i8086 (16-bit) is supported experimentally.\n- Notes\n    - Most commands should work fine unless `CONFIG_RANDSTRUCT=y`.\n    - It works with any version of `qemu-system`, but the latest version is recommended.\n    - It is preferable to run `qemu-system` on `localhost`.\n        - If you run `qemu-system` remotely (another host), you can not handle SecureWorld's memory.\n    - For more information, see [docs/FAQ.md](FAQ.md).\n\n## With Qemu-user\n- Usage\n    - Start `qemu-user` with the `-g 1234` option to listen on `localhost:1234`.\n    - Attach using `gdb-multiarch /PATH/TO/BINARY -ex 'target remote localhost:1234'`.\n        - Alternatively, use `gdb-multiarch -ex 'set architecture TARGET_ARCH' -ex 'target remote localhost:1234'` (for old versions of QEMU).\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Qemu-user) host\n        - x64\n    - Debuggee (ELF)\n        - See [docs/QEMU-USER-SUPPORTED-ARCH.md](QEMU-USER-SUPPORTED-ARCH.md) for details.\n- Notes\n    - It works with any version of `qemu-user`, but the latest version is recommended.\n        - From QEMU 8.1 onwards, the `info proc mappings` command is supported in `qemu-user`, which significantly speeds up memory map generation.\n        - However, in some architectures (e.g., `x86_64`), this may not be possible, and it will fall back to heuristic detection.\n    - It is preferable to run `qemu-user` on `localhost`.\n        - If you run `qemu-user` remotely (another host), you can not use memory patching.\n\n## With Intel Pin\n- Usage\n    - Listen using `pin -appdebug -appdebug_server_port 1234 -t obj-intel64/inscount0.so -- /PATH/TO/BINARY`.\n    - Attach using `gdb-multiarch /PATH/TO/BINARY -ex 'target remote localhost:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Intel Pin) host\n        - x64\n    - Debuggee (ELF)\n        - x86 and x64\n- Note\n    - This runs very slowly and is not recommended.\n\n## With Intel SDE\n- Usage\n    - Listen using `sde64 -debug -debug-port 1234 -- /PATH/TO/BINARY`.\n    - Attach using `gdb-multiarch /PATH/TO/BINARY -ex 'target remote localhost:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Intel SDE) host\n        - x64\n    - Debuggee (ELF)\n        - x86 and x64\n- Note\n    - This runs very slowly and is not recommended.\n\n## With Qiling framework\n- Usage\n    - Run `qltool run -f /PATH/TO/BINARY --rootfs / --gdb :1234`.\n        - Alternatively, write a harness. See [here](https://docs.qiling.io/en/latest/debugger/) for more information.\n        - If the target architecture differs from the host architecture, specify the appropriate `rootfs` directory.\n    - Attach using `gdb-multiarch /PATH/TO/BINARY -ex 'target remote localhost:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Qiling framework) host\n        - x64\n    - Debuggee (ELF)\n        - x86, x64, ARM and ARM64\n- Notes\n    - When debugging ARM64 binaries, the flag register is not available, so branch taken/not taken detection may be incorrect.\n    - This is experimental support, so some commands may not work.\n\n## With KGDB\n- Usage\n    - Host OS\n        - Configure two serial ports as named pipes in both the debugger and debuggee virtual machine settings.\n        - Vmware example:\n            - Debugger\n                - Use named pipe: `\\\\.\\pipe\\pipe0` (Windows host) / `/tmp/sock0` (Linux host)\n                    - Configure as `This end is the client.` and `The other end is a virtual machine.`\n                - Use named pipe: `\\\\.\\pipe\\pipe1` (Windows host) / `/tmp/sock1` (Linux host)\n                    - configure as `This end is the client.` and `The other end is a virtual machine.`\n            - Debuggee\n                - Use named pipe: `\\\\.\\pipe\\pipe0` (Windows host) / `/tmp/sock0` (Linux Host)\n                    - Configure as `This end is the server.` and `The other end is an application.`\n                - Use named pipe: `\\\\.\\pipe\\pipe1` (Windows host) / `/tmp/sock1` (Linux host)\n                    - Configure as `This end is the server.` and `The other end is an application.`\n    - Debuggee\n        - Build the kernel with configurations such as `CONFIG_KGDB=y`. Ubuntu supports this by default.\n        - Edit `/etc/default/grub` and append `kgdbwait kgdboc=ttyS0,115200 console=ttyS1,115200 nokaslr` to the end of `GRUB_CMDLINE_LINUX_DEFAULT`.\n        - Then run `update-grub && reboot`.\n        - See [official documentation](https://www.kernel.org/doc/html/latest/dev-tools/kgdb.html) for more information.\n    - Debugger\n        - Attach using `gdb-multiarch -ex 'target remote /dev/ttyS0'`.\n        - Connect with `screen /dev/ttyS1 115200` for console access.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debuggee (debugged kernel)\n        - x64, ARM64\n- Notes\n    - You need `gdb` version 12.x or later.\n    - This runs very slowly over a serial interface; without a vmlinux with symbols, debugging is effectively impractical.\n    - The `Ctrl+C` interrupt does not work; instead, use `echo g > /proc/sysrq-trigger` in the console.\n    - Unlike qemu-system, some commands are unsupported in KGDB mode because it is still under development.\n\n## With VMware\n- Usage\n    - Host OS\n        - Add the following configurations to the `vmx` file.\n            - `debugStub.listen.guest64 = \"TRUE\"`\n            - `debugStub.listen.guest64.remote = \"TRUE\"`\n            - `debugStub.hideBreakpoints = \"TRUE\"`\n            - `debugStub.port.guest64 = \"1234\"`\n            - See [here](https://communities.vmware.com/t5/VMware-Fusion-Discussions/Using-debugStub-to-debug-a-guest-linux-kernel/td-p/394906).\n        - Start the guest OS normally.\n    - Debugger\n        - Attach using `gdb-multiarch -ex 'target remote <IP address>:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debuggee (debugged kernel)\n        - x64\n- Notes\n    - It runs faster than KGDB mode, and `Ctrl+C` interrupt works, but it is still slow.\n    - Access to physical memory and control registers is possible thanks to the `monitor` command.\n\n## With rr\n- Usage\n    - First, run `rr record /PATH/TO/BINARY`.\n    - Then, use `rr replay` for time-travel debugging.\n- Supported architectures\n    - Debugger (`rr`) host (= Debuggee (ELF) host)\n        - x86 and x64\n- Note\n    - This is experimental support, so some commands may not work.\n\n## With Wine\n- Usage\n    - Run `winedbg --gdb --no-start /PATH/TO/BINARY` and attach using `gdb -ex 'target remote localhost:<port>'`.\n        - It is recommended to use the `--no-start` option because pressing `Ctrl+C` without `--no-start` will terminate `gdb`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (`winedbg`) host\n        - x64\n    - Debuggee (PE)\n        - x86 and x64\n- Notes\n    - You must run `winedbg` on `localhost`.\n    - This is experimental support, so some commands may not work.\n\n## With Qemu-system for Android kernel (when using Android Studio)\n- Usage\n    - Start as `emulator -avd <AVD_NAME> -no-audio -no-snapshot -qemu -s` to listen on `localhost:1234`.\n        - If `-no-audio -no-snapshot` are not necessary, you can remove them.\n        - Available `<AVD_NAME>` values can be obtained with `emulator -list-avds`.\n    - Attach using `gdb-multiarch -ex 'set architecture i386:x86-64' -ex 'target remote localhost:1234'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Qemu-system) host\n        - x64\n    - Debuggee (Qemu-system guest)\n        - x64\n        - Possibly x86, ARM and ARM64\n- Notes\n    - This method sometimes fails.\n        - For more information, see [docs/FAQ.md](FAQ.md).\n        - If an issue occurs, try closing `gdb` and reconnecting.\n    - To connect from another machine, specify the IP address.\n        - `gdb-multiarch -ex 'set architecture i386:x86-64' -ex 'target remote <Android Studio host machine's IP address>:1234'`.\n\n## With Android userland binary (when using Android Studio)\n- Usage\n    - Setup `adb` settings.\n        - Run `adb root` if necessary.\n        - Use `adb forward tcp:9999 tcp:9999` for port forwarding.\n    - Push the statically built `gdbserver` to the Android device.\n        - `adb push gdbserver-static /data/local/tmp`.\n        - `adb shell chmod +x /data/local/tmp/gdbserver-static`.\n    - Start `gdbserver`.\n        - `adb shell /data/local/tmp/gdbserver-static localhost:9999 /PATH/TO/BINARY`.\n    - Attach using `gdb-multiarch 'target remote localhost:9999'`.\n- Supported architectures\n    - Debugger (GDB) host\n        - x64\n    - Debugger stub (Gdbserver) host (= Debuggee (ELF) host)\n        - x64\n        - Possibly x86, ARM and ARM64\n- Notes\n    - To connect from another machine, you can forward the port further.\n        - Run `socat TCP-LISTEN:9998,fork,reuseaddr TCP-CONNECT:localhost:9999` on the `Android Studio` host machine.\n        - Attach using `gdb-multiarch 'target remote <Android Studio host machine's IP address>:9998'` from another machine.\n"
  },
  {
    "path": "gef.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n#\n#######################################################################################\n# GEF - Multi-Architecture GDB Enhanced Features for Exploiters & Reverse-Engineers\n#   * Original: by @_hugsy_\n#   * Improvement: by @bata_24\n#\n#######################################################################################\n# This GEF solely supports GDB compiled with Python3 and running on Linux.\n#\n# Supported architectures are the following (some require qemu).\n#   * x86-32 & x86-64\n#   * arm v5,v6,v7\n#   * aarch64 (armv8)\n#   * mips & mipsn32 & mips64\n#   * powerpc & powerpc64\n#   * sparc & sparc32plus & sparc64\n#   * riscv32 & riscv64\n#   * s390x\n#   * sh4\n#   * m68k\n#   * alpha\n#   * hppa32 (pa-risc)\n#   * or1k (openrisc)\n#   * nios2\n#   * microblaze\n#   * xtensa\n#   * cris\n#   * loongarch64\n#   * arc32 (v2, v3) & arc64\n#   * csky\n# See README.md for details.\n#\n# To start: in gdb, type `source /path/to/gef.py`\n#\n#######################################################################################\n# GEF is distributed under the MIT License.\n#\n# Copyright (c) 2021-2026 bata24 (@bata_24)\n#\n# This is a fork of GEF (https://github.com/hugsy/gef).\n# This software is released under the MIT license.\n# See https://opensource.org/licenses/MIT\n#\n# Copyright (c) 2013-2026 crazy rabbidz\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in all\n# copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n#\n#######################################################################################\n# Use this command when checking with `ruff`:\n#   $ ruff check gef.py --select B,C4,E,F --ignore B905,E402,E501,E731\n#\n# B905: `zip()` without an explicit `strict=` parameter\n#   -> The strict argument of zip() is from python3.10. Too new to apply.\n# E402: module level import not at top of file\n#   -> For faster startup, less frequently used modules should be loaded on demand.\n# E501: line too long (> 79 characters)\n#   -> This rule does not seem to make sense in a modern environment.\n# E731: do not assign a lambda expression, use a def\n#   -> It can be written more cleanly using lambdas.\n#\n#######################################################################################\n# Use this command when checking with `vulture`:\n#   $ vulture gef.py --ignore-names=\"*Command\"\n#\n#######################################################################################\n# Use this command when checking with `codespell`:\n#   $ codespell gef.py\n#\n#######################################################################################\n# Use this command to measure the time:\n#   $ PYTHONPROFILEIMPORTTIME=1 gdb\n#\n\n\nprint(\"Loading GEF...\")\n\n\nimport abc\nimport argparse\nimport builtins\nimport binascii\nimport codecs\nimport collections\nimport configparser\nimport ctypes\nimport datetime\nimport functools\nimport hashlib\nimport itertools\nimport json\nimport os\nimport re\nimport struct\nimport subprocess\nimport sys\nimport tempfile\nimport time\nimport traceback\n\n\ndef http_get(url):\n    \"\"\"Basic HTTP wrapper for GET request.\"\"\"\n    import urllib.request\n    try:\n        req = urllib.request.Request(url)\n        req.add_header(\"Cache-Control\", \"no-cache, no-store\")\n        http = urllib.request.urlopen(req, timeout=5)\n        if http.getcode() != 200:\n            return None\n        return http.read()\n    except Exception:\n        return None\n\n\ndef update_gef(argv):\n    \"\"\"Try to update `gef` to the latest version.\"\"\"\n    gef_local = os.path.realpath(argv[0])\n    hash_gef_local = hashlib.sha512(open(gef_local, \"rb\").read()).digest()\n    gef_remote = \"https://raw.githubusercontent.com/bata24/gef/dev/gef.py\"\n    gef_remote_data = http_get(gef_remote)\n    if gef_remote_data is None:\n        print(\"[-] Failed to get remote gef\")\n        return 1\n\n    hash_gef_remote = hashlib.sha512(gef_remote_data).digest()\n    if hash_gef_local == hash_gef_remote:\n        print(\"[-] No update\")\n    else:\n        with open(gef_local, \"wb\") as f:\n            f.write(gef_remote_data)\n        print(\"[+] Updated\")\n    return 0\n\n\ntry:\n    # GEF determines whether it is inside or outside gdb\n    # based on whether it can import the gdb module.\n    import gdb\nexcept ImportError:\n    # If out of gdb, the only action allowed is to update gef.py.\n    # No further code will be executed.\n    if len(sys.argv) == 2 and sys.argv[1].lower() in (\"--update\", \"--upgrade\", \"-u\"):\n        ret = update_gef(sys.argv)\n        sys.exit(ret)\n    else:\n        print(\"[-] gef cannot run as standalone\")\n        sys.exit(0)\n\n\n# Very important global variables.\n__gef_commands__            = [] # gef command classes for registering\n__gef_command_instances__   = {} # gef command instances\nGCI                         = __gef_command_instances__ # short cut for debug # noqa: F841\n__gef_alias_instances__     = {} # gef alias instances\nGAI                         = __gef_alias_instances__ # short cut for debug # noqa: F841\ncurrent_arch                = None # keep Architecture instance\n\nGEF_RC                      = os.getenv(\"GEF_RC\") or os.path.join(os.getenv(\"HOME\") or \"~\", \".gef.rc\")\nGEF_TEMP_DIR                = os.path.join(tempfile.gettempdir(), \"gef\")\nGEF_FILEPATH                = os.path.expanduser(http_get.__code__.co_filename) # the full path of GEF\n                            # note: __file__ will no longer be available from gdb 15\n\n\ndef get_current_arch(): # noqa\n    global current_arch\n    return current_arch\n\n\ndef perf(f): # noqa\n    \"\"\"Decorator wrapper to measure performance.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        import io\n        import line_profiler\n        pr = line_profiler.LineProfiler()\n        pr.add_function(f)\n        pr.enable()\n        ret = f(*args, **kwargs)\n        pr.disable()\n        s = io.StringIO()\n        pr.print_stats(stream=s)\n        print(s.getvalue())\n        return ret\n\n    return wrapper\n\n\ndef cperf(f): # noqa\n    \"\"\"Decorator wrapper to measure performance.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        import cProfile\n        import pstats\n        import io\n        pr = cProfile.Profile()\n        pr.enable()\n        ret = f(*args, **kwargs)\n        pr.disable()\n        s = io.StringIO()\n        #sortby = pstats.SortKey.CUMULATIVE\n        sortby = pstats.SortKey.TIME\n        ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n        ps.print_stats(20)\n        print(s.getvalue())\n        return ret\n\n    return wrapper\n\n\nclass DisplayHook:\n    \"\"\"It enables pretty printing of list, dict, set, and so on.\n    It also displays in hexadecimal by default.\"\"\"\n\n    @staticmethod\n    def pp(o, idt):\n        \"\"\"Create a string for pretty print recursively.\"\"\"\n\n        def I1(idt):\n            \"\"\"Create an indent for current level.\"\"\"\n            return \"  \" * idt\n\n        def I2(idt):\n            \"\"\"Create an indent for next level.\"\"\"\n            return \"  \" * (idt + 1)\n\n        def R(o, idt):\n            return [DisplayHook.pp(x, idt + 1) for x in o]\n\n        def R1(o, idt):\n            \"\"\"Return a string of the elements concatenated with commas (for list, tuple, set, ...).\"\"\"\n            return \", \".join(R(o, idt))\n\n        def R2(o, idt):\n            \"\"\"Return a list of the elements with indentation and commas (for list, tuple, set, ...).\"\"\"\n            return [I2(idt) + x + \",\" for x in R(o, idt)]\n\n        def Z(s, e, o, idt):\n            \"\"\"Return a string of the elements concatenated with commas (for list, tuple, set, ...),\n            taking into account the width of the screen.\"\"\"\n            # Create a string without newlines and return it if it's short enough.\n            f = s + R1(o, idt) + e\n            if len(f) < width:\n                return f\n            # Return a string with a newline for each element.\n            f = [s] + R2(o, idt) + [I1(idt) + e]\n            return \"\\n\".join(f)\n\n        def RD(o, idt):\n            return [DisplayHook.pp(k, idt + 1) + \": \" + DisplayHook.pp(v, idt + 1) for k, v in o]\n\n        def RD1(o, idt):\n            \"\"\"Return a string of the elements concatenated with commas (for dict, ...).\"\"\"\n            return \", \".join(RD(o, idt))\n\n        def RD2(o, idt):\n            \"\"\"Return a list of the elements with indentation and commas (for dict, ...).\"\"\"\n            return [I2(idt) + x + \",\" for x in RD(o, idt)]\n\n        def ZD(s, e, o, idt):\n            \"\"\"Return a string of the elements concatenated with commas (for dict, ...),\n            taking into account the width of the screen.\"\"\"\n            # Create a string without newlines and return it if it's short enough.\n            f = s + RD1(o, idt) + e\n            if len(f) < width:\n                return f\n            # Return a string with a newline for each element.\n            f = [s] + RD2(o, idt) + [I1(idt) + e]\n            return \"\\n\".join(f)\n\n        name = type(o).__name__\n        width = GefUtil.get_terminal_size()[1] + len(I1(idt))\n\n        if name in (\"int\", \"long\"):\n            return hex(o)\n\n        if name == \"list\":\n            return Z(\"[\", \"]\", o, idt)\n\n        elif name == \"tuple\":\n            return Z(\"(\", \")\", o, idt)\n\n        elif name == \"set\":\n            return Z(\"{\", \"}\", o, idt)\n\n        elif name == \"dict\":\n            return ZD(\"{\", \"}\", o.items(), idt)\n\n        elif name == \"dict_keys\":\n            return Z(\"dict_keys([\", \"])\", o, idt)\n\n        elif name == \"dict_values\":\n            return Z(\"dict_values([\", \"])\", o, idt)\n\n        elif name == \"dict_items\":\n            return ZD(\"dict_items([\", \"])\", o, idt)\n\n        elif name == \"Zone\":\n            return re.sub(r\"(zone_start=|zone_end=)(\\d+)\", lambda x:x.group(1) + hex(int(x.group(2))), str(o))\n\n        elif name == \"Table\":\n            f = \"Table(arch={!r}, mode={!r}, name_table={{...}}, nr_table={{\\n\".format(o.arch, o.mode)\n            f += \"\\n\".join(RD2(o.nr_table.items(), idt))\n            f += \"\\n\" + I1(idt) + \"})\"\n            return f\n\n        elif name == \"Kinfo\":\n            f = \"Kinfo(\\n\"\n            f += I1(idt + 1) + \"text_base=\" + DisplayHook.pp(o.text_base, 0) + \", \"\n            f += \"text_size=\" + DisplayHook.pp(o.text_size, 0) + \", \"\n            f += \"text_end=\" + DisplayHook.pp(o.text_end, 0) + \",\\n\"\n            f += I1(idt + 1) + \"ro_base=\" + DisplayHook.pp(o.ro_base, 0) + \", \"\n            f += \"ro_size=\" + DisplayHook.pp(o.ro_size, 0) + \", \"\n            f += \"ro_end=\" + DisplayHook.pp(o.ro_end, 0) + \",\\n\"\n            f += I1(idt + 1) + \"rw_base=\" + DisplayHook.pp(o.rw_base, 0) + \", \"\n            f += \"rw_size=\" + DisplayHook.pp(o.rw_size, 0) + \", \"\n            f += \"rw_end=\" + DisplayHook.pp(o.rw_end, 0) + \",\\n\"\n            f += I1(idt + 1) + \"rwx=\" + DisplayHook.pp(o.rwx, 0) + \", \"\n            f += \"has_none=\" + DisplayHook.pp(o.has_none, 0) + \", \"\n            if o.maps is None:\n                f += \"maps=\" + DisplayHook.pp(o.maps, 0) + \",\\n\"\n            else:\n                f += \"maps=[\\n\"\n                f += \"\\n\".join(R2(o.maps, idt + 1))\n                f += \"\\n\" + I1(idt + 1) + \"]\\n\"\n            f += I1(idt) + \")\"\n            return f\n\n        elif name == \"Entry\":\n            f = \"Entry(\\n\"\n            f += I2(idt) + \"nr={:#x},\\n\".format(o.nr)\n            f += I2(idt) + \"name={!r},\\n\".format(o.name)\n            f += I2(idt) + \"ret_regs={!s},\\n\".format(o.ret_regs)\n            f += I2(idt) + \"arg_regs={!s},\\n\".format(o.arg_regs)\n            f += I2(idt) + \"args_full={!s},\\n\".format(o.args_full)\n            f += I2(idt) + \"args={!s},\\n\".format(o.args)\n            f += I1(idt) + \")\"\n            return f\n        return repr(o)\n\n    @staticmethod\n    def displayhook(o): # noqa\n        \"\"\"An alternative to the default display function.\"\"\"\n        builtins._ = o # noqa\n\n        if o is None:\n            return\n\n        out = DisplayHook.pp(o, 0)\n        print(out)\n        return\n\n\ndef hexon(): # noqa\n    \"\"\"Replace the print function that is implicitly called when running \"python-interactive 1\" etc.\"\"\"\n    sys.displayhook = DisplayHook.displayhook # noqa\n    return\n\n\ndef hexoff(): # noqa\n    \"\"\"Revert the print function that is implicitly called when running \"python-interactive 1\" etc.\"\"\"\n    sys.displayhook = sys.__displayhook__ # noqa\n    return\n\n\nclass Cache:\n    \"\"\"Manage the gef cache. The cache has 2 types: \"until_next\" and \"this_session\".\n    \"until_next\": Cached for a very short period of time. Cleared every time an instruction is stepped, etc.\n    \"this_session\": Cached until gdb exits.\n    Note: each command may have its own cache outside this mechanism. Not all caches are centralized here.\"\"\"\n\n    __gef_caches__ = {\"until_next\": {}, \"this_session\": {}}\n\n    @staticmethod\n    def cache_wrap(life_time, f, skip_None_cache=False):\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            caches = Cache.__gef_caches__[life_time]\n            fname = f\"{f.__module__}:{f.__qualname__}\"\n            fcache = caches.setdefault(fname, {})\n\n            try:\n                kw = tuple(sorted(kwargs.items()))\n                key = (args, kw)\n                return fcache[key]\n            except KeyError:\n                ret = f(*args, **kwargs)\n                if skip_None_cache is False or ret is not None:\n                    fcache[key] = ret\n                return ret\n            except TypeError:\n                return f(*args, **kwargs)\n\n        return wrapper\n\n    @staticmethod\n    def cache_until_next(f):\n        return Cache.cache_wrap(\"until_next\", f)\n\n    @staticmethod # noqa\n    def cache_until_next_skip_None_cache(f):\n        return Cache.cache_wrap(\"until_next\", f, skip_None_cache=True)\n\n    @staticmethod\n    def cache_this_session(f):\n        return Cache.cache_wrap(\"this_session\", f)\n\n    @staticmethod\n    def cache_this_session_skip_None_cache(f):\n        return Cache.cache_wrap(\"this_session\", f, skip_None_cache=True)\n\n    @staticmethod\n    def reset_gef_caches(all=False):\n        \"\"\"Clear the cache of GEF.\n        By default, it only clears caches of `until_next` type.\"\"\"\n\n        Cache.__gef_caches__[\"until_next\"].clear()\n\n        if all:\n            Cache.__gef_caches__[\"this_session\"].clear()\n\n        # gdb cache\n        try:\n            gdb.execute(\"maintenance flush dcache\", to_string=True)\n        except Exception:\n            pass\n        return\n\n    @staticmethod # noqa\n    def clear_cache_for(f):\n        \"\"\"Clear the cache of specified function.\"\"\"\n\n        fname = f\"{f.__module__}:{f.__qualname__}\"\n        Cache.__gef_caches__[\"until_next\"].pop(fname, None)\n        Cache.__gef_caches__[\"this_session\"].pop(fname, None)\n        return\n\n\nclass Config:\n    \"\"\"Manage gef configurations. Most configs are tied to specific commands.\n    They are defined in the form `command_name.config_name`.\n    Internally it is stored as a triple (value, type, description).\"\"\"\n\n    __gef_config__ = {} # keep gef configs\n    __gef_config_orig__ = {} # for debugging\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_gef_setting(name):\n        \"\"\"Read global gef settings. Return None if not found.\"\"\"\n        setting = Config.__gef_config__.get(name, None)\n        if setting is None:\n            return None # A valid config can never return None, but False, 0 or \"\"\n        return setting[0]\n\n    @staticmethod\n    def set_gef_setting(name, value, _type=None, _desc=None):\n        \"\"\"Set global gef settings.\n        Raise ValueError if `name` doesn't exist and `type` and `desc` are not provided.\"\"\"\n        Cache.reset_gef_caches()\n\n        if name not in Config.__gef_config__:\n            # create new setting\n            if _type is None or _desc is None:\n                raise ValueError(\"Setting '{}' is undefined, need to provide type and description\".format(name))\n            Config.__gef_config__[name] = [_type(value), _type, _desc]\n            return\n\n        # set existing setting\n        func = Config.__gef_config__[name][1]\n        Config.__gef_config__[name][0] = func(value)\n        return\n\n\ndef gef_print(x=\"\", less=False, redirect=None, skip_color=False, *args, **kwargs):\n    \"\"\"Wrapper around print(), with pager, redirecting and coloring.\"\"\"\n    if not skip_color:\n        x = HighlightCommand.highlight_text(x)\n\n    if redirect:\n        with open(redirect, \"w\") as f:\n            print(x, *args, **kwargs, file=f)\n        return\n\n    if less:\n        try:\n            less = GefUtil.which(\"less\")\n        except FileNotFoundError:\n            less = False\n\n    if not less:\n        # if x is blank, print a blank line.\n        print(x, *args, **kwargs)\n        return\n\n    # use pager but x is blank\n    if not x:\n        return\n\n    always_no_pager = Config.get_gef_setting(\"gef.always_no_pager\")\n    if always_no_pager:\n        print(x, *args, **kwargs)\n        return\n\n    pager_min_lines = Config.get_gef_setting(\"gef.pager_min_lines\")\n    if len(x.splitlines()) < pager_min_lines:\n        print(x, *args, **kwargs)\n        return\n\n    # write to file and less\n    if isinstance(x, bytes):\n        tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"gef_print\", suffix=\".txt\")\n        os.fdopen(tmp_fd, \"wb\").write(x)\n    else:\n        try:\n            # this is faster than converting to bytes and then writing.\n            tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"gef_print\", suffix=\".txt\")\n            os.fdopen(tmp_fd, \"w\").write(x)\n        except Exception:\n            # fallback if a write error occurs\n            # tmp_fd is closed at this point, so delete it and reopen it\n            os.unlink(tmp_path)\n            tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"gef_print\", suffix=\".txt\")\n            os.fdopen(tmp_fd, \"wb\").write(String.str2bytes(x))\n\n    # less\n    less_option = Config.get_gef_setting(\"gef.less_option\")\n    os.system(\"{!r} {:s} {!r}\".format(less, less_option, tmp_path))\n\n    # cleanup\n    keep_pager_result = Config.get_gef_setting(\"gef.keep_pager_result\")\n    if keep_pager_result:\n        print(\"result saved at {:s}\".format(tmp_path))\n    else:\n        os.unlink(tmp_path)\n    return\n\n\nclass Color:\n    \"\"\"Used to colorify terminal output.\"\"\"\n\n    # https://en.wikipedia.org/wiki/ANSI_escape_code\n    colors = {\n        \"normal\"               : \"\\033[0m\",\n\n        \"bold\"                 : \"\\033[1m\",\n        \"bold_off\"             : \"\\033[21m\",\n        \"highlight\"            : \"\\033[2m\",\n        \"highlight_off\"        : \"\\033[22m\",\n        \"italic\"               : \"\\033[3m\",\n        \"italic_off\"           : \"\\033[23m\",\n        \"underline\"            : \"\\033[4m\",\n        \"underline_off\"        : \"\\033[24m\",\n        \"blink\"                : \"\\033[5m\",\n        \"blink_off\"            : \"\\033[25m\",\n\n        \"black\"                : \"\\033[30m\",\n        \"red\"                  : \"\\033[31m\",\n        \"green\"                : \"\\033[32m\",\n        \"yellow\"               : \"\\033[33m\",\n        \"blue\"                 : \"\\033[34m\",\n        \"magenta\"              : \"\\033[35m\",\n        \"cyan\"                 : \"\\033[36m\",\n\n        \"bright_black\"         : \"\\033[90m\",\n        \"bright_red\"           : \"\\033[91m\",\n        \"bright_green\"         : \"\\033[92m\",\n        \"bright_yellow\"        : \"\\033[93m\",\n        \"bright_blue\"          : \"\\033[94m\",\n        \"bright_magenta\"       : \"\\033[95m\",\n        \"bright_cyan\"          : \"\\033[96m\",\n        \"bright_white\"         : \"\\033[97m\",\n\n        \"coral_red\"            : \"\\033[38;2;239;133;125m\",\n        \"sunshine_yellow\"      : \"\\033[38;2;255;237;171m\",\n        \"ice_green\"            : \"\\033[38;2;163;214;204m\",\n        \"wistaria\"             : \"\\033[38;2;141;147;200m\",\n        \"pink_almond\"          : \"\\033[38;2;227;172;174m\",\n        \"poppy_red\"            : \"\\033[38;2;234;85;80m\",\n        \"cream_yellow\"         : \"\\033[38;2;255;243;184m\",\n        \"turquoise_green\"      : \"\\033[38;2;0;148;122m\",\n        \"blue_lavender\"        : \"\\033[38;2;164;168;212m\",\n        \"rose_dust\"            : \"\\033[38;2;230;192;192m\",\n        \"_red\"                 : \"\\033[38;2;234;85;80m\",\n        \"naples_yellow\"        : \"\\033[38;2;253;211;92m\",\n        \"sea_green\"            : \"\\033[38;2;0;172;151m\",\n        \"pannsy\"               : \"\\033[38;2;77;67;152m\",\n        \"white\"                : \"\\033[38;2;255;255;255m\",\n        \"tomato_red\"           : \"\\033[38;2;234;85;73m\",\n        \"topaz\"                : \"\\033[38;2;233;188;0m\",\n        \"peppermint_green\"     : \"\\033[38;2;0;172;154m\",\n        \"violet\"               : \"\\033[38;2;90;68;152m\",\n        \"snow_white\"           : \"\\033[38;2;250;253;255m\",\n        \"vermilion\"            : \"\\033[38;2;234;85;58m\",\n        \"chrome_yellow\"        : \"\\033[38;2;252;200;0m\",\n        \"peacock_green\"        : \"\\033[38;2;0;164;151m\",\n        \"heliotrope\"           : \"\\033[38;2;144;121;182m\",\n        \"pink_white\"           : \"\\033[38;2;254;249;251m\",\n        \"scarlet\"              : \"\\033[38;2;234;85;50m\",\n        \"cream\"                : \"\\033[38;2;227;215;163m\",\n        \"nile_blue\"            : \"\\033[38;2;44;180;173m\",\n        \"deep_royal_purple\"    : \"\\033[38;2;71;38;110m\",\n        \"milky_white\"          : \"\\033[38;2;255;255;249m\",\n        \"carrot_orange\"        : \"\\033[38;2;237;109;53m\",\n        \"straw\"                : \"\\033[38;2;236;224;147m\",\n        \"saxe_blue\"            : \"\\033[38;2;65;139;137m\",\n        \"grape\"                : \"\\033[38;2;86;37;110m\",\n        \"amber_white\"          : \"\\033[38;2;255;249;245m\",\n        \"chinese_red\"          : \"\\033[38;2;237;109;70m\",\n        \"jasmine_yellow\"       : \"\\033[38;2;237;222;123m\",\n        \"slate_green\"          : \"\\033[38;2;60;113;112m\",\n        \"mauve\"                : \"\\033[38;2;145;93;163m\",\n        \"lavender_ice\"         : \"\\033[38;2;247;246;251m\",\n        \"terracotta\"           : \"\\033[38;2;189;104;86m\",\n        \"antique_gold\"         : \"\\033[38;2;193;171;5m\",\n        \"teal_green\"           : \"\\033[38;2;0;106;108m\",\n        \"iris\"                 : \"\\033[38;2;199;165;204m\",\n        \"pearl_white\"          : \"\\033[38;2;247;246;245m\",\n        \"cocoa_brown\"          : \"\\033[38;2;152;96;94m\",\n        \"olive\"                : \"\\033[38;2;114;100;12m\",\n        \"aqua_green\"           : \"\\033[38;2;136;191;191m\",\n        \"lilac\"                : \"\\033[38;2;209;186;218m\",\n        \"ivory\"                : \"\\033[38;2;248;244;230m\",\n        \"mahogany\"             : \"\\033[38;2;107;63;49m\",\n        \"olive_drab\"           : \"\\033[38;2;102;90;26m\",\n        \"aquamarine\"           : \"\\033[38;2;103;181;183m\",\n        \"lavender\"             : \"\\033[38;2;202;184;217m\",\n        \"powder_pink\"          : \"\\033[38;2;245;236;244m\",\n        \"chocolate\"            : \"\\033[38;2;108;53;36m\",\n        \"jaune_brillant\"       : \"\\033[38;2;255;220;0m\",\n        \"peacock_blue\"         : \"\\033[38;2;0;158;159m\",\n        \"crocus\"               : \"\\033[38;2;183;159;203m\",\n        \"silver_white\"         : \"\\033[38;2;239;239;239m\",\n        \"marron\"               : \"\\033[38;2;106;25;23m\",\n        \"_yellow\"              : \"\\033[38;2;255;220;0m\",\n        \"turquoise\"            : \"\\033[38;2;0;155;159m\",\n        \"lavender_mauve\"       : \"\\033[38;2;166;136;189m\",\n        \"frosty_gray\"          : \"\\033[38;2;232;236;233m\",\n        \"sepia\"                : \"\\033[38;2;98;45;24m\",\n        \"citrus\"               : \"\\033[38;2;237;220;68m\",\n        \"capri_blue\"           : \"\\033[38;2;0;163;167m\",\n        \"purple\"               : \"\\033[38;2;155;114;176m\",\n        \"silver_pink\"          : \"\\033[38;2;238;234;236m\",\n        \"coffee\"               : \"\\033[38;2;123;85;68m\",\n        \"limelight\"            : \"\\033[38;2;255;247;153m\",\n        \"cambridge_blue\"       : \"\\033[38;2;37;183;192m\",\n        \"royal_purple\"         : \"\\033[38;2;127;17;132m\",\n        \"beige_cameo\"          : \"\\033[38;2;238;233;230m\",\n        \"brown\"                : \"\\033[38;2;143;101;82m\",\n        \"canary_yellow\"        : \"\\033[38;2;255;244;98m\",\n        \"turquoise_blue\"       : \"\\033[38;2;0;175;204m\",\n        \"raisin\"               : \"\\033[38;2;107;57;95m\",\n        \"ecru\"                 : \"\\033[38;2;238;231;224m\",\n        \"burnt_sienna\"         : \"\\033[38;2;187;85;53m\",\n        \"mimosa\"               : \"\\033[38;2;255;244;98m\",\n        \"horizon_blue\"         : \"\\033[38;2;130;205;221m\",\n        \"plum\"                 : \"\\033[38;2;108;36;99m\",\n        \"pink_beige\"           : \"\\033[38;2;237;228;225m\",\n        \"amber_rose\"           : \"\\033[38;2;230;191;178m\",\n        \"lemon_yellow\"         : \"\\033[38;2;255;243;82m\",\n        \"summer_shower\"        : \"\\033[38;2;161;216;226m\",\n        \"raspberry\"            : \"\\033[38;2;132;26;117m\",\n        \"frosty_white\"         : \"\\033[38;2;230;234;230m\",\n        \"beige_rose\"           : \"\\033[38;2;232;211;202m\",\n        \"melon_yellow\"         : \"\\033[38;2;224;222;148m\",\n        \"_horizon_blue\"        : \"\\033[38;2;161;216;230m\",\n        \"framboise\"            : \"\\033[38;2;154;13;124m\",\n        \"oyster_white\"         : \"\\033[38;2;234;232;225m\",\n        \"salmon_pink\"          : \"\\033[38;2;243;166;140m\",\n        \"chartreuse_yellow\"    : \"\\033[38;2;227;229;72m\",\n        \"cerulean_blue\"        : \"\\033[38;2;0;141;183m\",\n        \"dahlia_purple\"        : \"\\033[38;2;165;0;130m\",\n        \"wisteria_mist\"        : \"\\033[38;2;211;214;221m\",\n        \"sahara\"               : \"\\033[38;2;226;150;118m\",\n        \"lime_yellow\"          : \"\\033[38;2;234;238;162m\",\n        \"duck_blue\"            : \"\\033[38;2;0;113;153m\",\n        \"orchid_purple\"        : \"\\033[38;2;175;0;130m\",\n        \"cloud\"                : \"\\033[38;2;212;217;223m\",\n        \"ash_rose\"             : \"\\033[38;2;230;191;171m\",\n        \"lime_green\"           : \"\\033[38;2;230;235;148m\",\n        \"marine_blue\"          : \"\\033[38;2;0;104;136m\",\n        \"raspberry_red\"        : \"\\033[38;2;159;22;106m\",\n        \"moon_gray\"            : \"\\033[38;2;212;217;220m\",\n        \"shell_pink\"           : \"\\033[38;2;251;218;200m\",\n        \"chartreuse_green\"     : \"\\033[38;2;217;227;103m\",\n        \"madonna_blue\"         : \"\\033[38;2;0;96;141m\",\n        \"orchid\"               : \"\\033[38;2;217;170;205m\",\n        \"china_clay\"           : \"\\033[38;2;212;220;211m\",\n        \"baby_pink\"            : \"\\033[38;2;253;237;228m\",\n        \"lettuce_green\"        : \"\\033[38;2;209;222;76m\",\n        \"egyptian_blue\"        : \"\\033[38;2;0;115;168m\",\n        \"lilla\"                : \"\\033[38;2;224;181;211m\",\n        \"sand_beige\"           : \"\\033[38;2;220;214;210m\",\n        \"nail_pink\"            : \"\\033[38;2;252;228;214m\",\n        \"olive_green\"          : \"\\033[38;2;95;101;39m\",\n        \"baby_blue\"            : \"\\033[38;2;187;226;241m\",\n        \"rose_tendre\"          : \"\\033[38;2;230;175;207m\",\n        \"orchid_mist\"          : \"\\033[38;2;211;211;216m\",\n        \"raw_sienna\"           : \"\\033[38;2;225;123;52m\",\n        \"moss_green\"           : \"\\033[38;2;119;126;65m\",\n        \"sky_blue\"             : \"\\033[38;2;160;216;239m\",\n        \"orchid_pink\"          : \"\\033[38;2;218;129;178m\",\n        \"reed_gray\"            : \"\\033[38;2;212;217;214m\",\n        \"caramel\"              : \"\\033[38;2;188;97;30m\",\n        \"grass_green\"          : \"\\033[38;2;123;141;66m\",\n        \"shadow_blue\"          : \"\\033[38;2;113;155;173m\",\n        \"cyclamen_pink\"        : \"\\033[38;2;208;79;151m\",\n        \"sky_gray\"             : \"\\033[38;2;203;208;211m\",\n        \"sunset\"               : \"\\033[38;2;246;180;131m\",\n        \"spring_green\"         : \"\\033[38;2;156;187;28m\",\n        \"_cyan\"                : \"\\033[38;2;0;161;233m\",\n        \"_magenta\"             : \"\\033[38;2;228;0;127m\",\n        \"lavender_gray\"        : \"\\033[38;2;188;186;206m\",\n        \"cinnamon\"             : \"\\033[38;2;190;143;104m\",\n        \"leaf_green\"           : \"\\033[38;2;159;194;77m\",\n        \"yacht_blue\"           : \"\\033[38;2;64;158;204m\",\n        \"bougainvillaea\"       : \"\\033[38;2;230;47;139m\",\n        \"silver\"               : \"\\033[38;2;201;202;202m\",\n        \"tan\"                  : \"\\033[38;2;191;120;62m\",\n        \"white_lily\"           : \"\\033[38;2;240;246;218m\",\n        \"chalk_blue\"           : \"\\033[38;2;104;169;207m\",\n        \"ruby\"                 : \"\\033[38;2;199;0;103m\",\n        \"pearl_gray\"           : \"\\033[38;2;201;201;196m\",\n        \"champagne\"            : \"\\033[38;2;233;218;203m\",\n        \"asparagus_green\"      : \"\\033[38;2;219;235;196m\",\n        \"pigeon_blue\"          : \"\\033[38;2;136;181;211m\",\n        \"claret\"               : \"\\033[38;2;148;31;87m\",\n        \"sand_gray\"            : \"\\033[38;2;201;201;194m\",\n        \"peach\"                : \"\\033[38;2;251;216;181m\",\n        \"citron_green\"         : \"\\033[38;2;97;142;52m\",\n        \"smoke_blue\"           : \"\\033[38;2;164;193;215m\",\n        \"azalee\"               : \"\\033[38;2;216;52;115m\",\n        \"marble_gray\"          : \"\\033[38;2;192;197;194m\",\n        \"cafe_au_lait\"         : \"\\033[38;2;148;108;69m\",\n        \"meadow_green\"         : \"\\033[38;2;101;171;49m\",\n        \"frosty_blue\"          : \"\\033[38;2;187;219;243m\",\n        \"cosmos\"               : \"\\033[38;2;220;107;154m\",\n        \"opal_gray\"            : \"\\033[38;2;191;190;197m\",\n        \"orange\"               : \"\\033[38;2;238;120;0m\",\n        \"apple_green\"          : \"\\033[38;2;167;210;141m\",\n        \"bleu_acide\"           : \"\\033[38;2;0;110;176m\",\n        \"lotus_pink\"           : \"\\033[38;2;222;130;167m\",\n        \"french_gray\"          : \"\\033[38;2;141;160;182m\",\n        \"apricot\"              : \"\\033[38;2;247;185;119m\",\n        \"ivy_green\"            : \"\\033[38;2;87;138;61m\",\n        \"cobalt_blue\"          : \"\\033[38;2;0;104;183m\",\n        \"old_orchid\"           : \"\\033[38;2;227;173;193m\",\n        \"mist\"                 : \"\\033[38;2;180;174;177m\",\n        \"amber\"                : \"\\033[38;2;194;137;75m\",\n        \"spinach_green\"        : \"\\033[38;2;65;112;56m\",\n        \"sapphire_blue\"        : \"\\033[38;2;0;104;183m\",\n        \"rose_mist\"            : \"\\033[38;2;222;190;204m\",\n        \"ash_blond\"            : \"\\033[38;2;181;181;174m\",\n        \"bronze\"               : \"\\033[38;2;172;107;37m\",\n        \"cactus\"               : \"\\033[38;2;56;125;57m\",\n        \"spectrum_blue\"        : \"\\033[38;2;0;117;194m\",\n        \"rose_dragee\"          : \"\\033[38;2;229;193;205m\",\n        \"fog\"                  : \"\\033[38;2;171;177;181m\",\n        \"vanilla\"              : \"\\033[38;2;232;197;156m\",\n        \"sky_green\"            : \"\\033[38;2;190;224;194m\",\n        \"_blue\"                : \"\\033[38;2;0;117;194m\",\n        \"cherry_pink\"          : \"\\033[38;2;235;110;160m\",\n        \"beige_gray\"           : \"\\033[38;2;180;173;169m\",\n        \"cork\"                 : \"\\033[38;2;196;154;106m\",\n        \"spearmint\"            : \"\\033[38;2;121;192;110m\",\n        \"zenith_blue\"          : \"\\033[38;2;68;150;211m\",\n        \"opera\"                : \"\\033[38;2;233;83;136m\",\n        \"silver_gray\"          : \"\\033[38;2;175;175;176m\",\n        \"burnt_umber\"          : \"\\033[38;2;111;84;54m\",\n        \"mint_green\"           : \"\\033[38;2;137;201;151m\",\n        \"heavenly_blue\"        : \"\\033[38;2;104;164;217m\",\n        \"rose_red\"             : \"\\033[38;2;234;97;142m\",\n        \"storm_gray\"           : \"\\033[38;2;170;170;176m\",\n        \"raw_umber\"            : \"\\033[38;2;134;102;41m\",\n        \"parrot_green\"         : \"\\033[38;2;55;163;74m\",\n        \"orchid_gray\"          : \"\\033[38;2;188;199;215m\",\n        \"old_lilac\"            : \"\\033[38;2;176;119;140m\",\n        \"green_fog\"            : \"\\033[38;2;171;177;173m\",\n        \"flesh\"                : \"\\033[38;2;250;208;158m\",\n        \"summer_green\"         : \"\\033[38;2;0;153;68m\",\n        \"powder_blue\"          : \"\\033[38;2;188;205;219m\",\n        \"cocoa\"                : \"\\033[38;2;110;74;85m\",\n        \"ash_gray\"             : \"\\033[38;2;159;160;158m\",\n        \"golden_yellow\"        : \"\\033[38;2;246;174;84m\",\n        \"opal_green\"           : \"\\033[38;2;190;224;206m\",\n        \"light_blue\"           : \"\\033[38;2;178;203;228m\",\n        \"wine_red\"             : \"\\033[38;2;179;62;92m\",\n        \"rose_gray\"            : \"\\033[38;2;157;142;135m\",\n        \"mandarin_orange\"      : \"\\033[38;2;243;152;29m\",\n        \"spray_green\"          : \"\\033[38;2;164;213;189m\",\n        \"_baby_blue\"           : \"\\033[38;2;162;194;230m\",\n        \"garnet\"               : \"\\033[38;2;148;35;67m\",\n        \"elephant_skin\"        : \"\\033[38;2;159;159;152m\",\n        \"marigold\"             : \"\\033[38;2;243;152;0m\",\n        \"bottle_green\"         : \"\\033[38;2;0;77;37m\",\n        \"day_dream\"            : \"\\033[38;2;163;185;224m\",\n        \"cochineal_red\"        : \"\\033[38;2;200;44;85m\",\n        \"battleship_gray\"      : \"\\033[38;2;137;137;137m\",\n        \"ecru_beige\"           : \"\\033[38;2;246;229;204m\",\n        \"cobalt_green\"         : \"\\033[38;2;60;179;122m\",\n        \"salvia_blue\"          : \"\\033[38;2;148;173;218m\",\n        \"strawberry\"           : \"\\033[38;2;231;53;98m\",\n        \"stone_gray\"           : \"\\033[38;2;137;136;128m\",\n        \"oyster\"               : \"\\033[38;2;234;225;207m\",\n        \"evergreen\"            : \"\\033[38;2;0;152;79m\",\n        \"hyacinth_blue\"        : \"\\033[38;2;122;153;207m\",\n        \"ruby_red\"             : \"\\033[38;2;231;53;98m\",\n        \"moss_gray\"            : \"\\033[38;2;126;131;127m\",\n        \"ochre\"                : \"\\033[38;2;186;139;64m\",\n        \"malachite_green\"      : \"\\033[38;2;0;152;84m\",\n        \"hyacinth\"             : \"\\033[38;2;108;155;210m\",\n        \"carmine\"              : \"\\033[38;2;215;0;53m\",\n        \"dove_gray\"            : \"\\033[38;2;125;123;131m\",\n        \"khaki\"                : \"\\033[38;2;197;160;90m\",\n        \"_green\"               : \"\\033[38;2;0;169;96m\",\n        \"midnight_blue\"        : \"\\033[38;2;0;30;67m\",\n        \"signal_red\"           : \"\\033[38;2;232;56;61m\",\n        \"gray\"                 : \"\\033[38;2;125;125;125m\",\n        \"buff\"                 : \"\\033[38;2;202;172;113m\",\n        \"emerald_green\"        : \"\\033[38;2;0;169;104m\",\n        \"navy_blue\"            : \"\\033[38;2;32;47;85m\",\n        \"burgundy\"             : \"\\033[38;2;108;39;53m\",\n        \"steel_gray\"           : \"\\033[38;2;115;109;113m\",\n        \"saffron_yellow\"       : \"\\033[38;2;250;197;89m\",\n        \"forest_green\"         : \"\\033[38;2;40;140;102m\",\n        \"prussian_blue\"        : \"\\033[38;2;25;47;96m\",\n        \"bordeaux\"             : \"\\033[38;2;108;39;45m\",\n        \"ivy_gray\"             : \"\\033[38;2;102;108;103m\",\n        \"pumpkin\"              : \"\\033[38;2;229;163;35m\",\n        \"viridian\"             : \"\\033[38;2;0;136;90m\",\n        \"iron_blue\"            : \"\\033[38;2;25;47;96m\",\n        \"camellia\"             : \"\\033[38;2;218;83;110m\",\n        \"slate_gray\"           : \"\\033[38;2;98;96;99m\",\n        \"yellow_ocher\"         : \"\\033[38;2;196;151;47m\",\n        \"holly_green\"          : \"\\033[38;2;0;105;72m\",\n        \"indigo\"               : \"\\033[38;2;4;60;120m\",\n        \"rose\"                 : \"\\033[38;2;233;84;100m\",\n        \"graphite\"             : \"\\033[38;2;89;78;82m\",\n        \"blond\"                : \"\\033[38;2;242;213;138m\",\n        \"billiard_green\"       : \"\\033[38;2;0;92;66m\",\n        \"ink_blue\"             : \"\\033[38;2;0;63;142m\",\n        \"rose_pink\"            : \"\\033[38;2;241;156;167m\",\n        \"charcoal_gray\"        : \"\\033[38;2;78;69;74m\",\n        \"beige\"                : \"\\033[38;2;238;220;179m\",\n        \"chrome_green\"         : \"\\033[38;2;0;83;63m\",\n        \"oriental_blue\"        : \"\\033[38;2;38;73;157m\",\n        \"pink\"                 : \"\\033[38;2;245;178;178m\",\n        \"taupe\"                : \"\\033[38;2;80;73;70m\",\n        \"biscuit\"              : \"\\033[38;2;234;215;164m\",\n        \"antique_green\"        : \"\\033[38;2;84;145;127m\",\n        \"ultramarine_blue\"     : \"\\033[38;2;71;83;162m\",\n        \"flamingo_pink\"        : \"\\033[38;2;245;178;172m\",\n        \"lamp_black\"           : \"\\033[38;2;36;20;14m\",\n        \"leghorn\"              : \"\\033[38;2;255;233;169m\",\n        \"water_green\"          : \"\\033[38;2;165;201;193m\",\n        \"ultramarine\"          : \"\\033[38;2;67;77;162m\",\n        \"old_rose\"             : \"\\033[38;2;226;147;153m\",\n        \"_black\"               : \"\\033[38;2;0;0;0m\",\n\n        \"__black\"              : \"\\033[38;2;0;0;0m\",\n        \"aliceblue\"            : \"\\033[38;2;240;248;255m\",\n        \"darkcyan\"             : \"\\033[38;2;0;139;139m\",\n        \"lightyellow\"          : \"\\033[38;2;255;255;224m\",\n        \"coral\"                : \"\\033[38;2;255;127;80m\",\n        \"dimgray\"              : \"\\033[38;2;105;105;105m\",\n        \"_lavender\"            : \"\\033[38;2;230;230;250m\",\n        \"teal\"                 : \"\\033[38;2;0;128;128m\",\n        \"lightgoldenrodyellow\" : \"\\033[38;2;250;250;210m\",\n        \"tomato\"               : \"\\033[38;2;255;99;71m\",\n        \"_gray\"                : \"\\033[38;2;128;128;128m\",\n        \"lightsteelblue\"       : \"\\033[38;2;176;196;222m\",\n        \"darkslategray\"        : \"\\033[38;2;47;79;79m\",\n        \"lemonchiffon\"         : \"\\033[38;2;255;250;205m\",\n        \"orangered\"            : \"\\033[38;2;255;69;0m\",\n        \"darkgray\"             : \"\\033[38;2;169;169;169m\",\n        \"lightslategray\"       : \"\\033[38;2;119;136;153m\",\n        \"darkgreen\"            : \"\\033[38;2;0;100;0m\",\n        \"wheat\"                : \"\\033[38;2;245;222;179m\",\n        \"__red\"                : \"\\033[38;2;255;0;0m\",\n        \"_silver\"              : \"\\033[38;2;192;192;192m\",\n        \"slategray\"            : \"\\033[38;2;112;128;144m\",\n        \"__green\"              : \"\\033[38;2;0;128;0m\",\n        \"burlywood\"            : \"\\033[38;2;222;184;135m\",\n        \"crimson\"              : \"\\033[38;2;220;20;60m\",\n        \"lightgray\"            : \"\\033[38;2;211;211;211m\",\n        \"steelblue\"            : \"\\033[38;2;70;130;180m\",\n        \"forestgreen\"          : \"\\033[38;2;34;139;34m\",\n        \"_tan\"                 : \"\\033[38;2;210;180;140m\",\n        \"mediumvioletred\"      : \"\\033[38;2;199;21;133m\",\n        \"gainsboro\"            : \"\\033[38;2;220;220;220m\",\n        \"royalblue\"            : \"\\033[38;2;65;105;225m\",\n        \"seagreen\"             : \"\\033[38;2;46;139;87m\",\n        \"_khaki\"               : \"\\033[38;2;240;230;140m\",\n        \"deeppink\"             : \"\\033[38;2;255;20;147m\",\n        \"whitesmoke\"           : \"\\033[38;2;245;245;245m\",\n        \"midnightblue\"         : \"\\033[38;2;25;25;112m\",\n        \"mediumseagreen\"       : \"\\033[38;2;60;179;113m\",\n        \"__yellow\"             : \"\\033[38;2;255;255;0m\",\n        \"hotpink\"              : \"\\033[38;2;255;105;180m\",\n        \"__white\"              : \"\\033[38;2;255;255;255m\",\n        \"navy\"                 : \"\\033[38;2;0;0;128m\",\n        \"mediumaquamarine\"     : \"\\033[38;2;102;205;170m\",\n        \"gold\"                 : \"\\033[38;2;255;215;0m\",\n        \"palevioletred\"        : \"\\033[38;2;219;112;147m\",\n        \"snow\"                 : \"\\033[38;2;255;250;250m\",\n        \"darkblue\"             : \"\\033[38;2;0;0;139m\",\n        \"darkseagreen\"         : \"\\033[38;2;143;188;143m\",\n        \"_orange\"              : \"\\033[38;2;255;165;0m\",\n        \"_pink\"                : \"\\033[38;2;255;192;203m\",\n        \"ghostwhite\"           : \"\\033[38;2;248;248;255m\",\n        \"mediumblue\"           : \"\\033[38;2;0;0;205m\",\n        \"_aquamarine\"          : \"\\033[38;2;127;255;212m\",\n        \"sandybrown\"           : \"\\033[38;2;244;164;96m\",\n        \"lightpink\"            : \"\\033[38;2;255;182;193m\",\n        \"floralwhite\"          : \"\\033[38;2;255;250;240m\",\n        \"__blue\"               : \"\\033[38;2;0;0;255m\",\n        \"palegreen\"            : \"\\033[38;2;152;251;152m\",\n        \"darkorange\"           : \"\\033[38;2;255;140;0m\",\n        \"thistle\"              : \"\\033[38;2;216;191;216m\",\n        \"linen\"                : \"\\033[38;2;250;240;230m\",\n        \"dodgerblue\"           : \"\\033[38;2;30;144;255m\",\n        \"lightgreen\"           : \"\\033[38;2;144;238;144m\",\n        \"goldenrod\"            : \"\\033[38;2;218;165;32m\",\n        \"__magenta\"            : \"\\033[38;2;255;0;255m\",\n        \"antiquewhite\"         : \"\\033[38;2;250;235;215m\",\n        \"cornflowerblue\"       : \"\\033[38;2;100;149;237m\",\n        \"springgreen\"          : \"\\033[38;2;0;255;127m\",\n        \"peru\"                 : \"\\033[38;2;205;133;63m\",\n        \"fuchsia\"              : \"\\033[38;2;255;0;255m\",\n        \"papayawhip\"           : \"\\033[38;2;255;239;213m\",\n        \"deepskyblue\"          : \"\\033[38;2;0;191;255m\",\n        \"mediumspringgreen\"    : \"\\033[38;2;0;250;154m\",\n        \"darkgoldenrod\"        : \"\\033[38;2;184;134;11m\",\n        \"_violet\"              : \"\\033[38;2;238;130;238m\",\n        \"blanchedalmond\"       : \"\\033[38;2;255;235;205m\",\n        \"lightskyblue\"         : \"\\033[38;2;135;206;250m\",\n        \"lawngreen\"            : \"\\033[38;2;124;252;0m\",\n        \"_chocolate\"           : \"\\033[38;2;210;105;30m\",\n        \"_plum\"                : \"\\033[38;2;221;160;221m\",\n        \"bisque\"               : \"\\033[38;2;255;228;196m\",\n        \"skyblue\"              : \"\\033[38;2;135;206;235m\",\n        \"chartreuse\"           : \"\\033[38;2;127;255;0m\",\n        \"sienna\"               : \"\\033[38;2;160;82;45m\",\n        \"_orchid\"              : \"\\033[38;2;218;112;214m\",\n        \"moccasin\"             : \"\\033[38;2;255;228;181m\",\n        \"lightblue\"            : \"\\033[38;2;173;216;230m\",\n        \"greenyellow\"          : \"\\033[38;2;173;255;47m\",\n        \"saddlebrown\"          : \"\\033[38;2;139;69;19m\",\n        \"mediumorchid\"         : \"\\033[38;2;186;85;211m\",\n        \"navajowhite\"          : \"\\033[38;2;255;222;173m\",\n        \"powderblue\"           : \"\\033[38;2;176;224;230m\",\n        \"lime\"                 : \"\\033[38;2;0;255;0m\",\n        \"maroon\"               : \"\\033[38;2;128;0;0m\",\n        \"darkorchid\"           : \"\\033[38;2;153;50;204m\",\n        \"peachpuff\"            : \"\\033[38;2;255;218;185m\",\n        \"paleturquoise\"        : \"\\033[38;2;175;238;238m\",\n        \"limegreen\"            : \"\\033[38;2;50;205;50m\",\n        \"darkred\"              : \"\\033[38;2;139;0;0m\",\n        \"darkviolet\"           : \"\\033[38;2;148;0;211m\",\n        \"mistyrose\"            : \"\\033[38;2;255;228;225m\",\n        \"lightcyan\"            : \"\\033[38;2;224;255;255m\",\n        \"yellowgreen\"          : \"\\033[38;2;154;205;50m\",\n        \"_brown\"               : \"\\033[38;2;165;42;42m\",\n        \"darkmagenta\"          : \"\\033[38;2;139;0;139m\",\n        \"lavenderblush\"        : \"\\033[38;2;255;240;245m\",\n        \"__cyan\"               : \"\\033[38;2;0;255;255m\",\n        \"darkolivegreen\"       : \"\\033[38;2;85;107;47m\",\n        \"firebrick\"            : \"\\033[38;2;178;34;34m\",\n        \"_purple\"              : \"\\033[38;2;128;0;128m\",\n        \"seashell\"             : \"\\033[38;2;255;245;238m\",\n        \"aqua\"                 : \"\\033[38;2;0;255;255m\",\n        \"olivedrab\"            : \"\\033[38;2;107;142;35m\",\n        \"indianred\"            : \"\\033[38;2;205;92;92m\",\n        \"_indigo\"              : \"\\033[38;2;75;0;130m\",\n        \"oldlace\"              : \"\\033[38;2;253;245;230m\",\n        \"_turquoise\"           : \"\\033[38;2;64;224;208m\",\n        \"_olive\"               : \"\\033[38;2;128;128;0m\",\n        \"rosybrown\"            : \"\\033[38;2;188;143;143m\",\n        \"darkslateblue\"        : \"\\033[38;2;72;61;139m\",\n        \"_ivory\"               : \"\\033[38;2;255;255;240m\",\n        \"mediumturquoise\"      : \"\\033[38;2;72;209;204m\",\n        \"darkkhaki\"            : \"\\033[38;2;189;183;107m\",\n        \"darksalmon\"           : \"\\033[38;2;233;150;122m\",\n        \"blueviolet\"           : \"\\033[38;2;138;43;226m\",\n        \"honeydew\"             : \"\\033[38;2;240;255;240m\",\n        \"darkturquoise\"        : \"\\033[38;2;0;206;209m\",\n        \"palegoldenrod\"        : \"\\033[38;2;238;232;170m\",\n        \"lightcoral\"           : \"\\033[38;2;240;128;128m\",\n        \"mediumpurple\"         : \"\\033[38;2;147;112;219m\",\n        \"mintcream\"            : \"\\033[38;2;245;255;250m\",\n        \"lightseagreen\"        : \"\\033[38;2;32;178;170m\",\n        \"cornsilk\"             : \"\\033[38;2;255;248;220m\",\n        \"salmon\"               : \"\\033[38;2;250;128;114m\",\n        \"slateblue\"            : \"\\033[38;2;106;90;205m\",\n        \"azure\"                : \"\\033[38;2;240;255;255m\",\n        \"cadetblue\"            : \"\\033[38;2;95;158;160m\",\n        \"_beige\"               : \"\\033[38;2;245;245;220m\",\n        \"lightsalmon\"          : \"\\033[38;2;255;160;122m\",\n        \"mediumslateblue\"      : \"\\033[38;2;123;104;238m\",\n    }\n\n    @staticmethod\n    def boldify(msg):\n        return Color.colorify(msg, \"bold\")\n\n    @staticmethod\n    def grayify(msg):\n        return Color.colorify(msg, \"bright_black\")\n\n    @staticmethod\n    def redify(msg):\n        return Color.colorify(msg, \"red\")\n\n    @staticmethod\n    def greenify(msg):\n        return Color.colorify(msg, \"green\")\n\n    @staticmethod\n    def yellowify(msg):\n        return Color.colorify(msg, \"yellow\")\n\n    @staticmethod\n    def blueify(msg):\n        return Color.colorify(msg, \"blue\")\n\n    @staticmethod\n    def cyanify(msg):\n        return Color.colorify(msg, \"cyan\")\n\n    NO_COLOR = None\n\n    @staticmethod\n    def disable_color():\n        if Config.get_gef_setting(\"gef.disable_color\") is True:\n            return True\n        if Color.NO_COLOR is None:\n            if os.environ.get(\"NO_COLOR\", None):\n                Color.NO_COLOR = True\n            else:\n                Color.NO_COLOR = False\n        if Color.NO_COLOR:\n            return True\n        return False\n\n    @staticmethod\n    def colorify(text, attrs):\n        \"\"\"Color text according to the given attributes.\"\"\"\n        if Color.disable_color():\n            return str(text)\n\n        colors = Color.colors\n        escapes = [colors[attr] for attr in attrs.split() if attr in colors]\n        if len(escapes) == 0:\n            return str(text)\n\n        out = \"\".join(escapes) + str(text) + colors[\"normal\"]\n        return out\n\n    @staticmethod\n    def colorify_hex(value, attrs):\n        text = \"{:#x}\".format(value)\n        return Color.colorify(text, attrs)\n\n    @staticmethod\n    def remove_color(text):\n        return re.sub(r\"\\x1B\\[([0-9]{1,2}(;[0-9]{1,3})*)?m\", \"\", text)\n\n\nclass Address:\n    \"\"\"GEF representation of memory addresses.\"\"\"\n\n    def __init__(self, addr):\n        if isinstance(addr, gdb.Value):\n            addr = to_unsigned_long(addr)\n        self.value = addr\n        return\n\n    @property\n    def section(self):\n        if hasattr(self, \"cached_section\"):\n            return self.cached_section\n        self.cached_section = ProcessMap.process_lookup_address(self.value)\n        return self.cached_section\n\n    @property\n    def info(self):\n        if hasattr(self, \"cached_info\"):\n            return self.cached_info\n        self.cached_info = ProcessMap.file_lookup_address(self.value)\n        return self.cached_info\n\n    @property\n    def valid(self):\n        return is_valid_addr(self.value)\n\n    def __repr__(self):\n        return '<{:s}.{:s} object at {:#x}, addr={:#x}, section={}, info={}, valid={}>'.format(\n            self.__module__, self.__class__.__name__, id(self),\n            self.value, bool(self.section), bool(self.info), self.valid,\n        )\n\n    def __str__(self):\n        value = AddressUtil.format_address(self.value)\n        if not self.valid:\n            return value\n        line_color = \"\"\n        if self.is_in_stack_segment():\n            line_color = Config.get_gef_setting(\"theme.address_stack\")\n        elif self.is_in_heap_segment():\n            line_color = Config.get_gef_setting(\"theme.address_heap\")\n        elif self.is_in_text_segment():\n            line_color = Config.get_gef_setting(\"theme.address_code\")\n        elif self.is_in_writable():\n            line_color = Config.get_gef_setting(\"theme.address_writable\")\n        elif self.is_in_readonly():\n            line_color = Config.get_gef_setting(\"theme.address_readonly\")\n        elif self.is_valid_but_none():\n            line_color = Config.get_gef_setting(\"theme.address_valid_but_none\")\n        if self.is_rwx():\n            line_color += \" \" + Config.get_gef_setting(\"theme.address_rwx\")\n        return Color.colorify(value, line_color)\n\n    def long_fmt(self):\n        value = AddressUtil.format_address(self.value, long_fmt=True)\n        if not self.valid:\n            return value\n        line_color = \"\"\n        if self.is_in_stack_segment():\n            line_color = Config.get_gef_setting(\"theme.address_stack\")\n        elif self.is_in_heap_segment():\n            line_color = Config.get_gef_setting(\"theme.address_heap\")\n        elif self.is_in_text_segment():\n            line_color = Config.get_gef_setting(\"theme.address_code\")\n        elif self.is_in_writable():\n            line_color = Config.get_gef_setting(\"theme.address_writable\")\n        elif self.is_in_readonly():\n            line_color = Config.get_gef_setting(\"theme.address_readonly\")\n        elif self.is_valid_but_none():\n            line_color = Config.get_gef_setting(\"theme.address_valid_but_none\")\n        if self.is_rwx():\n            line_color += \" \" + Config.get_gef_setting(\"theme.address_rwx\")\n        return Color.colorify(value, line_color)\n\n    def is_rwx(self):\n        if self.section is None:\n            return False\n        r = hasattr(self.section, \"is_readable\") and self.section.is_readable()\n        w = hasattr(self.section, \"is_writable\") and self.section.is_writable()\n        x = hasattr(self.section, \"is_executable\") and self.section.is_executable()\n        return r and w and x\n\n    def is_in_stack_segment(self):\n        if self.section is None:\n            return False\n        return hasattr(self.section, \"path\") and self.section.path.startswith(\"[stack]\")\n\n    def is_in_heap_segment(self):\n        if self.section is None:\n            return False\n        return hasattr(self.section, \"path\") and self.section.path.startswith(\"[heap]\")\n\n    def is_in_text_segment(self):\n        if self.section is None:\n            return False\n        a = hasattr(self.info, \"name\") and isinstance(self.info.name, str) and \".text\" in self.info.name\n        e = hasattr(self.section, \"is_executable\") and self.section.is_executable()\n        return a or e\n\n    def is_in_writable(self):\n        if self.section is None:\n            return False\n        w = hasattr(self.section, \"is_writable\") and self.section.is_writable()\n        return w\n\n    def is_in_readonly(self):\n        if self.section is None:\n            return False\n        r = hasattr(self.section, \"is_readable\") and self.section.is_readable()\n        w = hasattr(self.section, \"is_writable\") and self.section.is_writable()\n        x = hasattr(self.section, \"is_executable\") and self.section.is_executable()\n        return r and (not w) and (not x)\n\n    def is_valid_but_none(self):\n        if self.section is None:\n            return False\n        r = hasattr(self.section, \"is_readable\") and self.section.is_readable()\n        x = hasattr(self.section, \"is_executable\") and self.section.is_executable()\n        w = hasattr(self.section, \"is_writable\") and self.section.is_writable()\n        return (not r) and (not w) and (not x)\n\n    def dereference(self):\n        # Even if the valid flag is not set, it still dereferences.\n        # This is because the valid flag is not set during kernel debugging.\n        value = AddressUtil.align_address(self.value)\n        derefed = AddressUtil.dereference(value)\n        if derefed is None:\n            return None\n        return int(derefed)\n\n\nclass AddressUtil:\n    \"\"\"A collection of utility functions that operate on addresses.\"\"\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def ptr_width():\n        \"\"\"Determine whether the environment is 32-bit or 64-bit.\"\"\"\n        void = GefUtil.cached_lookup_type(\"void\")\n        if void:\n            return void.pointer().sizeof\n\n        uintptr_t = GefUtil.cached_lookup_type(\"uintptr_t\")\n        if uintptr_t:\n            return uintptr_t.sizeof\n\n        raise EnvironmentError(\"GEF is running under an unsupported mode\")\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_memory_alignment(in_bits=False):\n        \"\"\"Try to determine the size of a pointer on this system.\"\"\"\n        if is_x86_16():\n            if current_arch.A20:\n                return 2 if not in_bits else 21\n            else:\n                return 2 if not in_bits else 20\n\n        if is_32bit():\n            return 4 if not in_bits else 32\n        elif is_64bit():\n            return 8 if not in_bits else 64\n\n        raise EnvironmentError(\"GEF is running under an unsupported mode\")\n\n    @staticmethod\n    def is_msb_on(addr):\n        \"\"\"Return whether provided address MSB is on.\"\"\"\n        align = AddressUtil.get_memory_alignment()\n        if align == 8:\n            return bool(addr & 0x8000_0000_0000_0000)\n        elif align == 4:\n            return bool(addr & 0x8000_0000)\n        elif align == 2:\n            return bool(addr & 0x8000)\n        raise EnvironmentError(\"GEF is running under an unsupported mode\")\n\n    @staticmethod\n    def get_format_address_width(memalign_size=None):\n        \"\"\"Return the width for compactly displaying the pointer.\"\"\"\n        if not is_alive():\n            return 16 + 2 # '0xAAABBBBCCCCDDDD' # assume 64bit\n        if is_32bit() or memalign_size == 4:\n            return 8 + 2 # '0xAAAABBBB'\n        if not is_in_kernel():\n            return 12 + 2 # '0x7fffAAAABBBB'\n        return 16 + 2 # '0xAAABBBBCCCCDDDD'\n\n    @staticmethod\n    def format_address(addr, memalign_size=None, long_fmt=False):\n        \"\"\"Format the address according to its size.\"\"\"\n        # if qemu-xxx(32bit arch) runs on x86-64 machine, memalign_size does not match\n        # AddressUtil.get_memory_alignment(), so use the value forcibly if memalign_size is not None\n        if memalign_size is None:\n            memalign_size = AddressUtil.get_memory_alignment()\n\n        if isinstance(addr, str):\n            addr = int(addr, 16)\n\n        addr = AddressUtil.align_address(addr, memalign_size)\n        if memalign_size == 4:\n            return \"{:#010x}\".format(addr)\n        elif memalign_size == 2:\n            return \"{:#06x}\".format(addr)\n        elif memalign_size == 2.5:\n            if current_arch.A20:\n                return \"{:#08x}\".format(addr)\n            else:\n                return \"{:#07x}\".format(addr)\n        if long_fmt:\n            return \"{:#018x}\".format(addr)\n        if is_in_kernel():\n            return \"{:#018x}\".format(addr)\n        return \"{:#014x}\".format(addr)\n\n    @staticmethod\n    def align_address(addr, memalign_size=None):\n        \"\"\"Align the provided address to the process's native length.\n        e.g., 0x1_2345_6789 -> 0x2345_6789 (for 32-bit arch)\"\"\"\n        # if qemu-xxx(32bit arch) runs on x86-64 machine, memalign_size does not match\n        # AddressUtil.get_memory_alignment(), so use the value forcibly if memalign_size is not None\n        if memalign_size is None:\n            memalign_size = AddressUtil.get_memory_alignment()\n\n        if memalign_size == 8:\n            return addr & 0xffff_ffff_ffff_ffff\n        elif memalign_size == 4:\n            return addr & 0xffff_ffff\n        elif memalign_size == 2:\n            return addr & 0xffff\n        elif memalign_size == 2.5:\n            if current_arch.A20:\n                return addr & 0x1f_ffff\n            else:\n                return addr & 0x0f_ffff\n\n        raise EnvironmentError(\"GEF is running under an unsupported mode\")\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_vmem_end():\n        return 1 << AddressUtil.get_memory_alignment(in_bits=True)\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_vmem_end_mask():\n        return AddressUtil.get_vmem_end() - 1\n\n    @staticmethod\n    def parse_address(addr):\n        \"\"\"Parse an address and return it as an Integer.\"\"\"\n        try:\n            return int(addr, 0)\n        except ValueError:\n            pass\n        # on some unsupported architectures (e.g., tricore), gdb.parse_and_eval may cause a crash\n        if current_arch is None:\n            raise ValueError\n        # Don't enclose it in a try-catch. This is because it is used with argparse,\n        # and is intended to raise an exception if parsing fails.\n        return to_unsigned_long(gdb.parse_and_eval(addr))\n\n    @staticmethod\n    def parse_string_range(s):\n        \"\"\"Parse an address range (e.g., 0x400000-0x401000)\"\"\"\n        addrs = s.split(\"-\")\n        return [int(x, 16) for x in addrs]\n\n    @staticmethod\n    @Cache.cache_until_next\n    def dereference(addr):\n        \"\"\"GEF wrapper for gdb dereference function.\"\"\"\n\n        def use_stdtype():\n            if is_32bit():\n                return \"uint32_t\"\n            elif is_64bit():\n                return \"uint64_t\"\n            return \"uint16_t\"\n\n        def use_default_type():\n            if is_32bit():\n                return \"unsigned int\"\n            elif is_64bit():\n                return \"unsigned long\"\n            return \"unsigned short\"\n\n        def use_golang_type():\n            if is_32bit():\n                return \"uint32\"\n            elif is_64bit():\n                return \"uint64\"\n            return \"uint16\"\n\n        def use_rust_type():\n            if is_32bit():\n                return \"u32\"\n            elif is_64bit():\n                return \"u64\"\n            return \"u16\"\n\n        ulong_t = GefUtil.cached_lookup_type(use_stdtype())\n        if not ulong_t:\n            ulong_t = GefUtil.cached_lookup_type(use_default_type())\n        if not ulong_t:\n            ulong_t = GefUtil.cached_lookup_type(use_golang_type())\n        if not ulong_t:\n            ulong_t = GefUtil.cached_lookup_type(use_rust_type())\n        if not ulong_t:\n            return None\n\n        try:\n            unsigned_long_type = ulong_t.pointer()\n        except (AttributeError, gdb.error):\n            return None\n\n        try:\n            res = gdb.Value(addr).cast(unsigned_long_type).dereference()\n            # GDB does lazy fetch by default so we need to force access to the value\n            res.fetch_lazy()\n            return res\n        except (gdb.MemoryError, gdb.error, ValueError, TypeError):\n            return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_recursive_dereference_blacklist():\n        \"\"\"Return the blacklist of addresses (for caching purposes after eval()).\"\"\"\n        blacklist = eval(Config.get_gef_setting(\"dereference.blacklist\"))\n        for range_list in blacklist:\n            assert isinstance(range_list, list)\n            assert len(range_list) == 2\n            assert isinstance(range_list[0], int)\n            assert isinstance(range_list[1], int)\n        return blacklist\n\n    @staticmethod\n    @Cache.cache_until_next\n    def recursive_dereference(addr, phys=False):\n        \"\"\"Create dereference array.\"\"\"\n        if not is_alive():\n            return [addr], None\n\n        recursion = Config.get_gef_setting(\"dereference.max_recursion\")\n        blacklist = AddressUtil.get_recursive_dereference_blacklist()\n        addr_list = []\n        error = None\n\n        while recursion > 0:\n            # check loop\n            if addr in addr_list:\n                if addr == 0 and len(addr_list) == 1:\n                    # the case that address 0x0 is valid and first element is 0x0 (i.e. telescope 0x0).\n                    # but no error because it is generally unnecessary information.\n                    addr_list.append(addr) # use [0, 0] instead of [0]\n                else:\n                    error = \"[loop detected]\"\n                break\n\n            # not loop\n            addr_list.append(addr)\n\n            # check blacklist\n            if any(bstart <= addr < bend for bstart, bend in blacklist):\n                error = \"[blacklist detected]\"\n                break\n\n            # check non-address\n            if len(addr_list) > 1 and addr < 0x100:\n                break\n\n            # goto next\n            if phys and len(addr_list) == 1:\n                mem = read_physmem(addr, current_arch.ptrsize)\n                unpack = u32 if current_arch.ptrsize == 4 else u64\n                addr = unpack(mem)\n            else:\n                try:\n                    addr = read_int_from_memory(addr)\n                except gdb.MemoryError:\n                    break\n            recursion -= 1\n\n        return addr_list, error\n\n    @staticmethod\n    @Cache.cache_until_next\n    def recursive_dereference_to_string(value, skip_idx=0, phys=False, quiet=False):\n        \"\"\"Create string from dereference array.\"\"\"\n        string_color = Config.get_gef_setting(\"theme.dereference_string\")\n        nb_max_string_length = Config.get_gef_setting(\"context.nb_max_string_length\")\n        recursion = Config.get_gef_setting(\"dereference.max_recursion\")\n\n        # dereference\n        addrs, error = AddressUtil.recursive_dereference(value, phys=phys)\n\n        # if addrs has one element and it is address with an error (e.g., address_A -> [loop detected]),\n        # don't skip the element even if skip_idx=1\n        if skip_idx == 1:\n            if len(addrs) == 1:\n                if error == \"[loop detected]\":\n                    skip_idx = 0\n\n        # add \"...\"\n        if error is None:\n            if addrs[-1] > 0x100 and is_valid_addr(addrs[-1]) and recursion > 1:\n                error = \"...\"\n\n        # replace to string if valid\n        def to_ascii(v):\n            if not isinstance(v, int) or v < 0:\n                return \"\"\n            s = \"\"\n            while v & 0xff: # \\0\n                if chr(v & 0xff) in String.STRING_PRINTABLE:\n                    s += chr(v & 0xff)\n                else:\n                    return \"\"\n                v >>= 8\n            return s\n\n        last_elem = None\n        if error is None and not quiet:\n            s = to_ascii(addrs[-1])\n            if len(s) < 2:\n                pass\n            elif 2 <= len(s) < current_arch.ptrsize:\n                fa = AddressUtil.format_address(addrs[-1], long_fmt=True)\n                last_elem = \"{:s} ({:s}?)\".format(fa, Color.colorify(repr(s), string_color))\n                addrs = addrs[:-1]\n            else: # len(s) == current_arch.ptrsize\n                if len(addrs) >= 2 and is_valid_addr(addrs[-2]):\n                    # read more string\n                    s = read_cstring_from_memory(addrs[-2], nb_max_string_length)\n                    if s:\n                        fa = AddressUtil.format_address(addrs[-1], long_fmt=True)\n                        last_elem = \"{:s} {:s}\".format(fa, Color.colorify(repr(s), string_color))\n                        addrs = addrs[:-1]\n                    else:\n                        # Ignore when the string that do not end with a null character\n                        pass\n                else:\n                    # fallback\n                    fa = AddressUtil.format_address(addrs[-1], long_fmt=True)\n                    last_elem = \"{:s} ({:s}?)\".format(fa, Color.colorify(repr(s), string_color))\n                    addrs = addrs[:-1]\n\n        # others\n        msg = []\n        for addr in addrs[skip_idx:]:\n            address = ProcessMap.lookup_address(addr)\n            if quiet:\n                msg.append(address.long_fmt())\n            else:\n                msg.append(address.long_fmt() + Symbol.get_symbol_string(addr))\n\n        if error:\n            msg.append(error)\n        elif last_elem:\n            msg.append(last_elem)\n\n        return \"  ->  \".join(msg)\n\n\nclass Permission:\n    \"\"\"GEF representation of Linux permission.\"\"\"\n\n    NONE    = 0\n    READ    = 1\n    WRITE   = 2\n    EXECUTE = 4\n    ALL     = READ | WRITE | EXECUTE\n\n    def __init__(self, **kwargs):\n        self.value = kwargs.get(\"value\", 0)\n        return\n\n    def __repr__(self):\n        return '<{:s}.{:s} object at {:#x}, perm=\"{}\">'.format(\n            self.__module__, self.__class__.__name__, id(self), str(self),\n        )\n\n    def __or__(self, value):\n        return self.value | value\n\n    def __and__(self, value):\n        return self.value & value\n\n    def __xor__(self, value):\n        return self.value ^ value\n\n    def __eq__(self, value):\n        return self.value == value\n\n    def __ne__(self, value):\n        return self.value != value\n\n    def __str__(self):\n        perm_str = \"\"\n        perm_str += \"r\" if self & Permission.READ else \"-\"\n        perm_str += \"w\" if self & Permission.WRITE else \"-\"\n        perm_str += \"x\" if self & Permission.EXECUTE else \"-\"\n        return perm_str\n\n    def match(self, perm_str):\n        if not isinstance(perm_str, str):\n            return False\n        if len(perm_str) != 3:\n            return False\n\n        if perm_str[0] not in \"rR-_?\":\n            return False\n        if perm_str[1] not in \"wR-_?\":\n            return False\n        if perm_str[2] not in \"xX-_?\":\n            return False\n\n        if perm_str[0] in \"rR\" and not bool(self.value & Permission.READ):\n            return False\n        if perm_str[0] in \"-_\" and bool(self.value & Permission.READ):\n            return False\n        if perm_str[1] in \"wW\" and not bool(self.value & Permission.WRITE):\n            return False\n        if perm_str[1] in \"-_\" and bool(self.value & Permission.WRITE):\n            return False\n        if perm_str[2] in \"xX\" and not bool(self.value & Permission.EXECUTE):\n            return False\n        if perm_str[2] in \"-_\" and bool(self.value & Permission.EXECUTE):\n            return False\n\n        return True\n\n    @staticmethod\n    def from_process_maps(perm_str):\n        perm = Permission()\n        if perm_str[0] == \"r\":\n            perm.value += Permission.READ\n        if perm_str[1] == \"w\":\n            perm.value += Permission.WRITE\n        if perm_str[2] == \"x\":\n            perm.value += Permission.EXECUTE\n        return perm\n\n\nclass Section:\n    \"\"\"GEF representation of process memory sections.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.page_start = kwargs.get(\"page_start\")\n        self.page_end = kwargs.get(\"page_end\")\n        self.offset = kwargs.get(\"offset\", 0)\n        self.permission = kwargs.get(\"permission\")\n        self.inode = kwargs.get(\"inode\", None)\n        self.path = kwargs.get(\"path\", \"\")\n        return\n\n    def __repr__(self):\n        return '<{:s}.{:s} object at {:#x}, page_start={:#x}, page_end={:#x}, perm=\"{}\", path=\"{:s}\">'.format(\n            self.__module__, self.__class__.__name__, id(self), self.page_start, self.page_end,\n            self.permission, self.path,\n        )\n\n    def is_readable(self):\n        v = self.permission.value\n        return v and bool(v & Permission.READ)\n\n    def is_writable(self):\n        v = self.permission.value\n        return v and bool(v & Permission.WRITE)\n\n    def is_executable(self):\n        v = self.permission.value\n        return v and bool(v & Permission.EXECUTE)\n\n    @property\n    def size(self):\n        if self.page_end is None or self.page_start is None:\n            return -1\n        return self.page_end - self.page_start\n\n\nclass Elf:\n    \"\"\"Basic ELF parsing.\"\"\"\n\n    # e_ident[EI_MAG0:EI_MAG3]\n    ELF_MAGIC                = 0x7f454c46\n\n    # e_ident[EI_CLASS]\n    ELF_CLASS_NONE           = 0\n    ELF_32_BITS              = 1\n    ELF_64_BITS              = 2\n\n    # e_ident[EI_DATA]\n    ELF_DATA_NONE            = 0\n    LITTLE_ENDIAN            = 1\n    BIG_ENDIAN               = 2\n\n    # e_ident[EI_OSABI]\n    OSABI_SYSTEMV            = 0 # UNIX System V ABI\n    OSABI_HPUX               = 1 # Hewlett-Packard HP-UX\n    OSABI_NETBSD             = 2 # NetBSD\n    OSABI_LINUX              = 3 # GNU Linux\n    OSABI_HURD               = 4 # GNU Hurd\n    OSABI_86OPEN             = 5 # 86Open Common IA32 ABI\n    OSABI_SOLARIS            = 6 # Sun Solaris\n    OSABI_AIX                = 7 # IBM AIX\n    OSABI_IRIX               = 8 # SGI Irix\n    OSABI_FREEBSD            = 9 # FreeBSD\n    OSABI_TRU64              = 10 # Compaq TRU64 UNIX\n    OSABI_MODESTO            = 11 # Novell Modesto\n    OSABI_OPENBSD            = 12 # OpenBSD\n    OSABI_OPENVMS            = 13 # OpenVMS\n    OSABI_NSK                = 14 # Hewlett-Packard Non-Stop Kernel\n    OSABI_AROS               = 15 # Amiga Research OS\n    OSABI_FENIXOS            = 16 # The FenixOS highly scalable multi-core OS\n    OSABI_CLOUDABI           = 17 # Nuxi CloudABI\n    OSABI_OPENVOS            = 18 # Stratus Technologies OpenVOS\n    OSABI_ARM_AEABI          = 64 # ARM EABI\n    OSABI_ARM                = 97 # ARM\n    OSABI_STANDALONE         = 255 # Standalone (embedded) application\n\n    # e_type\n    ET_NONE                  = 0\n    ET_REL                   = 1\n    ET_EXEC                  = 2\n    ET_DYN                   = 3\n    ET_CORE                  = 4\n\n    # e_machine\n    EM_NONE                  = 0 # No machine\n    EM_M32                   = 1 # AT&T WE 32100\n    EM_SPARC                 = 2 # SUN SPARC\n    EM_386                   = 3 # Intel 80386\n    EM_68K                   = 4 # Motorola m68k family\n    EM_88K                   = 5 # Motorola m88k family\n    EM_IAMCU                 = 6 # Intel MCU\n    EM_860                   = 7 # Intel 80860\n    EM_MIPS                  = 8 # MIPS R3000 big-endian\n    EM_S370                  = 9 # IBM System/370 Processor\n    EM_MIPS_RS3_LE           = 10 # MIPS RS3000 Little-endian\n    #                          11-14 # Reserved for future use\n    EM_PARISC                = 15 # Hewlett-Packard PA-RISC\n    #                          16 # Reserved for future use\n    EM_VPP500                = 17 # Fujitsu VPP500\n    EM_SPARC32PLUS           = 18 # Enhanced instruction set SPARC\n    EM_960                   = 19 # Intel 80960\n    EM_PPC                   = 20 # PowerPC\n    EM_PPC64                 = 21 # 64-bit PowerPC\n    EM_S390                  = 22 # IBM System/390 Processor\n    EM_SPU                   = 23 # IBM SPU/SPC\n    #                          24-35 # Reserved for future use\n    EM_V800                  = 36 # NEC V800\n    EM_FR20                  = 37 # Fujitsu FR20\n    EM_RH32                  = 38 # TRW RH-32\n    EM_RCE                   = 39 # Motorola RCE\n    EM_ARM                   = 40 # ARM 32-bit architecture (AARCH32)\n    EM_ALPHA                 = 41 # Digital Alpha\n    EM_SH                    = 42 # Hitachi SH\n    EM_SPARCV9               = 43 # SPARC Version 9\n    EM_TRICORE               = 44 # Siemens TriCore embedded processor\n    EM_ARC                   = 45 # Argonaut RISC Core, Argonaut Technologies Inc.\n    EM_H8_300                = 46 # Hitachi H8/300\n    EM_H8_300H               = 47 # Hitachi H8/300H\n    EM_H8S                   = 48 # Hitachi H8S\n    EM_H8_500                = 49 # Hitachi H8/500\n    EM_IA_64                 = 50 # Intel IA-64 processor architecture\n    EM_MIPS_X                = 51 # Stanford MIPS-X\n    EM_COLDFIRE              = 52 # Motorola ColdFire\n    EM_68HC12                = 53 # Motorola M68HC12\n    EM_MMA                   = 54 # Fujitsu MMA Multimedia Accelerator\n    EM_PCP                   = 55 # Siemens PCP\n    EM_NCPU                  = 56 # Sony nCPU embedded RISC processor\n    EM_NDR1                  = 57 # Denso NDR1 microprocessor\n    EM_STARCORE              = 58 # Motorola Star*Core processor\n    EM_ME16                  = 59 # Toyota ME16 processor\n    EM_ST100                 = 60 # STMicroelectronics ST100 processor\n    EM_TINYJ                 = 61 # Advanced Logic Corp. TinyJ embedded processor family\n    EM_X86_64                = 62 # AMD x86-64 architecture\n    EM_PDSP                  = 63 # Sony DSP Processor\n    EM_PDP10                 = 64 # Digital Equipment Corp. PDP-10\n    EM_PDP11                 = 65 # Digital Equipment Corp. PDP-11\n    EM_FX66                  = 66 # Siemens FX66 microcontroller\n    EM_ST9PLUS               = 67 # STMicroelectronics ST9+ 8/16 bit microcontroller\n    EM_ST7                   = 68 # STMicroelectronics ST7 8-bit microcontroller\n    EM_68HC16                = 69 # Motorola MC68HC16 Microcontroller\n    EM_68HC11                = 70 # Motorola MC68HC11 Microcontroller\n    EM_68HC08                = 71 # Motorola MC68HC08 Microcontroller\n    EM_68HC05                = 72 # Motorola MC68HC05 Microcontroller\n    EM_SVX                   = 73 # Silicon Graphics SVx\n    EM_ST19                  = 74 # STMicroelectronics ST19 8-bit microcontroller\n    EM_VAX                   = 75 # Digital VAX\n    EM_CRIS                  = 76 # Axis Communications 32-bit embedded processor\n    EM_JAVELIN               = 77 # Infineon Technologies 32-bit embedded processor\n    EM_FIREPATH              = 78 # Element 14 64-bit DSP Processor\n    EM_ZSP                   = 79 # LSI Logic 16-bit DSP Processor\n    EM_MMIX                  = 80 # Donald Knuth's educational 64-bit processor\n    EM_HUANY                 = 81 # Harvard University machine-independent object files\n    EM_PRISM                 = 82 # SiTera Prism\n    EM_AVR                   = 83 # Atmel AVR 8-bit microcontroller\n    EM_FR30                  = 84 # Fujitsu FR30\n    EM_D10V                  = 85 # Mitsubishi D10V\n    EM_D30V                  = 86 # Mitsubishi D30V\n    EM_V850                  = 87 # NEC v850\n    EM_M32R                  = 88 # Mitsubishi M32R\n    EM_MN10300               = 89 # Matsushita MN10300\n    EM_MN10200               = 90 # Matsushita MN10200\n    EM_PJ                    = 91 # picoJava\n    EM_OPENRISC              = 92 # OpenRISC 32-bit embedded processor\n    EM_ARC_COMPACT           = 93 # ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)\n    EM_XTENSA                = 94 # Tensilica Xtensa Architecture\n    EM_VIDEOCORE             = 95 # Alphamosaic VideoCore processor\n    EM_TMM_GPP               = 96 # Thompson Multimedia General Purpose Processor\n    EM_NS32K                 = 97 # National Semiconductor 32000 series\n    EM_TPC                   = 98 # Tenor Network TPC processor\n    EM_SNP1K                 = 99 # Trebia SNP 1000 processor\n    EM_ST200                 = 100 # STMicroelectronics ST200 microcontroller\n    EM_IP2K                  = 101 # Ubicom IP2xxx microcontroller family\n    EM_MAX                   = 102 # MAX Processor\n    EM_CR                    = 103 # National Semiconductor CompactRISC microprocessor\n    EM_F2MC16                = 104 # Fujitsu F2MC16\n    EM_MSP430                = 105 # Texas Instruments embedded microcontroller msp430\n    EM_BLACKFIN              = 106 # Analog Devices Blackfin (DSP) processor\n    EM_SE_C33                = 107 # S1C33 Family of Seiko Epson processors\n    EM_SEP                   = 108 # Sharp embedded microprocessor\n    EM_ARCA                  = 109 # Arca RISC Microprocessor\n    EM_UNICORE               = 110 # Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University\n    EM_EXCESS                = 111 # eXcess: 16/32/64-bit configurable embedded CPU\n    EM_DXP                   = 112 # Icera Semiconductor Inc. Deep Execution Processor\n    EM_ALTERA_NIOS2          = 113 # Altera Nios II soft-core processor\n    EM_CRX                   = 114 # National Semiconductor CompactRISC CRX microprocessor\n    EM_XGATE                 = 115 # Motorola XGATE embedded processor\n    EM_C166                  = 116 # Infineon C16x/XC16x processor\n    EM_M16C                  = 117 # Renesas M16C series microprocessors\n    EM_DSPIC30F              = 118 # Microchip Technology dsPIC30F Digital Signal Controller\n    EM_CE                    = 119 # Freescale Communication Engine RISC core\n    EM_M32C                  = 120 # Renesas M32C series microprocessors\n    #                          121-130 # Reserved for future use\n    EM_TSK3000               = 131 # Altium TSK3000 core\n    EM_RS08                  = 132 # Freescale RS08 embedded processor\n    EM_SHARC                 = 133 # Analog Devices SHARC family of 32-bit DSP processors\n    EM_ECOG2                 = 134 # Cyan Technology eCOG2 microprocessor\n    EM_SCORE7                = 135 # Sunplus S+core7 RISC processor\n    EM_DSP24                 = 136 # New Japan Radio (NJR) 24-bit DSP Processor\n    EM_VIDEOCORE3            = 137 # Broadcom VideoCore III processor\n    EM_LATTICEMICO32         = 138 # RISC processor for Lattice FPGA architecture\n    EM_SE_C17                = 139 # Seiko Epson C17 family\n    EM_TI_C6000              = 140 # The Texas Instruments TMS320C6000 DSP family\n    EM_TI_C2000              = 141 # The Texas Instruments TMS320C2000 DSP family\n    EM_TI_C5500              = 142 # The Texas Instruments TMS320C55x DSP family\n    EM_TI_ARP32              = 143 # Texas Instruments Application Specific RISC Processor, 32bit fetch\n    EM_TI_PRU                = 144 # Texas Instruments Programmable Realtime Unit\n    #                          145-159 # Reserved for future use\n    EM_MMDSP_PLUS            = 160 # STMicroelectronics 64bit VLIW Data Signal Processor\n    EM_CYPRESS_M8C           = 161 # Cypress M8C microprocessor\n    EM_R32C                  = 162 # Renesas R32C series microprocessors\n    EM_TRIMEDIA              = 163 # NXP Semiconductors TriMedia architecture family\n    EM_QDSP6                 = 164 # QUALCOMM DSP6 Processor\n    EM_8051                  = 165 # Intel 8051 and variants\n    EM_STXP7X                = 166 # STMicroelectronics STxP7x family of configurable and extensible RISC processors\n    EM_NDS32                 = 167 # Andes Technology compact code size embedded RISC processor family\n    EM_ECOG1                 = 168 # Cyan Technology eCOG1X family\n    EM_ECOG1X                = 168 # Cyan Technology eCOG1X family\n    EM_MAXQ30                = 169 # Dallas Semiconductor MAXQ30 Core Micro-controllers\n    EM_XIMO16                = 170 # New Japan Radio (NJR) 16-bit DSP Processor\n    EM_MANIK                 = 171 # M2000 Reconfigurable RISC Microprocessor\n    EM_CRAYNV2               = 172 # Cray Inc. NV2 vector architecture\n    EM_RX                    = 173 # Renesas RX family\n    EM_METAG                 = 174 # Imagination Technologies META processor architecture\n    EM_MCST_ELBRUS           = 175 # MCST Elbrus general purpose hardware architecture\n    EM_ECOG16                = 176 # Cyan Technology eCOG16 family\n    EM_CR16                  = 177 # National Semiconductor CompactRISC CR16 16-bit microprocessor\n    EM_ETPU                  = 178 # Freescale Extended Time Processing Unit\n    EM_SLE9X                 = 179 # Infineon Technologies SLE9X core\n    EM_L10M                  = 180 # Intel L10M\n    EM_K10M                  = 181 # Intel K10M\n    #                          182 # Reserved for future Intel use\n    EM_AARCH64               = 183 # ARM 64-bit architecture (AARCH64)\n    #                          184 # Reserved for future ARM use\n    EM_AVR32                 = 185 # Atmel Corporation 32-bit microprocessor family\n    EM_STM8                  = 186 # STMicroeletronics STM8 8-bit microcontroller\n    EM_TILE64                = 187 # Tilera TILE64 multicore architecture family\n    EM_TILEPRO               = 188 # Tilera TILEPro multicore architecture family\n    EM_MICROBLAZE            = 189 # Xilinx MicroBlaze 32-bit RISC soft processor core\n    EM_CUDA                  = 190 # NVIDIA CUDA architecture\n    EM_TILEGX                = 191 # Tilera TILE-Gx multicore architecture family\n    EM_CLOUDSHIELD           = 192 # CloudShield architecture family\n    EM_COREA_1ST             = 193 # KIPO-KAIST Core-A 1st generation processor family\n    EM_COREA_2ND             = 194 # KIPO-KAIST Core-A 2nd generation processor family\n    EM_ARCV2                 = 195 # Synopsys ARCompact V2 # codespell:ignore\n    EM_OPEN8                 = 196 # Open8 8-bit RISC soft processor core\n    EM_RL78                  = 197 # Renesas RL78 family\n    EM_VIDEOCORE5            = 198 # Broadcom VideoCore V processor\n    EM_78KOR                 = 199 # Renesas 78KOR family\n    EM_56800EX               = 200 # Freescale 56800EX Digital Signal Controller (DSC)\n    EM_BA1                   = 201 # Beyond BA1 CPU architecture\n    EM_BA2                   = 202 # Beyond BA2 CPU architecture\n    EM_XCORE                 = 203 # XMOS xCORE processor family\n    EM_MCHP_PIC              = 204 # Microchip 8-bit PIC(r) family\n    EM_INTELGT               = 205 # Intel Graphics Technology\n    EM_INTEL206              = 206 # Reserved by Intel\n    EM_INTEL207              = 207 # Reserved by Intel\n    EM_INTEL208              = 208 # Reserved by Intel\n    EM_INTEL209              = 209 # Reserved by Intel\n    EM_KM32                  = 210 # KM211 KM32 32-bit processor\n    EM_KMX32                 = 211 # KM211 KMX32 32-bit processor\n    EM_KMX16                 = 212 # KM211 KMX16 16-bit processor\n    EM_KMX8                  = 213 # KM211 KMX8 8-bit processor\n    EM_KVARC                 = 214 # KM211 KVARC processor\n    EM_CDP                   = 215 # Paneve CDP architecture family\n    EM_COGE                  = 216 # Cognitive Smart Memory Processor\n    EM_COOL                  = 217 # Bluechip Systems CoolEngine\n    EM_NORC                  = 218 # Nanoradio Optimized RISC\n    EM_CSR_KALIMBA           = 219 # CSR Kalimba architecture family\n    EM_Z80                   = 220 # Zilog Z80\n    EM_VISIUM                = 221 # Controls and Data Services VISIUMcore processor\n    EM_FT32                  = 222 # FTDI Chip FT32 high performance 32-bit RISC architecture\n    EM_MOXIE                 = 223 # Moxie processor family\n    EM_AMDGPU                = 224 # AMD GPU architecture\n    #                          225-242 # Reserved\n    EM_RISCV                 = 243 # RISC-V\n    EM_LANAI                 = 244 # Lanai 32-bit processor\n    EM_CEVA                  = 245 # CEVA Processor Architecture Family\n    EM_CEVA_X2               = 246 # CEVA X2 Processor Family\n    EM_BPF                   = 247 # Linux BPF - in-kernel virtual machine\n    EM_GRAPHCORE_IPU         = 248 # Graphcore Intelligent Processing Unit\n    EM_IMG1                  = 249 # Imagination Technologies\n    EM_NFP                   = 250 # Netronome Flow Processor\n    EM_VE                    = 251 # NEC Vector Engine\n    EM_CSKY                  = 252 # C-SKY processor family\n    EM_ARC_COMPACT3_64       = 253 # Synopsys ARCv2.3 64-bit # codespell:ignore\n    EM_MCS6502               = 254 # MOS Technology MCS 6502 processor\n    EM_ARC_COMPACT3          = 255 # Synopsys ARCv2.3 32-bit # codespell:ignore\n    EM_KVX                   = 256 # Kalray VLIW core of the MPPA processor family\n    EM_65816                 = 257 # WDC 65816/65C816\n    EM_LOONGARCH             = 258 # LoongArch\n    EM_KF32                  = 259 # ChipON KungFu32\n    EM_U16_U8CORE            = 260 # LAPIS nX-U16/U8\n    EM_TACHYUM               = 261 # Tachyum\n    EM_56800EF               = 262 # NXP 56800EF Digital Signal Controller (DSC)\n\n    EM_AVR_UNOFFICIAL        = 0x1057 # AVR (unofficial)\n    EM_MSP430_UNOFFICIAL     = 0x1059 # MSP430 (unofficial)\n    EM_EPIPHANY_UNOFFICIAL   = 0x1223 # Adapteva Epiphany (unofficial)\n    EM_AVR32_UNOFFICIAL      = 0x18ad # Atmel AVR32 (unofficial)\n    EM_MT_UNOFFICIAL         = 0x2530 # Morpho MT (unofficial)\n    EM_FR30_UNOFFICIAL       = 0x3330 # FR30 (unofficial)\n    EM_OPENRISC_OLD          = 0x3426 # OpenRISC (obsolete)\n    EM_WEBASSEMBLY           = 0x4157 # Web Assembly binaries (unofficial)\n    EM_C166_UNOFFICIAL       = 0x4688 # Infineon C166 (unofficial)\n    EM_S12Z                  = 0x4DEF # Freescale S12Z\n    EM_FRV_UNOFFICIAL        = 0x5441 # Cygnus FR-V (unofficial)\n    EM_DLX_UNOFFICIAL        = 0x5aa5 # DLX (unofficial)\n    EM_D10V_UNOFFICIAL       = 0x7650 # Cygnus D10V (unofficial)\n    EM_D30V_UNOFFICIAL       = 0x7676 # Cygnus D30V (unofficial)\n    EM_IP2K_UNOFFICIAL       = 0x8217 # Ubicom IP2xxx (unofficial)\n    EM_OPENRISC_OLD2         = 0x8472 # OpenRISC (obsolete)\n    EM_PPC_UNOFFICIAL        = 0x9025 # Cygnus PowerPC (unofficial)\n    EM_ALPHA_UNOFFICIAL      = 0x9026 # Digital Alpha (unofficial)\n    EM_M32R_UNOFFICIAL       = 0x9041 # Cygnus M32R (unofficial)\n    EM_V850_UNOFFICIAL       = 0x9080 # Cygnus V859 (unofficial)\n    EM_S390_OLD              = 0xa390 # IBM S/390 (obsolete)\n    EM_XTENSA_UNOFFICIAL     = 0xabc7 # Old Xtensa (unofficial)\n    EM_XSTORMY_UNOFFICIAL    = 0xad45 # xstormy16 (unofficial)\n    EM_MICROBLAZE_UNOFFICIAL = 0xbaab # Old MicroBlaze (unofficial)\n    EM_MN10300_UNOFFICIAL    = 0xbeef # Cygnus MN10300 (unofficial)\n    EM_MN10200_UNOFFICIAL    = 0xdead # Cygnus MN10200 (unofficial)\n    EM_MEP_UNOFFICIAL        = 0xf00d # Toshiba MeP (unofficial)\n    EM_M32C_UNOFFICIAL       = 0xfeb0 # Renesas M32C (unofficial)\n    EM_IQ2000_UNOFFICIAL     = 0xfeba # Vitesse IQ2000 (unofficial)\n    EM_NIOS_UNOFFICIAL       = 0xfebb # NIOS (unofficial)\n    EM_MOXIE_UNOFFICIAL      = 0xfeed # Moxie (unofficial)\n\n    # e_version\n    EV_NONE                  = 0\n    EV_CURRENT               = 1\n\n    # default values\n    e_magic                  = ELF_MAGIC\n    e_class                  = ELF_64_BITS\n    e_endianness             = LITTLE_ENDIAN\n    e_eiversion              = None\n    e_osabi                  = None\n    e_abiversion             = None\n    e_pad                    = None # noqa: F841\n    e_type                   = ET_EXEC\n    e_machine                = EM_X86_64\n    e_version                = None\n    e_entry                  = 0x00\n    e_phoff                  = None\n    e_shoff                  = None\n    e_flags                  = None\n    e_ehsize                 = None\n    e_phentsize              = None\n    e_phnum                  = None\n    e_shentsize              = None\n    e_shnum                  = None\n    e_shstrndx               = None\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_elf(filepath=None):\n        \"\"\"Return an Elf object with caching.\"\"\"\n        try:\n            elf = Elf(filepath)\n        except Exception:\n            elf = None\n        return elf\n\n    def __init__(self, elf=None, file_offset=0):\n        \"\"\"Instantiate an ELF object.\"\"\"\n        if elf is None:\n            elf = Path.get_filepath()\n            if elf is None:\n                self.e_magic = None\n                err(\"Could not find the path\")\n                return\n\n        if isinstance(elf, str):\n            if not os.access(elf, os.R_OK):\n                err(\"'{:s}' not found/readable\".format(elf))\n                self.e_magic = None\n                return\n            self.fd = open(elf, \"rb\")\n            self.addr = None\n            self.seek_init_offset = file_offset\n            self.pos = 0\n            self.seek(self.pos)\n            self.filename = elf\n        elif isinstance(elf, int):\n            self.fd = None\n            self.addr = elf\n            self.pos = 0\n            self.filename = None\n        else:\n            raise\n\n        # off 0x0\n        self.e_magic, self.e_class, self.e_endianness, self.e_eiversion = struct.unpack(\">IBBB\", self.read(7))\n        # adjust endianness in bin reading\n        endian = \"<\" if self.e_endianness == Elf.LITTLE_ENDIAN else \">\"\n        # off 0x7\n        self.e_osabi, self.e_abiversion = struct.unpack(\"{}BB\".format(endian), self.read(2))\n        # off 0x9\n        self.e_pad = self.read(7) # noqa\n        # off 0x10\n        self.e_type, self.e_machine, self.e_version = struct.unpack(\"{}HHI\".format(endian), self.read(8))\n        # off 0x18\n        if self.e_class == Elf.ELF_64_BITS:\n            self.e_entry, self.e_phoff, self.e_shoff = struct.unpack(\"{}QQQ\".format(endian), self.read(24))\n        else:\n            self.e_entry, self.e_phoff, self.e_shoff = struct.unpack(\"{}III\".format(endian), self.read(12))\n        self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum = struct.unpack(\"{}IHHH\".format(endian), self.read(10))\n        self.e_shentsize, self.e_shnum, self.e_shstrndx = struct.unpack(\"{}HHH\".format(endian), self.read(6))\n\n        # phdr\n        self.phdrs = []\n        for i in range(self.e_phnum):\n            phdr = Elf.Phdr(self, self.e_phoff + self.e_phentsize * i)\n            self.phdrs.append(phdr)\n\n        # shdr\n        self.shdrs = []\n        for i in range(self.e_shnum):\n            try:\n                shdr = Elf.Shdr(self, self.e_shoff + self.e_shentsize * i)\n                self.shdrs.append(shdr)\n            except gdb.MemoryError:\n                # Perspective failure. Probably it occurs when parsing ELF loaded into memory.\n                # Even if the ELF is loaded, the section header is not loaded. Therefore, it is ignored.\n                self.shdrs = []\n                break\n        else:\n            # multiple SHT_NULLs are treated as abnormal\n            if sum([x.sh_type == Elf.Shdr.SHT_NULL for x in self.shdrs]) > 1:\n                self.shdrs = []\n\n        if self.fd is not None:\n            self.fd.close()\n            self.fd = None\n\n        # It will be unusable after initialization.\n        self.read = None\n        self.seek = None\n        return\n\n    def __repr__(self):\n        if not hasattr(self, \"filename\"):\n            msg = '<{:s}.{:s} object at {:#x}, invalid>'.format(\n                self.__module__, self.__class__.__name__, id(self),\n            )\n        elif self.filename:\n            msg = '<{:s}.{:s} object at {:#x}, filename=\"{:s}\">'.format(\n                self.__module__, self.__class__.__name__, id(self), self.filename,\n            )\n        else:\n            msg = \"<{:s}.{:s} object at {:#x}, address={:#x}>\".format(\n                self.__module__, self.__class__.__name__, id(self), self.addr,\n            )\n        return msg\n\n    def read(self, size):\n        if self.fd is not None:\n            v = self.fd.read(size)\n        elif self.addr is not None:\n            v = read_memory(self.addr + self.pos, size)\n        else:\n            raise\n        self.pos += size\n        return v\n\n    def seek(self, off):\n        if self.fd is not None:\n            self.fd.seek(self.seek_init_offset + off, 0)\n        elif self.addr is not None:\n            self.pos = off\n        else:\n            raise\n        return\n\n    def is_valid(self):\n        return self.e_magic == Elf.ELF_MAGIC\n\n    def get_bits(self):\n        if self.e_class == Elf.ELF_64_BITS:\n            return 64\n        if self.e_class == Elf.ELF_32_BITS:\n            return 32\n        raise\n\n    def get_phdr(self, p_type):\n        for phdr in self.phdrs:\n            if phdr.p_type == p_type:\n                return phdr\n        return None\n\n    def get_shdr(self, name):\n        for shdr in self.shdrs:\n            if shdr.sh_name == name:\n                return shdr\n        return None\n\n    def read_phdr(self, p_type):\n        phdr = self.get_phdr(p_type)\n        if phdr is None:\n            return None\n\n        if self.filename:\n            fd = open(self.filename, \"rb\")\n            fd.seek(phdr.p_offset)\n            data = fd.read(phdr.p_filesz)\n            fd.close()\n            return data\n\n        if self.addr:\n            read_addr = phdr.p_vaddr\n            if self.is_pie():\n                read_addr += self.addr\n\n            data = read_memory(read_addr, phdr.p_memsz)\n            return data\n\n        return None\n\n    def read_shdr(self, name):\n        shdr = self.get_shdr(name)\n        if shdr is None:\n            return None\n\n        if self.filename:\n            fd = open(self.filename, \"rb\")\n            fd.seek(shdr.sh_offset)\n            data = fd.read(shdr.sh_size)\n            fd.close()\n            return data\n\n        if self.addr:\n            if shdr.sh_addr > 0:\n                read_addr = shdr.sh_addr\n            else:\n                # e.g., .comment section of vdso\n                \"\"\"\n                [ #] Name                      Type Address Offset Size EntSiz Flags Link Info Align\n                ...\n                [13] .altinstr_replacement PROGBITS  0x106f 0x106f 0x3c    0x0 AX     0x0  0x0   0x1\n                [14] .comment              PROGBITS     0x0 0x10ab 0x25    0x1 MS     0x0  0x0   0x1\n                [15] .shstrtab               STRTAB     0x0 0x10d0 0x9e    0x0        0x0  0x0   0x1\n                \"\"\"\n                read_addr = shdr.sh_offset\n\n            if self.is_pie():\n                read_addr += self.addr\n\n            data = read_memory(read_addr, shdr.sh_size)\n            return data\n\n        return None\n\n    def is_static(self):\n        # note: static-pie has no PT_INTERP\n        return not bool(self.get_phdr(Elf.Phdr.PT_INTERP))\n\n    def has_dynamic(self):\n        # note: static-pie has PT_DYNAMIC\n        return bool(self.get_phdr(Elf.Phdr.PT_DYNAMIC))\n\n    def is_stripped(self):\n        return not bool(self.get_shdr(\".symtab\"))\n\n    def has_debuginfo(self):\n        return bool(self.get_shdr(\".debug_info\"))\n\n    def has_canary_heuristic(self):\n        try:\n            objdump_command = GefUtil.which(Config.get_gef_setting(\"gef.objdump_command\"))\n        except FileNotFoundError:\n            return None # it means unknown\n\n        # heuristic search\n        if self.e_machine in (Elf.EM_X86_64, Elf.EM_386):\n            if self.e_machine == Elf.EM_X86_64:\n                kw = b\"%fs:0x28\"\n            else: # 32-bit\n                kw = b\"%gs:0x14\"\n\n            proc = subprocess.Popen(\n                [objdump_command, \"-d\", self.filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n            )\n            for _ in range(0x10000):\n                if kw in proc.stdout.readline():\n                    proc.kill()\n                    return True\n            proc.kill()\n            return False\n        return None # it means unknown\n\n    def is_pie(self):\n        return self.e_type == Elf.ET_DYN\n\n    def is_nx(self):\n        phdr = self.get_phdr(Elf.Phdr.PT_GNU_STACK)\n        if phdr:\n            return not bool(phdr.p_flags & Elf.Phdr.PF_X)\n        return False\n\n    def is_relro(self):\n        # both partial and full have PT_GNU_RELRO\n        return bool(self.get_phdr(Elf.Phdr.PT_GNU_RELRO))\n\n    def get_dynamic_data(self):\n        # find dynamic\n        phdr = self.get_phdr(Elf.Phdr.PT_DYNAMIC)\n        if phdr is None:\n            return None\n\n        # read dynamic\n        fd = open(self.filename, \"rb\")\n        fd.seek(phdr.p_offset)\n        data = fd.read(phdr.p_filesz)\n        fd.close()\n\n        # unpack\n        data = slice_unpack(data, self.get_bits() // 8)\n        return data\n\n    def is_full_relro(self):\n        data = self.get_dynamic_data()\n        if data is None:\n            return False\n\n        # check\n        for tag, value in slicer(data, 2):\n            if tag == 0x18: # DT_BIND_NOW\n                return True\n            if tag == 0x1e: # DT_FLAGS\n                return bool(value & 0x08) # DF_BIND_NOW\n        return False\n\n    def has_rpath(self):\n        data = self.get_dynamic_data()\n        if data is None:\n            return False\n\n        for tag, _ in slicer(data, 2):\n            if tag == 0xf: # DT_RPATH\n                return True\n        return False\n\n    def has_runpath(self):\n        data = self.get_dynamic_data()\n        if data is None:\n            return False\n\n        for tag, _ in slicer(data, 2):\n            if tag == 0x1d: # DT_RUNPATH\n                return True\n        return False\n\n    def has_pac_heuristic(self):\n        pac_ops = [\n            b\"paciasp\", b\"pacia\", b\"pacibsp\", b\"pacib\", b\"pacda\", b\"pacdb\", b\"pacga\",\n            b\"autiasp\", b\"autia\", b\"autibsp\", b\"autib\", b\"autda\", b\"autdb\",\n            b\"retaa\", b\"retab\", b\"braa\", b\"brab\", b\"blraa\", b\"blrab\",\n            b\"eretaa\", b\"eretab\", b\"ldraa\", b\"ldrab\"\n        ]\n\n        try:\n            objdump_command = GefUtil.which(Config.get_gef_setting(\"gef.objdump_command\"))\n        except FileNotFoundError:\n            return None # it means unknown\n\n        proc = subprocess.Popen(\n            [objdump_command, \"-d\", self.filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n        )\n        for _ in range(0x10000):\n            line = proc.stdout.readline().strip()\n            if not line:\n                continue\n            if line.split()[-1] in pac_ops:\n                proc.kill()\n                return True\n        proc.kill()\n        return False\n\n    def checksec(self):\n        \"\"\"Check the following security properties of the ELF binary.\n        Canary, NX, PIE, RELRO, Fortify, Static, Symbol, Debuginfo, CET,\n        RPATH/RUNPATH, and Clang CFI/SafeStack.\"\"\"\n\n        def exists_sym(dynstr, strtab, keywords):\n            if dynstr:\n                for kw in keywords:\n                    if kw in dynstr:\n                        return True\n            if strtab:\n                for kw in keywords:\n                    if kw in strtab:\n                        return True\n            return False\n\n        def get_features_from_note(note):\n            note = note[0x10:] # skip header\n            while note:\n                pr_type, note = u32(note[:4]), note[4:]\n                pr_datasz, note = u32(note[:4]), note[4:]\n                pr_data, note = note[:pr_datasz], note[pr_datasz:]\n\n                if pr_type == 0xc000_0002: # GNU_PROPERTY_X86_FEATURE_1_AND\n                    if pr_datasz == 4:\n                        return u32(pr_data)\n\n                pr_padding = 0\n                while (pr_datasz + pr_padding) % current_arch.ptrsize:\n                    pr_padding += 1\n                note = note[pr_padding:]\n            return 0\n\n        dynstr = self.read_shdr(\".dynstr\")\n        if dynstr:\n            dynstr = dynstr.split(b\"\\0\")\n        strtab = self.read_shdr(\".strtab\")\n        if strtab:\n            strtab = strtab.split(b\"\\0\")\n\n        sec = {}\n\n        # Static\n        sec[\"Static\"] = self.is_static()\n\n        # Symbol\n        sec[\"Symbol\"] = not self.is_stripped()\n\n        # Debuginfo\n        sec[\"Debuginfo\"] = self.has_debuginfo()\n\n        # Canary\n        if self.is_static() and self.is_stripped():\n            sec[\"Canary\"] = self.has_canary_heuristic()\n        else:\n            keywords = [\n                b\"__stack_chk_fail\",\n                b\"__stack_chk_fail_local\",\n                b\"__stack_chk_guard\", # for non-x86\n                b\"__intel_security_cookie\", # for intel compiler\n            ]\n            sec[\"Canary\"] = exists_sym(dynstr, strtab, keywords)\n\n        # NX\n        sec[\"NX\"] = self.is_nx()\n\n        # PIE\n        sec[\"PIE\"] = self.is_pie()\n\n        # RELRO\n        sec[\"Partial RELRO\"] = self.is_relro()\n        sec[\"Full RELRO\"] = sec[\"Partial RELRO\"] and self.is_full_relro()\n\n        # Fortify\n        if self.is_static() and self.is_stripped():\n            sec[\"Fortify\"] = None # it means unknown\n        else:\n            keywords = [\n                b\"__memcpy_chk\",\n                b\"__memmove_chk\",\n                b\"__mempcpy_chk\",\n                b\"__memset_chk\",\n                b\"__printf_chk\",\n                b\"__fprintf_chk\",\n                b\"__dprintf_chk\",\n                b\"__sprintf_chk\",\n                b\"__asprintf_chk\",\n                b\"__snprintf_chk\",\n                b\"__wprintf_chk\",\n                b\"__fwprintf_chk\",\n                b\"__swprintf_chk\",\n                b\"__obstack_printf_chk\",\n                b\"__vprintf_chk\",\n                b\"__vfprintf_chk\",\n                b\"__vdprintf_chk\",\n                b\"__vsprintf_chk\",\n                b\"__vasprintf_chk\",\n                b\"__vsnprintf_chk\",\n                b\"__vwprintf_chk\",\n                b\"__vfwprintf_chk\",\n                b\"__vswprintf_chk\",\n                b\"__obstack_vprintf_chk\",\n                b\"__syslog_chk\",\n                b\"__vsyslog_chk\",\n            ]\n            sec[\"Fortify\"] = exists_sym(dynstr, strtab, keywords)\n\n        # CET flags via Ehdr\n        if self.e_machine in (Elf.EM_X86_64, Elf.EM_386):\n            sec[\"CET IBT flag\"] = False\n            sec[\"CET SHSTK flag\"] = False\n            note_gnu_property = self.read_phdr(Elf.Phdr.PT_GNU_PROPERTY)\n            if note_gnu_property:\n                features = get_features_from_note(note_gnu_property)\n                sec[\"CET IBT flag\"] = features & 1 # GNU_PROPERTY_X86_FEATURE_1_IBT\n                sec[\"CET SHSTK flag\"] = features & 2 # GNU_PROPERTY_X86_FEATURE_1_SHSTK\n\n        # PAC\n        if self.e_machine == Elf.EM_AARCH64:\n            sec[\"PAC\"] = self.has_pac_heuristic()\n\n        # RPATH\n        sec[\"RPATH\"] = self.has_rpath()\n\n        # RUNPATH\n        sec[\"RUNPATH\"] = self.has_runpath()\n\n        # Clang CFI (detected only when `-fno-sanitize-trap=all`)\n        if self.is_static() and self.is_stripped():\n            sec[\"Clang CFI\"] = None\n        else:\n            sec[\"Clang CFI\"] = exists_sym(dynstr, strtab, [\"__ubsan_handle_cfi_\"])\n\n        # Clang SafeStack\n        if self.is_static() and self.is_stripped():\n            sec[\"Clang SafeStack\"] = None\n        else:\n            sec[\"Clang SafeStack\"] = exists_sym(dynstr, strtab, [\"__safestack_init\"])\n        return sec\n\n    class Phdr:\n        # p_type\n        PT_NULL               = 0\n        PT_LOAD               = 1\n        PT_DYNAMIC            = 2\n        PT_INTERP             = 3\n        PT_NOTE               = 4\n        PT_SHLIB              = 5\n        PT_PHDR               = 6\n        PT_TLS                = 7\n        #PT_LOOS              = 0x6000_0000\n        PT_GNU_EH_FRAME       = 0x6474_e550\n        PT_GNU_STACK          = 0x6474_e551\n        PT_GNU_RELRO          = 0x6474_e552\n        PT_GNU_PROPERTY       = 0x6474_e553\n        PT_GNU_SFRAME         = 0x6474_e554\n        #PT_GNU_MBIND_LO      = 0x6474_e555\n        #PT_GNU_MBIND_HI      = 0x6474_f554\n        #PT_LOSUNW            = 0x6fff_fffa\n        PT_SUNWBSS            = 0x6fff_fffa\n        PT_SUNWSTACK          = 0x6fff_fffb\n        #PT_HISUNW            = 0x6fff_ffff\n        #PT_HIOS              = 0x6fff_ffff\n        #PT_LOPROC            = 0x7000_0000\n        #PT_HIPROC            = 0x7fff_ffff\n        PT_AARCH64_ARCHEXT    = 0x7000_0000 # noqa: F841\n        PT_AARCH64_MEMTAG_MTE = 0x7000_0002 # noqa: F841\n        PT_ARM_ARCHEXT        = 0x7000_0000 # noqa: F841\n        PT_ARM_EXIDX          = 0x7000_0001 # noqa: F841\n        PT_HP_TLS             = 0x6000_0000 # noqa: F841\n        PT_HP_CORE_NONE       = 0x6000_0001 # noqa: F841\n        PT_HP_CORE_VERSION    = 0x6000_0002 # noqa: F841\n        PT_HP_CORE_KERNEL     = 0x6000_0003 # noqa: F841\n        PT_HP_CORE_COMM       = 0x6000_0004 # noqa: F841\n        PT_HP_CORE_PROC       = 0x6000_0005 # noqa: F841\n        PT_HP_CORE_LOADABLE   = 0x6000_0006 # noqa: F841\n        PT_HP_CORE_STACK      = 0x6000_0007 # noqa: F841\n        PT_HP_CORE_SHM        = 0x6000_0008 # noqa: F841\n        PT_HP_CORE_MMF        = 0x6000_0009 # noqa: F841\n        PT_HP_PARALLEL        = 0x6000_0010 # noqa: F841\n        PT_HP_FASTBIND        = 0x6000_0011 # noqa: F841\n        PT_HP_OPT_ANNOT       = 0x6000_0012 # noqa: F841\n        PT_HP_HSL_ANNOT       = 0x6000_0013 # noqa: F841\n        PT_HP_STACK           = 0x6000_0014 # noqa: F841\n        PT_HP_CORE_UTSNAME    = 0x6000_0015 # noqa: F841\n        PT_IA_64_HP_OPT_ANOT  = 0x6000_0012 # noqa: F841\n        PT_IA_64_HP_HSL_ANOT  = 0x6000_0013 # noqa: F841\n        PT_IA_64_HP_STACK     = 0x6000_0014 # noqa: F841\n        PT_IA_64_ARCHEXT      = 0x7000_0000 # noqa: F841\n        PT_IA_64_UNWIND       = 0x7000_0001 # noqa: F841\n        PT_MIPS_REGINFO       = 0x7000_0000 # noqa: F841\n        PT_MIPS_RTPROC        = 0x7000_0001 # noqa: F841\n        PT_MIPS_OPTIONS       = 0x7000_0002 # noqa: F841\n        PT_MIPS_ABIFLAGS      = 0x7000_0003 # noqa: F841\n        PT_PARISC_ARCHEXT     = 0x7000_0000 # noqa: F841\n        PT_PARISC_UNWIND      = 0x7000_0001 # noqa: F841\n        PT_PARISC_WEAKORDER   = 0x7000_0002 # noqa: F841\n        PT_RISCV_ATTRIBUTES   = 0x7000_0003 # noqa: F841\n        PT_S390_PGSTE         = 0x7000_0000 # noqa: F841\n\n        # p_flags\n        PF_X                = 1\n        PF_W                = 2\n        PF_R                = 4\n        PF_ARM_SB           = 0x1000_0000 # noqa: F841\n        PF_ARM_PI           = 0x2000_0000 # noqa: F841\n        PF_ARM_ABS          = 0x4000_0000 # noqa: F841\n        PF_HP_CODE          = 0x0004_0000 # noqa: F841\n        PF_HP_MODIFY        = 0x0008_0000 # noqa: F841\n        PF_HP_PAGE_SIZE     = 0x0010_0000 # noqa: F841\n        PF_HP_FAR_SHARED    = 0x0020_0000 # noqa: F841\n        PF_HP_NEAR_SHARED   = 0x0040_0000 # noqa: F841\n        PF_HP_LAZYSWAP      = 0x0080_0000 # noqa: F841\n        PF_HP_CODE_DEPR     = 0x0100_0000 # noqa: F841\n        PF_HP_MODIFY_DEPR   = 0x0200_0000 # noqa: F841\n        PF_HP_LAZYSWAP_DEPR = 0x0400_0000 # noqa: F841\n        PF_HP_SBP           = 0x0800_0000 # noqa: F841\n        PF_IA_64_NORECOV    = 0x8000_0000 # noqa: F841\n        PF_OVERRAY          = 0x0800_0000 # noqa: F841\n        PF_PARISC_SBP       = 0x0800_0000 # noqa: F841\n\n        p_type   = None\n        p_flags  = None\n        p_offset = None\n        p_vaddr  = None\n        p_paddr  = None\n        p_filesz = None\n        p_memsz  = None\n        p_align  = None\n\n        def __init__(self, elf, off):\n            if elf is None:\n                return None\n            elf.seek(off)\n            endian = \"<\" if elf.e_endianness == Elf.LITTLE_ENDIAN else \">\"\n            if elf.e_class == Elf.ELF_64_BITS:\n                self.p_type, self.p_flags, self.p_offset = struct.unpack(\"{}IIQ\".format(endian), elf.read(16))\n                self.p_vaddr, self.p_paddr = struct.unpack(\"{}QQ\".format(endian), elf.read(16))\n                self.p_filesz, self.p_memsz, self.p_align = struct.unpack(\"{}QQQ\".format(endian), elf.read(24))\n            else:\n                self.p_type, self.p_offset = struct.unpack(\"{}II\".format(endian), elf.read(8))\n                self.p_vaddr, self.p_paddr = struct.unpack(\"{}II\".format(endian), elf.read(8))\n                self.p_filesz, self.p_memsz, = struct.unpack(\"{}II\".format(endian), elf.read(8))\n                self.p_flags, self.p_align = struct.unpack(\"{}II\".format(endian), elf.read(8))\n\n        def __repr__(self):\n            for e in dir(self):\n                if e.startswith(\"PT_\"):\n                    if self.p_type == getattr(self, e):\n                        return \"<{:s}.{:s} object at {:#x}, p_type={:s}>\".format(\n                            self.__module__, self.__class__.__name__, id(self), e,\n                        )\n            return \"<{:s}.{:s} object at {:#x}, p_type={:#x}>\".format(\n                self.__module__, self.__class__.__name__, id(self), self.p_type,\n            )\n\n    class Shdr:\n        # sh_type\n        SHT_NULL                           = 0\n        SHT_PROGBITS                       = 1\n        SHT_SYMTAB                         = 2\n        SHT_STRTAB                         = 3\n        SHT_RELA                           = 4\n        SHT_HASH                           = 5\n        SHT_DYNAMIC                        = 6\n        SHT_NOTE                           = 7\n        SHT_NOBITS                         = 8\n        SHT_REL                            = 9\n        SHT_SHLIB                          = 10\n        SHT_DYNSYM                         = 11\n        SHT_INIT_ARRAY                     = 14\n        SHT_FINI_ARRAY                     = 15\n        SHT_PREINIT_ARRAY                  = 16\n        SHT_GROUP                          = 17\n        SHT_SYMTAB_SHNDX                   = 18\n        SHT_RELR                           = 19\n        #SHT_LOOS                          = 0x6000_0000\n        SHT_ANDROID_REL                    = 0x6000_0001\n        SHT_ANDROID_RELA                   = 0x6000_0002\n        SHT_HP_OVLBITS                     = 0x6000_0000 # noqa: F841\n        SHT_HP_DLKM                        = 0x6000_0001 # noqa: F841\n        SHT_HP_COMDAT                      = 0x6000_0002 # noqa: F841\n        SHT_HP_OBJDICT                     = 0x6000_0003 # noqa: F841\n        SHT_HP_ANNOT                       = 0x6000_0004 # noqa: F841\n        SHT_IA_64_VMS_TRACE                = 0x6000_0000 # noqa: F841\n        SHT_IA_64_VMS_TIE_SIGNATURES       = 0x6000_0001 # noqa: F841\n        SHT_IA_64_VMS_DEBUG                = 0x6000_0002 # noqa: F841\n        SHT_IA_64_VMS_DEBUG_STR            = 0x6000_0003 # noqa: F841\n        SHT_IA_64_VMS_LINKAGES             = 0x6000_0004 # noqa: F841\n        SHT_IA_64_VMS_SYMBOL_VECTOR        = 0x6000_0005 # noqa: F841\n        SHT_IA_64_VMS_FIXUP                = 0x6000_0006 # noqa: F841\n        SHT_IA_64_VMS_DISPLAY_NAME_INFO    = 0x6000_0007 # noqa: F841\n        SHT_GNU_INCREMENTAL_INPUTS         = 0x6fff_4700\n        SHT_LLVM_ODRTAB                    = 0x6fff_4c00\n        SHT_LLVM_LINKER_OPTIONS            = 0x6fff_4c01\n        SHT_LLVM_CALL_GRAPH_PROFILE        = 0x6fff_4c02\n        SHT_LLVM_ADDRSIG                   = 0x6fff_4c03\n        SHT_LLVM_DEPENDENT_LIBRARIES       = 0x6fff_4c04\n        SHT_LLVM_SYMPART                   = 0x6fff_4c05\n        SHT_LLVM_PART_EHDR                 = 0x6fff_4c06\n        SHT_LLVM_PART_PHDR                 = 0x6fff_4c07\n        SHT_LLVM_BB_ADDR_MAP_V0            = 0x6fff_4c08\n        SHT_LLVM_CALL_GRAPH_PROFILE        = 0x6fff_4c09\n        SHT_LLVM_BB_ADDR_MAP               = 0x6fff_4c0a\n        SHT_LLVM_OFFLOADING                = 0x6fff_4c0b\n        SHT_LLVM_LTO                       = 0x6fff_4c0c\n        SHT_ANDROID_RELR                   = 0x6fff_ff00\n        SHT_GNU_ATTRIBUTES                 = 0x6fff_fff5\n        SHT_GNU_HASH                       = 0x6fff_fff6\n        SHT_GNU_LIBLIST                    = 0x6fff_fff7\n        SHT_CHECKSUM                       = 0x6fff_fff8\n        #SHT_LOSUNW                        = 0x6fff_fffa\n        SHT_SUNW_move                      = 0x6fff_fffa\n        SHT_SUNW_COMDAT                    = 0x6fff_fffb\n        SHT_SUNW_syminfo                   = 0x6fff_fffc\n        SHT_GNU_verdef                     = 0x6fff_fffd\n        SHT_GNU_verneed                    = 0x6fff_fffe\n        SHT_GNU_versym                     = 0x6fff_ffff\n        #SHT_HISUNW                        = 0x6fff_ffff\n        #SHT_HIOS                          = 0x6fff_ffff\n        #SHT_LOPROC                        = 0x7000_0000\n        SHT_AARCH64_ATTRIBUTES             = 0x7000_0003 # noqa: F841\n        SHT_AARCH64_AUTH_RELR              = 0x7000_0004 # noqa: F841\n        SHT_AARCH64_MEMTAG_GLOBALS_STATIC  = 0x7000_0007 # noqa: F841\n        SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC = 0x7000_0008 # noqa: F841\n        SHT_ALPHA_DEBUG                    = 0x7000_0001 # noqa: F841\n        SHT_ALPHA_REGINFO                  = 0x7000_0002 # noqa: F841\n        SHT_ARC_ATTRIBUTES                 = 0x7000_0001 # noqa: F841\n        SHT_ARM_EXIDX                      = 0x7000_0001 # noqa: F841\n        SHT_ARM_PREEMPTMAP                 = 0x7000_0002 # noqa: F841\n        SHT_ARM_ATTRIBUTES                 = 0x7000_0003 # noqa: F841\n        SHT_ARM_DEBUGOVERLAY               = 0x7000_0004 # noqa: F841\n        SHT_ARM_OVERLAYSECTION             = 0x7000_0005 # noqa: F841\n        SHT_C6000_UNWIND                   = 0x7000_0001 # noqa: F841\n        SHT_C6000_PREEMPTMAP               = 0x7000_0002 # noqa: F841\n        SHT_C6000_ATTRIBUTES               = 0x7000_0003 # noqa: F841\n        SHT_CSKY_ATTRIBUTES                = 0x7000_0001 # noqa: F841\n        SHT_IA_64_EXT                      = 0x7000_0000 # noqa: F841\n        SHT_IA_64_UNWIND                   = 0x7000_0001 # noqa: F841\n        SHT_IA_64_LOPSREG                  = 0x7800_0000 # noqa: F841\n        SHT_IA_64_HIPSREG                  = 0x78ff_ffff # noqa: F841\n        SHT_IA_64_PRIORITY_INIT            = 0x7900_0000 # noqa: F841\n        SHT_MIPS_LIBLIST                   = 0x7000_0000 # noqa: F841\n        SHT_MIPS_MSYM                      = 0x7000_0001 # noqa: F841\n        SHT_MIPS_CONFLICT                  = 0x7000_0002 # noqa: F841\n        SHT_MIPS_GPTAB                     = 0x7000_0003 # noqa: F841\n        SHT_MIPS_UCODE                     = 0x7000_0004 # noqa: F841\n        SHT_MIPS_DEBUG                     = 0x7000_0005 # noqa: F841\n        SHT_MIPS_REGINFO                   = 0x7000_0006 # noqa: F841\n        SHT_MIPS_PACKAGE                   = 0x7000_0007 # noqa: F841\n        SHT_MIPS_PACKSYM                   = 0x7000_0008 # noqa: F841\n        SHT_MIPS_RELD                      = 0x7000_0009 # noqa: F841\n        SHT_MIPS_IFACE                     = 0x7000_000b # noqa: F841\n        SHT_MIPS_CONTENT                   = 0x7000_000c # noqa: F841\n        SHT_MIPS_OPTIONS                   = 0x7000_000d # noqa: F841\n        SHT_MIPS_SHDR                      = 0x7000_0010 # noqa: F841\n        SHT_MIPS_FDESC                     = 0x7000_0011 # noqa: F841\n        SHT_MIPS_EXTSYM                    = 0x7000_0012 # noqa: F841\n        SHT_MIPS_DENSE                     = 0x7000_0013 # noqa: F841\n        SHT_MIPS_PDESC                     = 0x7000_0014 # noqa: F841\n        SHT_MIPS_LOCSYM                    = 0x7000_0015 # noqa: F841\n        SHT_MIPS_AUXSYM                    = 0x7000_0016 # noqa: F841\n        SHT_MIPS_OPTSYM                    = 0x7000_0017 # noqa: F841\n        SHT_MIPS_LOCSTR                    = 0x7000_0018 # noqa: F841\n        SHT_MIPS_LINE                      = 0x7000_0019 # noqa: F841\n        SHT_MIPS_RFDESC                    = 0x7000_001a # noqa: F841\n        SHT_MIPS_DELTASYM                  = 0x7000_001b # noqa: F841\n        SHT_MIPS_DELTAINST                 = 0x7000_001c # noqa: F841\n        SHT_MIPS_DELTACLASS                = 0x7000_001d # noqa: F841\n        SHT_MIPS_DWARF                     = 0x7000_001e # noqa: F841\n        SHT_MIPS_DELTADECL                 = 0x7000_001f # noqa: F841\n        SHT_MIPS_SYMBOL_LIB                = 0x7000_0020 # noqa: F841\n        SHT_MIPS_EVENTS                    = 0x7000_0021 # noqa: F841\n        SHT_MIPS_TRANSLATE                 = 0x7000_0022 # noqa: F841\n        SHT_MIPS_PIXIE                     = 0x7000_0023 # noqa: F841\n        SHT_MIPS_XLATE                     = 0x7000_0024 # noqa: F841\n        SHT_MIPS_XLATE_DEBUG               = 0x7000_0025 # noqa: F841\n        SHT_MIPS_WHIRL                     = 0x7000_0026 # noqa: F841\n        SHT_MIPS_EH_REGION                 = 0x7000_0027 # noqa: F841\n        SHT_MIPS_XLATE_OLD                 = 0x7000_0028 # noqa: F841\n        SHT_MIPS_PDR_EXCEPTION             = 0x7000_0029 # noqa: F841\n        SHT_MIPS_ABIFLAGS                  = 0x7000_002a # noqa: F841\n        SHT_MIPS_XHASH                     = 0x7000_002b # noqa: F841\n        SHT_MSP430_ATTRIBUTES              = 0x7000_0003 # noqa: F841\n        SHT_MSP430_SEC_FLAGS               = 0x7000_0005 # noqa: F841\n        SHT_MSP430_SYM_ALIASES             = 0x7000_0006 # noqa: F841\n        SHT_NFP_MECONFIG                   = 0x7000_0001 # noqa: F841\n        SHT_NFP_INITREG                    = 0x7000_0002 # noqa: F841\n        SHT_PARISC_EXT                     = 0x7000_0000 # noqa: F841\n        SHT_PARISC_UNWIND                  = 0x7000_0001 # noqa: F841\n        SHT_PARISC_DOC                     = 0x7000_0002 # noqa: F841\n        SHT_PARISC_ANNOT                   = 0x7000_0003 # noqa: F841\n        SHT_PARISC_DLKM                    = 0x7000_0004 # noqa: F841\n        SHT_PARISC_SYMEXTN                 = 0x7000_0008 # noqa: F841\n        SHT_PARISC_STUBS                   = 0x7000_0009 # noqa: F841\n        SHT_RISCV_ATTRIBUTES               = 0x7000_0003 # noqa: F841\n        SHT_V850_SCOMMON                   = 0x7000_0000 # noqa: F841\n        SHT_V850_TCOMMON                   = 0x7000_0001 # noqa: F841\n        SHT_V850_ZCOMMON                   = 0x7000_0002 # noqa: F841\n        SHT_X86_64_UNWIND                  = 0x7000_0001 # noqa: F841\n        SHT_TI_ICODE                       = 0x7F00_0000 # noqa: F841\n        SHT_TI_XREF                        = 0x7F00_0001 # noqa: F841\n        SHT_TI_HANDLER                     = 0x7F00_0002 # noqa: F841\n        SHT_TI_INITINFO                    = 0x7F00_0003 # noqa: F841\n        SHT_TI_PHATTRS                     = 0x7F00_0004 # noqa: F841\n        SHT_ORDERED                        = 0x7fff_ffff # noqa: F841\n        #SHT_HIPROC                        = 0x7fff_ffff\n        #SHT_LOUSER                        = 0x8000_0000\n        SHT_NFP_UDEBUG                     = 0x8000_0000 # noqa: F841\n        SHT_RENESAS_IOP                    = 0x8000_0000 # noqa: F841\n        #SHT_HIUSER                        = 0x8fff_ffff\n        SHT_RENESAS_INFO                   = 0xa000_0000 # noqa: F841\n\n        # sh_flags\n        SHF_WRITE            = 1\n        SHF_ALLOC            = 2\n        SHF_EXECINSTR        = 4\n        SHF_MERGE            = 0x10\n        SHF_STRINGS          = 0x20\n        SHF_INFO_LINK        = 0x40\n        SHF_LINK_ORDER       = 0x80\n        SHF_OS_NONCONFORMING = 0x100\n        SHF_GROUP            = 0x200\n        SHF_TLS              = 0x400\n        SHF_COMPRESSED       = 0x800\n        SHF_RELA_LIVEPATCH   = 0x0010_0000 # noqa: F841\n        SHF_RO_AFTER_INIT    = 0x0020_0000 # noqa: F841\n        SHF_ORDERED          = 0x4000_0000 # noqa: F841\n        SHF_EXCLUDE          = 0x8000_0000\n        SHF_MIPS_NODUPES     = 0x0100_0000 # noqa: F841\n        SHF_MIPS_NAMES       = 0x0200_0000 # noqa: F841\n        SHF_MIPS_LOCAL       = 0x0400_0000 # noqa: F841\n        SHF_MIPS_NOSTRIP     = 0x0800_0000 # noqa: F841\n        SHF_MIPS_GPREL       = 0x1000_0000 # noqa: F841\n        SHF_MIPS_MERGE       = 0x2000_0000 # noqa: F841\n        SHF_MIPS_ADDR        = 0x4000_0000 # noqa: F841\n        SHF_MIPS_STRING      = 0x8000_0000 # noqa: F841\n        SHF_PARISC_SHORT     = 0x2000_0000 # noqa: F841\n        SHF_PARISC_HUGE      = 0x4000_0000 # noqa: F841\n        SHF_PARISC_SBP       = 0x8000_0000 # noqa: F841\n        SHF_ALPHA_GPREL      = 0x1000_0000 # noqa: F841\n        SHF_IA_64_SHORT      = 0x1000_0000 # noqa: F841\n\n        sh_name              = None\n        sh_type              = None\n        sh_flags             = None\n        sh_addr              = None\n        sh_offset            = None\n        sh_size              = None\n        sh_link              = None\n        sh_info              = None\n        sh_addralign         = None\n        sh_entsize           = None\n\n        def __init__(self, elf, off):\n            if elf is None:\n                return None\n            elf.seek(off)\n            endian = \"<\" if elf.e_endianness == Elf.LITTLE_ENDIAN else \">\"\n            if elf.e_class == Elf.ELF_64_BITS:\n                self.sh_name, self.sh_type, self.sh_flags = struct.unpack(\"{}IIQ\".format(endian), elf.read(16))\n                self.sh_addr, self.sh_offset = struct.unpack(\"{}QQ\".format(endian), elf.read(16))\n                self.sh_size, self.sh_link, self.sh_info = struct.unpack(\"{}QII\".format(endian), elf.read(16))\n                self.sh_addralign, self.sh_entsize = struct.unpack(\"{}QQ\".format(endian), elf.read(16))\n            else:\n                self.sh_name, self.sh_type, self.sh_flags = struct.unpack(\"{}III\".format(endian), elf.read(12))\n                self.sh_addr, self.sh_offset = struct.unpack(\"{}II\".format(endian), elf.read(8))\n                self.sh_size, self.sh_link, self.sh_info = struct.unpack(\"{}III\".format(endian), elf.read(12))\n                self.sh_addralign, self.sh_entsize = struct.unpack(\"{}II\".format(endian), elf.read(8))\n\n            # name\n            stroff = elf.e_shoff + elf.e_shentsize * elf.e_shstrndx\n\n            if elf.e_class == Elf.ELF_64_BITS:\n                elf.seek(stroff + 16 + 8)\n                offset = struct.unpack(\"{}Q\".format(endian), elf.read(8))[0]\n            else:\n                elf.seek(stroff + 12 + 4)\n                offset = struct.unpack(\"{}I\".format(endian), elf.read(4))[0]\n            elf.seek(offset + self.sh_name)\n            self.sh_name = \"\"\n            while True:\n                c = ord(elf.read(1))\n                if c == 0:\n                    break\n                self.sh_name += chr(c)\n            return\n\n        def __repr__(self):\n            return '<{:s}.{:s} object at {:#x}, sh_name=\"{:s}\">'.format(\n                self.__module__, self.__class__.__name__, id(self), self.sh_name,\n            )\n\n\nclass Instruction:\n    \"\"\"GEF representation of a CPU instruction.\"\"\"\n\n    RE_SPLIT_LAST_OPERAND_X86_64 = re.compile(r\"(.*?)\\s+(#.+)$\")\n    RE_SPLIT_LAST_OPERAND_ARM64 = re.compile(r\"//.+$\")\n    RE_SPLIT_LAST_OPERAND_ARM32 = re.compile(r\";.+$\")\n    RE_SPLIT_LAST_OPERAND_MICROBLAZE = re.compile(r\"//.+$\")\n    RE_SPLIT_LAST_OPERAND_LOONGARCH64 = re.compile(r\"(# .*)$\")\n    RE_SPLIT_ELEM = re.compile(r\"([*%\\[\\](): ]|(?<![#@%])(?<=.)[-+]|<.+>)\")\n    RE_IS_DIGIT_COMMENT = re.compile(r\"#?-?(0x[0-9a-f]+|\\d+)\")\n    RE_SPLIT_SYMBOL = re.compile(r\"(.*?)<(.+)>(.*)$\")\n    RE_SPLIT_SYMBOL_OFFSET = re.compile(r\"(.+)\\+(\\d+)$\")\n\n    def __init__(self, address, mnemo, operands, opcodes):\n        # example:\n        #   address: 0x55555555a7d0\n        #   mnemo: \"lea\"\n        #   operands: \"rcx, [rip+0x11ee5]        # 0x55555556c69a\"\n        #     -> [\"rcx\", \"[rip+0x11ee5]        # 0x55555556c69a\"]\n        #   opcodes: b'H\\x8d\\r\\xe5\\x1e\\x01\\x00'\n        self.address = address\n        self.mnemonic = mnemo\n\n        # merge symbol includes \",\"; e.g., <... , ...>\n        operands = [x.strip() for x in operands.split(\",\")]\n        if len(operands) > 1:\n            operands, o = operands[:-1], operands[-1]\n            while (o.count(\"<\") - o.count(\"operator<<\") * 2) != (o.count(\">\") - o.count(\"operator>>\") * 2):\n                # The split location is incorrect, so fix it.\n                # This is because there are cases where symbols contain `,`, such as C++ binaries.\n                if len(operands) > 1:\n                    operands, oo = operands[:-1], operands[-1]\n                    o = oo + \", \" + o\n                else:\n                    o = operands[0] + \", \" + o\n                    operands = []\n                    break\n            operands += [o]\n\n        self.operands = operands\n        self.opcodes = opcodes\n        self.size = len(opcodes)\n        return\n\n    @property\n    def location(self):\n        if hasattr(self, \"__location\"):\n            return self.__location\n        # evaluate when needed\n        self.__location = Symbol.get_symbol_string(self.address, nosymbol_string=\" <NO_SYMBOL>\")\n        return self.__location\n\n    @property\n    def is_branch(self):\n        \"\"\"Return whether it is a branch instruction. Cache the results.\"\"\"\n        if hasattr(self, \"__is_branch\"):\n            return self.__is_branch\n\n        if current_arch.is_syscall(self):\n            self.__is_branch = True\n        elif current_arch.is_call(self):\n            self.__is_branch = True\n        elif current_arch.is_jump(self):\n            self.__is_branch = True\n        elif current_arch.is_ret(self):\n            self.__is_branch = True\n        elif current_arch.is_conditional_branch(self):\n            self.__is_branch = True\n        else:\n            self.__is_branch = False\n        return self.__is_branch\n\n    def get_color(self, highlight, config_name):\n        \"\"\"A wrapper to easily retrieve color-related configurations.\"\"\"\n        if highlight:\n            return Config.get_gef_setting(config_name + \"_highlight\")\n        else:\n            return Config.get_gef_setting(config_name)\n\n    def get_string_if_valid_addr(self, operands):\n        \"\"\"If the last operand is an address and is valid, read and return the string.\"\"\"\n        if not operands:\n            return None\n        last_operand = operands[-1]\n        if \" \" in last_operand:\n            last_operand = last_operand.split()[-1]\n        if len(last_operand) < 10: # len(\"0xXXXXXXXX\") or len(\"0xXXXXXXXXXXXXXXXX\")\n            return None\n        try:\n            v = int(last_operand, 0)\n        except ValueError:\n            return None\n        if not is_valid_addr(v):\n            return None\n        s = read_cstring_from_memory(v)\n        return s\n\n    def split_last_operands(self, operands):\n        \"\"\"Separate `operands` into real operands and comment for each architecture.\"\"\"\n        if len(operands) == 0:\n            return [], \"\"\n\n        comment = \"\"\n        last_operand = operands[-1]\n        if is_x86_64():\n            r = self.RE_SPLIT_LAST_OPERAND_X86_64.match(last_operand) # r\"(.*?)\\s+(#.+)$\"\n            if r:\n                last_operand = r.group(1)\n                comment = r.group(2)\n                operands = operands[:-1] + [last_operand]\n        elif is_arm64():\n            r = self.RE_SPLIT_LAST_OPERAND_ARM64.match(last_operand) # r\"//.+$\"\n            if r:\n                comment = last_operand\n                operands = operands[:-1]\n        elif is_arm32() or is_arm32_cortex_m():\n            r = self.RE_SPLIT_LAST_OPERAND_ARM32.match(last_operand) # r\";.+$\"\n            if r:\n                comment = last_operand\n                operands = operands[:-1]\n        elif is_microblaze():\n            r = self.RE_SPLIT_LAST_OPERAND_MICROBLAZE.match(last_operand) # r\"//.+$\"\n            if r:\n                comment = last_operand\n                operands = operands[:-1]\n        elif is_loongarch64():\n            r = self.RE_SPLIT_LAST_OPERAND_LOONGARCH64.match(last_operand) # r\"(# .*)$\"\n            if r:\n                comment = r.group(1)\n                operands = operands[:-1]\n        return operands, comment\n\n    def colored_operands_text(self, highlight, operands):\n        \"\"\"Parse the operands, color each element, and return it as a string.\"\"\"\n        color_operands_normal = self.get_color(highlight, \"theme.disassemble_operands_normal\")\n        color_operands_const = self.get_color(highlight, \"theme.disassemble_operands_const\")\n        color_operands_symbol = self.get_color(highlight, \"theme.disassemble_operands_symbol\")\n\n        # extract -> coloring -> join\n        colored_operands = []\n        for o1 in operands:\n            colored_o1 = []\n            # split by *, [, ], (, ), %, :, space, non-first +, - (without #, @, %), <...>\n            for o2 in self.RE_SPLIT_ELEM.split(o1): # r\"([*%\\[\\](): ]|(?<![#@%])(?<=.)[-+]|<.+>)\"\n                o2 = o2.strip()\n                if o2 == \"\":\n                    continue\n                if o2[0] == \"<\":\n                    colored_o1.append(self.hexlify_symbol_offset(o2))\n                    colored_o1.append(\" \")\n                elif o2 in [\"-\", \"+\", \"*\"]:\n                    colored_o1.append(Color.colorify(o2, color_operands_symbol))\n                    colored_o1.append(\" \")\n                elif o2 in [\":\", \"%\"]:\n                    if colored_o1 and colored_o1[-1] == \" \":\n                        colored_o1 = colored_o1[:-1]\n                    colored_o1.append(Color.colorify(o2, color_operands_symbol))\n                elif o2 in [\"[\", \"(\"]:\n                    colored_o1.append(Color.colorify(o2, color_operands_symbol))\n                elif o2 in [\"]\", \")\"]:\n                    if colored_o1 and colored_o1[-1] == \" \":\n                        colored_o1 = colored_o1[:-1]\n                    colored_o1.append(Color.colorify(o2, color_operands_symbol))\n                elif self.RE_IS_DIGIT_COMMENT.match(o2): # r\"#?-?(0x[0-9a-f]+|\\d+)\"\n                    colored_o1.append(Color.colorify(o2, color_operands_const))\n                    colored_o1.append(\" \")\n                else:\n                    colored_o1.append(Color.colorify(o2, color_operands_normal))\n                    colored_o1.append(\" \")\n            colored_operands.append(\"\".join(colored_o1).strip())\n        operands_text = Color.colorify(\", \", color_operands_symbol).join(colored_operands)\n        return operands_text\n\n    def hexlify_symbol_offset(self, x):\n        \"\"\"i.e., <memcmp+20> -> <memcmp+0x14>\"\"\"\n        r1 = self.RE_SPLIT_SYMBOL.match(x) # r\"(.*?)<(.+)>(.*)$\"\n        if not r1:\n            return x\n        r2 = self.RE_SPLIT_SYMBOL_OFFSET.match(r1.group(2)) # r\"(.+)\\+(\\d+)$\"\n        if r2:\n            sym_x = \"{}+{:#x}\".format(self.smartify_text(r2.group(1)), int(r2.group(2)))\n        else:\n            sym_x = self.smartify_text(r1.group(2))\n        return \"{:s}<{:s}>{:s}\".format(r1.group(1), sym_x, r1.group(3))\n\n    def get_opcodes_hex(self, opcodes_len):\n        opcodes_hex = \"\".join(\"{:02x}\".format(b) for b in self.opcodes) # e.g., \"488d0de51e0100\"\n        # e.g., len=4: opcodes:01020304   -> 01020304\n        # e.g., len=4: opcodes:0102030405 -> 010203..\n        if opcodes_len < len(self.opcodes):\n            opcodes_hex = opcodes_hex[:opcodes_len * 2 - 2] + \"..\"\n        opcodes_hex = \"{:{:d}}\".format(opcodes_hex, opcodes_len * 2)\n        return opcodes_hex\n\n    def colored_text(self, opcodes_len=0, highlight=False, disable_color=False):\n        \"\"\"Color the entire instruction, format it as a string and return it.\"\"\"\n        if opcodes_len == 0:\n            return str(self)\n\n        enable_color = not disable_color\n\n        # format address\n        address_text = hex(self.address)\n\n        # format location\n        location_text = self.smartify_text(self.location)\n\n        if enable_color:\n            color_address = self.get_color(highlight, \"theme.disassemble_address\")\n            address_text = Color.colorify(address_text, color_address)\n            location_text = Color.colorify(location_text, color_address)\n\n        # format opcode\n        opcodes_hex = self.get_opcodes_hex(opcodes_len)\n\n        if enable_color:\n            color_opcode = self.get_color(highlight, \"theme.disassemble_opcode\")\n            opcodes_hex = Color.colorify(opcodes_hex, color_opcode)\n\n        # format mnemonic\n        mnemonic_text = \"{:6s}\".format(self.mnemonic)\n\n        if enable_color:\n            if self.is_branch:\n                color_mnemonic = self.get_color(highlight, \"theme.disassemble_mnemonic_branch\")\n            else:\n                color_mnemonic = self.get_color(highlight, \"theme.disassemble_mnemonic_normal\")\n            mnemonic_text = Color.colorify(mnemonic_text, color_mnemonic)\n\n        # split last operand by ;, #, //\n        operands_array, comment = self.split_last_operands(self.operands[::])\n        comment = self.hexlify_symbol_offset(comment)\n\n        # format operands\n        if enable_color:\n            operands_text = self.colored_operands_text(highlight, operands_array)\n        else:\n            operands_text = \", \".join(operands_array)\n\n        # the case that gdb does not append symbol but symbol exists\n        if self.is_branch:\n            if \"<\" not in operands_text and \"<\" not in comment:\n                if self.operands and self.operands[-1]:\n                    addr = ContextCodeCommand.get_branch_addr(self)\n                    # Not using += is intentional; useless comments are discarded\n                    comment = Symbol.get_symbol_string(addr).lstrip()\n\n        # add strings\n        if not self.is_branch:\n            if not comment:\n                s = self.get_string_if_valid_addr(operands_array)\n            else:\n                s = self.get_string_if_valid_addr([comment])\n            if s:\n                if enable_color:\n                    string_color = Config.get_gef_setting(\"theme.dereference_string\")\n                    if len(s) < current_arch.ptrsize:\n                        comment += \" ({:s}?)\".format(Color.colorify(repr(s), string_color))\n                    else:\n                        comment += \" ({:s})\".format(Color.colorify(repr(s), string_color))\n                else:\n                    if len(s) < current_arch.ptrsize:\n                        comment += \" ({:s}?)\".format(repr(s))\n                    else:\n                        comment += \" ({:s})\".format(repr(s))\n\n        # formatting\n        out = \"{:s} {:s} {:s}   {:s} {:s} {:s}\".format(\n            address_text, opcodes_hex, location_text, mnemonic_text, operands_text, comment,\n        ).rstrip()\n        return out\n\n    def __repr__(self):\n        return '<{:s}.{:s} object at {:#x}, asm=\"{:s}\">'.format(\n            self.__module__, self.__class__.__name__, id(self), str(self),\n        )\n\n    def __str__(self):\n        location = self.smartify_text(self.location)\n        operands = self.smartify_text(\", \".join(self.operands))\n        return \"{:#10x} {:20s} {:6s} {:s}\".format(self.address, location, self.mnemonic, operands)\n\n    def is_valid(self):\n        return \"(bad)\" not in self.mnemonic\n\n    @staticmethod\n    def smartify_text(text):\n        \"\"\"Simplify and shorten C++ function/type names for improved readability.\"\"\"\n        smart_cpp_function_name = Config.get_gef_setting(\"context.smart_cpp_function_name\")\n        if not smart_cpp_function_name:\n            return text\n\n        if text is None:\n            return text\n\n        if len(text) == 0:\n            return text\n\n        text = re.sub(r\"\\bstd::__1::\", \"\", text)\n\n        old_text = text[::]\n        while True:\n            text = re.sub(r\"\\([^(]+?\\)\", \"__MARKER_GEF__\", text)\n            if text == old_text:\n                break\n            old_text = text[::]\n        text = re.sub(\"__MARKER_GEF__\", \"(...)\", text)\n\n        m = re.match(r\"^(\\s*\\<)(.*)(\\>\\s*)$\", text)\n        if m:\n            text_0, text, text_end = m.group(1), m.group(2), m.group(3)\n        else:\n            text_0, text, text_end = \"\", text, \"\"\n\n        while True:\n            text = re.sub(r\"\\<[^<]+?\\>\", \"__MARKER_GEF__\", text)\n            if text == old_text:\n                break\n            old_text = text[::]\n        text = re.sub(\"__MARKER_GEF__\", \"<...>\", text)\n        if text_0:\n            text = text_0 + text\n        if text_end:\n            text = text + text_end\n        return text\n\n\nclass GenericType:\n    def __init__(self, addr):\n        self.__addr = addr\n\n        self.char_t = GefUtil.cached_lookup_type(\"unsigned char\")\n        self.int_t = GefUtil.cached_lookup_type(\"unsigned int\")\n        self.long_t = GefUtil.cached_lookup_type(\"unsigned long\")\n        self.size_t = GefUtil.cached_lookup_type(\"size_t\")\n        if not self.size_t:\n            ptr_type = \"unsigned long\" if current_arch.ptrsize == 8 else \"unsigned int\"\n            self.size_t = GefUtil.cached_lookup_type(ptr_type)\n        return\n\n    @property\n    def addr(self):\n        return self.__addr\n\n    @property\n    @abc.abstractmethod\n    def sizeof(self):\n        pass\n\n    # helper methods\n    def __getitem__(self, item):\n        return getattr(self, item)\n\n    def get_size_t(self, addr):\n        return AddressUtil.dereference(addr).cast(self.size_t)\n\n    def get_size_t_pointer(self, addr):\n        size_t_pointer = self.size_t.pointer()\n        return AddressUtil.dereference(addr).cast(size_t_pointer)\n\n    def get_size_t_array(self, addr, length):\n        size_t_array = self.size_t.array(length)\n        return AddressUtil.dereference(addr).cast(size_t_array)\n\n    def get_int_t(self, addr):\n        return AddressUtil.dereference(addr).cast(self.int_t)\n\n    def get_int_t_array(self, addr, length):\n        int_t_array = self.int_t.array(length)\n        return AddressUtil.dereference(addr).cast(int_t_array)\n\n    def get_char_t_pointer(self, addr):\n        char_t_pointer = self.char_t.pointer()\n        return AddressUtil.dereference(addr).cast(char_t_pointer)\n\n    def get_char_t_array(self, addr, length):\n        char_t_array = self.char_t.array(length)\n        return AddressUtil.dereference(addr).cast(char_t_array)\n\n    def get_long_t(self, addr):\n        return AddressUtil.dereference(addr).cast(self.long_t)\n\n\nclass GlibcHeap:\n    \"\"\"Manage glibc heap-specific settings.\"\"\"\n\n    class HeapInfo(GenericType):\n        \"\"\"GEF representation of heap_info.\"\"\"\n\n        @staticmethod\n        def MALLOC_ALIGNMENT():\n            if is_64bit():\n                return 0x10\n            elif (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                return 0x10\n            else:\n                return 0x8\n\n        @staticmethod\n        def MIN_SIZE():\n            if is_64bit():\n                return 0x20\n            else:\n                return 0x10\n\n        def __init__(self, addr):\n            super().__init__(addr)\n            self.MALLOC_ALIGN_MASK = GlibcHeap.HeapInfo.MALLOC_ALIGNMENT() - 1\n            return\n\n        # struct offsets\n        @property\n        def addrof_ar_ptr(self):\n            return self.addr\n\n        @property\n        def addrof_prev(self):\n            return self.addrof_ar_ptr + self.char_t.pointer().sizeof\n\n        @property\n        def addrof_size(self):\n            return self.addrof_prev + self.char_t.pointer().sizeof\n\n        @property\n        def addrof_mprotect_size(self):\n            return self.addrof_size + self.size_t.sizeof\n\n        @property\n        def addrof_pagesize(self):\n            if get_libc_version() >= (2, 35):\n                return self.addrof_mprotect_size + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_pad(self):\n            if get_libc_version() >= (2, 35):\n                return self.addrof_pagesize + self.size_t.sizeof\n            else:\n                return self.addrof_mprotect_size + self.size_t.sizeof\n\n        @property\n        def sizeof(self):\n            if get_libc_version() >= (2, 35):\n                end = self.addrof_pad + (-3 * self.size_t.sizeof) & self.MALLOC_ALIGN_MASK\n            else:\n                end = self.addrof_pad + (-6 * self.size_t.sizeof) & self.MALLOC_ALIGN_MASK\n            return end - self.addr\n\n        # struct members\n        @property\n        def ar_ptr(self):\n            return self.get_char_t_pointer(self.addrof_ar_ptr)\n\n        @property\n        def prev(self):\n            return self.get_char_t_pointer(self.addrof_prev)\n\n        @property\n        def size(self):\n            return self.get_size_t(self.addrof_size)\n\n        @property\n        def mprotect_size(self):\n            return self.get_size_t(self.addrof_mprotect_size)\n\n        @property\n        def pagesize(self):\n            if get_libc_version() >= (2, 35):\n                return self.get_size_t(self.addrof_pagesize)\n            else:\n                return None\n\n        @property\n        def pad(self):\n            if get_libc_version() >= (2, 35):\n                length = (-3 * self.size_t.sizeof) & self.MALLOC_ALIGN_MASK\n            else:\n                length = (-6 * self.size_t.sizeof) & self.MALLOC_ALIGN_MASK\n            return self.get_char_t_array(self.addrof_pad, length)\n\n    class MallocPar(GenericType):\n        \"\"\"GEF representation of malloc_par.\"\"\"\n\n        # struct offsets\n        @property\n        def addrof_trim_threshold(self):\n            return self.addr\n\n        @property\n        def addrof_top_pad(self):\n            return self.addrof_trim_threshold + self.long_t.sizeof\n\n        @property\n        def addrof_mmap_threshold(self):\n            return self.addrof_top_pad + self.size_t.sizeof\n\n        @property\n        def addrof_arena_test(self):\n            return self.addrof_mmap_threshold + self.size_t.sizeof\n\n        @property\n        def addrof_arena_max(self):\n            return self.addrof_arena_test + self.size_t.sizeof\n\n        @property\n        def addrof_thp_mode(self):\n            if get_libc_version() >= (2, 43):\n                return self.addrof_arena_max + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_thp_pagesize(self):\n            if get_libc_version() >= (2, 43):\n                return self.addrof_thp_mode + self.size_t.sizeof\n            elif get_libc_version() >= (2, 35):\n                return self.addrof_arena_max + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_hp_pagesize(self):\n            if get_libc_version() >= (2, 35):\n                return self.addrof_thp_pagesize + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_hp_flags(self):\n            if get_libc_version() >= (2, 35):\n                return self.addrof_hp_pagesize + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_n_mmaps(self):\n            if get_libc_version() >= (2, 35):\n                return self.addrof_hp_flags + self.int_t.sizeof\n            else:\n                return self.addrof_arena_max + self.size_t.sizeof\n\n        @property\n        def addrof_n_mmaps_max(self):\n            return self.addrof_n_mmaps + self.int_t.sizeof\n\n        @property\n        def addrof_max_n_mmaps(self):\n            return self.addrof_n_mmaps_max + self.int_t.sizeof\n\n        @property\n        def addrof_no_dyn_threshold(self):\n            return self.addrof_max_n_mmaps + self.int_t.sizeof\n\n        @property\n        def addrof_pagesize(self):\n            if get_libc_version() >= (2, 15):\n                return None\n            else:\n                return self.addrof_max_n_mmaps + self.int_t.sizeof\n\n        @property\n        def addrof_mmapped_mem(self):\n            if get_libc_version() >= (2, 15):\n                return align_to_ptrsize(self.addrof_no_dyn_threshold + self.int_t.sizeof)\n            else:\n                return align_to_ptrsize(self.addrof_pagesize + self.int_t.sizeof)\n\n        @property\n        def addrof_max_mmapped_mem(self):\n            return self.addrof_mmapped_mem + self.size_t.sizeof\n\n        @property\n        def addrof_max_total_mem(self):\n            if get_libc_version() >= (2, 24):\n                return None\n            else:\n                return self.addrof_mmapped_mem + self.size_t.sizeof\n\n        @property\n        def addrof_sbrk_base(self):\n            if get_libc_version() >= (2, 24):\n                return self.addrof_max_mmapped_mem + self.size_t.sizeof\n            else:\n                return self.addrof_max_total_mem + self.size_t.sizeof\n\n        @property\n        def addrof_tcache_bins(self):\n            if get_libc_version() >= (2, 26):\n                return self.addrof_sbrk_base + self.char_t.pointer().sizeof\n            else:\n                return None\n\n        @property\n        def addrof_tcache_max_bytes(self):\n            if get_libc_version() >= (2, 26):\n                return self.addrof_tcache_bins + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_tcache_count(self):\n            if get_libc_version() >= (2, 26):\n                return self.addrof_tcache_max_bytes + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_tcache_unsorted_limit(self):\n            if get_libc_version() >= (2, 26):\n                return self.addrof_tcache_count + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def sizeof(self):\n            if get_libc_version() >= (2, 26):\n                end = self.addrof_tcache_unsorted_limit + self.size_t.sizeof\n            else:\n                end = self.addrof_sbrk_base + self.char_t.pointer().sizeof\n            return end - self.addr\n\n        # struct members\n        @property\n        def trim_threshold(self):\n            return self.get_long_t(self.addrof_trim_threshold)\n\n        @property\n        def top_pad(self):\n            return self.get_size_t(self.addrof_top_pad)\n\n        @property\n        def mmap_threshold(self):\n            return self.get_size_t(self.addrof_mmap_threshold)\n\n        @property\n        def arena_test(self):\n            return self.get_size_t(self.addrof_arena_test)\n\n        @property\n        def arena_max(self):\n            return self.get_size_t(self.addrof_arena_max)\n\n        @property\n        def thp_pagesize(self):\n            if get_libc_version() >= (2, 35):\n                return self.get_size_t(self.addrof_thp_pagesize)\n            else:\n                return None\n\n        @property\n        def hp_pagesize(self):\n            if get_libc_version() >= (2, 35):\n                return self.get_size_t(self.addrof_hp_pagesize)\n            else:\n                return None\n\n        @property\n        def hp_flags(self):\n            if get_libc_version() >= (2, 35):\n                return self.get_int_t(self.addrof_hp_flags)\n            else:\n                return None\n\n        @property\n        def n_mmaps(self):\n            return self.get_int_t(self.addrof_n_mmaps)\n\n        @property\n        def n_mmaps_max(self):\n            return self.get_int_t(self.addrof_n_mmaps_max)\n\n        @property\n        def max_n_mmaps(self):\n            return self.get_int_t(self.addrof_max_n_mmaps)\n\n        @property\n        def no_dyn_threshold(self):\n            return self.get_int_t(self.addrof_no_dyn_threshold)\n\n        @property\n        def pagesize(self):\n            if get_libc_version() >= (2, 15):\n                return None\n            else:\n                return self.get_int_t(self.addrof_pagesize)\n\n        @property\n        def mmapped_mem(self):\n            return self.get_size_t(self.addrof_mmapped_mem)\n\n        @property\n        def max_mmapped_mem(self):\n            return self.get_size_t(self.addrof_max_mmapped_mem)\n\n        @property\n        def max_total_mem(self):\n            if get_libc_version() >= (2, 24):\n                return None\n            else:\n                return self.get_size_t(self.addrof_max_total_mem)\n\n        @property\n        def sbrk_base(self):\n            return self.get_char_t_pointer(self.addrof_sbrk_base)\n\n        @property\n        def tcache_bins(self):\n            if get_libc_version() >= (2, 26):\n                return self.get_size_t(self.addrof_tcache_bins)\n            else:\n                return None\n\n        @property\n        def tcache_max_bytes(self):\n            if get_libc_version() >= (2, 26):\n                return self.get_size_t(self.addrof_tcache_max_bytes)\n            else:\n                return None\n\n        @property # noqa\n        def tcache_count(self):\n            if get_libc_version() >= (2, 26):\n                return self.get_size_t(self.addrof_tcache_count)\n            else:\n                return None\n\n        @property\n        def tcache_unsorted_limit(self):\n            if get_libc_version() >= (2, 26):\n                return self.get_size_t(self.addrof_tcache_unsorted_limit)\n            else:\n                return None\n\n    @staticmethod\n    @Cache.cache_until_next\n    def search_for_mp_():\n        \"\"\"search for mp_ from main_arena, then return addr.\"\"\"\n        main_arena_ptr = GlibcHeap.search_for_main_arena_from_tls()\n        if main_arena_ptr is None:\n            return None\n        main_arena = read_int_from_memory(main_arena_ptr)\n\n        heap_base = HeapbaseCommand.heap_base()\n        if heap_base is None:\n            return None\n\n        offsetof_sbrk_base = GlibcHeap.MallocPar(0).addrof_sbrk_base\n        current = main_arena - GlibcHeap.MallocPar(0).sizeof\n        for _ in range(0, 500):\n            try:\n                x = read_int_from_memory(current)\n            except gdb.MemoryError:\n                return None\n            if x == heap_base:\n                mp_ = current - offsetof_sbrk_base\n                return mp_\n            current -= current_arch.ptrsize\n        return None\n\n    class MallocStateStruct(GenericType):\n        \"\"\"GEF representation of malloc_state.\"\"\"\n\n        def __init__(self, addr):\n            super().__init__(addr)\n\n            if get_libc_version() >= (2, 43):\n                self.num_fastbins = 0\n            elif (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                # MALLOC_ALIGNMENT is changed from libc 2.26.\n                # for x86_32, MALLOC_ALIGNMENT = 16, so NFASTBINS = 11.\n                self.num_fastbins = 11\n            else:\n                self.num_fastbins = 10\n\n            NBINS = 128\n            BINMAPSHIFT = 5\n            BITSPERMAP = 1 << BINMAPSHIFT\n            BINMAPSIZE = NBINS // BITSPERMAP\n\n            self.num_bins = NBINS * 2 - 2\n            self.num_binmap = BINMAPSIZE\n            return\n\n        # struct offsets\n        @property\n        def addrof_mutex(self):\n            return self.addr\n\n        @property\n        def addrof_flags(self):\n            return self.addrof_mutex + self.int_t.sizeof\n\n        @property\n        def addrof_have_fastchunks(self):\n            if get_libc_version() >= (2, 43):\n                return None\n            elif get_libc_version() >= (2, 27):\n                return self.addrof_flags + self.int_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_fastbins(self):\n            if get_libc_version() >= (2, 43):\n                return None\n            elif get_libc_version() >= (2, 27):\n                fastbin_offset = align(self.int_t.sizeof * 3, self.size_t.sizeof)\n            else:\n                fastbin_offset = self.int_t.sizeof * 2\n            return self.addr + fastbin_offset\n\n        @property\n        def addrof_top(self):\n            if get_libc_version() >= (2, 43):\n                return self.addrof_flags + self.int_t.sizeof\n            else:\n                return self.addrof_fastbins + self.size_t.sizeof * self.num_fastbins\n\n        @property\n        def addrof_last_remainder(self):\n            return self.addrof_top + self.size_t.sizeof\n\n        @property\n        def addrof_bins(self):\n            return self.addrof_last_remainder + self.size_t.sizeof\n\n        @property\n        def addrof_binmap(self):\n            return self.addrof_bins + self.size_t.sizeof * self.num_bins\n\n        @property\n        def addrof_next(self):\n            return self.addrof_binmap + self.int_t.sizeof * self.num_binmap\n\n        @property\n        def addrof_next_free(self):\n            if get_libc_version() >= (2, 19):\n                return self.addrof_next + self.size_t.sizeof\n            else:\n                # Before glibc 2.19, the presence of next_free depends on the environment.\n                # However, it appears to be more likely absent, so None is returned.\n                return None\n\n        @property\n        def addrof_attached_threads(self):\n            if get_libc_version() >= (2, 23):\n                return self.addrof_next_free + self.size_t.sizeof\n            else:\n                return None\n\n        @property\n        def addrof_system_mem(self):\n            if get_libc_version() >= (2, 23):\n                return self.addrof_attached_threads + self.size_t.sizeof\n            elif get_libc_version() >= (2, 19):\n                return self.addrof_next_free + self.size_t.sizeof\n            else:\n                return self.addrof_next + self.size_t.sizeof\n\n        @property\n        def addrof_max_system_mem(self):\n            return self.addrof_system_mem + self.size_t.sizeof\n\n        @property\n        def sizeof(self):\n            return self.addrof_max_system_mem + self.size_t.sizeof - self.addr\n\n        # struct members\n        @property\n        def mutex(self):\n            return self.get_int_t(self.addrof_mutex)\n\n        @property\n        def flags(self):\n            return self.get_int_t(self.addrof_flags)\n\n        @property\n        def have_fastchunks(self):\n            if get_libc_version() >= (2, 43):\n                return None\n            elif get_libc_version() >= (2, 27):\n                return self.get_int_t(self.addrof_have_fastchunks)\n            else:\n                return None\n\n        @property\n        def fastbinsY(self):\n            if get_libc_version() >= (2, 43):\n                return None\n            else:\n                return self.get_size_t_array(self.addrof_fastbins, self.num_fastbins)\n\n        @property\n        def top(self):\n            return self.get_size_t_pointer(self.addrof_top)\n\n        @property\n        def last_remainder(self):\n            return self.get_size_t_pointer(self.addrof_last_remainder)\n\n        @property\n        def bins(self):\n            return self.get_size_t_array(self.addrof_bins, self.num_bins)\n\n        @property\n        def binmap(self):\n            return self.get_int_t_array(self.addrof_binmap, self.num_binmap)\n\n        @property\n        def next(self):\n            return self.get_size_t_pointer(self.addrof_next)\n\n        @property\n        def next_free(self):\n            if get_libc_version() >= (2, 19):\n                return self.get_size_t_pointer(self.addrof_next_free)\n            else:\n                return None\n\n        @property\n        def attached_threads(self):\n            if get_libc_version() >= (2, 23):\n                return self.get_size_t(self.addrof_attached_threads)\n            else:\n                return None\n\n        @property\n        def system_mem(self):\n            return self.get_size_t(self.addrof_system_mem)\n\n        @property\n        def max_system_mem(self):\n            return self.get_size_t(self.addrof_max_system_mem)\n\n    @staticmethod\n    @Cache.cache_until_next\n    def search_for_main_arena_from_tls():\n        \"\"\"search for main arena from TLS, then return &addr.\"\"\"\n\n        \"\"\"\n        [x64]\n        0x7ffff7f986f8|+0x0038|007: 0x0000555555559010  ->  0x0000000000000000\n        0x7ffff7f98700|+0x0040|008: 0x0000000000000000\n        0x7ffff7f98708|+0x0048|009: 0x00007ffff7e19c80 <main_arena>  ->  0x0000000000000000\n        0x7ffff7f98710|+0x0050|010: 0x0000000000000000\n        0x7ffff7f98718|+0x0058|011: 0x0000000000000000\n        0x7ffff7f98720|+0x0060|012: 0x0000000000000000\n        0x7ffff7f98728|+0x0068|013: 0x0000000000000000\n        0x7ffff7f98730|+0x0070|014: 0x0000000000000000\n        0x7ffff7f98738|+0x0078|015: 0x0000000000000000\n        -- TLS --\n        0x7ffff7f98740|+0x0000|000: 0x00007ffff7f98740  ->  [loop detected]\n        0x7ffff7f98748|+0x0008|001: 0x00007ffff7f99160  ->  0x0000000000000001\n        0x7ffff7f98750|+0x0010|002: 0x00007ffff7f98740  ->  [loop detected]\n\n        [x86]\n        0xf7fbf4d0|+0x00d0|052: 0x5655a010  ->  0x00000000\n        0xf7fbf4d4|+0x00d4|053: 0x00000000\n        0xf7fbf4d8|+0x00d8|054: 0xf7e2a7c0 <main_arena>  ->  0x00000000\n        0xf7fbf4dc|+0x00dc|055: 0x00000000\n        0xf7fbf4e0|+0x00e0|056: 0x00000000\n        0xf7fbf4e4|+0x00e4|057: 0x00000000\n        0xf7fbf4e8|+0x00e8|058: 0x00000000\n        0xf7fbf4ec|+0x00ec|059: 0x00000000\n        0xf7fbf4f0|+0x00f0|060: 0x00000000\n        0xf7fbf4f4|+0x00f4|061: 0x00000000\n        0xf7fbf4f8|+0x00f8|062: 0x00000000\n        0xf7fbf4fc|+0x00fc|063: 0x00000000\n        -- TLS --\n        0xf7fbf500|+0x0100|064: 0xf7fbf500  ->  [loop detected]\n        0xf7fbf504|+0x0104|065: 0xf7fbfa88  ->  0x00000001\n        0xf7fbf508|+0x0108|066: 0xf7fbf500  ->  [loop detected]\n\n        [ARM]\n        -- TLS --\n        0x0007d580|+0x0000|000: 0x0007a3c8 <_dl_static_dtv+0x8>  ->  0x00000000\n        0x0007d584|+0x0004|001: 0x00000000\n        0x0007d588|+0x0008|002: 0x00079fa0 <_nl_global_locale>  ->  ...\n        0x0007d58c|+0x000c|003: 0x00079fa0 <_nl_global_locale>  ->  ...\n        0x0007d590|+0x0010|004: 0x00079fa4 <_nl_global_locale+0x4>  ->  ...\n        0x0007d594|+0x0014|005: 0x00079fb0 <_nl_global_locale+0x10>  ->  ...\n        0x0007d598|+0x0018|006: 0x00000000\n        0x0007d59c|+0x001c|007: 0x00079660 <main_arena>  ->  0x00000000\n        0x0007d5a0|+0x0020|008: 0x0007d908  ->  0x00000000\n        0x0007d5a4|+0x0024|009: 0x00000000\n        0x0007d5a8|+0x0028|010: 0x00000000\n\n        [ARM64]\n        -- TLS --\n        0x0000004997c0|+0x0000|000: 0x0000000000493078 <_dl_static_dtv+0x10>  ->  0x0000000000000000\n        0x0000004997c8|+0x0008|001: 0x0000000000000000\n        0x0000004997d0|+0x0010|002: 0x0000000000492838 <_nl_global_locale>  ->  ...\n        0x0000004997d8|+0x0018|003: 0x0000000000492840 <_nl_global_locale+0x8>  ->  ...\n        0x0000004997e0|+0x0020|004: 0x0000000000492838 <_nl_global_locale>  ->  ...\n        0x0000004997e8|+0x0028|005: 0x0000000000492858 <_nl_global_locale+0x20>  ->  ...\n        0x0000004997f0|+0x0030|006: 0x0000000000000000\n        0x0000004997f8|+0x0038|007: 0x0000000000491678 <main_arena>  ->  0x0000000000000000\n        0x000000499800|+0x0040|008: 0x0000000000499b90  ->  0x0000000000000000\n        0x000000499808|+0x0048|009: 0x0000000000000000\n        0x000000499810|+0x0050|010: 0x0000000000000000\n        0x000000499818|+0x0058|011: 0x000000000045e780 <_nl_C_LC_CTYPE_class+0x100>  ->  0x0002000200020002\n        0x000000499820|+0x0060|012: 0x000000000045de80 <_nl_C_LC_CTYPE_toupper+0x200>  ->  0x0000000100000000\n        0x000000499828|+0x0068|013: 0x000000000045d880 <_nl_C_LC_CTYPE_tolower+0x200>  ->  0x0000000100000000\n        0x000000499830|+0x0070|014: 0x0000000000000000\n        0x000000499838|+0x0078|015: 0x0000000000000000\n        \"\"\"\n\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        main_thread = [th for th in threads if th.num == 1][0]\n        main_thread.switch()\n\n        tls = current_arch.get_tls()\n        if tls is None:\n            return None\n\n        direction = TlsCommand.get_direction()\n\n        for i in range(1, 500):\n            addr = tls + (current_arch.ptrsize * i) * direction\n\n            if is_m68k():\n                addr += 2\n\n            if not is_valid_addr(addr):\n                break\n\n            candidate_arena_addr = read_int_from_memory(addr)\n            if not is_valid_addr(candidate_arena_addr):\n                continue\n\n            candidate_arena = GlibcHeap.MallocStateStruct(candidate_arena_addr)\n            if candidate_arena.system_mem < get_pagesize():\n                continue\n            # Statically built binaries have an unaligned system_mem,\n            # so alignment should not be used to determine the validity of system_mem.\n\n            top = candidate_arena.top\n            if not is_valid_addr(top):\n                continue\n\n            next_addr = to_unsigned_long(candidate_arena.next)\n            while True:\n                if not is_valid_addr(next_addr):\n                    break\n                if candidate_arena_addr == next_addr:\n                    orig_thread.switch() # revert thread\n                    orig_frame.select()\n                    return addr\n                next_addr = to_unsigned_long(GlibcHeap.MallocStateStruct(next_addr).next)\n\n        # not found\n        orig_thread.switch() # revert thread\n        orig_frame.select()\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session_skip_None_cache\n    def search_for_main_arena():\n        \"\"\"Search for the address of main_arena using multiple strategies and caches the result.\"\"\"\n        if is_arm64():\n            # For some reason, native gdb (at least v10.1) on ARM64 has a bug where evaluating main_arena\n            # destroys tcache symbols. See issues #95\n            # Once you evaluate it, it will work without any problems after that.\n            # This is a temporary workaround.\n            try:\n                gdb.execute(\"p (void*) &tcache\", to_string=True)\n            except gdb.error:\n                pass\n\n        # plan 1 (directly)\n        try:\n            return AddressUtil.parse_address(\"(void*) &main_arena\")\n        except gdb.error:\n            pass\n\n        # plan 2 (from __malloc_hook)\n        if get_libc_version() < (2, 34):\n            try:\n                malloc_hook_addr = AddressUtil.parse_address(\"(void*) &__malloc_hook\")\n                if is_x86():\n                    return align(malloc_hook_addr + current_arch.ptrsize, 0x20)\n                elif is_arm64():\n                    mstate_size = GlibcHeap.MallocStateStruct(0).sizeof\n                    return malloc_hook_addr - current_arch.ptrsize * 2 - mstate_size\n                elif is_arm32():\n                    mstate_size = GlibcHeap.MallocStateStruct(0).sizeof\n                    return malloc_hook_addr - current_arch.ptrsize - mstate_size\n                else:\n                    raise\n            except gdb.error:\n                pass\n\n        # plan 3 (from TLS)\n        ptr = GlibcHeap.search_for_main_arena_from_tls()\n        if ptr:\n            return read_int_from_memory(ptr)\n\n        raise OSError(\"Cannot find main_arena for {}\".format(current_arch.arch))\n\n    # It must be a static method because it is also used to calculate the Heapbase.\n    @staticmethod\n    def search_for_tcache_from_tls(arena_addr):\n        if get_libc_version() < (2, 26):\n            return None\n        if not current_arch.tls_supported:\n            return None\n\n        \"\"\"\n        [2.42; x86_64 main-heap]\n        gef> tls\n        ...\n              0x7af8dd82b700|+0x0040|+008: 0x000055555555b010 <----- here\n              0x7af8dd82b708|+0x0048|+009: 0x0000000000000000\n              0x7af8dd82b710|+0x0050|+010: 0x00007af8d4034ac0 <main_arena>\n              0x7af8dd82b718|+0x0058|+011: 0x0000000000000000\n              0x7af8dd82b720|+0x0060|+012: 0x0000000000000000\n              0x7af8dd82b728|+0x0068|+013: 0x0000000000000000\n              0x7af8dd82b730|+0x0070|+014: 0x0000000000000000\n              0x7af8dd82b738|+0x0078|+015: 0x0000000000000000\n        ----- TLS\n\n        [2.42.9000; x86_64 main-heap]\n        gef> tls\n        ...\n              0x7d630b7a16e0|+0x0020|+004: 0x00005eafad721d20 <----- here\n              0x7d630b7a16e8|+0x0028|+005: 0x00007d630b995740 <res>\n              0x7d630b7a16f0|+0x0030|+006: 0x0000000000000000\n              0x7d630b7a16f8|+0x0038|+007: 0x0000000000000000\n              0x7d630b7a1700|+0x0040|+008: 0x0000000000000000\n              0x7d630b7a1708|+0x0048|+009: 0x0000000000000000\n              0x7d630b7a1710|+0x0050|+010: 0x00007d630b98dac0 <main_arena>\n              0x7d630b7a1718|+0x0058|+011: 0x0000000000000000\n              0x7d630b7a1720|+0x0060|+012: 0x0000000000000000\n              0x7d630b7a1728|+0x0068|+013: 0x0000000000000000\n              0x7d630b7a1730|+0x0070|+014: 0x0000000000000000\n              0x7d630b7a1738|+0x0078|+015: 0x0000000000000000\n        ----- TLS\n        \"\"\"\n\n        def get_all_tls():\n            orig_thread = gdb.selected_thread()\n            orig_frame = gdb.selected_frame()\n            threads = gdb.selected_inferior().threads()\n            threads = sorted(threads, key=lambda th: th.num)\n            tls_list = []\n            if not threads:\n                return None\n            for thread in threads:\n                try:\n                    thread.switch()\n                except gdb.error:\n                    continue\n                tls = current_arch.get_tls()\n                tls_list.append(tls)\n            orig_thread.switch() # revert thread\n            orig_frame.select()\n            return tls_list\n\n        def get_suitable_tls_addr(arena_addr):\n            tls_list = get_all_tls()\n            if not tls_list:\n                return None\n            for i in range(1, 500):\n                for direction in [1, -1]:\n                    for tls in tls_list:\n                        tls_addr_i = tls + (current_arch.ptrsize * i) * direction\n                        if not is_valid_addr(tls_addr_i):\n                            continue\n                        x = read_int_from_memory(tls_addr_i)\n                        if is_valid_addr(x) and x == arena_addr:\n                            return tls_addr_i\n            return None\n\n        def get_tcache_perthread_struct_size():\n            TCACHE_MAX_BINS = GlibcHeap.GlibcArena.TCACHE_MAX_BINS()\n            if get_libc_version() < (2, 30):\n                tcache_perthread_struct_size_real = TCACHE_MAX_BINS * (1 + current_arch.ptrsize)\n            else:\n                tcache_perthread_struct_size_real = TCACHE_MAX_BINS * (2 + current_arch.ptrsize)\n\n            for _k, v in GlibcHeap.get_binsize_table()[\"tcache\"].items():\n                if v.get(\"size\", 0) > tcache_perthread_struct_size_real:\n                    return v[\"size\"]\n            return None\n\n        def search_tcache_perthread_struct(arena, tls):\n            tcache_perthread_struct_size = get_tcache_perthread_struct_size()\n            if tcache_perthread_struct_size is None:\n                return None\n            for i in range(1, 20): # \"20\" has no special meaning\n                for direction in [1, -1]:\n                    tls_addr_i = tls + (current_arch.ptrsize * i) * direction\n                    if not is_valid_addr(tls_addr_i):\n                        continue\n                    x = read_int_from_memory(tls_addr_i)\n                    if not is_valid_addr(x):\n                        continue\n                    chunk = GlibcHeap.GlibcChunk(arena, x)\n                    try:\n                        if chunk.size == tcache_perthread_struct_size:\n                            return x\n                    except gdb.MemoryError:\n                        continue\n            return None\n\n        tls = get_suitable_tls_addr(arena_addr)\n        if tls is None:\n            return None\n        return search_tcache_perthread_struct(arena_addr, tls)\n\n    class GlibcArena:\n        \"\"\"Glibc arena class.\"\"\"\n\n        @staticmethod\n        def TCACHE_SMALL_BINS():\n            if get_libc_version() < (2, 42):\n                return None\n            else:\n                return 0x40\n\n        @staticmethod\n        def TCACHE_LARGE_BINS():\n            if get_libc_version() < (2, 42):\n                return None\n            else:\n                return 12\n\n        @staticmethod\n        @Cache.cache_this_session\n        def TCACHE_MAX_BINS():\n            if get_libc_version() < (2, 42):\n                return 0x40\n            else:\n                return GlibcHeap.GlibcArena.TCACHE_SMALL_BINS() + GlibcHeap.GlibcArena.TCACHE_LARGE_BINS()\n\n        @staticmethod\n        @Cache.cache_this_session\n        def TCACHE_FILL_COUNT():\n            v = Config.get_gef_setting(\"heap.tcache_max_count\")\n            if v != -1:\n                return v\n            if get_libc_version() < (2, 43):\n                return 7\n            else:\n                return 16\n\n        def __init__(self, arena_addr=None):\n            # Manually calling a command like `call malloc(0x10)` alters the heap's internal structure.\n            # However, the call command does not notify the `memory_changed` event.\n            # Therefore, the GEF cache is not cleared, resulting in wrong output.\n            #   gef> bs\n            #   gef> call malloc(0x10)\n            #   gef> bs <-- wrong result\n            # This is probably a bug in GDB. The solution is to clear the GEF cache.\n            Cache.reset_gef_caches()\n\n            # get address\n            if arena_addr is None:\n                self.__addr = GlibcHeap.search_for_main_arena()\n                self.__is_main_arena = True\n            else:\n                self.__addr = arena_addr\n                self.__is_main_arena = bool(arena_addr == GlibcHeap.search_for_main_arena())\n\n            # get type\n            try:\n                arena = gdb.parse_and_eval(\"*{:#x}\".format(self.__addr))\n                malloc_state_t = GefUtil.cached_lookup_type(\"struct malloc_state\")\n                self.__arena = arena.cast(malloc_state_t)\n                self.__size = malloc_state_t.sizeof\n            except RuntimeError:\n                self.__arena = GlibcHeap.MallocStateStruct(self.__addr)\n                self.__size = self.__arena.sizeof\n\n            # This structure (GlibcArena) is created every time you run a heap-related command.\n            # Therefore, it is safe to cache the current value.\n            # The `visual-heap` command evaluates `top` and `last_remainder` many times.\n            # These are expensive because the value is actually retrieved via `__getattr__`.\n            # Caching will improve speed, so it'll cache it here.\n            self.top = int(self.top)\n            self.last_remainder = int(self.last_remainder)\n            return\n\n        def __getitem__(self, item):\n            return self.__arena[item]\n\n        def __getattr__(self, item):\n            try:\n                return self.__arena[item]\n            except RuntimeError:\n                raise AttributeError from None\n\n        def __int__(self):\n            return self.__addr\n\n        @property\n        def is_main_arena(self):\n            return self.__is_main_arena\n\n        @property\n        def addr(self):\n            return self.__addr\n\n        @property\n        def name(self):\n            if self.is_main_arena:\n                return \"main_arena\"\n            else:\n                return \"*{:#x}\".format(self.__addr)\n\n        @property\n        def sizeof(self):\n            # arena aligned_size\n            if current_arch.ptrsize == 4:\n                aligned_size = (self.__size + 7) & ~0b111\n            else:\n                aligned_size = (self.__size + 15) & ~0b1111\n            return aligned_size\n\n        @property\n        def heap_base(self):\n            if self.is_main_arena:\n                return HeapbaseCommand.heap_base()\n            else:\n                return self.addr + self.sizeof\n\n        @property\n        def tcache(self):\n            return self.addrof_tcachebins_base()\n\n        @property\n        def tcache_perthread_struct(self):\n            return self.addrof_tcachebins_base()\n\n        @Cache.cache_until_next\n        def addrof_tcachebins_base(self, force_heuristic=False):\n            if self.heap_base is None:\n                return None\n\n            def tcache_from_symbol():\n                if force_heuristic:\n                    return None\n                # tcache is per-thread, so the address obtained by a symbol is depending on the current thread.\n                # so we get all tcaches from all threads and take the address closest to self.heap_base.\n                orig_thread = gdb.selected_thread()\n                orig_frame = gdb.selected_frame()\n                if not orig_thread: # orig_thread may be None if under winedbg\n                    return None\n                tcache = None\n                for thread in gdb.selected_inferior().threads():\n                    thread.switch() # change thread\n                    try:\n                        tcache_candidate = AddressUtil.parse_address(\"(void*) tcache\")\n                        if tcache_candidate <= self.heap_base:\n                            continue\n                        if tcache is None or tcache > tcache_candidate:\n                            tcache = tcache_candidate\n                    except gdb.error:\n                        tcache_candidate = None\n                        break\n                orig_thread.switch() # revert thread\n                orig_frame.select()\n                return tcache\n\n            def tcache_from_heuristic_offset():\n                # In 2.42 and later, tcache_perthread_struct is not necessarily the first chunk,\n                # so this detection method does not work.\n                if get_libc_version() >= (2, 42):\n                    return None\n\n                # There is no problem if you allocate a small chunk (in the size range of tcache)\n                # at the beginning after executing the binary. Here is an example.\n\n                # In a 64-bit environment, the first 8 bytes are zeros\n                \"\"\"\n                [2.42; x64 main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x555555559000\n                gef> telescope -n 0x555555559000 3\n                      0x555555559000|+0x0000|+000: 0x0000000000000000 <----- here\n                      0x555555559008|+0x0008|+001: 0x0000000000000301\n                      0x555555559010|+0x0010|+002: 0x0007000700070000\n                gef>\n\n                [2.42; x64 non-main-heap]\n                gef> pi GlibcHeap.get_arena(1).heap_base\n                0x7fffe80008d0\n                gef> telescope -n 0x7fffe80008d0 3\n                      0x7fffe80008d0|+0x0000|+000: 0x0000000000000000 <----- here\n                      0x7fffe80008d8|+0x0008|+001: 0x0000000000000305\n                      0x7fffe80008e0|+0x0010|+002: 0x0007000700070000\n                gef>\n\n                [2.42; x64 static; main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x4e5d40\n                gef> telescope -n 0x4e5d40 3\n                      0x0000004e5d40|+0x0000|+000: 0x0000000000000000 <----- here\n                      0x0000004e5d48|+0x0008|+001: 0x0000000000000301\n                      0x0000004e5d50|+0x0010|+002: 0x0007000700070000\n                gef>\n                \"\"\"\n\n                # On some 32-bit architectures, the first 8 bytes of main-heap are zeros.\n                \"\"\"\n                [2.42; x86 main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x5655a000\n                gef> telescope -n 0x5655a000 6\n                      0x5655a000|+0x0000|+000: 0x00000000 <----- here\n                      0x5655a004|+0x0004|+001: 0x00000000 <----- here\n                      0x5655a008|+0x0008|+002: 0x00000000\n                      0x5655a00c|+0x000c|+003: 0x000001d1\n                      0x5655a010|+0x0010|+004: 0x00000007\n                      0x5655a014|+0x0014|+005: 0x00070007\n                gef>\n\n                [2.42; x86 non-main-heap]\n                gef> pi GlibcHeap.get_arena(1).heap_base\n                0xf6a00478\n                gef> telescope -n 0xf6a00478 4\n                      0xf6a00478|+0x0000|+000: 0x00000000\n                      0xf6a0047c|+0x0004|+001: 0x000001d5\n                      0xf6a00480|+0x0008|+002: 0x00000007\n                      0xf6a00484|+0x000c|+003: 0x00070007\n                gef>\n\n                [2.42; x86 static; main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x810c880\n                gef> telescope -n 0x810c880 6\n                      0x0810c880|+0x0000|+000: 0x00000000 <----- here\n                      0x0810c884|+0x0004|+001: 0x00000000 <----- here\n                      0x0810c888|+0x0008|+002: 0x00000000\n                      0x0810c88c|+0x000c|+003: 0x000001d1\n                      0x0810c890|+0x0010|+004: 0x00000007\n                      0x0810c894|+0x0014|+005: 0x00070007\n                gef>\n                \"\"\"\n\n                # On most 32-bit architectures, the first 8 bytes are non-zeros\n                \"\"\"\n                [2.42; arm32 main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x421000\n                gef> telescope -n 0x421000 4\n                      0x00421000|+0x0000|+000: 0x00000000\n                      0x00421004|+0x0004|+001: 0x000001d1\n                      0x00421008|+0x0008|+002: 0x00000007\n                      0x0042100c|+0x000c|+003: 0x00070007\n                gef>\n\n                [2.42; arm32 non-main-heap]\n                gef> pi GlibcHeap.get_arena(1).heap_base\n                0x41b00470\n                gef> telescope -n 0x41b00470 4\n                      0x41b00470|+0x0000|+000: 0x00000000\n                      0x41b00474|+0x0004|+001: 0x000001d5\n                      0x41b00478|+0x0008|+002: 0x00000007\n                      0x41b0047c|+0x000c|+003: 0x00070007\n                gef>\n\n                [2.42; arm32 static; main-heap]\n                gef> pi GlibcHeap.get_arena(0).heap_base\n                0x84880\n                gef> telescope -n 0x84880 4\n                      0x00084880|+0x0000|+000: 0x00000000\n                      0x00084884|+0x0004|+001: 0x000001d1\n                      0x00084888|+0x0008|+002: 0x00000007\n                      0x0008488c|+0x000c|+003: 0x00070007\n                gef>\n                \"\"\"\n                first_8 = read_memory(self.heap_base, 8)\n                if first_8 == b\"\\0\\0\\0\\0\\0\\0\\0\\0\":\n                    return self.heap_base + 0x10\n                else:\n                    return self.heap_base + 0x8\n\n            # strict way (from symbol)\n            tcache = tcache_from_symbol()\n            if is_valid_addr(tcache):\n                return tcache\n\n            # heuristic way 1\n            tcache = tcache_from_heuristic_offset()\n            if tcache:\n                return tcache\n\n            # heuristic way 2\n            tcache = GlibcHeap.search_for_tcache_from_tls(self.addr)\n            if tcache:\n                return tcache\n\n            return None\n\n        def addrof_tcachebins_i_count(self, i):\n            \"\"\"return &tcache_perthread_struct.counts[i]\n            or return &tcache_perthread_struct.num_slots[i]\"\"\"\n            tcache_perthread_struct = self.tcache_perthread_struct\n            if tcache_perthread_struct is None:\n                return None\n\n            \"\"\"\n            [2.26~2.29]\n            # define TCACHE_MAX_BINS 64\n            typedef struct tcache_perthread_struct\n            {\n              char counts[TCACHE_MAX_BINS];\n              tcache_entry *entries[TCACHE_MAX_BINS];\n            } tcache_perthread_struct;\n\n            [2.30~2.41]\n            # define TCACHE_MAX_BINS 64\n            typedef struct tcache_perthread_struct\n            {\n              uint16_t counts[TCACHE_MAX_BINS];\n              tcache_entry *entries[TCACHE_MAX_BINS];\n            } tcache_perthread_struct;\n\n            [2.42~]\n            # define TCACHE_SMALL_BINS 64\n            # define TCACHE_LARGE_BINS 12\n            # define TCACHE_MAX_BINS (TCACHE_SMALL_BINS + TCACHE_LARGE_BINS)\n            typedef struct tcache_perthread_struct\n            {\n              uint16_t num_slots[TCACHE_MAX_BINS];\n              tcache_entry *entries[TCACHE_MAX_BINS];\n            } tcache_perthread_struct;\n            \"\"\"\n            if get_libc_version() < (2, 30):\n                offset = i\n            else:\n                offset = i * 2\n            return tcache_perthread_struct + offset\n\n        def tcachebins_i_count(self, i):\n            \"\"\"return tcache_perthread_struct.counts[i]\"\"\"\n            counts_i_addr = self.addrof_tcachebins_i_count(i)\n            if counts_i_addr is None:\n                return None\n\n            if get_libc_version() < (2, 30):\n                count = read_int8_from_memory(counts_i_addr)\n            else:\n                count = read_int16_from_memory(counts_i_addr)\n\n            if get_libc_version() >= (2, 42): # num_slot -> count\n                count = self.TCACHE_FILL_COUNT() - count\n            return count\n\n        def addrof_tcachebins_i(self, i):\n            \"\"\"return &tcache_perthread_struct.entries[i]\"\"\"\n            tcache_perthread_struct = self.tcache_perthread_struct\n            if tcache_perthread_struct is None:\n                return None\n\n            if get_libc_version() < (2, 30):\n                sizeof_counts = self.TCACHE_MAX_BINS()\n            else:\n                sizeof_counts = self.TCACHE_MAX_BINS() * 2\n\n            return tcache_perthread_struct + sizeof_counts + current_arch.ptrsize * i\n\n        def addrof_fastbins_i(self, i):\n            if hasattr(self.__arena, \"addrof_fastbins\"):\n                fastbins_addr = self.__arena.addrof_fastbins\n            else:\n                fastbins_type = [x for x in self.__arena.type.fields() if x.name == \"fastbinsY\"][0]\n                fastbins_addr = self.__addr + fastbins_type.bitpos // 8\n            return fastbins_addr + i * current_arch.ptrsize\n\n        def addrof_top(self):\n            if hasattr(self.__arena, \"addrof_top\"):\n                top_addr = self.__arena.addrof_top\n            else:\n                top_type = [x for x in self.__arena.type.fields() if x.name == \"top\"][0]\n                top_addr = self.__addr + top_type.bitpos // 8\n            return top_addr\n\n        def addrof_last_remainder(self):\n            if hasattr(self.__arena, \"addrof_last_remainder\"):\n                last_remainder_addr = self.__arena.addrof_last_remainder\n            else:\n                last_remainder_type = [x for x in self.__arena.type.fields() if x.name == \"last_remainder\"][0]\n                last_remainder_addr = self.__addr + last_remainder_type.bitpos // 8\n            return last_remainder_addr\n\n        def addrof_bins_i(self, i):\n            if hasattr(self.__arena, \"addrof_bins\"):\n                bins_addr = self.__arena.addrof_bins\n            else:\n                bins_type = [x for x in self.__arena.type.fields() if x.name == \"bins\"][0]\n                bins_addr = self.__addr + bins_type.bitpos // 8\n            return bins_addr + i * current_arch.ptrsize * 2\n\n        def addrof_next(self):\n            if hasattr(self.__arena, \"addrof_next\"):\n                next_addr = self.__arena.addrof_next\n            else:\n                next_type = [x for x in self.__arena.type.fields() if x.name == \"next\"][0]\n                next_addr = self.__addr + next_type.bitpos // 8\n            return next_addr\n\n        def addrof_next_free(self):\n            if hasattr(self.__arena, \"addrof_next_free\"):\n                next_free_addr = self.__arena.addrof_next_free\n            else:\n                next_free_type = [x for x in self.__arena.type.fields() if x.name == \"next_free\"][0]\n                next_free_addr = self.__addr + next_free_type.bitpos // 8\n            return next_free_addr\n\n        def addrof_system_mem(self):\n            if hasattr(self.__arena, \"addrof_system_mem\"):\n                system_mem_addr = self.__arena.addrof_system_mem\n            else:\n                system_mem_type = [x for x in self.__arena.type.fields() if x.name == \"system_mem\"][0]\n                system_mem_addr = self.__addr + system_mem_type.bitpos // 8\n            return system_mem_addr\n\n        def get_tcachebins_i(self, i):\n            \"\"\"Return head chunk in tcache[i].\"\"\"\n            tcache_i_head = self.addrof_tcachebins_i(i)\n            if not tcache_i_head:\n                return None\n            addr = AddressUtil.dereference(tcache_i_head)\n            if not addr:\n                return None\n            return GlibcHeap.GlibcChunk(self, int(addr))\n\n        def get_fastbins_i(self, i):\n            \"\"\"Return head chunk in fastbinsY[i].\"\"\"\n            addr = int(self.fastbinsY[i])\n            if addr == 0:\n                return None\n            return GlibcHeap.GlibcChunk(self, addr + 2 * current_arch.ptrsize)\n\n        def get_bins_i(self, i):\n            \"\"\"Return the forward and backward pointers for the specified bin index.\"\"\"\n            idx = i * 2\n            fd = int(self.bins[idx])\n            bw = int(self.bins[idx + 1])\n            return fd, bw\n\n        def get_next(self):\n            \"\"\"Return the next arena object if available; otherwise returns None.\"\"\"\n            try:\n                addr_next = int(self.next)\n                if addr_next == 0:\n                    return None\n                if addr_next == GlibcHeap.get_main_arena().addr:\n                    return None\n                next_arena = GlibcHeap.GlibcArena(addr_next)\n                str(next_arena) # check memory error\n                return next_arena\n            except gdb.error:\n                return None\n\n        def __str__(self):\n            \"\"\"Return a formatted string representation of the arena and its key attributes.\"\"\"\n            arena = Color.colorify(\"Arena\", Config.get_gef_setting(\"theme.heap_arena_label\"))\n            if self.heap_base is None:\n                heap_base = \"uninitialized\"\n            else:\n                heap_base = ProcessMap.lookup_address(self.heap_base)\n            arena_addr = ProcessMap.lookup_address(self.__addr)\n            top = ProcessMap.lookup_address(self.top)\n            if is_valid_addr(self.last_remainder):\n                last_remainder = ProcessMap.lookup_address(self.last_remainder)\n            else:\n                last_remainder = hex(self.last_remainder)\n            next = ProcessMap.lookup_address(self.next)\n            system_mem = int(self.system_mem)\n            try:\n                if is_valid_addr(self.next_free):\n                    next_free = ProcessMap.lookup_address(self.next_free)\n                else:\n                    next_free = hex(self.next_free)\n                fmt = \"{:s}(addr={!s}, heap_base={!s}, top={!s}, last_remainder={!s}, \"\n                fmt += \"next={!s}, next_free={!s}, system_mem={:#x})\"\n                args = (arena, arena_addr, heap_base, top, last_remainder, next, next_free, system_mem)\n            except (gdb.error, TypeError):\n                fmt = \"{:s}(addr={!s}, heap_base={!s}, top={!s}, last_remainder={!s}, \"\n                fmt += \"next={!s}, system_mem={:#x})\"\n                args = (arena, arena_addr, heap_base, top, last_remainder, next, system_mem)\n            return fmt.format(*args)\n\n        def get_tcache_list(self):\n            \"\"\"Return a dictionary mapping tcache bin indices to lists of chunk addresses,\n            handling loops and corruption.\"\"\"\n            if get_libc_version() < (2, 26):\n                return {}\n\n            if self.heap_base is None:\n                return {}\n\n            chunks_all = {}\n            for i in range(self.TCACHE_MAX_BINS()):\n                # head check\n                try:\n                    chunk = self.get_tcachebins_i(i)\n                except gdb.MemoryError:\n                    chunks_all[i] = [\"Corrupted\"]\n                    continue\n\n                # parse list\n                chunks = []\n                while chunk is not None:\n                    if chunk.address in chunks:\n                        chunks.append(chunk.address)\n                        chunks.append(\"Loop detected\")\n                        break # loop detected\n\n                    chunks.append(chunk.address)\n                    next_chunk = chunk.get_fwd_ptr(True)\n                    if next_chunk is None:\n                        chunks.append(\"Corrupted\")\n                        break # invalid\n\n                    if next_chunk == 0:\n                        break # valid end\n\n                    chunk = GlibcHeap.GlibcChunk(self, next_chunk)\n                chunks_all[i] = chunks\n\n            return chunks_all\n\n        def get_fastbins_list(self):\n            \"\"\"Return a dictionary of fastbin indices mapped to lists of chunk addresses,\n            handling loops and corruption.\"\"\"\n            if get_libc_version() >= (2, 43):\n                return {}\n\n            def fastbin_index(sz):\n                return (sz >> 4) - 2 if SIZE_SZ == 8 else (sz >> 3) - 2\n\n            SIZE_SZ = current_arch.ptrsize\n            MAX_FAST_SIZE = (80 * SIZE_SZ // 4)\n            NFASTBINS = fastbin_index(MAX_FAST_SIZE) - 1\n            chunks_all = {}\n            for i in range(NFASTBINS):\n                # head check\n                try:\n                    chunk = self.get_fastbins_i(i)\n                except gdb.MemoryError:\n                    chunks_all[i] = [\"Corrupted\"]\n                    continue\n\n                # parse list\n                chunks = []\n                while chunk is not None:\n                    if chunk.address in chunks:\n                        chunks.append(chunk.address)\n                        chunks.append(\"Loop detected\")\n                        break # loop detected\n\n                    chunks.append(chunk.address)\n                    next_chunk = chunk.get_fwd_ptr(True)\n                    if next_chunk is None:\n                        chunks.append(\"Corrupted\")\n                        break # invalid\n\n                    if next_chunk == 0:\n                        break # valid end\n\n                    chunk = GlibcHeap.GlibcChunk(self, next_chunk, from_base=True)\n                chunks_all[i] = chunks\n\n            return chunks_all\n\n        def get_bins_list(self, index):\n            \"\"\"Return a list of chunk addresses in the specified bin, handling loops and corruption.\"\"\"\n            try:\n                fw, bk = self.get_bins_i(index)\n            except gdb.MemoryError:\n                return [\"Corrupted\"]\n            if bk == 0x00 and fw == 0x00:\n                return [\"Corrupted\"]\n\n            head = self.addrof_bins_i(index) - current_arch.ptrsize * 2\n            if fw == head:\n                return [] # no entry\n\n            corrupted = False\n            chunks_bk = []\n\n            # first: process backward\n            while bk != head:\n                chunk = GlibcHeap.GlibcChunk(self, bk, from_base=True)\n\n                if chunk.chunk_base_address in chunks_bk:\n                    chunks_bk.append(chunk.chunk_base_address)\n                    chunks_bk.append(\"Loop detected\")\n                    corrupted = True\n                    break\n\n                chunks_bk.append(chunk.chunk_base_address)\n\n                bk = chunk.bck\n                if bk is None:\n                    chunks_bk.append(\"Corrupted\")\n                    corrupted = True\n                    break\n\n            chunks = chunks_bk[::-1]\n\n            if corrupted:\n                # second: process forward\n                chunks_fw = []\n                while fw != head:\n                    chunk = GlibcHeap.GlibcChunk(self, fw, from_base=True)\n\n                    if chunk.chunk_base_address in chunks:\n                        break # meet backward's list\n                    if chunk.chunk_base_address in chunks_fw:\n                        break # loop\n\n                    chunks_fw.append(chunk.chunk_base_address)\n                    fw = chunk.fwd\n                    if fw is None:\n                        break # corrupted\n\n                chunks = chunks_fw + chunks\n\n            return chunks\n\n        def get_unsortedbin_list(self):\n            \"\"\"Return a dictionary containing the list of chunks in the unsorted bin.\"\"\"\n            chunks_all = {}\n            chunks_all[0] = self.get_bins_list(0)\n            return chunks_all\n\n        def get_smallbins_list(self):\n            \"\"\"Return a dictionary mapping small bin indices to lists of chunk addresses.\"\"\"\n            chunks_all = {}\n            for i in range(1, 63):\n                chunks_all[i] = self.get_bins_list(i)\n            return chunks_all\n\n        def get_largebins_list(self):\n            \"\"\"Return a dictionary mapping large bin indices to lists of chunk addresses.\"\"\"\n            chunks_all = {}\n            for i in range(63, 126):\n                chunks_all[i] = self.get_bins_list(i)\n            return chunks_all\n\n        def reset_cache(self):\n            \"\"\"Make some caches.\n                - cached_XXX_list\n                - cached_XXX_addr_list\n                - bins_dict_for_address\n                - bins_dict_for_base_address\n            \"\"\"\n            # cached_XXX_list = {bin_idx1: [chunk, chunk, ...], bin_idx2: [chunk, chunk, ...]}\n            self.cached_tcache_list = self.get_tcache_list()\n            self.cached_fastbins_list = self.get_fastbins_list()\n            self.cached_unsortedbin_list = self.get_unsortedbin_list()\n            self.cached_smallbins_list = self.get_smallbins_list()\n            self.cached_largebins_list = self.get_largebins_list()\n\n            def int_filter(a):\n                return {x for x in a if isinstance(x, int)}\n\n            # cacheed_XXX_addr_list = {chunk, chunk, ...}\n            self.cached_tcache_addr_list = int_filter(set().union(*self.cached_tcache_list.values()))\n            self.cached_fastbins_addr_list = int_filter(set().union(*self.cached_fastbins_list.values()))\n            self.cached_unsortedbin_addr_list = int_filter(self.cached_unsortedbin_list[0])\n            self.cached_smallbins_addr_list = int_filter(set().union(*self.cached_smallbins_list.values()))\n            self.cached_largebins_addr_list = int_filter(set().union(*self.cached_largebins_list.values()))\n\n            # dict[address] = [\"bins info1\", \"bins info2\", ...]\n            self.bins_dict_for_address = {}\n            for tcache_idx, tcache_list in self.cached_tcache_list.items():\n                for address in tcache_list:\n                    if not isinstance(address, int):\n                        continue\n                    pos = \",\".join([str(i + 1) for i, x in enumerate(tcache_list) if x == address])\n                    if \"size\" in  GlibcHeap.get_binsize_table()[\"tcache\"][tcache_idx]:\n                        sz = GlibcHeap.get_binsize_table()[\"tcache\"][tcache_idx][\"size\"]\n                        m = \"tcache[idx={:d},sz={:#x}][{:s}/{:d}]\".format(tcache_idx, sz, pos, len(tcache_list))\n                    else:\n                        sz_min = GlibcHeap.get_binsize_table()[\"tcache\"][tcache_idx][\"size_min\"]\n                        sz_max = GlibcHeap.get_binsize_table()[\"tcache\"][tcache_idx][\"size_max\"]\n                        m = \"tcache[idx={:d},sz={:#x}-{:#x}][{:s}/{:d}]\".format(\n                            tcache_idx, sz_min, sz_max, pos, len(tcache_list),\n                        )\n                    new_list = self.bins_dict_for_address.get(address, []) + [m]\n                    self.bins_dict_for_address[address] = new_list\n\n            for fastbin_idx, fastbin_list in self.cached_fastbins_list.items():\n                for address in set(fastbin_list):\n                    if not isinstance(address, int):\n                        continue\n                    pos = \",\".join([str(i + 1) for i, x in enumerate(fastbin_list) if x == address])\n                    sz = GlibcHeap.get_binsize_table()[\"fastbins\"][fastbin_idx][\"size\"]\n                    m = \"fastbins[idx={:d},sz={:#x}][{:s}/{:d}]\".format(fastbin_idx, sz, pos, len(fastbin_list))\n                    new_list = self.bins_dict_for_address.get(address, []) + [m]\n                    self.bins_dict_for_address[address] = new_list\n\n            # dict[base_address] = [\"bins info1\", \"bins info2\", ...]\n            self.bins_dict_for_base_address = {}\n            for _, unsortedbin_list in self.cached_unsortedbin_list.items():\n                for base_address in unsortedbin_list:\n                    if not isinstance(base_address, int):\n                        continue\n                    pos = \",\".join([str(i + 1) for i, x in enumerate(unsortedbin_list) if x == base_address])\n                    m = \"unsortedbins[{:s}/{:d}]\".format(pos, len(unsortedbin_list))\n                    new_list = self.bins_dict_for_base_address.get(base_address, []) + [m]\n                    self.bins_dict_for_base_address[base_address] = new_list\n\n            for smallbin_idx, smallbin_list in self.cached_smallbins_list.items():\n                for base_address in smallbin_list:\n                    if not isinstance(base_address, int):\n                        continue\n                    pos = \",\".join([str(i + 1) for i, x in enumerate(smallbin_list) if x == base_address])\n                    sz = GlibcHeap.get_binsize_table()[\"small_bins\"][smallbin_idx][\"size\"]\n                    m = \"smallbins[idx={:d},sz={:#x}][{:s}/{:d}]\".format(smallbin_idx, sz, pos, len(smallbin_list))\n                    new_list = self.bins_dict_for_base_address.get(base_address, []) + [m]\n                    self.bins_dict_for_base_address[base_address] = new_list\n\n            for largebin_idx, largebin_list in self.cached_largebins_list.items():\n                for base_address in largebin_list:\n                    if not isinstance(base_address, int):\n                        continue\n                    pos = \",\".join([str(i + 1) for i, x in enumerate(largebin_list) if x == base_address])\n                    sz_min = GlibcHeap.get_binsize_table()[\"large_bins\"][largebin_idx][\"size_min\"]\n                    sz_max = GlibcHeap.get_binsize_table()[\"large_bins\"][largebin_idx][\"size_max\"]\n                    m = \"largebins[idx={:d},sz={:#x}-{:#x}][{:s}/{:d}]\".format(\n                        largebin_idx, sz_min, sz_max, pos, len(largebin_list),\n                    )\n                    new_list = self.bins_dict_for_base_address.get(base_address, []) + [m]\n                    self.bins_dict_for_base_address[base_address] = new_list\n            return\n\n        def is_chunk_in_tcache(self, chunk):\n            if not hasattr(self, \"cached_tcache_addr_list\"):\n                self.reset_cache()\n            return chunk.address in self.cached_tcache_addr_list\n\n        def is_chunk_in_fastbins(self, chunk):\n            if not hasattr(self, \"cached_fastbins_addr_list\"):\n                self.reset_cache()\n            return chunk.address in self.cached_fastbins_addr_list\n\n        def is_chunk_in_unsortedbin(self, chunk):\n            if not hasattr(self, \"cached_unsortedbin_addr_list\"):\n                self.reset_cache()\n            return chunk.chunk_base_address in self.cached_unsortedbin_addr_list\n\n        def is_chunk_in_smallbins(self, chunk):\n            if not hasattr(self, \"cached_smallbins_addr_list\"):\n                self.reset_cache()\n            return chunk.chunk_base_address in self.cached_smallbins_addr_list\n\n        def is_chunk_in_largebins(self, chunk):\n            if not hasattr(self, \"cached_largebins_addr_list\"):\n                self.reset_cache()\n            return chunk.chunk_base_address in self.cached_largebins_addr_list\n\n        def is_chunk_in_freelists(self, chunk):\n            if self.is_chunk_in_tcache(chunk):\n                return True\n            if self.is_chunk_in_fastbins(chunk):\n                return True\n            if self.is_chunk_in_unsortedbin(chunk):\n                return True\n            if self.is_chunk_in_smallbins(chunk):\n                return True\n            if self.is_chunk_in_largebins(chunk):\n                return True\n            return False\n\n        def get_bins_info(self, address_or_chunk, skip_top=False):\n            \"\"\"Return a list of bin information for the given address or chunk,\n            optionally including the \"top\" marker.\"\"\"\n            if isinstance(address_or_chunk, GlibcHeap.GlibcChunk):\n                address = address_or_chunk.address\n                base_address = address_or_chunk.chunk_base_address\n            elif isinstance(address_or_chunk, int):\n                address = address_or_chunk\n                base_address = address_or_chunk\n\n            info = []\n            if not hasattr(self, \"bins_dict_for_address\"):\n                self.reset_cache()\n            info.extend(self.bins_dict_for_address.get(address, []))\n\n            if not hasattr(self, \"bins_dict_for_base_address\"):\n                self.reset_cache()\n            info.extend(self.bins_dict_for_base_address.get(base_address, []))\n\n            if not skip_top:\n                if base_address == self.top:\n                    info.append(\"top\")\n            return info\n\n    @staticmethod\n    def get_arena(address=None):\n        \"\"\"Return the arena object for the given address or arena index, or None if not found.\"\"\"\n        if address is None or is_valid_addr(address):\n            try:\n                arena = GlibcHeap.GlibcArena(address)\n                str(arena) # check memory error\n                return arena\n            except (OSError, AttributeError, gdb.MemoryError, RuntimeError):\n                err(\"Failed to get the arena, heap commands may not work properly\")\n                return None\n\n        # interpret `address` as the number, not the address of arena.\n        arena_number = address\n\n        # main_arena\n        arena = GlibcHeap.get_main_arena()\n        if arena is None:\n            return None\n\n        arenas = []\n        while arena:\n            arenas.append(arena)\n            arena = arena.get_next()\n\n        if arena_number >= len(arenas):\n            err(\"Failed to get the arena, heap commands may not work properly\")\n            return None\n\n        return arenas[arena_number]\n\n    @staticmethod\n    def get_main_arena():\n        return GlibcHeap.get_arena(None)\n\n    @staticmethod\n    def get_all_arenas():\n        arenas = []\n        arena = GlibcHeap.get_main_arena()\n        while arena:\n            arenas.append(arena)\n            arena = arena.get_next()\n        return arenas\n\n    class GlibcChunk:\n        \"\"\"Glibc chunk class.\"\"\"\n\n        def __init__(self, arena, addr, from_base=False):\n            self.arena = arena\n            self.ptrsize = current_arch.ptrsize\n            if from_base:\n                self.chunk_base_address = addr\n                self.address = addr + 2 * self.ptrsize\n            else:\n                self.chunk_base_address = AddressUtil.align_address(addr - 2 * self.ptrsize)\n                self.address = addr\n\n            self.size_addr = AddressUtil.align_address(self.address - self.ptrsize)\n            self.prev_size_addr = self.chunk_base_address\n            return\n\n        def get_chunk_size(self):\n            return read_int_from_memory(self.size_addr) & (~0x07)\n\n        @property\n        def size(self):\n            return self.get_chunk_size()\n\n        def get_usable_size(self):\n            cursz = self.get_chunk_size()\n            if cursz == 0:\n                return cursz\n            if self.has_m_bit():\n                return cursz - 2 * self.ptrsize\n            return cursz - self.ptrsize\n\n        def get_prev_chunk_size(self):\n            return read_int_from_memory(self.prev_size_addr)\n\n        def get_next_chunk(self):\n            try:\n                addr = self.address + self.get_chunk_size()\n                return GlibcHeap.GlibcChunk(self.arena, addr)\n            except gdb.MemoryError:\n                return None\n\n        # if freed functions\n        def get_fwd_ptr(self, sll):\n            try:\n                # Not a single-linked-list (sll) or no Safe-Linking support yet\n                if not sll or get_libc_version() < (2, 32):\n                    return read_int_from_memory(self.address)\n                # Unmask (\"reveal\") the Safe-Linking pointer\n                else:\n                    return read_int_from_memory(self.address) ^ (self.address >> 12)\n            except gdb.MemoryError:\n                return None\n\n        @property\n        def fwd(self):\n            return self.get_fwd_ptr(False)\n\n        fd = fwd # for compat\n\n        def get_bkw_ptr(self):\n            try:\n                return read_int_from_memory(self.address + self.ptrsize)\n            except gdb.MemoryError:\n                return None\n\n        @property\n        def bck(self):\n            return self.get_bkw_ptr()\n\n        bk = bck # for compat\n\n        def get_fd_nextsize_ptr(self):\n            return read_int_from_memory(self.address + self.ptrsize * 2)\n\n        @property\n        def fd_nextsize(self):\n            return self.get_fd_nextsize_ptr()\n\n        def get_bk_nextsize_ptr(self):\n            return read_int_from_memory(self.address + self.ptrsize * 3)\n\n        @property\n        def bk_nextsize(self):\n            return self.get_bk_nextsize_ptr()\n        # endif freed functions\n\n        def has_p_bit(self):\n            return read_int_from_memory(self.size_addr) & 0x01\n\n        def has_m_bit(self):\n            return read_int_from_memory(self.size_addr) & 0x02\n\n        def has_n_bit(self):\n            return read_int_from_memory(self.size_addr) & 0x04\n\n        def is_used(self):\n            # Check if the current block is used by:\n            # - checking the M bit is true\n            # - or checking that next chunk PREV_INUSE flag is true\n            if self.has_m_bit():\n                return True\n            next_chunk = self.get_next_chunk()\n            try:\n                return True if next_chunk.has_p_bit() else False\n            except gdb.MemoryError as e:\n                # top?\n                if (next_chunk.chunk_base_address & 0xfff) == 0:\n                    if is_valid_addr(next_chunk.chunk_base_address - 1):\n                        return False\n                raise gdb.MemoryError from e\n\n        def is_real_used(self):\n            # Even if a chunk has been freed, if it is in tcache or fastbin,\n            # the PREV_IN_USE bit of the chunk directly below it will be set.\n            # This bit will be ignored and we will determine whether it is on the free list.\n            if self.arena.top == self.chunk_base_address:\n                return False\n            return not self.arena.is_chunk_in_freelists(self)\n\n        def is_top(self):\n            return self.arena.top == self.chunk_base_address\n\n        def str_chunk_size_flag(self):\n            msg = []\n            if self.has_p_bit():\n                msg.append(\"  PREV_INUSE flag: {}\".format(Color.greenify(\"On\")))\n            else:\n                msg.append(\"  PREV_INUSE flag: {}\".format(Color.redify(\"Off\")))\n            if self.has_m_bit():\n                msg.append(\"  IS_MMAPPED flag: {}\".format(Color.greenify(\"On\")))\n            else:\n                msg.append(\"  IS_MMAPPED flag: {}\".format(Color.redify(\"Off\")))\n            if self.has_n_bit():\n                msg.append(\"  NON_MAIN_ARENA flag: {}\".format(Color.greenify(\"On\")))\n            else:\n                msg.append(\"  NON_MAIN_ARENA flag: {}\".format(Color.redify(\"Off\")))\n            return \"\\n\".join(msg)\n\n        def _str_sizes(self):\n            msg = []\n            failed = False\n\n            try:\n                msg.append(\"  Chunk size: {:#x}\".format(self.get_chunk_size()))\n                msg.append(\"  Usable size: {:#x}\".format(self.get_usable_size()))\n            except gdb.MemoryError:\n                msg.append(\"  Chunk size: Cannot read at {:#x} (Corrupted?)\".format(self.size_addr))\n                failed = True\n\n            if self.has_p_bit():\n                msg.append(\"  Previous chunk size: ??? (PREV_INUSE flag: On)\")\n            else:\n                try:\n                    msg.append(\"  Previous chunk size: {:#x}\".format(self.get_prev_chunk_size()))\n                except gdb.MemoryError:\n                    msg.append(\"  Previous chunk size: Cannot read at {:#x} (Corrupted?)\".format(self.chunk_base_address))\n                    failed = True\n\n            if not failed:\n                msg.append(self.str_chunk_size_flag())\n\n            return \"\\n\".join(msg)\n\n        def _str_pointers(self):\n            fwd = self.address\n            bkw = self.address + self.ptrsize\n\n            msg = []\n            try:\n                msg.append(\"  Forward pointer: {:#x}\".format(self.get_fwd_ptr(False)))\n            except gdb.MemoryError:\n                msg.append(\"  Forward pointer: {:#x} (Corrupted?)\".format(fwd))\n\n            try:\n                msg.append(\"  Backward pointer: {:#x}\".format(self.get_bkw_ptr()))\n            except gdb.MemoryError:\n                msg.append(\"  Backward pointer: {:#x} (Corrupted?)\".format(bkw))\n\n            return \"\\n\".join(msg)\n\n        def str_as_alloced(self):\n            return self._str_sizes()\n\n        def str_as_freed(self):\n            return \"{}\\n\\n{}\".format(self._str_sizes(), self._str_pointers())\n\n        def flags_as_string(self):\n            flags = []\n            if self.has_p_bit():\n                flags.append(Color.colorify(\n                    \"PREV_INUSE\", Config.get_gef_setting(\"theme.heap_chunk_flag_prev_inuse\"),\n                ))\n            if self.has_m_bit():\n                flags.append(Color.colorify(\n                    \"IS_MMAPPED\", Config.get_gef_setting(\"theme.heap_chunk_flag_is_mmapped\"),\n                ))\n            if self.has_n_bit():\n                flags.append(Color.colorify(\n                    \"NON_MAIN_ARENA\", Config.get_gef_setting(\"theme.heap_chunk_flag_non_main_arena\"),\n                ))\n            return \"|\".join(flags)\n\n        def __str__(self):\n            \"\"\"Return a formatted string representation of the chunk and its key attributes,\n            including color and symbol information.\"\"\"\n\n            def get_sym(addr):\n                a = ProcessMap.lookup_address(addr)\n                b = Symbol.get_symbol_string(addr)\n                return a, b\n\n            def get_sym_chunk(addr):\n                a = ProcessMap.lookup_address(addr)\n                b1 = Color.colorify_hex(addr, Config.get_gef_setting(\"theme.heap_chunk_address_freed\"))\n                b2 = Color.colorify_hex(addr, Config.get_gef_setting(\"theme.heap_chunk_address_used\"))\n                c = Symbol.get_symbol_string(addr)\n                return a, (b1, b2), c\n\n            def get_err(addrs, sll=False):\n                for a in addrs:\n                    if not a.valid:\n                        if sll and a.value == 0:\n                            # single link-list && 0: ok\n                            continue\n                        return \" [{:s}]\".format(Color.colorify(\n                            \"Corrupted\", Config.get_gef_setting(\"theme.heap_corrupted_msg\"),\n                        ))\n                return \"\"\n\n            chunk_c = Color.colorify(\"Chunk\", Config.get_gef_setting(\"theme.heap_chunk_label\"))\n            size_c = Color.colorify_hex(self.get_chunk_size(), Config.get_gef_setting(\"theme.heap_chunk_size\"))\n            base, (base_c_f, base_c_u), base_sym = get_sym_chunk(self.chunk_base_address)\n            addr, (addr_c_f, addr_c_u), addr_sym = get_sym_chunk(self.address)\n            flags = self.flags_as_string()\n\n            # large bins\n            if self.arena.is_chunk_in_largebins(self):\n                fd, fd_sym = get_sym(self.fd)\n                bk, bk_sym = get_sym(self.bk)\n                err = get_err([fd, bk])\n                if is_valid_addr(self.fd_nextsize) or is_valid_addr(self.bk_nextsize):\n                    # largebin and valid (fd|bk)_nextsize\n                    fdn, fdn_sym = get_sym(self.fd_nextsize)\n                    bkn, bkn_sym = get_sym(self.bk_nextsize)\n                    fmt = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s}, fd={!s}{:s}, bk={!s}{:s}, \"\n                    fmt += \"fd_nextsize={!s}{:s}, bk_nextsize={!s}{:s})\"\n                    msg = fmt.format(\n                        chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags,\n                        fd, fd_sym, bk, bk_sym, fdn, fdn_sym, bkn, bkn_sym, err,\n                    )\n                else:\n                    msg = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s}, fd={!s}{:s}, bk={!s}{:s}{:s})\".format(\n                        chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags, fd, fd_sym, bk, bk_sym, err,\n                    )\n\n            # small bins / unsorted bin\n            elif self.arena.is_chunk_in_smallbins(self) or self.arena.is_chunk_in_unsortedbin(self):\n                fd, fd_sym = get_sym(self.fd)\n                bk, bk_sym = get_sym(self.bk)\n                err = get_err([fd, bk])\n                msg = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s}, fd={!s}{:s}, bk={!s}{:s}{:s})\".format(\n                    chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags, fd, fd_sym, bk, bk_sym, err,\n                )\n\n            # tcache / fastbins\n            elif self.arena.is_chunk_in_fastbins(self) or self.arena.is_chunk_in_tcache(self):\n                if get_libc_version() < (2, 32):\n                    fd, fd_sym = get_sym(self.get_fwd_ptr(sll=False))\n                    err = get_err([fd], sll=True)\n                    msg = \"{:s}(base={:s}{:s}. addr={:s}{:s}, size={:s}, flags={:s}, fd={!s}{:s}{:s})\".format(\n                        chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags, fd, fd_sym, err,\n                    )\n                else:\n                    fd, fd_sym = get_sym(self.get_fwd_ptr(sll=False))\n                    decoded_fd, decoded_fd_sym = get_sym(self.get_fwd_ptr(sll=True))\n                    err = get_err([decoded_fd], sll=True)\n                    msg = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s}, fd={!s}{:s}(={!s}{:s}){:s})\".format(\n                        chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags,\n                        fd, fd_sym, decoded_fd, decoded_fd_sym, err,\n                    )\n\n            # top\n            elif self.arena.top == self.chunk_base_address:\n                msg = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s})\".format(\n                    chunk_c, base_c_f, base_sym, addr_c_f, addr_sym, size_c, flags,\n                )\n\n            # used chunk\n            else:\n                msg = \"{:s}(base={:s}{:s}, addr={:s}{:s}, size={:s}, flags={:s})\".format(\n                    chunk_c, base_c_u, base_sym, addr_c_u, addr_sym, size_c, flags,\n                )\n            return msg\n\n        def psprint(self):\n            \"\"\"Return a detailed, multi-line string representation of the chunk,\n            showing both its summary and allocation state.\"\"\"\n            msg = []\n            msg.append(str(self))\n            if self.is_used():\n                msg.append(self.str_as_alloced())\n            else:\n                msg.append(self.str_as_freed())\n            return \"\\n\".join(msg)\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_binsize_table():\n        \"\"\"Return a dictionary containing size information for tcache, fastbins, unsorted bin,\n        small bins, and large bins, based on architecture and libc version.\"\"\"\n        table = {\n            \"tcache\": {},\n            \"fastbins\": {},\n            \"unsorted_bin\": {},\n            \"small_bins\": {},\n            \"large_bins\": {},\n        }\n\n        MIN_SIZE = GlibcHeap.HeapInfo.MIN_SIZE()\n        MALLOC_ALIGNMENT = GlibcHeap.HeapInfo.MALLOC_ALIGNMENT()\n\n        # tcache\n        for i in range(64):\n            # MALLOC_ALIGNMENT is changed from libc 2.26.\n            # for x86_32, tcache 0x8 align is no longer used.\n            # but for ARM32, or maybe other arch, still 0x8 align is used.\n            table[\"tcache\"][i] = {\"size\": MIN_SIZE + MALLOC_ALIGNMENT * i}\n\n        if get_libc_version() >= (2, 42):\n            if is_64bit():\n                table[\"tcache\"][64] = {\"size_min\": 0x420, \"size_max\": 0x800}\n                table[\"tcache\"][65] = {\"size_min\": 0x800, \"size_max\": 0x1000}\n                table[\"tcache\"][66] = {\"size_min\": 0x1000, \"size_max\": 0x2000}\n                table[\"tcache\"][67] = {\"size_min\": 0x2000, \"size_max\": 0x4000}\n                table[\"tcache\"][68] = {\"size_min\": 0x4000, \"size_max\": 0x8000}\n                table[\"tcache\"][69] = {\"size_min\": 0x8000, \"size_max\": 0x10000}\n                table[\"tcache\"][70] = {\"size_min\": 0x10000, \"size_max\": 0x20000}\n                table[\"tcache\"][71] = {\"size_min\": 0x20000, \"size_max\": 0x40000}\n                table[\"tcache\"][72] = {\"size_min\": 0x40000, \"size_max\": 0x80000}\n                table[\"tcache\"][73] = {\"size_min\": 0x80000, \"size_max\": 0x100000}\n                table[\"tcache\"][74] = {\"size_min\": 0x100000, \"size_max\": 0x200000}\n                table[\"tcache\"][75] = {\"size_min\": 0x200000, \"size_max\": 0x400000}\n            elif is_x86_32() or is_riscv32() or is_ppc32():\n                table[\"tcache\"][64] = {\"size_min\": 0x410, \"size_max\": 0x800}\n                table[\"tcache\"][65] = {\"size_min\": 0x800, \"size_max\": 0x1000}\n                table[\"tcache\"][66] = {\"size_min\": 0x1000, \"size_max\": 0x2000}\n                table[\"tcache\"][67] = {\"size_min\": 0x2000, \"size_max\": 0x4000}\n                table[\"tcache\"][68] = {\"size_min\": 0x4000, \"size_max\": 0x8000}\n                table[\"tcache\"][69] = {\"size_min\": 0x8000, \"size_max\": 0x10000}\n                table[\"tcache\"][70] = {\"size_min\": 0x10000, \"size_max\": 0x20000}\n                table[\"tcache\"][71] = {\"size_min\": 0x20000, \"size_max\": 0x40000}\n                table[\"tcache\"][72] = {\"size_min\": 0x40000, \"size_max\": 0x80000}\n                table[\"tcache\"][73] = {\"size_min\": 0x80000, \"size_max\": 0x100000}\n                table[\"tcache\"][74] = {\"size_min\": 0x100000, \"size_max\": 0x200000}\n                table[\"tcache\"][75] = {\"size_min\": 0x200000, \"size_max\": 0x400000}\n            else: # arm32, m68k, sh4, etc\n                table[\"tcache\"][64] = {\"size_min\": 0x210, \"size_max\": 0x400}\n                table[\"tcache\"][65] = {\"size_min\": 0x400, \"size_max\": 0x800}\n                table[\"tcache\"][66] = {\"size_min\": 0x800, \"size_max\": 0x1000}\n                table[\"tcache\"][67] = {\"size_min\": 0x1000, \"size_max\": 0x2000}\n                table[\"tcache\"][68] = {\"size_min\": 0x2000, \"size_max\": 0x4000}\n                table[\"tcache\"][69] = {\"size_min\": 0x4000, \"size_max\": 0x8000}\n                table[\"tcache\"][70] = {\"size_min\": 0x8000, \"size_max\": 0x10000}\n                table[\"tcache\"][71] = {\"size_min\": 0x10000, \"size_max\": 0x20000}\n                table[\"tcache\"][72] = {\"size_min\": 0x20000, \"size_max\": 0x40000}\n                table[\"tcache\"][73] = {\"size_min\": 0x40000, \"size_max\": 0x80000}\n                table[\"tcache\"][74] = {\"size_min\": 0x80000, \"size_max\": 0x100000}\n                table[\"tcache\"][75] = {\"size_min\": 0x100000, \"size_max\": 0x200000}\n\n        # fastbins\n        if is_64bit():\n            for i in range(7):\n                size = MIN_SIZE + i * 0x10\n                table[\"fastbins\"][i] = {\"size\": size}\n        elif (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n            # MALLOC_ALIGNMENT is changed from libc 2.26.\n            # for x86_32, fastbin exists every 8 bytes, but only used every 16 bytes.\n            table[\"fastbins\"][0] = {\"size\": 0x10}\n            table[\"fastbins\"][2] = {\"size\": 0x20}\n            table[\"fastbins\"][4] = {\"size\": 0x30}\n            table[\"fastbins\"][6] = {\"size\": 0x40}\n        else:\n            for i in range(7):\n                size = MIN_SIZE + i * 8\n                table[\"fastbins\"][i] = {\"size\": size}\n\n        # unsorted bins\n        table[\"unsorted_bin\"][0] = {}\n\n        # smallbins\n        for i in range(1, 63):\n            if is_64bit() or (is_x86_32() and get_libc_version() >= (2, 26)):\n                size = MIN_SIZE + (i - 1) * 0x10\n            else:\n                size = MIN_SIZE + (i - 1) * 0x8\n            table[\"small_bins\"][i] = {\"size\": size}\n\n        # largebins\n        if is_64bit():\n            table[\"large_bins\"][63] = {\"size_min\": 0x400, \"size_max\": 0x440}\n            table[\"large_bins\"][64] = {\"size_min\": 0x440, \"size_max\": 0x480}\n            table[\"large_bins\"][65] = {\"size_min\": 0x480, \"size_max\": 0x4c0}\n            table[\"large_bins\"][66] = {\"size_min\": 0x4c0, \"size_max\": 0x500}\n            table[\"large_bins\"][67] = {\"size_min\": 0x500, \"size_max\": 0x540}\n            table[\"large_bins\"][68] = {\"size_min\": 0x540, \"size_max\": 0x580}\n            table[\"large_bins\"][69] = {\"size_min\": 0x580, \"size_max\": 0x5c0}\n            table[\"large_bins\"][70] = {\"size_min\": 0x5c0, \"size_max\": 0x600}\n            table[\"large_bins\"][71] = {\"size_min\": 0x600, \"size_max\": 0x640}\n            table[\"large_bins\"][72] = {\"size_min\": 0x640, \"size_max\": 0x680}\n            table[\"large_bins\"][73] = {\"size_min\": 0x680, \"size_max\": 0x6c0}\n            table[\"large_bins\"][74] = {\"size_min\": 0x6c0, \"size_max\": 0x700}\n            table[\"large_bins\"][75] = {\"size_min\": 0x700, \"size_max\": 0x740}\n            table[\"large_bins\"][76] = {\"size_min\": 0x740, \"size_max\": 0x780}\n            table[\"large_bins\"][77] = {\"size_min\": 0x780, \"size_max\": 0x7c0}\n            table[\"large_bins\"][78] = {\"size_min\": 0x7c0, \"size_max\": 0x800}\n            table[\"large_bins\"][79] = {\"size_min\": 0x800, \"size_max\": 0x840}\n            table[\"large_bins\"][80] = {\"size_min\": 0x840, \"size_max\": 0x880}\n            table[\"large_bins\"][81] = {\"size_min\": 0x880, \"size_max\": 0x8c0}\n            table[\"large_bins\"][82] = {\"size_min\": 0x8c0, \"size_max\": 0x900}\n            table[\"large_bins\"][83] = {\"size_min\": 0x900, \"size_max\": 0x940}\n            table[\"large_bins\"][84] = {\"size_min\": 0x940, \"size_max\": 0x980}\n            table[\"large_bins\"][85] = {\"size_min\": 0x980, \"size_max\": 0x9c0}\n            table[\"large_bins\"][86] = {\"size_min\": 0x9c0, \"size_max\": 0xa00}\n            table[\"large_bins\"][87] = {\"size_min\": 0xa00, \"size_max\": 0xa40}\n            table[\"large_bins\"][88] = {\"size_min\": 0xa40, \"size_max\": 0xa80}\n            table[\"large_bins\"][89] = {\"size_min\": 0xa80, \"size_max\": 0xac0}\n            table[\"large_bins\"][90] = {\"size_min\": 0xac0, \"size_max\": 0xb00}\n            table[\"large_bins\"][91] = {\"size_min\": 0xb00, \"size_max\": 0xb40}\n            table[\"large_bins\"][92] = {\"size_min\": 0xb40, \"size_max\": 0xb80}\n            table[\"large_bins\"][93] = {\"size_min\": 0xb80, \"size_max\": 0xbc0}\n            table[\"large_bins\"][94] = {\"size_min\": 0xbc0, \"size_max\": 0xc00}\n            table[\"large_bins\"][95] = {\"size_min\": 0xc00, \"size_max\": 0xc40}\n            table[\"large_bins\"][96] = {\"size_min\": 0xc40, \"size_max\": 0xe00}\n        elif is_x86_32() and get_libc_version() >= (2, 26):\n            table[\"large_bins\"][63] = {\"size_min\": 0x3f0, \"size_max\": 0x400}\n            table[\"large_bins\"][64] = {\"size_min\": 0x400, \"size_max\": 0x440}\n            table[\"large_bins\"][65] = {\"size_min\": 0x440, \"size_max\": 0x480}\n            table[\"large_bins\"][66] = {\"size_min\": 0x480, \"size_max\": 0x4c0}\n            table[\"large_bins\"][67] = {\"size_min\": 0x4c0, \"size_max\": 0x500}\n            table[\"large_bins\"][68] = {\"size_min\": 0x500, \"size_max\": 0x540}\n            table[\"large_bins\"][69] = {\"size_min\": 0x540, \"size_max\": 0x580}\n            table[\"large_bins\"][70] = {\"size_min\": 0x580, \"size_max\": 0x5c0}\n            table[\"large_bins\"][71] = {\"size_min\": 0x5c0, \"size_max\": 0x600}\n            table[\"large_bins\"][72] = {\"size_min\": 0x600, \"size_max\": 0x640}\n            table[\"large_bins\"][73] = {\"size_min\": 0x640, \"size_max\": 0x680}\n            table[\"large_bins\"][74] = {\"size_min\": 0x680, \"size_max\": 0x6c0}\n            table[\"large_bins\"][75] = {\"size_min\": 0x6c0, \"size_max\": 0x700}\n            table[\"large_bins\"][76] = {\"size_min\": 0x700, \"size_max\": 0x740}\n            table[\"large_bins\"][77] = {\"size_min\": 0x740, \"size_max\": 0x780}\n            table[\"large_bins\"][78] = {\"size_min\": 0x780, \"size_max\": 0x7c0}\n            table[\"large_bins\"][79] = {\"size_min\": 0x7c0, \"size_max\": 0x800}\n            table[\"large_bins\"][80] = {\"size_min\": 0x800, \"size_max\": 0x840}\n            table[\"large_bins\"][81] = {\"size_min\": 0x840, \"size_max\": 0x880}\n            table[\"large_bins\"][82] = {\"size_min\": 0x880, \"size_max\": 0x8c0}\n            table[\"large_bins\"][83] = {\"size_min\": 0x8c0, \"size_max\": 0x900}\n            table[\"large_bins\"][84] = {\"size_min\": 0x900, \"size_max\": 0x940}\n            table[\"large_bins\"][85] = {\"size_min\": 0x940, \"size_max\": 0x980}\n            table[\"large_bins\"][86] = {\"size_min\": 0x980, \"size_max\": 0x9c0}\n            table[\"large_bins\"][87] = {\"size_min\": 0x9c0, \"size_max\": 0xa00}\n            table[\"large_bins\"][88] = {\"size_min\": 0xa00, \"size_max\": 0xa40}\n            table[\"large_bins\"][89] = {\"size_min\": 0xa40, \"size_max\": 0xa80}\n            table[\"large_bins\"][90] = {\"size_min\": 0xa80, \"size_max\": 0xac0}\n            table[\"large_bins\"][91] = {\"size_min\": 0xac0, \"size_max\": 0xb00}\n            table[\"large_bins\"][92] = {\"size_min\": 0xb00, \"size_max\": 0xb40}\n            table[\"large_bins\"][93] = {\"size_min\": 0xb40, \"size_max\": 0xb80}\n            # table[\"large_bins\"][94] is unused\n            table[\"large_bins\"][95] = {\"size_min\": 0xb80, \"size_max\": 0xc00}\n            table[\"large_bins\"][96] = {\"size_min\": 0xc00, \"size_max\": 0xe00}\n        else:\n            table[\"large_bins\"][63] = {\"size_min\": 0x200, \"size_max\": 0x240}\n            table[\"large_bins\"][64] = {\"size_min\": 0x240, \"size_max\": 0x280}\n            table[\"large_bins\"][65] = {\"size_min\": 0x280, \"size_max\": 0x2c0}\n            table[\"large_bins\"][66] = {\"size_min\": 0x2c0, \"size_max\": 0x300}\n            table[\"large_bins\"][67] = {\"size_min\": 0x300, \"size_max\": 0x340}\n            table[\"large_bins\"][68] = {\"size_min\": 0x340, \"size_max\": 0x380}\n            table[\"large_bins\"][69] = {\"size_min\": 0x380, \"size_max\": 0x3c0}\n            table[\"large_bins\"][70] = {\"size_min\": 0x3c0, \"size_max\": 0x400}\n            table[\"large_bins\"][71] = {\"size_min\": 0x400, \"size_max\": 0x440}\n            table[\"large_bins\"][72] = {\"size_min\": 0x440, \"size_max\": 0x480}\n            table[\"large_bins\"][73] = {\"size_min\": 0x480, \"size_max\": 0x4c0}\n            table[\"large_bins\"][74] = {\"size_min\": 0x4c0, \"size_max\": 0x500}\n            table[\"large_bins\"][75] = {\"size_min\": 0x500, \"size_max\": 0x540}\n            table[\"large_bins\"][76] = {\"size_min\": 0x540, \"size_max\": 0x580}\n            table[\"large_bins\"][77] = {\"size_min\": 0x580, \"size_max\": 0x5c0}\n            table[\"large_bins\"][78] = {\"size_min\": 0x5c0, \"size_max\": 0x600}\n            table[\"large_bins\"][79] = {\"size_min\": 0x600, \"size_max\": 0x640}\n            table[\"large_bins\"][80] = {\"size_min\": 0x640, \"size_max\": 0x680}\n            table[\"large_bins\"][81] = {\"size_min\": 0x680, \"size_max\": 0x6c0}\n            table[\"large_bins\"][82] = {\"size_min\": 0x6c0, \"size_max\": 0x700}\n            table[\"large_bins\"][83] = {\"size_min\": 0x700, \"size_max\": 0x740}\n            table[\"large_bins\"][84] = {\"size_min\": 0x740, \"size_max\": 0x780}\n            table[\"large_bins\"][85] = {\"size_min\": 0x780, \"size_max\": 0x7c0}\n            table[\"large_bins\"][86] = {\"size_min\": 0x7c0, \"size_max\": 0x800}\n            table[\"large_bins\"][87] = {\"size_min\": 0x800, \"size_max\": 0x840}\n            table[\"large_bins\"][88] = {\"size_min\": 0x840, \"size_max\": 0x880}\n            table[\"large_bins\"][89] = {\"size_min\": 0x880, \"size_max\": 0x8c0}\n            table[\"large_bins\"][90] = {\"size_min\": 0x8c0, \"size_max\": 0x900}\n            table[\"large_bins\"][91] = {\"size_min\": 0x900, \"size_max\": 0x940}\n            table[\"large_bins\"][92] = {\"size_min\": 0x940, \"size_max\": 0x980}\n            table[\"large_bins\"][93] = {\"size_min\": 0x980, \"size_max\": 0x9c0}\n            table[\"large_bins\"][94] = {\"size_min\": 0x9c0, \"size_max\": 0xa00}\n            table[\"large_bins\"][95] = {\"size_min\": 0xa00, \"size_max\": 0xc00}\n            table[\"large_bins\"][96] = {\"size_min\": 0xc00, \"size_max\": 0xe00}\n\n        table[\"large_bins\"][97] = {\"size_min\": 0xe00, \"size_max\": 0x1000}\n        table[\"large_bins\"][98] = {\"size_min\": 0x1000, \"size_max\": 0x1200}\n        table[\"large_bins\"][99] = {\"size_min\": 0x1200, \"size_max\": 0x1400}\n        table[\"large_bins\"][100] = {\"size_min\": 0x1400, \"size_max\": 0x1600}\n        table[\"large_bins\"][101] = {\"size_min\": 0x1600, \"size_max\": 0x1800}\n        table[\"large_bins\"][102] = {\"size_min\": 0x1800, \"size_max\": 0x1a00}\n        table[\"large_bins\"][103] = {\"size_min\": 0x1a00, \"size_max\": 0x1c00}\n        table[\"large_bins\"][104] = {\"size_min\": 0x1c00, \"size_max\": 0x1e00}\n        table[\"large_bins\"][105] = {\"size_min\": 0x1e00, \"size_max\": 0x2000}\n        table[\"large_bins\"][106] = {\"size_min\": 0x2000, \"size_max\": 0x2200}\n        table[\"large_bins\"][107] = {\"size_min\": 0x2200, \"size_max\": 0x2400}\n        table[\"large_bins\"][108] = {\"size_min\": 0x2400, \"size_max\": 0x2600}\n        table[\"large_bins\"][109] = {\"size_min\": 0x2600, \"size_max\": 0x2800}\n        table[\"large_bins\"][110] = {\"size_min\": 0x2800, \"size_max\": 0x2a00}\n        table[\"large_bins\"][111] = {\"size_min\": 0x2a00, \"size_max\": 0x3000}\n        table[\"large_bins\"][112] = {\"size_min\": 0x3000, \"size_max\": 0x4000}\n        table[\"large_bins\"][113] = {\"size_min\": 0x4000, \"size_max\": 0x5000}\n        table[\"large_bins\"][114] = {\"size_min\": 0x5000, \"size_max\": 0x6000}\n        table[\"large_bins\"][115] = {\"size_min\": 0x6000, \"size_max\": 0x7000}\n        table[\"large_bins\"][116] = {\"size_min\": 0x7000, \"size_max\": 0x8000}\n        table[\"large_bins\"][117] = {\"size_min\": 0x8000, \"size_max\": 0x9000}\n        table[\"large_bins\"][118] = {\"size_min\": 0x9000, \"size_max\": 0xa000}\n        table[\"large_bins\"][119] = {\"size_min\": 0xa000, \"size_max\": 0x10000}\n        table[\"large_bins\"][120] = {\"size_min\": 0x10000, \"size_max\": 0x18000}\n        table[\"large_bins\"][121] = {\"size_min\": 0x18000, \"size_max\": 0x20000}\n        table[\"large_bins\"][122] = {\"size_min\": 0x20000, \"size_max\": 0x28000}\n        table[\"large_bins\"][123] = {\"size_min\": 0x28000, \"size_max\": 0x40000}\n        table[\"large_bins\"][124] = {\"size_min\": 0x40000, \"size_max\": 0x80000}\n        table[\"large_bins\"][125] = {\"size_min\": 0x80000, \"size_max\": 0x0}\n        table[\"large_bins\"][126] = {\"size_min\": 0x0, \"size_max\": 0x0} # maybe unused\n        return table\n\n    # for convenience\n    H = HeapInfo # noqa\n    M = MallocPar # noqa\n    A = GlibcArena # noqa\n    C = GlibcChunk # noqa\n\n\n# for convenience\nGH = GlibcHeap # noqa\n\n\n@Cache.cache_this_session\ndef get_libc_version(verbose=False):\n    \"\"\"Detect and return the glibc version as a tuple, using cache, configuration,\n    process maps, or system fallback.\"\"\"\n\n    RE_LIBC_PATH = re.compile(r\"libc6?[-_](\\d+)\\.(\\d+)\\.so\")\n    RE_GLIBC_VERSION = re.compile(rb\"glibc (\\d+)\\.(\\d+)\")\n\n    def get_libc_version_from_path():\n        Cache.reset_gef_caches() # get_process_maps may be caching old information\n\n        sections = ProcessMap.get_process_maps()\n        for section in sections:\n            r = RE_LIBC_PATH.search(section.path)\n            if r:\n                return tuple(int(x) for x in r.groups())\n\n            if \"libc\" not in section.path:\n                continue\n\n            if is_container_attach():\n                real_libc_path = Path.append_proc_root(section.path)\n                if not os.path.exists(real_libc_path):\n                    continue\n                data = open(real_libc_path, \"rb\").read()\n\n            elif is_remote_debug():\n                if is_qemu_user():\n                    data = None\n                    for maps in ProcessMap.get_process_maps(outer=True):\n                        if os.path.basename(maps.path) != os.path.basename(section.path):\n                            continue\n                        if maps.size != section.size:\n                            continue\n                        real_libc_path = maps.path\n                        data = open(real_libc_path, \"rb\").read()\n                        break\n                else:\n                    data = Path.read_remote_file(section.path)\n                if not data:\n                    continue\n            else:\n                if not os.path.exists(section.path):\n                    continue\n                data = open(section.path, \"rb\").read()\n\n            r = RE_GLIBC_VERSION.search(data)\n            if r:\n                return tuple(int(x) for x in r.groups())\n        return None\n\n    def get_system_libc_version():\n        res = GefUtil.gef_execute_external([\"cat\", \"/proc/self/maps\"], as_list=True)\n        libc_targets = (\"libc-2.\", \"libc.so.6\")\n        for line in res:\n            if not any(kw in line for kw in libc_targets):\n                continue\n            path = line.split()[-1]\n            if not os.path.exists(path):\n                continue\n            data = open(path, \"rb\").read()\n            r = RE_GLIBC_VERSION.search(data)\n            if r:\n                return tuple(int(x) for x in r.groups())\n        return None\n\n    # use manual settings\n    libc_assume_version = eval(Config.get_gef_setting(\"libc.assume_version\"))\n    if libc_assume_version != ():\n        if verbose:\n            info(\"Use libc.assume_version\")\n        return libc_assume_version\n\n    # resolve from maps information\n    libc_version = get_libc_version_from_path()\n    if libc_version is not None:\n        if verbose:\n            info(\"Resolve from maps\")\n        return libc_version\n\n    # resolve from system libc\n    if not is_container_attach():\n        libc_version = get_system_libc_version()\n        if libc_version is not None:\n            if verbose:\n                info(\"Resolve from system libc\")\n            return libc_version\n\n    err(\"The libc version could not be determined.\")\n    err(\"Please specify it with the following command: `gef config libc.assume_version (2,39)`\")\n    raise\n\n\ndef titlify(text, color=None, msg_color=None, horizontal_line=\"-\"):\n    \"\"\"Print a centered title.\"\"\"\n    cols = GefUtil.get_terminal_size()[1]\n    if color is None:\n        color = Config.get_gef_setting(\"theme.default_title_line\")\n    if msg_color is None:\n        msg_color = Config.get_gef_setting(\"theme.default_title_message\")\n\n    msg = []\n    if text:\n        nb = (cols - len(text) - 2) // 2\n        msg.append(Color.colorify(\"{} \".format(horizontal_line * nb), color))\n        msg.append(Color.colorify(text, msg_color))\n        msg.append(Color.colorify(\" {}\".format(horizontal_line * nb), color))\n    else:\n        msg.append(Color.colorify(\"{}\".format(horizontal_line * cols), color))\n    return \"\".join(msg)\n\n\ndef err(msg, redirect=\"\"):\n    \"\"\"The wrapper of gef_print for error level message.\"\"\"\n    gef_print(\"{} {}\".format(Color.colorify(\"[!]\", \"bold red\"), msg), redirect=redirect)\n    return\n\n\ndef warn(msg, redirect=\"\"):\n    \"\"\"The wrapper of gef_print for warning level message.\"\"\"\n    gef_print(\"{} {}\".format(Color.colorify(\"[*]\", \"bold yellow\"), msg), redirect=redirect)\n    return\n\n\ndef ok(msg, redirect=\"\"):\n    \"\"\"The wrapper of gef_print for ok level message.\"\"\"\n    gef_print(\"{} {}\".format(Color.colorify(\"[+]\", \"bold green\"), msg), redirect=redirect)\n    return\n\n\ndef info(msg, redirect=\"\"):\n    \"\"\"The wrapper of gef_print for information level message.\"\"\"\n    gef_print(\"{} {}\".format(Color.colorify(\"[+]\", \"bold blue\"), msg), redirect=redirect)\n    return\n\n\nclass String:\n    \"\"\"A collection of utility functions that are related to strings.\"\"\"\n\n    STRING_ASCII_LOWERCASE = \"abcdefghijklmnopqrstuvwxyz\"\n    STRING_ASCII_UPPERCASE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n    STRING_ASCII_LETTERS = STRING_ASCII_LOWERCASE + STRING_ASCII_UPPERCASE\n    STRING_DIGITS = \"0123456789\"\n    STRING_HEXDIGITS = \"0123456789abcdefABCDEF\"\n    STRING_PUNCTUATION = \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~\"\n    STRING_WHITESPACE = \" \\t\\n\\r\\x0b\\x0c\"\n    STRING_PRINTABLE = STRING_DIGITS + STRING_ASCII_LETTERS + STRING_PUNCTUATION + STRING_WHITESPACE\n    MORSE_CODE_DICT = {\n        b\".-\"     : b\"A\",\n        b\"-...\"   : b\"B\",\n        b\"-.-.\"   : b\"C\",\n        b\"-..\"    : b\"D\",\n        b\".\"      : b\"E\",\n        b\"..-.\"   : b\"F\",\n        b\"--.\"    : b\"G\",\n        b\"....\"   : b\"H\",\n        b\"..\"     : b\"I\",\n        b\".---\"   : b\"J\",\n        b\"-.-\"    : b\"K\",\n        b\".-..\"   : b\"L\",\n        b\"--\"     : b\"M\",\n        b\"-.\"     : b\"N\",\n        b\"---\"    : b\"O\",\n        b\".--.\"   : b\"P\",\n        b\"--.-\"   : b\"Q\",\n        b\".-.\"    : b\"R\",\n        b\"...\"    : b\"S\",\n        b\"-\"      : b\"T\",\n        b\"..-\"    : b\"U\",\n        b\"...-\"   : b\"V\",\n        b\".--\"    : b\"W\",\n        b\"-..-\"   : b\"X\",\n        b\"-.--\"   : b\"Y\",\n        b\"--..\"   : b\"Z\",\n        b\".----\"  : b\"1\",\n        b\"..---\"  : b\"2\",\n        b\"...--\"  : b\"3\",\n        b\"....-\"  : b\"4\",\n        b\".....\"  : b\"5\",\n        b\"-....\"  : b\"6\",\n        b\"--...\"  : b\"7\",\n        b\"---..\"  : b\"8\",\n        b\"----.\"  : b\"9\",\n        b\"-----\"  : b\"0\",\n        b\"--..--\" : b\",\",\n        b\".-.-.-\" : b\".\",\n        b\"..--..\" : b\"?\",\n        b\"-..-.\"  : b\"/\",\n        b\"-....-\" : b\"-\",\n        b\"-.--.\"  : b\"(\",\n        b\"-.--.-\" : b\")\",\n    }\n\n    @staticmethod\n    def str2bytes(x):\n        \"\"\"Helper function for str -> bytes.\"\"\"\n        if isinstance(x, bytes):\n            return x\n        if isinstance(x, str):\n            try:\n                return bytes(ord(xx) for xx in x)\n            except ValueError:\n                # If str is UTF-8 multi-byte string, raise an error.\n                # e.g., `pi String.str2bytes(b\"\\xc5\\x82\".decode(\"utf-8\"))`\n                # In that case, you should simply encode it as UTF-8.\n                return x.encode(\"utf-8\")\n        raise\n\n    @staticmethod\n    def bytes2str(x):\n        \"\"\"Helper function for bytes -> str.\"\"\"\n        if isinstance(x, str):\n            return x\n        if isinstance(x, bytes):\n            return \"\".join(chr(xx) for xx in x)\n        raise\n\n    @staticmethod # noqa\n    def bits2bytes(a, endian=\"big\"):\n        \"\"\"Helper function for bits -> bytes.\"\"\"\n        if isinstance(a, str):\n            a = String.str2bytes(a)\n        if isinstance(a, bytes):\n            a = a.replace(b\"0\", b\"\\x00\")\n            a = a.replace(b\"1\", b\"\\x01\")\n        if not isinstance(a, list):\n            a = list(a)\n        assert set(a) <= {0x0, 0x1}\n\n        out = []\n\n        if endian == \"little\":\n            s = i = 0\n            for x in a:\n                s += x << i\n                i += 1\n                if i == 8:\n                    out.append(s)\n                    s = i = 0\n            if i > 0:\n                out.append(s)\n        else:\n            s = i = 0\n            for x in a:\n                s += s + x\n                i += 1\n                if i == 8:\n                    out.append(s)\n                    s = i = 0\n            if i > 0:\n                s = s << (8 - i)\n                out.append(s)\n        return bytes(out)\n\n    @staticmethod # noqa\n    def bytes2bits(a, endian=\"big\"):\n        \"\"\"Helper function for bytes -> bits.\"\"\"\n        if isinstance(a, str):\n            a = String.str2bytes(a)\n\n        out = []\n\n        if endian == \"little\":\n            for x in a:\n                for i in range(8):\n                    b = (x >> i) & 1\n                    out.append(b)\n        else:\n            for x in a:\n                for i in range(8):\n                    b = (x >> (7 - i)) & 1\n                    out.append(b)\n        return out\n\n    @staticmethod\n    def morse_decode(a):\n        \"\"\"Decode a bytes or string sequence from Morse code to text.\"\"\"\n        if isinstance(a, str):\n            a = String.str2bytes(a)\n\n        decoded = b\"\"\n        for elem in a.split():\n            decoded += String.MORSE_CODE_DICT.get(elem, elem)\n        return decoded\n\n    @staticmethod\n    def morse_encode(a):\n        \"\"\"Encode a bytes or string sequence from text to Morse code.\"\"\"\n        if isinstance(a, str):\n            a = String.str2bytes(a)\n\n        MORSE_CODE_REVERSE_DICT = {v: k for k, v in String.MORSE_CODE_DICT.items()}\n\n        encoded = b\"\"\n        for elem in a:\n            elem = bytes([elem])\n            encoded += MORSE_CODE_REVERSE_DICT.get(elem.upper(), elem)\n            encoded += b\" \"\n        return encoded[:-1]\n\n    @staticmethod\n    def is_hex(pattern):\n        \"\"\"Return whether provided string is a hexadecimal value.\"\"\"\n        if not pattern.startswith(\"0x\") and not pattern.startswith(\"0X\"):\n            return False\n        return len(pattern) % 2 == 0 and all(c in String.STRING_HEXDIGITS for c in pattern[2:])\n\n\ndef slicer(data, n):\n    \"\"\"Helper function for slice.\"\"\"\n    return [data[i:i + n] for i in range(0, len(data), n)]\n\n\ndef slice_unpack(data, n):\n    \"\"\"Helper function for slice then unpack.\"\"\"\n    if n in [1, 2, 4, 8]:\n        length = len(data) // n\n        fmt = \"{:s}{:d}{:s}\".format(Endian.endian_str(), length, {1: \"B\", 2: \"H\", 4: \"I\", 8: \"Q\"}[n])\n        return struct.unpack(fmt, data)\n    elif n == 16:\n        return [u128(data[i:i + 16]) for i in range(0, len(data), 16)]\n    else:\n        raise\n\n\ndef align(value, align):\n    \"\"\"Align the value to the given size.\n    e.g., 0xdeadbeef with align 8 -> 0xdeadbef0\"\"\"\n    return value + ((align - (value % align)) % align)\n\n\ndef align_to_ptrsize(addr):\n    \"\"\"Align the address to the ptrsize.\"\"\"\n    return align(addr, current_arch.ptrsize)\n\n\ndef align_to_pagesize(addr):\n    \"\"\"Align the address to the pagesize.\"\"\"\n    return align(addr, get_pagesize())\n\n\ndef byteswap(x, byte_size=None):\n    \"\"\"Helper function for byte swap.\"\"\"\n    byte_size = byte_size or current_arch.ptrsize\n    bit_size = byte_size * 8\n    s = 0\n    for i in range(0, bit_size, 8):\n        s += ((x >> i) & 0xff) << (bit_size - (i + 8))\n    return s\n\n\ndef xor(a, b=None):\n    \"\"\"Helper function for xor.\n    xor(\"AAA\", \"BBB\") -> \"\\x03\\x03\\x03\"\n    xor(b\"AAA\", b\"BBB\") -> b\"\\x03\\x03\\x03\"\n    xor([\"AAA\", \"BBB\", \"\\x03\\x03\\x03\"]) -> \"\\0\\0\\0\"\n    \"\"\"\n\n    def _xor(a, b):\n        if len(a) < len(b):\n            a, b = b, a\n        if isinstance(a, str) and isinstance(b, str):\n            return ''.join([chr(ord(c1) ^ ord(c2)) for (c1, c2) in zip(a, itertools.cycle(b))])\n        elif isinstance(a, bytes) and isinstance(b, bytes):\n            return bytes([c1 ^ c2 for (c1, c2) in zip(a, itertools.cycle(b))])\n        elif isinstance(a, bytearray) and isinstance(b, bytearray):\n            return bytearray([c1 ^ c2 for (c1, c2) in zip(a, itertools.cycle(b))])\n        raise\n\n    if b is None:\n        if hasattr(a, \"__iter__\"):\n            return functools.reduce(_xor, a)\n        raise\n    return _xor(a, b)\n\n\ndef ror(val, bits, arch_bits=64):\n    \"\"\"Helper function for rotate right.\"\"\"\n    new_val = (val >> bits) | (val << (arch_bits - bits))\n    mask = (1 << arch_bits) - 1\n    return new_val & mask\n\n\ndef rol(val, bits, arch_bits=64):\n    \"\"\"Helper function for rotate left.\"\"\"\n    new_val = (val << bits) | (val >> (arch_bits - bits))\n    mask = (1 << arch_bits) - 1\n    return new_val & mask\n\n\ndef hexdump(source, length=0x10, separator=\".\", color=True, show_symbol=True, base=0x00, unit=1):\n    \"\"\"Return the hexdump of `src` argument.\"\"\"\n\n    style = {\n        \"nonprintable\": \"yellow\",\n        \"printable\": \"white\",\n        \"00\": \"bright_black\",\n        \"0a\": \"blue\",\n        \"ff\": \"green\",\n    }\n\n    def style_byte(b, color=True):\n        sbyte = \"{:02x}\".format(b)\n        if not color or Config.get_gef_setting(\"highlight.regex\"):\n            return sbyte\n        if sbyte in style:\n            st = style[sbyte]\n        elif chr(b) in String.STRING_PRINTABLE:\n            st = style[\"printable\"]\n        else:\n            st = style[\"nonprintable\"]\n        return Color.colorify(sbyte, st)\n\n    align = AddressUtil.get_format_address_width()\n\n    tmp = []\n    max_sym_width = 0\n    for i in range(0, len(source), length):\n        addr = base + i\n\n        if show_symbol:\n            sym = Symbol.get_symbol_string(addr)\n        else:\n            sym = \"\"\n        if len(sym) > max_sym_width:\n            max_sym_width = len(sym)\n\n        chunk = bytearray(source[i : i + length])\n\n        if unit == 1:\n            padlen = (0x10 - len(chunk)) * 3\n        else:\n            padlen = (0x10 - len(chunk)) // unit * (unit * 2 + 3)\n            if len(chunk) % unit:\n                padlen += ((unit - len(chunk) % unit) * 2)\n\n        hexa = [style_byte(b, color=color) for b in chunk]\n        if unit > 1:\n            hexa = [\"0x\" + \"\".join(x[::-1]) for x in slicer(hexa, unit)]\n        if unit == 1:\n            hexa[min(len(hexa), 8) - 1] += \" \" # double the blank at the 8th byte\n        hexa = \" \".join(hexa)\n        padded_hexa = hexa + \" \" * padlen\n\n        text = \"\".join([chr(b) if 0x20 <= b < 0x7f else separator for b in chunk])\n        text_padlen = 0x10 - len(text)\n        padded_text = text + \" \" * text_padlen\n\n        tmp.append([addr, sym, hexa, padded_hexa, padded_text])\n\n    result = []\n    for addr, sym, _, data, text in tmp:\n        result.append(\"{:#0{:d}x}:{:<{:d}}    {:s}    |  {:s}  |\".format(\n            addr, align, sym, max_sym_width, data, text,\n        ))\n    return \"\\n\".join(result)\n\n\nclass Symbol:\n    \"\"\"A collection of utility functions that are related to symbols.\"\"\"\n\n    # `info symbol` called from gdb_get_location is heavy processing.\n    # Moreover, AddressUtil.recursive_dereference causes each address to be resolved every time.\n    # Cache.cache_until_next is ineffective due to frequent resets (each time the `stepi` runs).\n    # Fortunately, symbol information rarely changes.\n    # The cache is retained until explicitly cleared.\n    @staticmethod\n    @Cache.cache_this_session\n    def gdb_get_location(address):\n        \"\"\"e.g., 0xffffffff9f6bd2a0 -> ('commit_creds', 0)\"\"\"\n        if address is None:\n            return None\n\n        # Do not use gdb.format_address available from gdb 13.x,\n        # because symbols added with add-symbol-temporary may not be recognized.\n\n        # slow path uses `info symbol` command\n        name = None\n        sym = gdb.execute(\"info symbol {:#x}\".format(address), to_string=True)\n        if sym.startswith(\"No symbol matches\"):\n            return None\n\n        i = sym.find(\" in section \")\n        sym = sym[:i].split()\n        if len(sym) >= 3 and sym[-1].isdigit():\n            # e.g., ptmalloc_init.part + 1 in section .text of /lib/x86_64-linux-gnu/libc.so.6\n            name = \" \".join(sym[:-2])\n            offset = int(sym[-1])\n        else:\n            # e.g., ptmalloc_init.part in section .text of /lib/x86_64-linux-gnu/libc.so.6\n            name = \" \".join(sym)\n            offset = 0\n        return name, offset\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_symbol_string(addr, nosymbol_string=\"\"):\n        \"\"\"e.g., 0xffffffff9f6bd2a1 -> ' <commit_creds+0x1>'. Be careful to include leading spaces.\"\"\"\n        try:\n            if isinstance(addr, str):\n                addr = Color.remove_color(addr)\n                addr = int(addr, 16)\n            ret = Symbol.gdb_get_location(addr)\n            if ret is None:\n                return nosymbol_string\n        except (ValueError, gdb.error):\n            return nosymbol_string\n\n        sym_name, sym_offset = ret[0], ret[1]\n        if addr - sym_offset == 0:\n            return nosymbol_string\n\n        sym_name = Instruction.smartify_text(sym_name)\n        if sym_offset == 0:\n            return \" <{}>\".format(sym_name)\n        else:\n            return \" <{}+{:#x}>\".format(sym_name, sym_offset)\n\n    @staticmethod\n    def get_ksymaddr(sym):\n        \"\"\"e.g., 'commit_creds' -> 0xffffffff9f6bd2a0\"\"\"\n        try:\n            res = gdb.execute(\"ksymaddr-remote --quiet --no-pager --exact {:s}\".format(sym), to_string=True)\n            return int(res.split()[0], 16)\n        except (gdb.error, IndexError, ValueError):\n            return None\n\n    @staticmethod\n    def get_ksymaddr_multiple(sym):\n        \"\"\"e.g., 'set_is_seen' -> [0xffffffffba146db0,0xffffffffba6d84e0,0xffffffffba6dd170]\"\"\"\n        out = []\n        try:\n            ret = gdb.execute(\"ksymaddr-remote --quiet --no-pager --exact {:s}\".format(sym), to_string=True)\n            for line in ret.splitlines():\n                addr = int(line.split()[0], 16)\n                out.append(addr)\n            return out\n        except (gdb.error, IndexError, ValueError):\n            return None\n\n    @staticmethod\n    def get_ksymaddr_symbol(addr):\n        \"\"\"e.g., 0xffffffff9f6bd2a0 -> 'commit_creds'\"\"\"\n        try:\n            res = gdb.execute(\"ksymaddr-remote --quiet --no-pager {:#x}\".format(addr), to_string=True)\n            res = res.splitlines()[-1]\n            return res.split()[2]\n        except (gdb.error, IndexError):\n            return None\n\n    @staticmethod\n    def get_symbol_by_monitor(symbol):\n        if not is_kdb():\n            return None\n        res = gdb.execute(\"monitor {:s}\".format(symbol), to_string=True)\n        r = re.search(symbol + r\" = 0x(\\S+)\", res)\n        if not r:\n            return None\n        v = int(r.group(1), 16)\n        if not is_valid_addr(v):\n            return None\n        return v\n\n\nclass ModuleLoader:\n    def load_capstone(f):\n        \"\"\"Decorator wrapper to load capstone.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                capstone = __import__(\"capstone\")\n                if capstone.cs_version()[0] == 6:\n                    LOONGARCH64.capstone_support = True\n                    ALPHA.capstone_support = True\n                    HPPA.capstone_support = True\n                    HPPA64.capstone_support = True\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `capstone` package for Python, try installing with `pip install capstone`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_unicorn(f):\n        \"\"\"Decorator wrapper to load unicorn.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"unicorn\")\n\n                if is_ppc32(): # unicorn does not support ppc64\n                    try:\n                        __import__(\"unicorn.ppc_const\")\n                    except ImportError:\n                        pass\n\n                if is_riscv32() or is_riscv64():\n                    try:\n                        __import__(\"unicorn.riscv_const\")\n                    except ImportError:\n                        pass\n\n                if is_s390x():\n                    try:\n                        __import__(\"unicorn.s390x_const\")\n                    except ImportError:\n                        pass\n\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `unicorn` package for Python, try installing with `pip install unicorn`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_keystone(f):\n        \"\"\"Decorator wrapper to load keystone.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"keystone\")\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `keystone-engine` package for Python, try installing with `pip install keystone-engine`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_ropper(f):\n        \"\"\"Decorator wrapper to load ropper.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"ropper\")\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `ropper` package for Python, try installing with `pip install ropper`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_binwalk(f):\n        \"\"\"Decorator wrapper to load binwalk.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"binwalk\")\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `binwalk` package for Python, try installing with `apt install binwalk`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_crccheck(f):\n        \"\"\"Decorator wrapper to load crccheck.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"crccheck\")\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `crccheck` package for Python, try installing with `pip install crccheck`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_codext(f):\n        \"\"\"Decorator wrapper to load codext.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                __import__(\"codext\")\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `codext` package for Python, try installing with `pip install codext`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\n    def load_angr(f):\n        \"\"\"Decorator wrapper to load angr.\"\"\"\n\n        @functools.wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                # Angr seems to import readline internally, so tab completion breaks after loading.\n                # Therefore, disable readline temporarily.\n                readline = sys.modules.get(\"readline\", None)\n                sys.modules[\"readline\"] = None\n                __import__(\"angr\")\n                sys.modules[\"readline\"] = readline\n                return f(*args, **kwargs)\n            except ImportError as err:\n                msg = \"Missing `angr` package for Python, try installing with `pip install angr`\"\n                raise ImportWarning(msg) from err\n\n        return wrapper\n\n\nclass Disasm:\n    \"\"\"A collection of utility functions that makes disassemble.\"\"\"\n\n    __gef_prev_arch__ = None # previous valid result of gdb.selected_frame().architecture()\n\n    @staticmethod\n    def gdb_disassemble(start_pc, nb_insn=None, end_pc=None):\n        \"\"\"Disassemble instructions from `start_pc` (Integer). Return an iterator of Instruction objects.\n        This is the backend used by Disasm.gef_disassemble by default.\"\"\"\n        if start_pc is None:\n            return None\n\n        try:\n            arch = gdb.selected_frame().architecture()\n            Disasm.__gef_prev_arch__ = arch\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            # At this time arch cannot be resolved, but if it was successful before, it will be used.\n            if Disasm.__gef_prev_arch__ is None:\n                raise\n            arch = Disasm.__gef_prev_arch__\n\n        kwargs = {}\n        if nb_insn is not None:\n            kwargs[\"count\"] = nb_insn\n        if end_pc is not None:\n            kwargs[\"end_pc\"] = end_pc\n\n        insn_list = list(arch.disassemble(start_pc, **kwargs))\n        if not insn_list:\n            return None\n\n        is_thumb = (is_arm32() or is_arm32_cortex_m())\n\n        def eff_addr(a):\n            return a - 1 if is_thumb and (a & 1) else a\n\n        def get_mnemo_operands(insn):\n            asm = insn[\"asm\"].rstrip().split(None, 1)\n            if len(asm) > 1:\n                mnemo = asm[0]\n                operands = asm[1].replace(\"\\t\", \" \")\n            else:\n                mnemo, operands = asm[0], \"\"\n            return mnemo, operands\n\n        try:\n            # fast path: read each instruction at once\n\n            # calc size\n            base = None\n            end = None\n            for insn in insn_list:\n                ea = eff_addr(insn[\"addr\"])\n                if base is None or ea < base:\n                    base = ea\n                e = ea + insn[\"length\"]\n                if end is None or e > end:\n                    end = e\n\n            blob = read_memory(base, end - base)\n\n            for insn in insn_list:\n                address = insn[\"addr\"]\n                mnemo, operands = get_mnemo_operands(insn)\n\n                ea = eff_addr(address)\n                off = ea - base\n                opcodes = blob[off: off + insn[\"length\"]]\n\n                yield Instruction(address, mnemo, operands, opcodes)\n\n        except gdb.MemoryError:\n            # slow path: read each instruction sequentially\n            for insn in insn_list:\n                address = insn[\"addr\"]\n                mnemo, operands = get_mnemo_operands(insn)\n\n                if is_thumb and (address & 1):\n                    opcodes = read_memory(address - 1, insn[\"length\"])\n                else:\n                    opcodes = read_memory(address, insn[\"length\"])\n\n                yield Instruction(address, mnemo, operands, opcodes)\n\n        return None\n\n    @staticmethod\n    def gdb_get_nth_previous_instruction_address(addr, n):\n        \"\"\"Return the address (Integer) of the `n`-th instruction before `addr`.\"\"\"\n        if addr is None:\n            return None\n\n        # fixed-length ABI\n        if current_arch.instruction_length:\n            return max(0, addr - n * current_arch.instruction_length)\n\n        # variable-length ABI\n        cur_insn_addr = get_insn(addr).address\n\n        # we try to find a good set of previous instructions by \"guessing\" disassembling backwards\n        # the 15 comes from the longest instruction valid size\n        for i in range(15 * n, 0, -1):\n            try:\n                insns = list(Disasm.gdb_disassemble(addr - i, end_pc=cur_insn_addr))\n            except gdb.MemoryError:\n                # this is because we can hit an unmapped page trying to read backward\n                break\n\n            # 1. check that the disassembled instructions list size can satisfy\n            if len(insns) < n + 1: # we expect the current instruction plus the n before it\n                continue\n\n            # If the list of instructions is longer than what we need, then we\n            # could get lucky and already have more than what we need, so slice down\n            insns = insns[-n - 1:]\n\n            # 2. check that the sequence ends with the current address\n            if insns[-1].address != cur_insn_addr:\n                continue\n\n            # 3. check all instructions are valid\n            if all(insn.is_valid() for insn in insns):\n                return insns[0].address\n        return None\n\n    @staticmethod\n    @ModuleLoader.load_capstone\n    def capstone_get_nth_previous_instruction_address(addr, n, cs=None):\n        \"\"\"Return the address (Integer) of the `n`-th instruction before `addr`.\"\"\"\n        if addr is None:\n            return None\n\n        if cs is None:\n            cs = sys.modules[\"capstone\"].Cs(*UnicornKeystoneCapstone.get_capstone_arch())\n\n        # fixed-length ABI\n        if current_arch.instruction_length:\n            return max(0, addr - n * current_arch.instruction_length)\n\n        # variable-length ABI\n\n        # we try to find a good set of previous instructions by \"guessing\" disassembling backwards\n        # the 15 comes from the longest instruction valid size\n        for i in range(15 * n, 0, -1):\n            try:\n                code = read_memory(addr - i, i)\n            except gdb.MemoryError:\n                continue\n\n            insns = list(cs.disasm(code, addr - i))\n\n            # 1. check that the disassembled instructions list size can satisfy\n            if len(insns) < n:\n                continue\n            insns = insns[-n:]\n\n            # 2. check that the sequence ends with the current address\n            if insns[-1].address + insns[-1].size != addr:\n                continue\n\n            return insns[0].address\n        return None\n\n    @staticmethod\n    @ModuleLoader.load_capstone\n    def capstone_disassemble(location, nb_insn, **kwargs):\n        \"\"\"Disassemble `nb_insn` instructions after `addr` and `nb_prev` before `addr`\n        using the capstone disassembler. Return an iterator of Instruction objects.\n        This is the backend used by Disasm.gef_disassemble if specified in the config.\n        It is also called directly from some commands such as Disasm.capstone_disassemble.\"\"\"\n\n        def cs_insn_to_gef_insn(cs_insn):\n            return Instruction(cs_insn.address, cs_insn.mnemonic, cs_insn.op_str, cs_insn.bytes)\n\n        capstone = sys.modules[\"capstone\"]\n        arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n            arch=kwargs.get(\"arch\", None),\n            mode=kwargs.get(\"mode\", None),\n            endian=kwargs.get(\"endian\", None),\n        )\n        try:\n            cs = capstone.Cs(arch, mode)\n            cs.detail = True # noqa\n        except capstone.CsError:\n            err(\"CsError\")\n            return\n\n        # fix location by nb_prev\n        nb_prev = kwargs.get(\"nb_prev\", 0)\n        if nb_prev > 0:\n            location_tmp = Disasm.capstone_get_nth_previous_instruction_address(\n                location, nb_prev, capstone.Cs(arch, mode),\n            )\n            if location_tmp is not None:\n                location = location_tmp\n                nb_insn += nb_prev\n\n        # split reading by page_size\n        read_addr = location\n        read_size = get_pagesize() - (location & get_pagesize_mask_low())\n\n        # fix for arm thumb2 mode\n        if (is_arm32() or is_arm32_cortex_m()) and read_addr & 1:\n            read_addr -= 1\n            read_size += 1\n\n        skip = kwargs.get(\"skip\", 0)\n        arch_inst_length = current_arch.instruction_length or 1\n        used_bytes = 0\n        code_remain = bytes.fromhex(kwargs.get(\"code\", \"\"))\n        dont_read = \"code\" in kwargs\n\n        # A loop to read the required memory until the specified length is reached\n        while True:\n            if not dont_read and len(code_remain) < get_pagesize():\n                # not enough code to disassemble, so read the memory to pool\n                try:\n                    read_data = read_memory(read_addr, read_size)\n                except gdb.MemoryError:\n                    err(\"Memory read error at {:#x}-{:#x}\".format(read_addr, read_addr + read_size))\n                    return\n                code_remain += read_data\n\n            # cs.disasm will terminate disassembling if an invalid instruction is detected.\n            # This is a loop to display \"(bad)\" and increment PC and reinterpret code.\n            while True:\n                # disasm\n                for insn in cs.disasm(code_remain, location):\n                    used_bytes += len(insn.bytes)\n                    if skip:\n                        skip -= 1\n                        continue\n                    yield cs_insn_to_gef_insn(insn)\n                    nb_insn -= 1\n                    if nb_insn == 0:\n                        return\n\n                # success (disassembled something)\n                if used_bytes > 0:\n                    break\n\n                # failure (maybe the code is invalid)\n                yield Instruction(location, \"(bad)\", \"\", code_remain[:arch_inst_length])\n                nb_insn -= 1\n                if nb_insn == 0:\n                    return\n                location += arch_inst_length\n                code_remain = code_remain[arch_inst_length:]\n\n            # go away only the size used\n            code_remain = code_remain[used_bytes:] # There may be instructions placed across page boundaries.\n            location += used_bytes\n            used_bytes = 0\n\n            read_addr += read_size # 1st loop is the offset size. 2nd~ loops are the page size.\n            read_size = get_pagesize()\n        return\n\n    @staticmethod\n    def gef_disassemble(addr, nb_insn, nb_prev=0):\n        \"\"\"Disassemble `nb_insn` instructions after `addr` and `nb_prev` before `addr`.\n        Return an iterator of Instruction objects.\n        Use Disasm.gdb_disassemble or Disasm.capstone_disassemble according to the settings.\"\"\"\n        if Config.get_gef_setting(\"context_code.use_capstone\"):\n            get_nth_prev_address = Disasm.capstone_get_nth_previous_instruction_address\n            get_insns = Disasm.capstone_disassemble\n        else:\n            get_nth_prev_address = Disasm.gdb_get_nth_previous_instruction_address\n            get_insns = Disasm.gdb_disassemble\n\n        if nb_prev:\n            for i in range(nb_prev):\n                nb_prev_addr = get_nth_prev_address(addr, nb_prev - i)\n                if not nb_prev_addr:\n                    continue\n                for insn in get_insns(nb_prev_addr, nb_prev):\n                    if insn.address == addr:\n                        break\n                    yield insn\n                break\n\n        nb_insn = max(1, nb_insn)\n        for insn in get_insns(addr, nb_insn):\n            yield insn\n        return None\n\n    @staticmethod\n    def gef_instruction_n(addr, n):\n        \"\"\"Return the `n`-th instruction after `addr` as an Instruction object.\"\"\"\n        try:\n            return list(Disasm.gef_disassemble(addr, n + 1))[n]\n        except IndexError:\n            return None\n\n\ndef get_insn(addr=None):\n    \"\"\"Return the current instruction as an Instruction object.\"\"\"\n    if addr is None:\n        if not is_alive():\n            return None\n        addr = current_arch.pc\n    return Disasm.gef_instruction_n(addr, 0)\n\n\ndef get_insn_next(addr=None):\n    \"\"\"Return the next instruction as an Instruction object.\"\"\"\n    if addr is None:\n        if not is_alive():\n            return None\n        addr = current_arch.pc\n    return Disasm.gef_instruction_n(addr, 1)\n\n\ndef get_insn_prev(addr=None):\n    \"\"\"Return the prev instruction as an Instruction object.\"\"\"\n    if addr is None:\n        if not is_alive():\n            return None\n        addr = current_arch.pc\n    try:\n        gen = Disasm.gef_disassemble(addr, 0, nb_prev=2)\n        gen.__next__()\n        return gen.__next__()\n    except (gdb.error, StopIteration):\n        return None\n\n\nclass Checksec:\n    \"\"\"Manage checksec related functions.\"\"\"\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_cet_status_old_interface():\n        # https://lore.kernel.org/lkml/1531342544.15351.37.camel@intel.com/\n        sp = current_arch.sp\n        mem = {}\n\n        # backup\n        for i in range(3):\n            # *addr = SHSTK/IBT status\n            # *(addr + 1) = SHSTK base address\n            # *(addr + 2) = SHSTK size\n            addr = sp + current_arch.ptrsize * i\n            mem[addr] = read_memory(addr, current_arch.ptrsize)\n\n        res = gdb.execute(\"call-syscall arch_prctl 0x3001 {:#x}\".format(sp), to_string=True) # ARCH_CET_STATUS\n        output_line = res.splitlines()[-1]\n        ret = int(output_line.split()[2], 0)\n\n        sp_value = read_int_from_memory(sp)\n\n        # revert\n        for addr, data in mem.items():\n            write_memory(addr, data)\n\n        # check ret\n        if ret != 0:\n            return None\n        return sp_value\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_cet_status_new_interface():\n        # https://www.kernel.org/doc/html/next/arch/x86/shstk.html\n        sp = current_arch.sp\n        mem = {}\n\n        # backup\n        for i in range(1):\n            # *addr = SHSTK status\n            addr = sp + current_arch.ptrsize * i\n            mem[addr] = read_memory(addr, current_arch.ptrsize)\n\n        res = gdb.execute(\"call-syscall arch_prctl 0x5005 {:#x}\".format(sp), to_string=True) # ARCH_SHSTK_STATUS\n        output_line = res.splitlines()[-1]\n        ret = int(output_line.split()[2], 0)\n\n        sp_value = read_int_from_memory(sp)\n\n        # revert\n        for addr, data in mem.items():\n            write_memory(addr, data)\n\n        if ret != 0:\n            return None\n        return sp_value\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_cet_status_via_procfs():\n        # https://www.kernel.org/doc/html/next/arch/x86/shstk.html\n        dic = {}\n        if is_remote_debug():\n            if Pid.get_pid(remote=True):\n                remote_status = \"/proc/{:d}/status\".format(Pid.get_pid(remote=True))\n            data = Path.read_remote_file(remote_status, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                return None\n        else:\n            if Pid.get_pid():\n                local_status = \"/proc/{:d}/status\".format(Pid.get_pid())\n            data = open(local_status, \"rb\").read()\n            if not data:\n                return None\n\n        if b\"x86_Thread_features:\" not in data:\n            return False # unsupported\n\n        dic[\"shstk\"] = b\"x86_Thread_features: shstk\" in data\n        dic[\"shstk lock\"] = b\"x86_Thread_features_locked: shstk\" in data\n        return dic\n\n    @staticmethod\n    def get_mte_status():\n        auxv = Auxv.get_auxiliary_values()\n        HWCAP2_MTE = 1 << 18\n        if auxv and \"AT_HWCAP2\" in auxv and (auxv[\"AT_HWCAP2\"] & HWCAP2_MTE) == 0:\n            return None # Unsupported\n        res = gdb.execute(\"call-syscall prctl 0x38 0 0 0 0\", to_string=True) # PR_GET_TAGGED_ADDR_CTRL\n        output_line = res.splitlines()[-1]\n        ret = int(output_line.split()[2], 0)\n\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        u2i = lambda a: uq(pQ(a))\n        return u2i(ret)\n\n    @staticmethod\n    def get_pac_status():\n        auxv = Auxv.get_auxiliary_values()\n        HWCAP_PACA = 1 << 30\n        HWCAP_PACG = 1 << 31\n        if auxv and \"AT_HWCAP\" in auxv and (auxv[\"AT_HWCAP\"] & (HWCAP_PACA | HWCAP_PACG)) == 0:\n            return None # Unsupported\n        res = gdb.execute(\"call-syscall prctl 0x3d 0 0 0 0\", to_string=True) # PR_PAC_GET_ENABLED_KEYS\n        output_line = res.splitlines()[-1]\n        ret = int(output_line.split()[2], 0)\n\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        u2i = lambda a: uq(pQ(a))\n        return u2i(ret)\n\n\nclass Endian:\n    \"\"\"Manage endianness related functions.\"\"\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_endian():\n        \"\"\"Return the binary endianness.\"\"\"\n        endian = gdb.execute(\"show endian\", to_string=True).strip().lower()\n        if \"little endian\" in endian:\n            return Elf.LITTLE_ENDIAN\n        if \"big endian\" in endian:\n            return Elf.BIG_ENDIAN\n        raise EnvironmentError(\"Invalid endianness\")\n\n    @staticmethod\n    def is_big_endian():\n        return Endian.get_endian() == Elf.BIG_ENDIAN\n\n    @staticmethod\n    def is_little_endian():\n        return not Endian.is_big_endian()\n\n    @staticmethod\n    @Cache.cache_this_session\n    def endian_str():\n        return \"<\" if Endian.is_little_endian() else \">\"\n\n\nclass Architecture:\n    \"\"\"Generic metaclass for the architecture supported by GEF.\"\"\"\n\n    __metaclass__ = abc.ABCMeta\n\n    # base properties\n\n    @property\n    @abc.abstractmethod\n    def arch(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def mode(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def load_condition(self):\n        pass\n\n    # register properties\n\n    @property\n    @abc.abstractmethod\n    def all_registers(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def alias_registers(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def special_registers(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def flag_register(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def flags_table(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def return_register(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def function_parameters(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def syscall_register(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def syscall_parameters(self):\n        pass\n\n    # architecture properties\n\n    @property\n    @abc.abstractmethod\n    def bit_length(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def endianness(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def instruction_length(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def has_delay_slot(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def has_syscall_delay_slot(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def has_ret_delay_slot(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def stack_grow_down(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def tls_supported(self):\n        pass\n\n    # module properties\n\n    @property\n    @abc.abstractmethod\n    def keystone_support(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def capstone_support(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def unicorn_support(self):\n        pass\n\n    # instruction properties\n\n    @property\n    @abc.abstractmethod\n    def nop_insn(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def infloop_insn(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def trap_insn(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def ret_insn(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def syscall_insn(self):\n        pass\n\n    # instruction methods\n\n    @abc.abstractmethod\n    def is_syscall(self, insn):\n        pass\n\n    @abc.abstractmethod\n    def is_call(self, insn):\n        pass\n\n    @abc.abstractmethod\n    def is_jump(self, insn):\n        pass\n\n    @abc.abstractmethod\n    def is_ret(self, insn):\n        pass\n\n    @abc.abstractmethod\n    def is_conditional_branch(self, insn):\n        pass\n\n    @abc.abstractmethod\n    def is_branch_taken(self, insn):\n        pass\n\n    # register methods\n\n    @abc.abstractmethod\n    def flag_register_to_human(self, val=None):\n        pass\n\n    @abc.abstractmethod\n    def get_ra(self, insn, frame):\n        pass\n\n    @abc.abstractmethod\n    def get_tls(self):\n        pass\n\n    @abc.abstractmethod\n    def decode_cookie(self, value, cookie):\n        pass\n\n    @abc.abstractmethod\n    def encode_cookie(self, value, cookie):\n        pass\n\n    @property\n    def pc(self):\n        return get_register(\"$pc\")\n\n    @property\n    def sp(self):\n        return get_register(\"$sp\")\n\n    @property\n    def ptrsize(self):\n        return AddressUtil.get_memory_alignment()\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i -= len(self.function_parameters)\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def get_aliased_registers(self):\n        # use cache\n        if hasattr(self, \"aliased_registers\"):\n            return self.aliased_registers\n\n        # {\"$zero\":\"$zero/$x0\", ...}\n        self.aliased_registers = {}\n        for reg in self.all_registers:\n            if self.alias_registers and reg in self.alias_registers:\n                reg_str = \"{:s}/{:s}\".format(reg, self.alias_registers[reg])\n            else:\n                reg_str = reg\n            self.aliased_registers[reg] = reg_str\n        return self.aliased_registers\n\n    def get_aliased_registers_name_max(self):\n        # use cache\n        if hasattr(self, \"aliased_registers_max_len\"):\n            return self.aliased_registers_max_len\n\n        # max(len(\"$zero/$x0\"), ...)\n        maxlen = max([len(v) for v in self.get_aliased_registers().values() if v != self.flag_register])\n        self.aliased_registers_max_len = maxlen\n        return self.aliased_registers_max_len\n\n    def get_registers_name_max(self):\n        # use cache\n        if hasattr(self, \"registers_max_len\"):\n            return self.registers_max_len\n\n        # max(len(\"$x0\"), ...)\n        maxlen = max([len(v) for v in self.all_registers if v != self.flag_register])\n        self.registers_max_len = maxlen\n        return self.registers_max_len\n\n    @staticmethod\n    def flags_to_human(reg_value, value_table):\n        \"\"\"Return a human readable string showing the flag states.\"\"\"\n        flags = []\n        for i in value_table:\n            if reg_value & (1 << i):\n                flag_str = Color.boldify(value_table[i].upper())\n            else:\n                flag_str = value_table[i].lower()\n            flags.append(flag_str)\n        return \"{:#x} [{}]\".format(reg_value, \" \".join(flags))\n\n\nclass RISCV(Architecture):\n    \"\"\"GEF representation of RISCV-32 architecture.\"\"\"\n\n    arch = \"RISCV\"\n    mode = \"32\"\n\n    load_condition = [\n        # Elf.EM_RISCV cannot determine whether it is 32-bit or 64-bit, so it should not be used.\n        \"RISCV\",\n        \"RISCV32\",\n        \"RISCV:RV32\",\n    ]\n\n    # https://msyksphinz-self.github.io/riscv-isadoc/html/index.html\n    all_registers = [\n        \"$zero\", \"$ra\", \"$sp\", \"$gp\", \"$tp\", \"$t0\", \"$t1\", \"$t2\",\n        \"$fp\", \"$s1\", \"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\",\n        \"$a6\", \"$a7\", \"$s2\", \"$s3\", \"$s4\", \"$s5\", \"$s6\", \"$s7\",\n        \"$s8\", \"$s9\", \"$s10\", \"$s11\", \"$t3\", \"$t4\", \"$t5\", \"$t6\",\n        \"$pc\",\n    ]\n    alias_registers = {\n        \"$zero\": \"$x0\", \"$ra\": \"$x1\", \"$sp\": \"$x2\", \"$gp\": \"$x3\",\n        \"$tp\": \"$x4\", \"$t0\": \"$x5\", \"$t1\": \"$x6\", \"$t2\": \"$x7\",\n        \"$fp\": \"$x8/$s0\", \"$s1\": \"$x9\", \"$a0\": \"$x10\", \"$a1\": \"$x11\",\n        \"$a2\": \"$x12\", \"$a3\": \"$x13\", \"$a4\": \"$x14\", \"$a5\": \"$x15\",\n        \"$a6\": \"$x16\", \"$a7\": \"$x17\", \"$s2\": \"$x18\", \"$s3\": \"$x19\",\n        \"$s4\": \"$x20\", \"$s5\": \"$x21\", \"$s6\": \"$x22\", \"$s7\": \"$x23\",\n        \"$s8\": \"$x24\", \"$s9\": \"$x25\", \"$s10\": \"$x26\", \"$s11\": \"$x27\",\n        \"$t3\": \"$x28\", \"$t4\": \"$x29\", \"$t5\": \"$x30\", \"$t6\": \"$x31\",\n    }\n    flag_register = None # RISC-V has no flags register\n    return_register = \"$a0\"\n    function_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\", \"$a6\", \"$a7\"]\n    syscall_register = \"$a7\"\n    syscall_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x13\\x00\\x00\\x00\" # nop\n    infloop_insn = b\"\\x6f\\x00\\x00\\x00\" # j self\n    trap_insn = b\"\\x73\\x00\\x10\\x00\" # ebreak\n    ret_insn = b\"\\x67\\x80\\x00\\x00\" # ret\n    syscall_insn = b\"\\x73\\x00\\x00\\x00\" # ecall\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"ecall\"]\n\n    def is_call(self, insn):\n        if self.is_ret(insn):\n            return False\n        if insn.mnemonic in [\"jal\", \"jalr\", \"c.jal\", \"c.jalr\"]:\n            return True\n        return False\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        if insn.mnemonic in [\"c.j\", \"c.jr\", \"j\", \"jr\"]:\n            return True\n        return False\n\n    def is_ret(self, insn):\n        mnemo = insn.mnemonic\n        if mnemo == \"ret\": # gdb interpret \"jalr zero, ra, 0\" as \"ret\"\n            return True\n        if mnemo == \"c.jalr\":\n            return insn.operands[0] == \"ra\"\n        return False\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"bne\", \"blt\", \"bge\", \"bltu\", \"bgeu\",\n            \"c.beqz\", \"c.bnez\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n\n        def long_to_twos_complement(v):\n            \"\"\"Convert a python long value to its two's complement.\"\"\"\n            if is_32bit():\n                if v & 0x8000_0000:\n                    return v - 0x1_0000_0000\n            elif is_64bit():\n                if v & 0x8000_0000_0000_0000:\n                    return v - 0x1_0000_0000_0000_0000\n            else:\n                raise OSError(\"RISC-V: ELF file is not ELF32 or ELF64. This is not currently supported\")\n            return v\n\n        mnemo = insn.mnemonic\n        if mnemo.startswith(\"c.\"):\n            mnemo = mnemo[2:]\n        condition = mnemo[1:]\n\n        if condition.endswith(\"z\"):\n            # r2 is the zero register if we are comparing to 0\n            rs1 = get_register(insn.operands[0])\n            rs2 = get_register(\"$zero\")\n            condition = condition[:-1]\n        elif len(insn.operands) > 2:\n            # r2 is populated with the second operand\n            rs1 = get_register(insn.operands[0])\n            rs2 = get_register(insn.operands[1])\n        else:\n            raise OSError(\"RISC-V: Failed to get rs1 and rs2 for instruction: `{}`\".format(insn))\n\n        # If the conditional operation is not unsigned, convert the python long into\n        # its two's complement\n        if not condition.endswith(\"u\"):\n            rs2 = long_to_twos_complement(rs2)\n            rs1 = long_to_twos_complement(rs1)\n        else:\n            condition = condition[:-1]\n\n        if condition == \"eq\":\n            if rs1 == rs2:\n                taken, reason = True, \"{}={}\".format(rs1, rs2)\n            else:\n                taken, reason = False, \"{}!={}\".format(rs1, rs2)\n        elif condition == \"ne\":\n            if rs1 != rs2:\n                taken, reason = True, \"{}!={}\".format(rs1, rs2)\n            else:\n                taken, reason = False, \"{}={}\".format(rs1, rs2)\n        elif condition == \"lt\":\n            if rs1 < rs2:\n                taken, reason = True, \"{}<{}\".format(rs1, rs2)\n            else:\n                taken, reason = False, \"{}>={}\".format(rs1, rs2)\n        elif condition == \"ge\":\n            if rs1 >= rs2:\n                taken, reason = True, \"{}>={}\".format(rs1, rs2)\n            else:\n                taken, reason = False, \"{}<{}\".format(rs1, rs2)\n        else:\n            raise OSError(\"RISC-V: Conditional instruction `{}` not supported yet\".format(insn))\n\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$ra\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$tp\")\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass RISCV64(RISCV):\n    \"\"\"GEF representation of RISCV-64 architecture.\"\"\"\n\n    arch = \"RISCV\"\n    mode = \"64\"\n\n    load_condition = [\n        # Elf.EM_RISCV cannot determine whether it is 32-bit or 64-bit, so it should not be used.\n        \"RISCV64\",\n        \"RISCV:RV64\",\n    ]\n\n    bit_length = 64\n\n\nclass ARM(Architecture):\n    \"\"\"GEF representation of ARM-32 architecture.\"\"\"\n\n    arch = \"ARM\"\n\n    load_condition = [\n        Elf.EM_ARM,\n        \"ARM\",\n        \"ARM_ANY\",\n        \"ARMV2\",\n        \"ARMV2A\",\n        \"ARMV3\",\n        \"ARMV4\",\n        \"ARMV4T\",\n        \"ARMV5\",\n        \"ARMV5T\",\n        \"ARMV5TE\",\n        \"ARMV5TEJ\",\n        \"ARMV6\",\n        \"ARMV6K\",\n        \"ARMV6KZ\",\n        \"ARMV6T2\",\n        \"ARMV7\",\n    ]\n\n    cached_is_cortex_m = None\n\n    def is_cortex_m(self):\n        if self.cached_is_cortex_m in (True, False):\n            return self.cached_is_cortex_m\n\n        if self.cached_is_cortex_m is None:\n            # is_alive and get_register are not yet defined here and cannot be used.\n            try:\n                gdb.execute(\"info registers cpsr\", to_string=True)\n                self.cached_is_cortex_m = False\n                return self.cached_is_cortex_m\n            except gdb.error:\n                pass\n            try:\n                gdb.execute(\"info registers xpsr\", to_string=True)\n                self.cached_is_cortex_m = True\n                return self.cached_is_cortex_m\n            except gdb.error:\n                pass\n\n        # default is Cortex-A\n        self.cached_is_cortex_m = False\n        return self.cached_is_cortex_m\n\n    @property\n    def all_registers(self):\n        if self.is_cortex_m():\n            return [\n                \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n                \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$sp\", \"$lr\", \"$pc\",\n                \"$xpsr\",\n                \"$msp\", \"$psp\", \"$primask\", \"$basepri\", \"$faultmask\", \"$control\",\n            ]\n        else:\n            return [\n                \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n                \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$sp\", \"$lr\", \"$pc\",\n                \"$cpsr\",\n            ]\n\n    @property\n    def flag_register(self):\n        if self.is_cortex_m():\n            return \"$xpsr\"\n        else:\n            return \"$cpsr\"\n\n    @property\n    def thumb_bit(self):\n        if self.is_cortex_m():\n            return 24\n        else:\n            return 5\n\n    @property\n    def flags_table(self):\n        if self.is_cortex_m():\n            return {\n                31: \"negative\",\n                30: \"zero\",\n                29: \"carry\",\n                28: \"overflow\",\n                self.thumb_bit: \"thumb\",\n            }\n        else:\n            return {\n                31: \"negative\",\n                30: \"zero\",\n                29: \"carry\",\n                28: \"overflow\",\n                7: \"interrupt\",\n                6: \"fast\",\n                self.thumb_bit: \"thumb\",\n            }\n\n    alias_registers = {\n        \"$r11\": \"$fp\", \"$r12\": \"$ip\",\n        \"$sp\": \"$r13\", \"$lr\": \"$r14\", \"$pc\": \"$r15\",\n    }\n    return_register = \"$r0\"\n    function_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\"]\n    syscall_register = \"$r7\"\n    syscall_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\"]\n\n    def is_thumb(self):\n        \"\"\"Determine if the machine is currently in THUMB mode.\"\"\"\n        if not is_alive():\n            return False\n        cpsr = get_register(self.flag_register)\n        if cpsr is None:\n            return False\n        return bool(cpsr & (1 << self.thumb_bit))\n\n    @property\n    def mode(self):\n        if self.is_thumb():\n            return \"THUMB\"\n        else:\n            return \"ARM\"\n\n    bit_length = 32\n    endianness = \"little / big\"\n\n    @property\n    def instruction_length(self):\n        # Thumb instructions have variable-length (2 or 4-byte)\n        if self.is_thumb():\n            return None # variable length\n        else:\n            return 4\n\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = True\n\n    # http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0041c/Caccegih.html\n    @property\n    def nop_insn(self):\n        if self.is_thumb():\n            return b\"\\x00\\xbf\" # nop\n        else:\n            return b\"\\x01\\x10\\xa0\\xe1\" # mov r1, r1\n\n    @property\n    def infloop_insn(self):\n        if self.is_thumb():\n            return b\"\\xfe\\xe7\" # b #0\n        else:\n            return b\"\\xfe\\xff\\xff\\xea\" # b #0\n\n    @property\n    def trap_insn(self):\n        if self.is_thumb():\n            return b\"\\x00\\xbe\" # bkpt #0\n        else:\n            return b\"\\x70\\x00\\x20\\xe1\" # bkpt #0\n\n    @property\n    def ret_insn(self):\n        if self.is_thumb():\n            return b\"\\xf7\\x46\" # mov pc, lr\n        else:\n            return b\"\\x0e\\xf0\\xa0\\xe1\" # mov pc, lr\n\n    @property\n    def syscall_insn(self):\n        if self.is_thumb():\n            return b\"\\x00\\xdf\" # svc 0x0\n        else:\n            return b\"\\x00\\x00\\x00\\xef\" # svc 0x0\n\n    @property\n    def pc(self):\n        pc = get_register(\"$pc\")\n        if self.is_thumb():\n            pc += 1\n        return pc\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"svc\", \"swi\"]\n\n    def is_call(self, insn):\n        conditions = [\n            \"\", \"eq\", \"ne\", \"lt\", \"le\", \"gt\", \"ge\", \"vs\", \"vc\",\n            \"mi\", \"pl\", \"hi\", \"ls\", \"cs\", \"cc\", \"hs\", \"lo\", \"al\",\n        ]\n        mnemo = insn.mnemonic\n        for cc in conditions:\n            if mnemo in [f\"bl{cc}\", f\"bl{cc}.n\", f\"bl{cc}.w\", f\"blx{cc}\", f\"blx{cc}.n\", f\"blx{cc}.w\"]:\n                return True\n        return False\n\n    def is_jump(self, insn):\n        if self.is_ret(insn):\n            return False\n        if self.is_conditional_branch(insn):\n            return True\n        mnemo = insn.mnemonic\n        if mnemo in [\"b\", \"b.n\", \"b.w\", \"bx\", \"bx.n\", \"bx.w\"]:\n            return True\n        if mnemo in [\"mov\", \"mov.n\", \"mov.w\", \"ldr\", \"ldr.n\", \"ldr.w\", \"add\", \"add.n\", \"add.w\"]:\n            return insn.operands[0] == \"pc\"\n        return False\n\n    def is_ret(self, insn):\n        load_mnemos = [\n            \"pop\", \"ldm\", \"ldmea\", \"ldmed\", \"ldmfa\",\n            \"ldmfd\", \"ldmia\", \"ldmib\", \"ldmda\", \"ldmdb\",\n            \"ldm.n\", \"ldmea.n\", \"ldmed.n\", \"ldmfa.n\",\n            \"ldmfd.n\", \"ldmia.n\", \"ldmib.n\", \"ldmda.n\", \"ldmdb.n\",\n            \"ldm.w\", \"ldmea.w\", \"ldmed.w\", \"ldmfa.w\",\n            \"ldmfd.w\", \"ldmia.w\", \"ldmib.w\", \"ldmda.w\", \"ldmdb.w\",\n        ]\n        mnemo = insn.mnemonic\n        if mnemo in load_mnemos:\n            return \"pc}\" in \"\".join(insn.operands)\n        if mnemo in [\"b\", \"b.n\", \"b.w\", \"bx\", \"bx.n\", \"bx.w\"]:\n            return insn.operands[0] == \"lr\"\n        if mnemo in [\"mov\", \"mov.n\", \"mov.w\"]:\n            return insn.operands[:2] == [\"pc\", \"lr\"]\n        if mnemo == \"add\" and len(insn.operands) >= 3:\n            return insn.operands[:2] == [\"pc\", \"lr\"] and int(insn.operands[2].lstrip(\"#\"), 0) == 0\n        if mnemo == \"rfe\":\n            return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        conditions = [\n            \"eq\", \"ne\", \"lt\", \"le\", \"gt\", \"ge\", \"vs\", \"vc\",\n            \"mi\", \"pl\", \"hi\", \"ls\", \"cs\", \"cc\", \"hs\", \"lo\", \"al\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"b{cc}\", f\"b{cc}.n\", f\"b{cc}.w\", f\"bx{cc}\", f\"bx{cc}.n\", f\"bx{cc}.w\"]:\n                return True\n        if insn.mnemonic in [\"cbnz\", \"cbz\", \"tbnz\", \"tbz\"]:\n            return True\n        return False\n\n    def is_branch_taken(self, insn):\n        mnemo, operands = insn.mnemonic, insn.operands\n        # ref: http://www.davespace.co.uk/arm/introduction-to-arm/conditional.html\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        val = get_register(self.flag_register)\n        taken, reason = False, \"\"\n\n        if val is not None:\n            zero = bool(val & (1 << flags[\"zero\"]))\n            negative = bool(val & (1 << flags[\"negative\"]))\n            overflow = bool(val & (1 << flags[\"overflow\"]))\n            carry = bool(val & (1 << flags[\"carry\"]))\n        else:\n            zero = False\n            negative = False\n            overflow = False\n            carry = False\n\n        if mnemo in [\"cbnz\", \"cbz\", \"tbnz\", \"tbz\"]:\n            reg = operands[0]\n            op = get_register(reg)\n            if mnemo == \"cbnz\":\n                if op != 0:\n                    taken, reason = True, \"{}!=0\".format(reg)\n                else:\n                    taken, reason = False, \"{}==0\".format(reg)\n            elif mnemo == \"cbz\":\n                if op == 0:\n                    taken, reason = True, \"{}==0\".format(reg)\n                else:\n                    taken, reason = False, \"{}!=0\".format(reg)\n            elif mnemo == \"tbnz\":\n                # operands[1] has a #, then the number\n                i = int(operands[1].lstrip(\"#\"), 0)\n                if (op & (1 << i)) != 0:\n                    taken, reason = True, \"{}&1<<{}!=0\".format(reg, i)\n                else:\n                    taken, reason = False, \"{}&1<<{}==0\".format(reg, i)\n            elif mnemo == \"tbz\":\n                # operands[1] has a #, then the number\n                i = int(operands[1].lstrip(\"#\"), 0)\n                if (op & (1 << i)) == 0:\n                    taken, reason = True, \"{}&1<<{}==0\".format(reg, i)\n                else:\n                    taken, reason = False, \"{}&1<<{}!=0\".format(reg, i)\n        elif mnemo.endswith((\"eq\", \"eq.n\", \"eq.w\")):\n            taken, reason = zero, \"Z\"\n        elif mnemo.endswith((\"ne\", \"ne.n\", \"ne.w\")):\n            taken, reason = not zero, \"!Z\"\n        elif mnemo.endswith((\"lt\", \"lt.n\", \"lt.w\")):\n            taken, reason = negative != overflow, \"N!=V\"\n        elif mnemo.endswith((\"le\", \"le.n\", \"le.w\")):\n            taken, reason = zero or negative != overflow, \"Z || N!=V\"\n        elif mnemo.endswith((\"gt\", \"gt.n\", \"gt.w\")):\n            taken, reason = not zero and negative == overflow, \"!Z && N==V\"\n        elif mnemo.endswith((\"ge\", \"ge.n\", \"ge.w\")):\n            taken, reason = negative == overflow, \"N==V\"\n        elif mnemo.endswith((\"vs\", \"vs.n\", \"vs.w\")):\n            taken, reason = overflow, \"V\"\n        elif mnemo.endswith((\"vc\", \"vc.n\", \"vc.w\")):\n            taken, reason = not overflow, \"!V\"\n        elif mnemo.endswith((\"mi\", \"mi.n\", \"mi.w\")):\n            taken, reason = negative, \"N\"\n        elif mnemo.endswith((\"pl\", \"pl.n\", \"pl.w\")):\n            taken, reason = not negative, \"N==0\"\n        elif mnemo.endswith((\"hi\", \"hi.n\", \"hi.w\")):\n            taken, reason = carry and not zero, \"C && !Z\"\n        elif mnemo.endswith((\"ls\", \"ls.n\", \"ls.w\")):\n            taken, reason = not carry or zero, \"!C || Z\"\n        elif mnemo.endswith((\"cs\", \"cs.n\", \"cs.w\")) or mnemo.endswith((\"hs\", \"hs.n\", \"hs.w\")):\n            taken, reason = carry, \"C\"\n        elif mnemo.endswith((\"cc\", \"cc.n\", \"cc.w\")) or mnemo.endswith((\"lo\", \"lo.n\", \"lo.w\")):\n            taken, reason = not carry, \"!C\"\n        return taken, reason\n\n    __mode_dic = {\n        # encoding: [mode, PL]\n        0b10000: [\"User\", 0],\n        0b10001: [\"FIQ\", 1],\n        0b10010: [\"IRQ\", 1],\n        0b10011: [\"Supervisor\", 1],\n        0b10110: [\"Monitor\", 1],\n        0b10111: [\"Abort\", 1],\n        0b11010: [\"Hypervisor\", 2],\n        0b11011: [\"Undefined\", 1],\n        0b11111: [\"System\", 1],\n    }\n\n    def flag_register_to_human(self, val=None):\n        # http://www.botskool.com/user-pages/tutorials/electronics/arm-7-tutorial-part-1\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg) & 0xffff_ffff\n\n        if self.is_cortex_m():\n            return Architecture.flags_to_human(val, self.flags_table)\n\n        key = val & 0b11111\n        CurrentMode, CurrentPL = self.__mode_dic[key]\n\n        if not is_support_secure_world():\n            mode = \" [Mode={:s}({:#07b},PL{:d})]\".format(CurrentMode, key, CurrentPL)\n        else:\n            scr = get_register(\"$SCR\")\n            if scr is None:\n                mode = \" [Mode={:s}({:#07b},PL{:d})]\".format(CurrentMode, key, CurrentPL)\n            else:\n                secure_state = [\"Secure\", \"Non-Secure\"][scr & 1]\n                mode = \" [Mode={:s}({:#07b},PL{:d}),{:s}]\".format(CurrentMode, key, CurrentPL, secure_state)\n        return Architecture.flags_to_human(val, self.flags_table) + mode\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                if insn.mnemonic == \"pop\":\n                    # If it's a pop, we have to peek into the stack.\n                    ra_addr = current_arch.sp + (len(insn.operands) - 1) * AddressUtil.get_memory_alignment()\n                    ra = read_int32_from_memory(ra_addr)\n                elif insn.mnemonic.startswith(\"ldm\"):\n                    # GDB seems to disassemble ldm* instructions as pop.\n                    # This branch may never be hit, but is kept just in case.\n                    ra = frame.older().pc() if frame.older() else None\n                else:\n                    # 'bx lr' or 'add pc, lr, #0'\n                    ra = get_register(\"$lr\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        if is_in_kernel() or is_in_secure():\n            return None\n\n        tls = get_register(\"$TPIDRURO\") # qemu-user + gdb-multiarch\n        if tls is not None:\n            return tls\n\n        if is_rr(): # unsupported ExecAsm when rr\n            return None\n        if self.is_thumb():\n            codes = [b\"\\x1d\\xee\", b\"\\x70\\x2f\"] # mrc p15, #0, r2, c13, c0, #3\n        else:\n            codes = [b\"\\x70\\x2f\\x1d\\xee\"] # mrc p15, #0, r2, c13, c0, #3\n        ret = ExecAsm(codes).exec_code()\n        return ret[\"reg\"][\"$r2\"]\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass AARCH64(ARM):\n    \"\"\"GEF representation of ARM-64 architecture.\"\"\"\n\n    arch = \"ARM64\"\n    mode = \"ARM\"\n\n    load_condition = [\n        Elf.EM_AARCH64,\n        \"AARCH64\",\n        \"ARM64\",\n        \"ARMV8\",\n        \"ARMV8-A\",\n        \"ARMV9\",\n        \"ARMV9-A\",\n    ]\n\n    all_registers = [\n        \"$x0\", \"$x1\", \"$x2\", \"$x3\", \"$x4\", \"$x5\", \"$x6\", \"$x7\",\n        \"$x8\", \"$x9\", \"$x10\", \"$x11\", \"$x12\", \"$x13\", \"$x14\", \"$x15\",\n        \"$x16\", \"$x17\", \"$x18\", \"$x19\", \"$x20\", \"$x21\", \"$x22\", \"$x23\",\n        \"$x24\", \"$x25\", \"$x26\", \"$x27\", \"$x28\", \"$x29\", \"$x30\", \"$sp\",\n        \"$pc\", \"$cpsr\", \"$fpsr\", \"$fpcr\",\n    ]\n    alias_registers = {\n        \"$x16\": \"$ip0\", \"$x17\": \"$ip1\", \"$x29\": \"$fp\", \"$x30\": \"$lr\",\n    }\n    flag_register = \"$cpsr\"\n    flags_table = {\n        31: \"negative\",\n        30: \"zero\",\n        29: \"carry\",\n        28: \"overflow\",\n        7: \"interrupt\",\n        6: \"fast\",\n    }\n    return_register = \"$x0\"\n    function_parameters = [\"$x0\", \"$x1\", \"$x2\", \"$x3\", \"$x4\", \"$x5\", \"$x6\", \"$x7\"]\n    syscall_register = \"$x8\"\n    syscall_parameters = [\"$x0\", \"$x1\", \"$x2\", \"$x3\", \"$x4\", \"$x5\"]\n\n    bit_length = 64\n    endianness = \"little\"\n    instruction_length = 4\n\n    nop_insn = b\"\\x1f\\x20\\x03\\xd5\" # nop\n    infloop_insn = b\"\\x00\\x00\\x00\\x14\" # b #0\n    trap_insn = b\"\\x00\\x00\\x20\\xd4\" # brk #0\n    ret_insn = b\"\\xc0\\x03\\x5f\\xd6\" # ret\n    syscall_insn = b\"\\x01\\x00\\x00\\xd4\" # svc #0x0\n\n    @property\n    def pc(self):\n        return get_register(\"$pc\")\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"svc\" and int(insn.operands[0].lstrip(\"#\"), 0) == 0\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"bl\", \"blr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"b\", \"br\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"eret\"]\n\n    def is_conditional_branch(self, insn):\n        mnemo = insn.mnemonic\n        # https://www.element14.com/community/servlet/JiveServlet/previewBody/41836-102-1-229511/ARM.Reference_Manual.pdf\n        # sect. 5.1.1\n        if mnemo in [\"cbnz\", \"cbz\", \"tbnz\", \"tbz\"]:\n            return True\n        if mnemo.startswith(\"b.\"):\n            return True\n        return False\n\n    # is_branch_taken is the same as ARM\n\n    def flag_register_to_human(self, val=None):\n        # http://events.linuxfoundation.org/sites/events/files/slides/KoreaLinuxForum-2014.pdf\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg) & 0xffff_ffff\n\n        if not is_support_secure_world():\n            mode = \" [EL={:d},SP={:d}]\".format((val >> 2) & 0b11, val & 0b11)\n        else:\n            scr = get_register(\"$SCR_EL3\")\n            if scr is None:\n                mode = \" [EL={:d},SP={:d}]\".format((val >> 2) & 0b11, val & 0b11)\n            else:\n                secure_state = [\"Secure\", \"Non-Secure\"][scr & 1]\n                mode = \" [EL={:d},SP={:d},{:s}]\".format((val >> 2) & 0b11, val & 0b11, secure_state)\n        return Architecture.flags_to_human(val, self.flags_table) + mode\n\n    def get_ra(self, insn, frame):\n        try:\n            if insn.mnemonic == \"ret\":\n                reg = insn.operands[0] if insn.operands else \"lr\"\n                return get_register(reg)\n            if frame and frame.older():\n                return frame.older().pc()\n        except gdb.error:\n            pass\n        return None\n\n    def get_tls(self):\n        if is_in_kernel() or is_in_secure():\n            return None\n\n        tls = get_register(\"$TPIDR_EL0\") # qemu-user + gdb-multiarch\n        if tls is not None:\n            return tls\n\n        tls = get_register(\"$tpidr\") # native gdb 14.0\n        if tls is not None:\n            return tls\n\n        if is_rr(): # unsupported ExecAsm when rr\n            return None\n        codes = [b\"\\x40\\xd0\\x3b\\xd5\"] # mrs x0, tpidr_el0\n        ret = ExecAsm(codes).exec_code()\n        return ret[\"reg\"][\"$x0\"]\n\n\nclass X86(Architecture):\n    \"\"\"GEF representation of x86-32 architecture.\"\"\"\n\n    arch = \"X86\"\n    mode = \"32\"\n\n    load_condition = [\n        Elf.EM_386,\n        \"X86\",\n        \"I386\",\n        \"I386:INTEL\",\n    ]\n\n    general_registers = [\"$eax\", \"$ebx\", \"$ecx\", \"$edx\", \"$esp\", \"$ebp\", \"$esi\", \"$edi\", \"$eip\", \"$eflags\"]\n    special_registers = [\"$cs\", \"$ss\", \"$ds\", \"$es\", \"$fs\", \"$gs\"]\n    virtual_registers = [\"$fs_base\", \"$gs_base\"]\n    flag_register = \"$eflags\"\n    all_registers = general_registers + special_registers\n    alias_registers = {}\n    flags_table = {\n        21: \"ident\",\n        #20: \"virtual_interrupt_pending\",\n        #19: \"virtual_interrupt\",\n        18: \"align\",\n        17: \"vx86\",\n        16: \"resume\",\n        #15: N/A\n        14: \"nested\",\n        #12-13: \"iopl\",\n        11: \"overflow\",\n        10: \"direction\",\n        9: \"interrupt\",\n        8: \"trap\",\n        7: \"sign\",\n        6: \"zero\",\n        #5: N/A\n        4: \"adjust\",\n        #3: N/A\n        2: \"parity\",\n        #1: N/A\n        0: \"carry\",\n    }\n    return_register = \"$eax\"\n    function_parameters = [\"$esp\"] # but unused because x86 uses stack\n    syscall_register = \"$eax\"\n    syscall_parameters = [\"$ebx\", \"$ecx\", \"$edx\", \"$esi\", \"$edi\", \"$ebp\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x90\" # nop\n    infloop_insn = b\"\\xeb\\xfe\" # jmp 0\n    trap_insn = b\"\\xcc\" # int3\n    ret_insn = b\"\\xc3\" # ret\n    syscall_insn = b\"\\xcd\\x80\" # int 0x80\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg) & 0xffff_ffff\n        mode = \" [Ring={:d}]\".format(get_register(\"$cs\") & 0b11)\n        return Architecture.flags_to_human(val, self.flags_table) + mode\n\n    def is_syscall(self, insn):\n        if insn.mnemonic in [\"sysenter\", \"syscall\"]:\n            return True\n        try:\n            return insn.mnemonic == \"int\" and int(insn.operands[0].lstrip(\"$\"), 0) == 0x80\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic == \"call\"\n\n    def is_jump(self, insn):\n        return insn.mnemonic == \"jmp\" or self.is_conditional_branch(insn)\n\n    def is_ret(self, insn):\n        if insn.mnemonic in [\"ret\", \"retf\"]:\n            return True\n        if insn.mnemonic in [\"sysret\"]:\n            return True\n        if insn.mnemonic in [\"iret\", \"iretd\", \"iretw\"]:\n            return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"ja\", \"jnbe\", \"jae\", \"jnb\", \"jnc\", \"jb\", \"jc\", \"jnae\", \"jbe\", \"jna\",\n            \"jcxz\", \"jecxz\", \"jrcxz\", \"je\", \"jz\", \"jg\", \"jnle\", \"jge\", \"jnl\",\n            \"jl\", \"jnge\", \"jle\", \"jng\", \"jne\", \"jnz\", \"jno\", \"jnp\", \"jpo\", \"jns\",\n            \"jo\", \"jp\", \"jpe\", \"js\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        # all kudos to fG! (https://github.com/gdbinit/Gdbinit/blob/master/gdbinit#L1654)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        val = get_register(self.flag_register)\n        taken, reason = False, \"\"\n\n        zero = bool(val & (1 << flags[\"zero\"]))\n        sign = bool(val & (1 << flags[\"sign\"]))\n        overflow = bool(val & (1 << flags[\"overflow\"]))\n        carry = bool(val & (1 << flags[\"carry\"]))\n        parity = bool(val & (1 << flags[\"parity\"]))\n\n        if mnemo in [\"ja\", \"jnbe\"]:\n            taken, reason = not carry and not zero, \"!C && !Z\"\n        elif mnemo in [\"jae\", \"jnb\", \"jnc\"]:\n            taken, reason = not carry, \"!C\"\n        elif mnemo in [\"jb\", \"jc\", \"jnae\"]:\n            taken, reason = carry, \"C\"\n        elif mnemo in [\"jbe\", \"jna\"]:\n            taken, reason = carry or zero, \"C || Z\"\n        elif mnemo == \"jcxz\":\n            cx = get_register(\"$cx\")\n            taken, reason = cx == 0, \"!$CX\"\n        elif mnemo == \"jecxz\":\n            ecx = get_register(\"$ecx\")\n            taken, reason = ecx == 0, \"!$ECX\"\n        elif mnemo == \"jrcxz\":\n            rcx = get_register(\"$rcx\")\n            taken, reason = rcx == 0, \"!$RCX\"\n        elif mnemo in [\"je\", \"jz\"]:\n            taken, reason = zero, \"Z\"\n        elif mnemo in [\"jne\", \"jnz\"]:\n            taken, reason = not zero, \"!Z\"\n        elif mnemo in [\"jg\", \"jnle\"]:\n            taken, reason = not zero and sign == overflow, \"!Z && S==O\"\n        elif mnemo in [\"jge\", \"jnl\"]:\n            taken, reason = sign == overflow, \"S==O\"\n        elif mnemo in [\"jl\", \"jnge\"]:\n            taken, reason = sign != overflow, \"S!=O\"\n        elif mnemo in [\"jle\", \"jng\"]:\n            taken, reason = zero or sign != overflow, \"Z || S!=O\"\n        elif mnemo in [\"jo\"]:\n            taken, reason = overflow, \"O\"\n        elif mnemo in [\"jno\"]:\n            taken, reason = not overflow, \"!O\"\n        elif mnemo in [\"jpe\", \"jp\"]:\n            taken, reason = parity, \"P\"\n        elif mnemo in [\"jnp\", \"jpo\"]:\n            taken, reason = not parity, \"!P\"\n        elif mnemo in [\"js\"]:\n            taken, reason = sign, \"S\"\n        elif mnemo in [\"jns\"]:\n            taken, reason = not sign, \"!S\"\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                if insn.mnemonic == \"ret\":\n                    ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n                elif insn.mnemonic == \"retf\": # eip, cs\n                    ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n                elif insn.mnemonic == \"sysret\": # ecx\n                    ra = get_register(\"$ecx\")\n                elif insn.mnemonic in [\"iret\", \"iretd\", \"iretw\"]: # eip, cs, eflags, esp, ss\n                    reg = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n                    eflags = AddressUtil.dereference(current_arch.sp + current_arch.ptrsize * 2)\n                    if eflags & (1 << 17): # eflags.vm\n                        seg = AddressUtil.dereference(current_arch.sp + current_arch.ptrsize) & 0xffff\n                        return ((seg << 4) + reg) & (0x1f_ffff if X86_16.A20 else 0x0f_ffff)\n                    return reg\n            elif frame.older():\n                ra = frame.older().pc()\n        except (gdb.error, AttributeError):\n            pass\n        return ra\n\n    def get_tls(self):\n        if is_in_kernel():\n            return None\n        return self.get_gs()\n\n    def decode_cookie(self, value, cookie):\n        return ror(value, 9, 32) ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return rol(value ^ cookie, 9, 32)\n\n    def get_fs(self):\n        # fastest path\n        fs = get_register(\"$fs_base\")\n        if fs is not None:\n            return fs\n        if is_rr(): # unsupported ptrace and ExecAsm when rr\n            return None\n        # fast path\n        if not is_remote_debug() and not is_in_kernel() and not is_qiling():\n            PTRACE_ARCH_PRCTL = 30\n            ARCH_GET_FS = 0x1003\n            pid, lwpid, tid = gdb.selected_thread().ptid\n            ppvoid = ctypes.POINTER(ctypes.c_void_p)\n            value = ppvoid(ctypes.c_void_p())\n            value.contents.value = 0\n            libc = ctypes.CDLL(\"libc.so.6\")\n            ret = libc.ptrace(PTRACE_ARCH_PRCTL, lwpid, value, ARCH_GET_FS)\n            if ret == 0: # success\n                return value.contents.value or 0\n        # slow path\n        if not is_kvm_enabled() and not is_qiling():\n            codes = [b\"\\x64\\xa1\\x00\\x00\\x00\\x00\"] # mov eax, dword ptr fs:[0x0]\n            ret = ExecAsm(codes).exec_code()\n            return ret[\"reg\"][\"$eax\"]\n        return None\n\n    def get_gs(self):\n        # fastest path\n        gs = get_register(\"$gs_base\")\n        if gs is not None:\n            return gs\n        if is_rr(): # unsupported ptrace and ExecAsm when rr\n            return None\n        # fast path\n        if not is_remote_debug() and not is_in_kernel() and not is_qiling():\n            PTRACE_ARCH_PRCTL = 30\n            ARCH_GET_GS = 0x1004\n            pid, lwpid, tid = gdb.selected_thread().ptid\n            ppvoid = ctypes.POINTER(ctypes.c_void_p)\n            value = ppvoid(ctypes.c_void_p())\n            value.contents.value = 0\n            libc = ctypes.CDLL(\"libc.so.6\")\n            ret = libc.ptrace(PTRACE_ARCH_PRCTL, lwpid, value, ARCH_GET_GS)\n            if ret == 0: # success\n                return value.contents.value or 0\n        # slow path\n        if not is_kvm_enabled() and not is_qiling():\n            codes = [b\"\\x65\\xa1\\x00\\x00\\x00\\x00\"] # mov eax, dword ptr gs:[0x0]\n            ret = ExecAsm(codes).exec_code()\n            return ret[\"reg\"][\"$eax\"]\n        return None\n\n    def get_ith_parameter(self, i, in_func=True):\n        if in_func:\n            i += 1 # Account for RA being at the top of the stack\n        sp = current_arch.sp\n        sz = current_arch.ptrsize\n        loc = sp + (i * sz)\n        val = read_int_from_memory(loc)\n        key = \"[sp + {:#x}]\".format(i * sz)\n        return key, val\n\n    def read28(self, addr):\n        codes = [\n            b\"\\x8b\\x00\", # mov eax, dword ptr [eax]\n            b\"\\x8b\\x1b\", # mov ebx, dword ptr [ebx]\n            b\"\\x8b\\x09\", # mov ecx, dword ptr [ecx]\n            b\"\\x8b\\x12\", # mov edx, dword ptr [edx]\n            b\"\\x8b\\x24\\x24\", # mov esp, dword ptr [esp]\n            # Rewriting EBP triggers an error message, which is noisy, so it is skipped.\n            #b\"\\x8b\\x6d\\x00\", # mov ebp, dword ptr [ebp]\n            b\"\\x8b\\x36\", # mov esi, dword ptr [esi]\n            b\"\\x8b\\x3f\", # mov edi, dword ptr [edi]\n        ]\n        regs = [\n            \"$eax\", \"$ebx\", \"$ecx\", \"$edx\", \"$esp\", \"$esi\", \"$edi\",\n        ]\n        regs = {reg: addr + i * current_arch.ptrsize for i, reg in enumerate(regs)}\n        ret = ExecAsm(codes, regs=regs, step=len(codes)).exec_code()\n        values = [ret[\"reg\"][reg] for reg in regs]\n        return b\"\".join([p32(v) for v in values])\n\n\nclass X86_64(X86):\n    \"\"\"GEF representation of x86-64 architecture.\"\"\"\n\n    arch = \"X86\"\n    mode = \"64\"\n\n    load_condition = [\n        Elf.EM_X86_64,\n        \"X64\",\n        \"AMD64\",\n        \"X86_64\",\n        \"X86-64\",\n        \"I386:X86-64\",\n        \"I386:X86-64:INTEL\",\n    ]\n\n    general_registers = [\n        \"$rax\", \"$rbx\", \"$rcx\", \"$rdx\", \"$rsp\", \"$rbp\", \"$rsi\", \"$rdi\", \"$rip\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\", \"$eflags\",\n    ]\n    all_registers = general_registers + X86.special_registers\n    alias_registers = {}\n\n    return_register = \"$rax\"\n    function_parameters = [\"$rdi\", \"$rsi\", \"$rdx\", \"$rcx\", \"$r8\", \"$r9\"]\n    syscall_register = \"$rax\"\n    syscall_parameters = [\"$rdi\", \"$rsi\", \"$rdx\", \"$r10\", \"$r8\", \"$r9\"]\n\n    bit_length = 64\n\n    syscall_insn = b\"\\x0f\\x05\" # syscall\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"sysenter\", \"syscall\"]\n\n    def is_ret(self, insn):\n        if insn.mnemonic in [\"ret\", \"retf\"]:\n            return True\n        if insn.mnemonic in [\"sysret\", \"sysretd\", \"sysretq\"]:\n            return True\n        if insn.mnemonic in [\"iret\", \"iretd\", \"iretq\", \"iretw\"]:\n            return True\n        return False\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                if insn.mnemonic == \"ret\":\n                    ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n                elif insn.mnemonic == \"retf\": # rip, cs\n                    ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n                elif insn.mnemonic in [\"sysret\", \"sysretd\", \"sysretq\"]: # rcx\n                    ra = get_register(\"$rcx\")\n                elif insn.mnemonic in [\"iret\", \"iretd\", \"iretq\", \"iretw\"]: # rip, cs, rflags, rsp, ss\n                    ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n            elif frame.older():\n                ra = frame.older().pc()\n        except (gdb.error, AttributeError):\n            pass\n        return ra\n\n    def get_tls(self):\n        if is_in_kernel():\n            return None\n        return self.get_fs()\n\n    def decode_cookie(self, value, cookie):\n        return ror(value, 17, 64) ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return rol(value ^ cookie, 17, 64)\n\n    def get_fs(self):\n        # fastest path\n        fs = get_register(\"$fs_base\")\n        if fs is not None:\n            return fs\n        if is_rr(): # unsupported ptrace and ExecAsm when rr\n            return None\n        # fast path\n        if not is_remote_debug() and not is_in_kernel() and not is_qiling():\n            PTRACE_ARCH_PRCTL = 30\n            ARCH_GET_FS = 0x1003\n            _pid, lwpid, _tid = gdb.selected_thread().ptid\n            ppvoid = ctypes.POINTER(ctypes.c_void_p)\n            value = ppvoid(ctypes.c_void_p())\n            value.contents.value = 0\n            libc = ctypes.CDLL(\"libc.so.6\")\n            ret = libc.ptrace(PTRACE_ARCH_PRCTL, lwpid, value, ARCH_GET_FS)\n            if ret == 0: # success\n                return value.contents.value or 0\n        # slow path\n        if not is_kvm_enabled() and not is_qiling():\n            codes = [b\"\\x64\\x48\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"] # movabs rax, qword ptr fs:[0x0]\n            ret = ExecAsm(codes).exec_code()\n            return ret[\"reg\"][\"$rax\"]\n        return None\n\n    def get_gs(self):\n        # fastest path\n        gs = get_register(\"$gs_base\")\n        if gs is not None:\n            return gs\n        if is_rr(): # unsupported ptrace and ExecAsm when rr\n            return None\n        # fast path\n        if not is_remote_debug() and not is_in_kernel() and not is_qiling():\n            PTRACE_ARCH_PRCTL = 30\n            ARCH_GET_GS = 0x1004\n            _pid, lwpid, _tid = gdb.selected_thread().ptid\n            ppvoid = ctypes.POINTER(ctypes.c_void_p)\n            value = ppvoid(ctypes.c_void_p())\n            value.contents.value = 0\n            libc = ctypes.CDLL(\"libc.so.6\")\n            ret = libc.ptrace(PTRACE_ARCH_PRCTL, lwpid, value, ARCH_GET_GS)\n            if ret == 0: # success\n                return value.contents.value or 0\n        # slow path\n        if not is_kvm_enabled() and not is_qiling():\n            codes = [b\"\\x65\\x48\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"] # movabs rax, qword ptr gs:[0x0]\n            ret = ExecAsm(codes).exec_code()\n            return ret[\"reg\"][\"$rax\"]\n        return None\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i -= len(self.function_parameters)\n            if in_func:\n                i += 1 # Account for RA being at the top of the stack\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def read128(self, addr):\n        codes = [\n            b\"\\x48\\x8b\\x00\", # mov rax, qword ptr [rax]\n            b\"\\x48\\x8b\\x09\", # mov rcx, qword ptr [rcx]\n            b\"\\x48\\x8b\\x12\", # mov rdx, qword ptr [rdx]\n            b\"\\x48\\x8b\\x1b\", # mov rbx, qword ptr [rbx]\n            b\"\\x48\\x8b\\x24\\x24\", # mov rsp, qword ptr [rsp]\n            b\"\\x48\\x8b\\x6d\\x00\", # mov rbp, qword ptr [rbp]\n            b\"\\x48\\x8b\\x36\", # mov rsi, qword ptr [rsi]\n            b\"\\x48\\x8b\\x3f\", # mov rdi, qword ptr [rdi]\n            b\"\\x4d\\x8b\\x00\", # mov r8, qword ptr [r8]\n            b\"\\x4d\\x8b\\x09\", # mov r9, qword ptr [r9]\n            b\"\\x4d\\x8b\\x12\", # mov r10, qword ptr [r10]\n            b\"\\x4d\\x8b\\x1b\", # mov r11, qword ptr [r11]\n            b\"\\x4d\\x8b\\x24\\x24\", # mov r12, qword ptr [r12]\n            b\"\\x4d\\x8b\\x6d\\x00\", # mov r13, qword ptr [r13]\n            b\"\\x4d\\x8b\\x36\", # mov r14, qword ptr [r14]\n            b\"\\x4d\\x8b\\x3f\", # mov r15, qword ptr [r15]\n        ]\n        regs = [\n            \"$rax\", \"$rcx\", \"$rdx\", \"$rbx\", \"$rsp\", \"$rbp\", \"$rsi\", \"$rdi\",\n            \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        ]\n        regs = {reg: addr + i * current_arch.ptrsize for i, reg in enumerate(regs)}\n        ret = ExecAsm(codes, regs=regs, step=len(codes)).exec_code()\n        values = [ret[\"reg\"][reg] for reg in regs]\n        return b\"\".join([p64(v) for v in values])\n\n\nclass X86_16(X86):\n    \"\"\"GEF representation of i8086 architecture.\"\"\"\n\n    arch = \"X86\"\n    mode = \"16\"\n\n    load_condition = [\n        \"I8086\",\n    ]\n\n    seg_extended_registers = {\n        \"$cs:$ip\": [\"$cs\", \"$pc\"],\n        \"$ss:$sp\": [\"$ss\", \"$sp\"],\n        \"$ss:$bp\": [\"$ss\", \"$bp\"],\n        \"$ds:$si\": [\"$ds\", \"$si\"],\n        \"$es:$di\": [\"$es\", \"$di\"],\n    }\n\n    # https://stanislavs.org/helppc/int_21.html\n    return_register = None\n    function_parameters = [\"$sp\"] # but unused because x86 uses stack\n    syscall_register = \"$ah\"\n    syscall_parameters = None\n\n    bit_length = 16\n\n    def __init__(self):\n        gdb.execute(\"gef config context_code.use_capstone True\")\n        return\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"int\" and int(insn.operands[0].lstrip(\"$\"), 0) == 0x21\n        except Exception:\n            return False\n\n    def is_jump(self, insn):\n        return insn.mnemonic in [\"jmp\", \"ljmp\"] or self.is_conditional_branch(insn)\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"retf\", \"iret\"]\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                if insn.mnemonic == \"ret\":\n                    reg = AddressUtil.dereference(current_arch.sp) & 0xffff\n                    ra = current_arch.real2phys(\"$cs\", reg)\n                elif insn.mnemonic == \"retf\": # ip, cs\n                    reg = AddressUtil.dereference(current_arch.sp) & 0xffff\n                    seg = AddressUtil.dereference(current_arch.sp + current_arch.ptrsize) & 0xffff\n                    ra = current_arch.real2phys(seg, reg)\n                elif insn.mnemonic == \"iret\": # ip, cs, flags, sp, ss\n                    reg = AddressUtil.dereference(current_arch.sp) & 0xffff\n                    seg = AddressUtil.dereference(current_arch.sp + current_arch.ptrsize) & 0xffff\n                    ra = current_arch.real2phys(seg, reg)\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    A20 = True\n\n    def real2phys(self, seg, reg):\n        if isinstance(seg, str):\n            segval = get_register(seg) & 0xffff\n        else:\n            segval = seg\n        if isinstance(reg, str):\n            regval = get_register(reg) & 0xffff\n        else:\n            regval = reg\n        if self.A20:\n            return ((segval << 4) + regval) & 0x1f_ffff\n        else:\n            return ((segval << 4) + regval) & 0x0f_ffff\n\n    @property\n    def pc(self):\n        return self.real2phys(\"$cs\", \"$pc\")\n\n    @property\n    def sp(self):\n        return self.real2phys(\"$ss\", \"$sp\")\n\n\nclass PPC(Architecture):\n    \"\"\"GEF representation of PowerPC-32 architecture.\"\"\"\n\n    arch = \"PPC\"\n    mode = \"32\"\n\n    load_condition = [\n        Elf.EM_PPC,\n        \"POWERPC\",\n        \"PPC\",\n        \"PPC32\",\n        \"POWERPC:COMMON\",\n    ]\n\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$pc\", \"$msr\", \"$cr\", \"$lr\", \"$ctr\", \"$xer\", \"$fpscr\",\n    ]\n    alias_registers = {\n        \"$r1\": \"$sp\", \"$r2\": \"$tp\",\n    }\n    flag_register = \"$cr\"\n    flags_table = {\n        # cr0\n        31: \"lt0\",\n        30: \"gt0\",\n        29: \"eq0\",\n        28: \"so0\",\n        # cr1\n        27: \"lt1\",\n        26: \"gt1\",\n        25: \"eq1\",\n        24: \"so1\",\n        # cr2\n        23: \"lt2\",\n        22: \"gt2\",\n        21: \"eq2\",\n        20: \"so2\",\n        # cr3\n        19: \"lt3\",\n        18: \"gt3\",\n        17: \"eq3\",\n        16: \"so3\",\n        # cr4\n        15: \"lt4\",\n        14: \"gt4\",\n        13: \"eq4\",\n        12: \"so4\",\n        # cr5\n        11: \"lt5\",\n        10: \"gt5\",\n        9: \"eq5\",\n        8: \"so5\",\n        # cr6\n        7: \"lt6\",\n        6: \"gt6\",\n        5: \"eq6\",\n        4: \"so6\",\n        # cr7\n        3: \"lt7\",\n        2: \"gt7\",\n        1: \"eq7\",\n        0: \"so7\",\n    }\n    return_register = \"$r3\"\n    function_parameters = [\"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\", \"$r10\"]\n    syscall_register = \"$r0\"\n    syscall_parameters = [\"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\"]\n\n    bit_length = 32\n    endianness = \"little / big\"\n    instruction_length = 4\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x00\\x00\\x00\\x60\" # nop\n    infloop_insn = b\"\\x00\\x00\\x00\\x48\" # b #0\n    trap_insn = b\"\\x08\\x00\\xe0\\x7f\" # trap\n    ret_insn = b\"\\x20\\x00\\x80\\x4e\" # blr\n    syscall_insn = b\"\\x02\\x00\\x00\\x44\" # sc\n\n    def flag_register_to_human(self, val=None):\n        # http://www.cebix.net/downloads/bebox/pem32b.pdf (% 2.1.3)\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"sc\"]\n\n    def is_call(self, insn):\n        conditions = [\n            \"\", \"lt\", \"le\", \"eq\", \"ge\", \"gt\", \"nl\",\n            \"ne\", \"ng\", \"so\", \"ns\", \"un\", \"nu\",\n        ]\n        mnemo = insn.mnemonic.rstrip(\"+-\")\n        for cc in conditions:\n            if mnemo == f\"b{cc}l\":\n                return True\n            if mnemo == f\"b{cc}la\":\n                return True\n            if mnemo == f\"b{cc}ctrl\":\n                return True\n            if mnemo == f\"b{cc}lrl\":\n                return True\n        modes = [\"dz\", \"dnzf\", \"dzt\", \"dzf\", \"dnzt\", \"dnz\"]\n        for m in modes:\n            if mnemo == f\"b{m}l\":\n                return True\n            if mnemo == f\"b{m}la\":\n                return True\n            if mnemo == f\"b{m}lrl\":\n                return True\n        return False\n\n    def is_jump(self, insn):\n        conditions = [\n            \"\", \"lt\", \"le\", \"eq\", \"ge\", \"gt\", \"nl\",\n            \"ne\", \"ng\", \"so\", \"ns\", \"un\", \"nu\",\n        ]\n        mnemo = insn.mnemonic.rstrip(\"+-\")\n        for cc in conditions:\n            if mnemo == f\"b{cc}\":\n                return True\n            if mnemo == f\"b{cc}a\":\n                return True\n            if mnemo == f\"b{cc}ctr\":\n                return True\n        modes = [\"dz\", \"dnzf\", \"dzt\", \"dzf\", \"dnzt\", \"dnz\"]\n        for m in modes:\n            if mnemo == f\"b{m}\":\n                return True\n            if mnemo == f\"b{m}a\":\n                return True\n        return False\n\n    def is_ret(self, insn):\n        conditions = [\n            \"\", \"lt\", \"le\", \"eq\", \"ge\", \"gt\", \"nl\",\n            \"ne\", \"ng\", \"so\", \"ns\", \"un\", \"nu\",\n        ]\n        mnemo = insn.mnemonic.rstrip(\"+-\")\n        for cc in conditions:\n            if mnemo == f\"b{cc}lr\":\n                return True\n            if mnemo == f\"b{cc}lrl\":\n                return True\n        modes = [\"dz\", \"dnzf\", \"dzt\", \"dzf\", \"dnzt\", \"dnz\"]\n        for m in modes:\n            if mnemo == f\"b{m}lr\":\n                return True\n            if mnemo == f\"b{m}lrl\":\n                return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = (\n            \"beq\", \"bne\", \"ble\", \"blt\", \"bgt\", \"bge\", \"bso\", \"bns\",\n            \"bdz\", \"bdnz\", \"bdzt\", \"bdnzt\", \"bdzf\", \"bdnzf\",\n        )\n        mnemo = insn.mnemonic.rstrip(\"+-\")\n        return mnemo.startswith(branch_mnemos)\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic.rstrip(\"+-\")\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        val = get_register(self.flag_register)\n        taken, reason = False, \"\"\n\n        m = re.search(r\"\\bcr([0-7])\\b\", insn.operands[0] if insn.operands else \"\")\n        cr_number = int(m.group(1)) if m else 0\n\n        equal = bool(val & (1 << flags[\"eq{}\".format(cr_number)]))\n        less = bool(val & (1 << flags[\"lt{}\".format(cr_number)]))\n        greater = bool(val & (1 << flags[\"gt{}\".format(cr_number)]))\n        overflow = bool(val & (1 << flags[\"so{}\".format(cr_number)]))\n\n        if mnemo.startswith(\"beq\"):\n            taken, reason = equal, \"E\"\n        elif mnemo.startswith(\"bne\"):\n            taken, reason = not equal, \"!E\"\n        elif mnemo.startswith(\"ble\"):\n            taken, reason = equal or less, \"E || L\"\n        elif mnemo.startswith(\"blt\"):\n            taken, reason = less, \"L\"\n        elif mnemo.startswith(\"bge\"):\n            taken, reason = equal or greater, \"E || G\"\n        elif mnemo.startswith(\"bgt\"):\n            taken, reason = greater, \"G\"\n        elif mnemo.startswith(\"bso\"):\n            taken, reason = overflow, \"V\"\n        elif mnemo.startswith(\"bns\"):\n            taken, reason = not overflow, \"!V\"\n        # todo: bdn?z[tf]? are unsupported\n        return taken, reason\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i -= len(self.function_parameters)\n            i += 2 # for EABI, not SysV\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$lr\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n\n        def adjust_offset(x):\n            TLS_TCB_OFFSET = 0x7000\n            if x == 0:\n                return x\n            return x - TLS_TCB_OFFSET\n\n        tls = get_register(\"$r2\")\n        return adjust_offset(tls)\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass PPC64(PPC):\n    \"\"\"GEF representation of PowerPC-64 architecture.\"\"\"\n\n    arch = \"PPC\"\n    mode = \"64\"\n\n    load_condition = [\n        Elf.EM_PPC64,\n        \"POWERPC64\",\n        \"PPC64\",\n        \"POWERPC:COMMON64\",\n    ]\n\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$pc\", \"$msr\", \"$cr\", \"$lr\", \"$ctr\", \"$xer\", \"$fpscr\", \"$vscr\", \"$vrsave\",\n    ]\n    alias_registers = {\n        \"$r1\": \"$sp\", \"$r13\": \"$tp\",\n    }\n    syscall_parameters = [\"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\"]\n\n    bit_length = 64\n\n    unicorn_support = False\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i += 4 # ???\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def get_tls(self):\n\n        def adjust_offset(x):\n            TLS_TCB_OFFSET = 0x7000\n            if x == 0:\n                return x\n            return x - TLS_TCB_OFFSET\n\n        tls = get_register(\"$r13\")\n        return adjust_offset(tls)\n\n\nclass SPARC(Architecture):\n    \"\"\"GEF representation of SPARC-32 architecture.\"\"\"\n\n    arch = \"SPARC\"\n    mode = \"32\"\n\n    load_condition = [\n        Elf.EM_SPARC,\n        \"SPARC\",\n        \"SPARC32\",\n        \"SPARC:V8\",\n    ]\n\n    # http://www.cse.scu.edu/~atkinson/teaching/sp05/259/sparc.pdf\n    all_registers = [\n        \"$g0\", \"$g1\", \"$g2\", \"$g3\", \"$g4\", \"$g5\", \"$g6\", \"$g7\",\n        \"$o0\", \"$o1\", \"$o2\", \"$o3\", \"$o4\", \"$o5\", \"$sp\", \"$o7\",\n        \"$l0\", \"$l1\", \"$l2\", \"$l3\", \"$l4\", \"$l5\", \"$l6\", \"$l7\",\n        \"$i0\", \"$i1\", \"$i2\", \"$i3\", \"$i4\", \"$i5\", \"$fp\", \"$i7\",\n        \"$y\", \"$psr\", \"$wim\", \"$tbr\", \"$pc\", \"$npc\", \"$fsr\", \"$csr\",\n    ]\n    alias_registers = {\n        \"$g0\": \"$zero\", \"$g7\": \"$tp\", \"$sp\": \"$o6\", \"$fp\": \"$i6\",\n    }\n    flag_register = \"$psr\"\n    flags_table = {\n        23: \"negative\",\n        22: \"zero\",\n        21: \"overflow\",\n        20: \"carry\",\n        7: \"supervisor\",\n        5: \"trap\",\n    }\n    return_register = \"$o0\"\n    function_parameters = [\"$o0\", \"$o1\", \"$o2\", \"$o3\", \"$o4\", \"$o5\"]\n    function_parameters_infunc = [\"$i0\", \"$i1\", \"$i2\", \"$i3\", \"$i4\", \"$i5\"]\n    syscall_register = \"$g1\"\n    syscall_parameters = [\"$o0\", \"$o1\", \"$o2\", \"$o3\", \"$o4\", \"$o5\"]\n\n    bit_length = 32\n    endianness = \"big\"\n    instruction_length = 4\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x00\\x00\\x00\\x01\" # nop\n    infloop_insn = b\"\\x00\\x00\\x80\\x10\" # b self\n    trap_insn = None\n    ret_insn = b\"\\x08\\xe0\\xc7\\x81\" # ret\n    syscall_insn = b\"\\x10\\x20\\xd0\\x91\" # trap 0x10\n\n    def flag_register_to_human(self, val=None):\n        # https://courses.grainger.illinois.edu/cs423/sp2011/lectures/sim_public/sparcv8.pdf\n        if val is None:\n            val = get_register(self.flag_register)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"ta\" and int(insn.operands[0], 0) == 0x10\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"jmpl\", \"call\"]\n\n    def is_jump(self, insn):\n        mnemo = insn.mnemonic.split(\",\")[0]\n        if mnemo.startswith(\"b\"):\n            return mnemo not in [\"btst\", \"bset\", \"bclr\", \"btog\"]\n        if mnemo.startswith(\"fb\"):\n            return True\n        if mnemo == \"jmpl\":\n            return True\n        return False\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"retl\", \"return\"]\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            # http://moss.csc.ncsu.edu/~mueller/codeopt/codeopt00/notes/condbranch.html\n            \"be\", \"bne\", \"bg\", \"bge\", \"bgeu\", \"bgu\", \"bl\", \"ble\", \"blu\", \"bleu\",\n            \"bneg\", \"bpos\", \"bvs\", \"bvc\", \"bcs\", \"bcc\",\n            # https://www.gaisler.com/doc/sparcv8.pdf\n            \"fbu\", \"fbg\", \"fbug\", \"fbl\", \"fbul\", \"fblg\", \"fbne\", \"fbe\", \"fbue\", \"fbge\",\n            \"fbuge\", \"fble\", \"fbule\", \"fbo\",\n            # https://docs.oracle.com/cd/E18752_01/html/816-1681/sparcv9-30990.html\n            \"bpne\", \"bpe\", \"bpg\", \"bple\", \"bpge\", \"bpl\", \"bpgu\", \"bpleu\", \"bpcc\", \"bpcs\",\n            \"bppos\", \"bpneg\", \"bpvc\", \"bpvs\", \"brz\", \"brlez\", \"brlz\", \"brnz\", \"brgz\", \"brgez\",\n            \"fbpu\", \"fbpg\", \"fbpug\", \"fbpl\", \"fbpul\", \"fbplg\", \"fbpne\", \"fbpe\", \"fbpue\", \"fbpge\",\n            \"fbpuge\", \"fbple\", \"fbpule\", \"fbpo\",\n        ]\n        # e.g., bne,pn -> bne\n        mnemo = insn.mnemonic.split(\",\")[0]\n        return mnemo in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic.split(\",\")[0]\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        val = get_register(self.flag_register)\n        taken, reason = False, \"\"\n\n        zero = bool(val & (1 << flags[\"zero\"]))\n        negative = bool(val & (1 << flags[\"negative\"]))\n        overflow = bool(val & (1 << flags[\"overflow\"]))\n        carry = bool(val & (1 << flags[\"carry\"]))\n\n        if mnemo in [\"be\", \"bpe\"]:\n            taken, reason = zero, \"Z\"\n        elif mnemo in [\"bne\", \"bpne\"]:\n            taken, reason = not zero, \"!Z\"\n        elif mnemo in [\"bg\", \"bpg\"]:\n            taken, reason = not zero and (negative == overflow), \"!Z && (N == V)\"\n        elif mnemo in [\"bge\", \"bpge\"]:\n            taken, reason = negative == overflow, \"N == V\"\n        elif mnemo in [\"bgu\", \"bpgu\"]:\n            taken, reason = not carry and not zero, \"!C && !Z\"\n        elif mnemo in [\"bgeu\"]:\n            taken, reason = not carry, \"!C\"\n        elif mnemo in [\"bl\", \"bpl\"]:\n            taken, reason = negative != overflow, \"N != V\"\n        elif mnemo in [\"blu\"]:\n            taken, reason = carry, \"C\"\n        elif mnemo in [\"ble\", \"bple\"]:\n            taken, reason = zero or (negative != overflow), \"Z || (N != V)\"\n        elif mnemo in [\"bleu\", \"bpleu\"]:\n            taken, reason = carry or zero, \"C || Z\"\n        elif mnemo in [\"bneg\", \"bpneg\"]:\n            taken, reason = negative, \"N\"\n        elif mnemo in [\"bpos\", \"bppos\"]:\n            taken, reason = not negative, \"!N\"\n        elif mnemo in [\"bvs\", \"bpvs\"]:\n            taken, reason = overflow, \"V\"\n        elif mnemo in [\"bvc\", \"bpvc\"]:\n            taken, reason = not overflow, \"!V\"\n        elif mnemo in [\"bcs\", \"bpcs\"]:\n            taken, reason = carry, \"C\"\n        elif mnemo in [\"bcc\", \"bpcc\"]:\n            taken, reason = not carry, \"!C\"\n        # todo: f* opcode, brn?z/br[lg]e?z are unsupported\n        return taken, reason\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            if in_func:\n                # TODO: Leaf functions use $o0...$o5 despite in_func=True\n                reg = self.function_parameters_infunc[i]\n            else:\n                reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            BIAS = 0\n            OUT_ARG_OVERFLOW = 0x5c\n            if in_func:\n                regname, base_addr = \"fp\", get_register(\"$fp\")\n            else:\n                regname, base_addr = \"sp\", current_arch.sp\n            offset = BIAS + OUT_ARG_OVERFLOW + ((i - 6) * current_arch.ptrsize)\n            val = read_int_from_memory(base_addr + offset)\n            key = \"[{:s} + {:#x}]\".format(regname, offset)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if insn.mnemonic == \"retl\":\n                ra = get_register(\"$o7\") + self.instruction_length * 2 # call, delay-slot\n            elif insn.mnemonic == \"ret\":\n                ra = get_register(\"$i7\") + self.instruction_length * 2 # call, delay-slot\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$g7\")\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass SPARC32PLUS(SPARC):\n    \"\"\"GEF representation of SPARC-32+ architecture.\"\"\"\n\n    arch = \"SPARC\"\n    mode = \"32PLUS\"\n\n    load_condition = [\n        Elf.EM_SPARC32PLUS,\n        \"SPARC32PLUS\",\n        \"SPARC32+\",\n        \"SPARCV8PLUS\",\n        \"SPARCV8+\",\n        \"SPARC:V8PLUS\",\n        \"SPARC:V8PLUSA\",\n        \"SPARC:V8PLUSB\",\n        \"SPARC:V8PLUSC\",\n        \"SPARC:V8PLUSD\",\n        \"SPARC:V8PLUSE\",\n        \"SPARC:V8PLUSM\",\n        \"SPARC:V8PLUSV\",\n    ]\n\n\nclass SPARC64(SPARC):\n    \"\"\"GEF representation of SPARC-64 architecture.\"\"\"\n\n    arch = \"SPARC\"\n    mode = \"64\"\n\n    load_condition = [\n        Elf.EM_SPARCV9,\n        \"SPARC64\",\n        \"SPARC:V9\",\n        \"SPARC:V9A\",\n        \"SPARC:V9B\",\n        \"SPARC:V9C\",\n        \"SPARC:V9D\",\n        \"SPARC:V9E\",\n        \"SPARC:V9M\",\n        \"SPARC:V9V\",\n    ]\n\n    # http://math-atlas.sourceforge.net/devel/assembly/abi_sysV_sparc.pdf\n    # https://cr.yp.to/2005-590/sparcv9.pdf\n    all_registers = [\n        \"$g0\", \"$g1\", \"$g2\", \"$g3\", \"$g4\", \"$g5\", \"$g6\", \"$g7\",\n        \"$o0\", \"$o1\", \"$o2\", \"$o3\", \"$o4\", \"$o5\", \"$sp\", \"$o7\",\n        \"$l0\", \"$l1\", \"$l2\", \"$l3\", \"$l4\", \"$l5\", \"$l6\", \"$l7\",\n        \"$i0\", \"$i1\", \"$i2\", \"$i3\", \"$i4\", \"$i5\", \"$fp\", \"$i7\",\n        \"$pc\", \"$npc\", \"$state\", \"$fsr\", \"$fprs\", \"$y\", \"$cwp\",\n        \"$pstate\", \"$asi\", \"$ccr\",\n    ]\n    flag_register = \"$state\" # sparcv9.pdf, 5.1.5.1 (ccr), because $state includes $ccr.\n    flags_table = {\n        35: \"negative\",\n        34: \"zero\",\n        33: \"overflow\",\n        32: \"carry\",\n    }\n\n    bit_length = 64\n\n    syscall_insn = b\"\\x6d\\x20\\xd0\\x91\" # trap 0x6d\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"ta\" and int(insn.operands[0], 0) == 0x6d\n        except Exception:\n            return False\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            if in_func:\n                # TODO: Leaf functions use $o0...$o5 despite in_func=True\n                reg = self.function_parameters_infunc[i]\n            else:\n                reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            BIAS = 0x7ff\n            OUT_ARG_OVERFLOW = 0xb0\n            if in_func:\n                regname, base_addr = \"fp\", get_register(\"$fp\")\n            else:\n                regname, base_addr = \"sp\", current_arch.sp\n            offset = BIAS + OUT_ARG_OVERFLOW + ((i - 6) * current_arch.ptrsize)\n            val = read_int_from_memory(base_addr + offset)\n            key = \"[{:s} + {:#x}]\".format(regname, offset)\n            return key, val\n\n\nclass MIPS(Architecture):\n    \"\"\"GEF representation of MIPS-32 architecture.\"\"\"\n\n    arch = \"MIPS\"\n    mode = \"32\"\n\n    load_condition = [\n        # Elf.EM_MIPS cannot determine whether it is 32-bit or 64-bit, so it should not be used.\n        \"MIPS\",\n        \"MIPS32\",\n        \"MIPS:ISA32\",\n        \"MIPS:ISA32R2\",\n        \"MIPS:ISA32R3\",\n        \"MIPS:ISA32R5\",\n        \"MIPS:ISA32R6\",\n    ]\n\n    # http://vhouten.home.xs4all.nl/mipsel/r3000-isa.html\n    all_registers = [\n        \"$zero\", \"$at\", \"$v0\", \"$v1\", \"$a0\", \"$a1\", \"$a2\", \"$a3\",\n        \"$t0\", \"$t1\", \"$t2\", \"$t3\", \"$t4\", \"$t5\", \"$t6\", \"$t7\",\n        \"$s0\", \"$s1\", \"$s2\", \"$s3\", \"$s4\", \"$s5\", \"$s6\", \"$s7\",\n        \"$t8\", \"$t9\", \"$k0\", \"$k1\", \"$gp\", \"$sp\", \"$fp\", \"$ra\",\n        \"$sr\", \"$lo\", \"$hi\", \"$bad\", \"$cause\", \"$fsr\", \"$fir\", \"$pc\",\n    ]\n    alias_registers = {\n        \"$zero\": \"$r0\", \"$at\": \"$r1\", \"$v0\": \"$r2\", \"$v1\": \"$r3\",\n        \"$a0\": \"$r4\", \"$a1\": \"$r5\", \"$a2\": \"$r6\", \"$a3\": \"$r7\",\n        \"$t0\": \"$r8\", \"$t1\": \"$r9\", \"$t2\": \"$r10\", \"$t3\": \"$r11\",\n        \"$t4\": \"$r12\", \"$t5\": \"$r13\", \"$t6\": \"$r14\", \"$t7\": \"$r15\",\n        \"$s0\": \"$r16\", \"$s1\": \"$r17\", \"$s2\": \"$r18\", \"$s3\": \"$r19\",\n        \"$s4\": \"$r20\", \"$s5\": \"$r21\", \"$s6\": \"$r22\", \"$s7\": \"$r23\",\n        \"$t8\": \"$r24\", \"$t9\": \"$r25\", \"$k0\": \"$r26\", \"$k1\": \"$r27\",\n        \"$gp\": \"$r28\", \"$sp\": \"$r29\", \"$fp\": \"$s8/$r30\", \"$ra\": \"$r31\",\n    }\n    flag_register = None # MIPS has no flags register\n    return_register = \"$v0\"\n    function_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\"]\n    syscall_register = \"$v0\"\n    syscall_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$sp+0x10\", \"$sp+0x14\", \"$sp+0x18\", \"$sp+0x1c\"]\n\n    bit_length = 32\n    bit_length_reg = 32\n    endianness = \"little / big\"\n    instruction_length = 4\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x00\\x00\\x00\\x00\" # nop\n    infloop_insn = b\"\\xff\\xff\\x00\\x10\" # b self\n    trap_insn = b\"\\x0d\\x00\\x00\\x00\" # break\n    ret_insn = b\"\\x08\\x00\\xe0\\x03\" # jr $ra\n    syscall_insn = b\"\\x0c\\x00\\x00\\x00\" # syscall\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"syscall\"]\n\n    def is_call(self, insn):\n        branch_mnemos = [\n            \"bal\", \"balc\", \"jal\", \"jalr\", \"jalrc\", \"jalrc.hb\",\n            \"bgezal\", \"bgezall\", \"bltzal\", \"bltzall\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_jump(self, insn):\n        if self.is_ret(insn):\n            return False\n        if insn.mnemonic in [\"b\", \"bc\", \"j\", \"jr\", \"jrc\", \"balrsc\", \"brsc\"]:\n            return True\n        if self.is_conditional_branch(insn):\n            return True\n        return False\n\n    def is_ret(self, insn):\n        if insn.mnemonic in [\"jr\", \"jrc\"] and insn.operands[0] == \"ra\":\n            return True\n        if insn.mnemonic in [\"deret\", \"eret\", \"eretnc\"]:\n            return True\n        if insn.mnemonic in [\"restore\", \"restore.jrc\"]:\n            return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"bne\", \"bgtz\", \"bgez\", \"bltz\", \"blez\", \"beqz\", \"bnez\",\n            \"beql\", \"bnel\", \"bgtzl\", \"bgezl\", \"bltzl\", \"blezl\",\n            \"bgezal\", \"bgezall\", \"bltzal\", \"bltzall\",\n            \"bc1f\", \"bc1fl\", \"bc1t\", \"bc1tl\", \"bc2f\", \"bc2fl\", \"bc2t\", \"bc2tl\",\n            \"beqc\", \"beqic\", \"beqzc\",\n            \"bnec\", \"bneic\", \"bnezc\",\n            \"bgec\", \"bgeic\", \"bgeiuc\", \"bgeuc\",\n            \"bltc\", \"bltic\", \"bltiuc\", \"bltuc\",\n            \"bbeqzc\", \"bbnezc\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        taken, reason = False, \"\"\n\n        def u2i(x):\n            if self.bit_length_reg == 64:\n                trans = lambda a: struct.unpack(\"<q\", struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff))[0]\n            else:\n                trans = lambda a: struct.unpack(\"<i\", struct.pack(\"<I\", a & 0xffff_ffff))[0]\n            return trans(x)\n\n        if mnemo in [\"beq\", \"beql\", \"beqc\"]:\n            taken, reason = get_register(ops[0]) == get_register(ops[1]), \"{0[0]} == {0[1]}\".format(ops)\n        elif mnemo in [\"beqic\"]:\n            taken, reason = get_register(ops[0]) == int(ops[1], 0), \"{0[0]} == {0[1]}\".format(ops)\n        elif mnemo in [\"bne\", \"bnel\", \"bnec\"]:\n            taken, reason = get_register(ops[0]) != get_register(ops[1]), \"{0[0]} != {0[1]}\".format(ops)\n        elif mnemo in [\"bneic\"]:\n            taken, reason = get_register(ops[0]) != int(ops[1], 0), \"{0[0]} != {0[1]}\".format(ops)\n        elif mnemo in [\"beqz\", \"beqzc\"]:\n            taken, reason = get_register(ops[0]) == 0, \"{0[0]} == 0\".format(ops)\n        elif mnemo in [\"bnez\", \"bnezc\"]:\n            taken, reason = get_register(ops[0]) != 0, \"{0[0]} != 0\".format(ops)\n        elif mnemo in [\"bgtz\", \"bgtzl\"]:\n            taken, reason = u2i(get_register(ops[0])) > 0, \"{0[0]} > 0\".format(ops)\n        elif mnemo in [\"bgez\", \"bgezl\"]:\n            taken, reason = u2i(get_register(ops[0])) >= 0, \"{0[0]} >= 0\".format(ops)\n        elif mnemo in [\"bltz\", \"bltzl\"]:\n            taken, reason = u2i(get_register(ops[0])) < 0, \"{0[0]} < 0\".format(ops)\n        elif mnemo in [\"blez\", \"blezl\"]:\n            taken, reason = u2i(get_register(ops[0])) <= 0, \"{0[0]} <= 0\".format(ops)\n        elif mnemo in [\"bbeqzc\"]:\n            taken, reason = (get_register(ops[0]) >> int(ops[1], 0) & 1) == 0, \"(({0[0]} >> {0[1]}) & 1) == 0\".format(ops)\n        elif mnemo in [\"bbnezc\"]:\n            taken, reason = (get_register(ops[0]) >> int(ops[1], 0) & 1) != 0, \"(({0[0]} >> {0[1]}) & 1) != 0\".format(ops)\n        elif mnemo in [\"bgec\"]:\n            taken, reason = u2i(get_register(ops[0])) >= u2i(get_register(ops[1])), \"{0[0]} >= {0[1]}\".format(ops)\n        elif mnemo in [\"bgeic\"]:\n            taken, reason = u2i(get_register(ops[0])) >= u2i(int(ops[1], 0)), \"{0[0]} >= {0[1]}\".format(ops)\n        elif mnemo in [\"bgeuc\"]:\n            taken, reason = get_register(ops[0]) >= get_register(ops[1]), \"{0[0]} >= {0[1]}\".format(ops)\n        elif mnemo in [\"bgeiuc\"]:\n            taken, reason = get_register(ops[0]) >= int(ops[1], 0), \"{0[0]} >= {0[1]}\".format(ops)\n        elif mnemo in [\"bltc\"]:\n            taken, reason = u2i(get_register(ops[0])) < u2i(get_register(ops[1])), \"{0[0]} < {0[1]}\".format(ops)\n        elif mnemo in [\"bltic\"]:\n            taken, reason = u2i(get_register(ops[0])) < u2i(int(ops[1], 0)), \"{0[0]} < {0[1]}\".format(ops)\n        elif mnemo in [\"bltuc\"]:\n            taken, reason = get_register(ops[0]) < get_register(ops[1]), \"{0[0]} < {0[1]}\".format(ops)\n        elif mnemo in [\"bltiuc\"]:\n            taken, reason = get_register(ops[0]) < int(ops[1], 0), \"{0[0]} < {0[1]}\".format(ops)\n        return taken, reason\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$ra\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n\n        def adjust_offset(x):\n            TLS_TCB_OFFSET = 0x7000\n            if x == 0:\n                return x\n            return x - TLS_TCB_OFFSET\n\n        codes = [b\"\\x3b\\xe8\\x03\\x7c\"] # rdhwr v1, $29\n        ret = ExecAsm(codes).exec_code()\n        tls = ret[\"reg\"][\"$v1\"]\n        return adjust_offset(tls)\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass MIPS64(MIPS):\n    \"\"\"GEF representation of MIPS-64 architecture.\"\"\"\n\n    arch = \"MIPS\"\n    mode = \"64\"\n\n    load_condition = [\n        # Elf.EM_MIPS cannot determine whether it is 32-bit or 64-bit, so it should not be used.\n        \"MIPS64\",\n        \"MIPS:ISA64\",\n        \"MIPS:ISA64R2\",\n        \"MIPS:ISA64R3\",\n        \"MIPS:ISA64R5\",\n        \"MIPS:ISA64R6\",\n    ]\n\n    all_registers = [\n        \"$zero\", \"$at\", \"$v0\", \"$v1\", \"$a0\", \"$a1\", \"$a2\", \"$a3\",\n        \"$a4\", \"$a5\", \"$a6\", \"$a7\", \"$t0\", \"$t1\", \"$t2\", \"$t3\",\n        \"$s0\", \"$s1\", \"$s2\", \"$s3\", \"$s4\", \"$s5\", \"$s6\", \"$s7\",\n        \"$t8\", \"$t9\", \"$k0\", \"$k1\", \"$gp\", \"$sp\", \"$fp\", \"$ra\",\n        \"$sr\", \"$lo\", \"$hi\", \"$bad\", \"$cause\", \"$fsr\", \"$fir\", \"$pc\",\n    ]\n    alias_registers = {\n        \"$zero\": \"$r0\", \"$at\": \"$r1\", \"$v0\": \"$r2\", \"$v1\": \"$r3\",\n        \"$a0\": \"$r4\", \"$a1\": \"$r5\", \"$a2\": \"$r6\", \"$a3\": \"$r7\",\n        \"$a4\": \"$r8\", \"$a5\": \"$r9\", \"$a6\": \"$r10\", \"$a7\": \"$r11\",\n        \"$t0\": \"$r12\", \"$t1\": \"$r13\", \"$t2\": \"$r14\", \"$t3\": \"$r15\",\n        \"$s0\": \"$r16\", \"$s1\": \"$r17\", \"$s2\": \"$r18\", \"$s3\": \"$r19\",\n        \"$s4\": \"$r20\", \"$s5\": \"$r21\", \"$s6\": \"$r22\", \"$s7\": \"$r23\",\n        \"$t8\": \"$r24\", \"$t9\": \"$r25\", \"$k0\": \"$r26\", \"$k1\": \"$r27\",\n        \"$gp\": \"$r28\", \"$sp\": \"$r29\", \"$fp\": \"$s8/$r30\", \"$ra\": \"$r31\",\n    }\n    function_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\", \"$a6\", \"$a7\"]\n    syscall_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\"]\n\n    bit_length = 64\n    bit_length_reg = 64\n\n    unicorn_support = False\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i -= len(self.function_parameters)\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n\nclass MIPSN32(MIPS64):\n    \"\"\"GEF representation of MIPS-N32-ABI architecture.\"\"\"\n\n    arch = \"MIPS\"\n    mode = \"n32\"\n\n    load_condition = [\n        \"MIPSN32\"\n    ]\n\n    bit_length = 32\n    bit_length_reg = 64\n\n\nclass S390X(Architecture):\n    \"\"\"GEF representation of s390x architecture.\"\"\"\n\n    arch = \"S390X\"\n    mode = \"64\"\n\n    load_condition = [\n        # Elf.EM_S390 cannot determine whether it is 32 bit or 64 bit,\n        # but since GEF only supports 64 bit (s390x), so we will use it.\n        Elf.EM_S390,\n        \"S390X\",\n        \"S390:64-BIT\",\n    ]\n\n    # https://www.ibm.com/docs/en/SSQ2R2_15.0.0/com.ibm.tpf.toolkit.hlasm.doc/dz9zr006.pdf\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$pswm\", \"$pswa\", \"$fpc\", \"$gsd\", \"$gssm\", \"$gsepla\",\n        \"$gs_reserved\", \"$pc\", \"$cc\",\n    ]\n    alias_registers = {\n        \"$r14\": \"$lr\", \"$r15\": \"$sp\",\n    }\n    flag_register = \"$cc\"\n    flags_table = {\n        1: \"cc1\",\n        0: \"cc0\",\n    }\n    return_register = \"$r2\"\n    function_parameters = [\"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\"]\n    syscall_register = [r\"svc\\s+(\\d+)\", \"$r1\"] # $r1 is used when NR > 127\n    syscall_parameters = [\"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\"]\n\n    bit_length = 64\n    endianness = \"big\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = True\n    capstone_support = True\n    unicorn_support = False # for some reason it doesn't work\n\n    nop_insn = b\"\\x07\\x07\" # bcr 0, %r7\n    infloop_insn = b\"\\x00\\x00\\xf4\\xa7\" # j 0\n    trap_insn = None\n    ret_insn = b\"\\xfe\\x07\" # br %r14\n    syscall_insn = b\"\\x00\\x0a\" # svc 0x0\n\n    def is_syscall(self, insn):\n        return insn.mnemonic == \"svc\"\n\n    # https://www.ibm.com/docs/en/zos/2.1.0?topic=statements-branching-extended-mnemonic-codes\n    def is_call(self, insn):\n        return insn.mnemonic in [\"bal\", \"balr\", \"bas\", \"basr\", \"bassm\", \"bsm\", \"bras\", \"brasl\"]\n\n    def is_jump(self, insn):\n        if self.is_ret(insn):\n            return False\n        if insn.mnemonic in [\"b\", \"br\", \"j\", \"bru\", \"brul\", \"jlu\"]:\n            return True\n        return self.is_conditional_branch(insn)\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"br\" and insn.operands[-1] == \"%r14\"\n\n    def is_conditional_branch(self, insn):\n        if insn.mnemonic in [\"bc\", \"bcr\", \"brc\", \"brcl\"]:\n            return True\n        conditions = [\"h\", \"l\", \"e\", \"nh\", \"nl\", \"ne\", \"p\", \"m\", \"z\", \"o\", \"np\", \"nm\", \"nz\", \"no\"]\n        for cc in conditions:\n            if insn.mnemonic == f\"b{cc}\": # alias for `bc N, ...`\n                return True\n            if insn.mnemonic == f\"b{cc}r\": # alias for `bcr N, ...`\n                return True\n            if insn.mnemonic in [f\"br{cc}\", f\"j{cc}\"]: # alias for `brc N, ...`\n                return True\n            if insn.mnemonic in [f\"br{cc}l\", f\"jl{cc}\"]: # alias for `brcl N, ...`\n                return True\n\n        if insn.mnemonic in [\"bct\", \"bctr\", \"bctg\", \"bctgr\", \"brct\", \"brctg\"]:\n            return True\n        if insn.mnemonic in [\"bxh\", \"bxhg\", \"brxh\", \"brxhg\"]:\n            return True\n        if insn.mnemonic in [\"bxle\", \"bxleg\", \"brxle\", \"brxlg\"]:\n            return True\n\n        if insn.mnemonic in [\"crb\", \"cgrb\", \"crj\", \"cgrj\"]:\n            return True\n        if insn.mnemonic in [\"cib\", \"cgib\", \"cij\", \"cgij\"]:\n            return True\n        if insn.mnemonic in [\"clrb\", \"clgrb\", \"clrj\", \"clgrj\"]:\n            return True\n        if insn.mnemonic in [\"clib\", \"clgib\", \"clij\", \"clgij\"]:\n            return True\n        conditions = [\"h\", \"l\", \"ne\"]\n        for cc in conditions:\n            if insn.mnemonic == f\"crb{cc}\": # alias for `crb r,r,N`\n                return True\n            if insn.mnemonic == f\"cgrb{cc}\": # alias for `cgrb r,r,N`\n                return True\n            if insn.mnemonic == f\"crj{cc}\": # alias for `crj r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"cgrj{cc}\": # alias for `cgrj r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"cib{cc}\": # alias for `cib r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"cgib{cc}\": # alias for `cgib r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"cij{cc}\": # alias for `cij r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"cgij{cc}\": # alias for `cgij r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"clrb{cc}\": # alias for `clrb r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"clgrb{cc}\": # alias for `clgrb r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"clrj{cc}\": # alias for `clrj r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"clgrj{cc}\": # alias for `clgrj r,r,N, ...`\n                return True\n            if insn.mnemonic == f\"clib{cc}\": # alias for `clib r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"clgib{cc}\": # alias for `clgib r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"clij{cc}\": # alias for `clij r,i,N, ...`\n                return True\n            if insn.mnemonic == f\"clgij{cc}\": # alias for `clgij r,i,N, ...`\n                return True\n        return False\n\n    def is_branch_taken(self, insn):\n        taken, reason = False, \"\"\n\n        def is_insn_condition_type1(insn):\n            if insn.mnemonic in [\"bc\", \"bcr\", \"brc\", \"brcl\"]:\n                return True\n            conditions = [\n                \"h\", \"l\", \"e\", \"nh\", \"nl\", \"ne\", \"p\", \"m\",\n                \"z\", \"o\", \"np\", \"nm\", \"nz\", \"no\",\n            ]\n            for cc in conditions:\n                if insn.mnemonic == f\"b{cc}\": # alias for `bc N, ...`\n                    return True\n                if insn.mnemonic == f\"b{cc}r\": # alias for `bcr N, ...`\n                    return True\n                if insn.mnemonic in [f\"br{cc}\", f\"j{cc}\"]: # alias for `brc N, ...`\n                    return True\n                if insn.mnemonic in [f\"br{cc}l\", f\"jl{cc}\"]: # alias for `brcl N, ...`\n                    return True\n            return False\n\n        def is_insn_condition_type2_signed32(insn):\n            if insn.mnemonic in [\"crb\", \"crj\"]:\n                return True\n            if insn.mnemonic in [\"cib\", \"cij\"]:\n                return True\n            conditions = [\"h\", \"l\", \"ne\"]\n            for cc in conditions:\n                if insn.mnemonic == f\"crb{cc}\": # alias for `crb r,r,N`\n                    return True\n                if insn.mnemonic == f\"crj{cc}\": # alias for `crj r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"cib{cc}\": # alias for `cib r,i,N, ...`\n                    return True\n                if insn.mnemonic == f\"cij{cc}\": # alias for `cij r,i,N, ...`\n                    return True\n            return False\n\n        def is_insn_condition_type2_signed64(insn):\n            if insn.mnemonic in [\"cgrb\", \"cgrj\"]:\n                return True\n            if insn.mnemonic in [\"cgib\", \"cgij\"]:\n                return True\n            conditions = [\"h\", \"l\", \"ne\"]\n            for cc in conditions:\n                if insn.mnemonic == f\"cgrb{cc}\": # alias for `cgrb r,r,N`\n                    return True\n                if insn.mnemonic == f\"cgrj{cc}\": # alias for `cgrj r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"cgib{cc}\": # alias for `cgib r,i,N, ...`\n                    return True\n                if insn.mnemonic == f\"cgij{cc}\": # alias for `cgij r,i,N, ...`\n                    return True\n            return False\n\n        def is_insn_condition_type2_unsigned32(insn):\n            if insn.mnemonic in [\"clrb\", \"clrj\"]:\n                return True\n            if insn.mnemonic in [\"clib\", \"clij\"]:\n                return True\n            conditions = [\"h\", \"l\", \"ne\"]\n            for cc in conditions:\n                if insn.mnemonic == f\"clrb{cc}\": # alias for `clrb r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"clrj{cc}\": # alias for `clrj r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"clib{cc}\": # alias for `clib r,i,N, ...`\n                    return True\n                if insn.mnemonic == f\"clij{cc}\": # alias for `clij r,i,N, ...`\n                    return True\n            return False\n\n        def is_insn_condition_type2_unsigned64(insn):\n            if insn.mnemonic in [\"clgrb\", \"clgrj\"]:\n                return True\n            if insn.mnemonic in [\"clgib\", \"clgij\"]:\n                return True\n            conditions = [\"h\", \"l\", \"ne\"]\n            for cc in conditions:\n                if insn.mnemonic == f\"clgrb{cc}\": # alias for `clgrb r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"clgrj{cc}\": # alias for `clgrj r,r,N, ...`\n                    return True\n                if insn.mnemonic == f\"clgib{cc}\": # alias for `clgib r,i,N, ...`\n                    return True\n                if insn.mnemonic == f\"clgij{cc}\": # alias for `clgij r,i,N, ...`\n                    return True\n            return False\n\n        if is_insn_condition_type1(insn):\n            mask = insn.opcodes[1] >> 4\n\n            val = get_register(self.flag_register)\n            flags = {self.flags_table[k]: k for k in self.flags_table}\n            cc1 = (val >> flags[\"cc1\"]) & 1\n            cc0 = (val >> flags[\"cc0\"]) & 1\n            cc = (cc1 << 1) + cc0\n\n            if (mask & 0b1) and cc == 3:\n                return True, \"cc==3\"\n            if (mask & 0b10) and cc == 2:\n                return True, \"cc==2\"\n            if (mask & 0b100) and cc == 1:\n                return True, \"cc==1\"\n            if (mask & 0b1000) and cc == 0:\n                return True, \"cc==0\"\n            return False, \"\"\n\n        if insn.mnemonic in [\"bct\", \"bctr\", \"bctg\", \"bctgr\", \"brct\", \"brctg\"]:\n            reg = insn.operands[0]\n            return get_register(reg) != 1, \"{:s}!=1\".format(reg)\n\n        def get_cmp_regname(reg3):\n            m = re.search(r\"(\\d+)$\", reg3)\n            if m is None:\n                return None\n            reg3_num = int(m.group(1), 10)\n            if reg3_num % 2 == 0:\n                cmp_reg = reg3_num + 1\n            else:\n                cmp_reg = reg3_num\n            return \"%r{:d}\".format(cmp_reg)\n\n        def u2i(x, mnemo):\n            if mnemo in (\"bxhg\", \"brxhg\", \"bxleg\", \"brxlg\"):\n                trans = lambda a: struct.unpack(\"<q\", struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff))[0]\n            else:\n                trans = lambda a: struct.unpack(\"<i\", struct.pack(\"<I\", a & 0xffff_ffff))[0]\n            return trans(x)\n\n        if insn.mnemonic in [\"bxh\", \"bxhg\", \"brxh\", \"brxhg\"]:\n            reg1, reg3 = insn.operands[0], insn.operands[1]\n            regC = get_cmp_regname(reg3)\n            if regC is not None:\n                taken = u2i(get_register(reg1) + get_register(reg3), insn.mnemonic) > u2i(get_register(regC), insn.mnemonic)\n                reason = \"({:s}+{:s})>{:s}\".format(reg1, reg3, regC)\n                return taken, reason\n\n        if insn.mnemonic in [\"bxle\", \"bxleg\", \"brxle\", \"brxlg\"]:\n            reg1, reg3 = insn.operands[0], insn.operands[1]\n            regC = get_cmp_regname(reg3)\n            if regC is not None:\n                taken = u2i(get_register(reg1) + get_register(reg3), insn.mnemonic) <= u2i(get_register(regC), insn.mnemonic)\n                reason = \"({:s}+{:s})<={:s}\".format(reg1, reg3, regC)\n                return taken, reason\n\n        def for_compare(insn, signed, bit):\n            if len(insn.opcodes) < 5:\n                return False, \"\"\n\n            if signed and bit == 32:\n                trans = lambda a: struct.unpack(\"<i\", struct.pack(\"<I\", a & 0xffff_ffff))[0]\n            elif signed and bit == 64:\n                trans = lambda a: struct.unpack(\"<q\", struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff))[0]\n            elif not signed and bit == 32:\n                trans = lambda a: a & 0xffff_ffff\n            elif not signed and bit == 64:\n                trans = lambda a: a & 0xffff_ffff_ffff_ffff\n            else:\n                raise\n\n            mask = insn.opcodes[4] >> 4\n            reg1 = insn.operands[0]\n            reg2_or_imm = insn.operands[1]\n\n            val1 = trans(get_register(reg1))\n            if reg2_or_imm.startswith(\"%\"):\n                val2 = trans(get_register(reg2_or_imm))\n            else:\n                val2 = trans(int(reg2_or_imm, 0))\n            if (mask & 0b1) and val1 == val2:\n                return True, \"{:s}=={:s}\".format(reg1, reg2_or_imm)\n            if (mask & 0b10) and val1 < val2:\n                return True, \"{:s}<{:s}\".format(reg1, reg2_or_imm)\n            if (mask & 0b100) and val1 > val2:\n                return True, \"{:s}>{:s}\".format(reg1, reg2_or_imm)\n            return False, \"\"\n\n        if is_insn_condition_type2_signed32(insn):\n            return for_compare(insn, signed=True, bit=32)\n        if is_insn_condition_type2_signed64(insn):\n            return for_compare(insn, signed=True, bit=64)\n        if is_insn_condition_type2_unsigned32(insn):\n            return for_compare(insn, signed=False, bit=32)\n        if is_insn_condition_type2_unsigned64(insn):\n            return for_compare(insn, signed=False, bit=64)\n\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n\n        extra_msg = \" [\"\n        if get_register(\"$pswm\") is not None:\n            addressing0 = (get_register(\"$pswm\") >> 31) & 1\n            addressing1 = (get_register(\"$pswm\") >> 32) & 1\n            addressing_mode = {\n                (0, 0): \"24-bit\",\n                (0, 1): \"31-bit\",\n                (1, 1): \"64-bit\",\n            }[addressing0, addressing1]\n            extra_msg += \"AddressingMode={:s}, \".format(addressing_mode)\n\n        cc1 = (val >> flags[\"cc1\"]) & 1\n        cc0 = (val >> flags[\"cc0\"]) & 1\n        condition_code = (cc1 << 1) + cc0\n        extra_msg += \"ConditionCode={:d}]\".format(condition_code)\n\n        return Architecture.flags_to_human(val, self.flags_table) + extra_msg\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            STACK_ARG_BASE = 0xa0\n            n_reg_args = len(self.function_parameters)\n            offset = STACK_ARG_BASE + ((i - n_reg_args) * current_arch.ptrsize)\n            val = read_int_from_memory(current_arch.sp + offset)\n            key = \"[sp + {:#x}]\".format(offset)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$r14\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        hi = get_register(\"$acr0\")\n        lo = get_register(\"$acr1\")\n        return (hi << 32) | lo\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass SH4(Architecture):\n    \"\"\"GEF representation of SH4 architecture.\"\"\"\n\n    arch = \"SH4\"\n    mode = \"SH4\"\n\n    load_condition = [\n        Elf.EM_SH,\n        \"SH4\",\n        \"SH4-NOFPU\",\n        \"SH4A\",\n        \"SH4A-NOFPU\",\n        \"SH2A-OR-SH4\",\n        \"SH2\",\n        \"SH3\",\n    ]\n\n    # https://www.renesas.com/us/en/document/man/705261\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$pc\", \"$pr\", \"$gbr\", \"$mach\", \"$macl\", \"$sr\",\n    ]\n    alias_registers = {\n        \"$r15\": \"$sp\",\n    }\n    flag_register = \"$sr\"\n    flags_table = {\n        0: \"t\",\n    }\n    return_register = \"$r0\"\n    function_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\"]\n    syscall_register = \"$r3\"\n    syscall_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r0\", \"$r1\", \"$r2\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = 2\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x09\\x00\" # nop\n    infloop_insn = b\"\\xfe\\xaf\" # bra self\n    trap_insn = None\n    ret_insn = b\"\\x0b\\x00\" # rts\n    syscall_insn = b\"\\x1f\\xc3\" # trapa #31\n\n    def is_syscall(self, insn):\n        if insn.mnemonic != \"trapa\":\n            return False\n        try:\n            imm = int(insn.operands[0].lstrip(\"#\"), 0)\n            return (0x10 <= imm <= 0x17) or (imm == 0x1f)\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"bsr\", \"bsrf\", \"jsr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"bra\", \"braf\", \"jmp\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"rts\"\n\n    def is_conditional_branch(self, insn):\n        return insn.mnemonic in [\"bf\", \"bf.s\", \"bt\", \"bt.s\"]\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        val = get_register(self.flag_register)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        taken, reason = False, \"\"\n\n        t = bool(val & (1 << flags[\"t\"]))\n\n        if mnemo in [\"bf\", \"bf.s\"]:\n            taken, reason = not t, \"!T\"\n        elif mnemo in [\"bt\", \"bt.s\"]:\n            taken, reason = t, \"T\"\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$pr\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$gbr\")\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass M68K(Architecture):\n    \"\"\"GEF representation of m68000 architecture.\"\"\"\n\n    arch = \"M68K\"\n    mode = \"32\"\n\n    load_condition = [\n        Elf.EM_68K,\n        \"M68K\",\n        \"M68000\",\n        \"M68K:68000\",\n        \"M68K:68008\",\n        \"M68K:68010\",\n        \"M68K:68020\",\n        \"M68K:68030\",\n        \"M68K:68040\",\n        \"M68K:68060\",\n    ]\n\n    # https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf\n    all_registers = [\n        \"$d0\", \"$d1\", \"$d2\", \"$d3\", \"$d4\", \"$d5\", \"$d6\", \"$d7\",\n        \"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\", \"$fp\", \"$sp\",\n        \"$ps\", \"$pc\",\n    ]\n    alias_registers = {\n        \"$fp\": \"$a6\", \"$sp\": \"$a7\", \"$ps\": \"$sr\",\n    }\n    flag_register = \"$ps\"\n    flags_table = {\n        0: \"carry\",\n        1: \"overflow\",\n        2: \"zero\",\n        3: \"negative\",\n        4: \"extend\",\n    }\n    return_register = \"$d0\"\n    function_parameters = [\"$sp\"] # but unused because m68k uses stack\n    syscall_register = \"$d0\"\n    syscall_parameters = [\"$d1\", \"$d2\", \"$d3\", \"$d4\", \"$d5\", \"$a0\"]\n\n    bit_length = 32\n    endianness = \"big\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = True\n    unicorn_support = True\n\n    nop_insn = b\"\\x71\\x4e\" # nop\n    infloop_insn = b\"\\xfe\\x60\" # bras self\n    trap_insn = b\"\\x48\\x48\" # bkpt 0\n    ret_insn = b\"\\x75\\x4e\" # rts\n    syscall_insn = b\"\\x40\\x4e\" # trap #0\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"trap\" and int(insn.operands[0].lstrip(\"#\"), 0) == 0\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"bsrs\", \"bsrw\", \"bsrl\", \"jsr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"bras\", \"braw\", \"bral\", \"jmp\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"rts\"\n\n    # https://sourceware.org/binutils/docs/as/M68K_002dBranch.html\n    # https://web.njit.edu/~rosensta/classes/architecture/252software/code.pdf\n    def is_conditional_branch(self, insn):\n        conditions = [\n            \"hi\", \"ls\", \"cc\", \"cs\", \"ne\", \"eq\", \"vc\",\n            \"vs\", \"pl\", \"mi\", \"ge\", \"lt\", \"gt\", \"le\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"b{cc}s\", f\"b{cc}w\", f\"b{cc}l\"]:\n                return True\n        conditions = [\n            \"hi\", \"ls\", \"cc\", \"cs\", \"ne\", \"eq\", \"vc\",\n            \"vs\", \"pl\", \"mi\", \"ge\", \"lt\", \"gt\", \"le\",\n            \"t\", \"f\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"db{cc}w\", f\"db{cc}\"]:\n                return True\n        conditions = [\n            \"ne\", \"eq\", \"ge\", \"lt\", \"gt\", \"le\", \"f\", \"t\",\n            \"gl\", \"gle\", \"nge\", \"ngl\", \"ngle\", \"ngt\", \"nle\", \"nlt\",\n            \"oge\", \"ogl\", \"ogt\", \"ole\", \"olt\", \"or\", # codespell:ignore\n            \"seq\", \"sf\", \"sne\", \"st\", \"ueq\", \"uge\", \"ugt\", \"ule\", \"ult\", \"un\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"fb{cc}w\", f\"fb{cc}l\"]:\n                return True\n        return False\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        val = get_register(self.flag_register)\n        taken, reason = False, \"\"\n\n        carry = bool(val & (1 << flags[\"carry\"]))\n        overflow = bool(val & (1 << flags[\"overflow\"]))\n        zero = bool(val & (1 << flags[\"zero\"]))\n        negative = bool(val & (1 << flags[\"negative\"]))\n\n        if mnemo in [\"bhis\", \"bhiw\", \"bhil\"]:\n            taken, reason = not carry and not zero, \"!C && !Z\"\n        elif mnemo in [\"blss\", \"blsw\", \"blsl\"]:\n            taken, reason = carry or zero, \"C || Z\"\n        elif mnemo in [\"bccs\", \"bccw\", \"bccl\"]:\n            taken, reason = not carry, \"!C\"\n        elif mnemo in [\"bcss\", \"bcsw\", \"bcsl\"]:\n            taken, reason = carry, \"C\"\n        elif mnemo in [\"bnes\", \"bnew\", \"bnel\"]:\n            taken, reason = not zero, \"!Z\"\n        elif mnemo in [\"beqs\", \"beqw\", \"beql\"]:\n            taken, reason = zero, \"Z\"\n        elif mnemo in [\"bvcs\", \"bvcw\", \"bvcl\"]:\n            taken, reason = not overflow, \"!V\"\n        elif mnemo in [\"bvss\", \"bvsw\", \"bvsl\"]:\n            taken, reason = overflow, \"V\"\n        elif mnemo in [\"bpls\", \"bplw\", \"bpll\"]:\n            taken, reason = not negative, \"!N\"\n        elif mnemo in [\"bmis\", \"bmiw\", \"bmil\"]:\n            taken, reason = negative, \"N\"\n        elif mnemo in [\"bges\", \"bgew\", \"bgel\"]:\n            taken, reason = (negative and overflow) or (not negative and not overflow), \"(N && V) || (!N && !V)\"\n        elif mnemo in [\"blts\", \"bltw\", \"bltl\"]:\n            taken, reason = (negative and not overflow) or (not negative and overflow), \"(N && !V) || (!N && V)\"\n        elif mnemo in [\"bgts\", \"bgtw\", \"bgtl\"]:\n            taken = (negative and overflow and not zero) or (not negative and not overflow and not zero)\n            reason = \"(N && V && !Z) || (!N && !V && !Z)\"\n        elif mnemo in [\"bles\", \"blew\", \"blel\"]:\n            taken, reason = zero or (negative and not overflow) or (not negative and overflow), \"Z || (N && !V) || (!N && V)\"\n        elif mnemo in [\"dbhiw\", \"dbhi\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = (carry or zero) and val != 0, \"(C || Z) && {:s}!=0\".format(regname)\n        elif mnemo in [\"dblsw\", \"dbls\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = not carry and not zero and val != 0, \"!C && !Z && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbccw\", \"dbcc\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = carry and val != 0, \"C && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbcsw\", \"dbcs\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = not carry and val != 0, \"!C && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbnew\", \"dbne\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = zero and val != 0, \"Z && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbeqw\", \"dbeq\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = not zero and val != 0, \"!Z && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbvcw\", \"dbvc\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = overflow and val != 0, \"V && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbvsw\", \"dbvs\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = not overflow and val != 0, \"!V && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbplw\", \"dbpl\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = negative and val != 0, \"N && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbmiw\", \"dbmi\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = not negative and val != 0, \"!N && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbgew\", \"dbge\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken = ((negative and not overflow) or (not negative and overflow)) and val != 0\n            reason = \"((N && !V) || (!N && V)) && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbltw\", \"dblt\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken = ((negative and overflow) or (not negative and not overflow)) and val != 0\n            reason = \"((N && V) || (!N && !V)) && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbgtw\", \"dbgt\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken = (zero or (negative and not overflow) or (not negative and overflow)) and val != 0\n            reason = \"(Z || (N && !V) || (!N && V)) && {:s}!=0\".format(regname)\n        elif mnemo in [\"dblew\", \"dble\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken = ((negative and overflow and not zero) or (not negative and not overflow and not zero)) and val != 0\n            reason = \"((N && V && !Z) || (!N && !V && !Z)) && {:s}!=0\".format(regname)\n        elif mnemo in [\"dbtw\", \"dbt\"]: # branch never taken\n            taken, reason = False, \"\"\n        elif mnemo in [\"dbfw\", \"dbf\"]:\n            regname = insn.operands[0].replace(\"%\", \"$\")\n            val = get_register(regname) & 0xffff\n            taken, reason = val != 0, \"{:s}!=0\".format(regname)\n        # TODO: fbXXw, fbXXl\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = to_unsigned_long(AddressUtil.dereference(current_arch.sp))\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_ith_parameter(self, i, in_func=True):\n        if in_func:\n            i += 1 # Account for RA being at the top of the stack\n        sp = current_arch.sp\n        sz = current_arch.ptrsize\n        loc = sp + (i * sz)\n        val = read_int_from_memory(loc)\n        key = \"[sp + {:#x}]\".format(i * sz)\n        return key, val\n\n    def get_tls(self):\n\n        def adjust_offset(x):\n            TLS_TCB_OFFSET = 0x7000\n            if x == 0:\n                return x\n            return x - TLS_TCB_OFFSET\n\n        ret = ExecSyscall(0x14d, []).exec_code() # get_thread_area\n        tls = ret[\"reg\"][\"$d0\"]\n        return adjust_offset(tls)\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass ALPHA(Architecture):\n    \"\"\"GEF representation of Alpha architecture.\"\"\"\n\n    arch = \"ALPHA\"\n    mode = \"ALPHA\"\n\n    load_condition = [\n        Elf.EM_ALPHA,\n        Elf.EM_ALPHA_UNOFFICIAL,\n        \"ALPHA\",\n        \"ALPHA:EV4\",\n        \"ALPHA:EV5\",\n        \"ALPHA:EV6\",\n    ]\n\n    # https://download.majix.org/dec/alpha_arch_ref.pdf\n    all_registers = [\n        \"$v0\", \"$t0\", \"$t1\", \"$t2\", \"$t3\", \"$t4\", \"$t5\", \"$t6\",\n        \"$t7\", \"$s0\", \"$s1\", \"$s2\", \"$s3\", \"$s4\", \"$s5\", \"$fp\",\n        \"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\", \"$t8\", \"$t9\",\n        \"$t10\", \"$t11\", \"$ra\", \"$t12\", \"$at\", \"$gp\", \"$sp\", \"$zero\", \"$pc\",\n    ]\n    alias_registers = {\n        \"$v0\": \"$r0\", \"$t0\": \"$r1\", \"$t1\": \"$r2\", \"$t2\": \"$r3\",\n        \"$t3\": \"$r4\", \"$t4\": \"$r5\", \"$t5\": \"$r6\", \"$t6\": \"$r7\",\n        \"$t7\": \"$r8\", \"$s0\": \"$r9\", \"$s1\": \"$r10\", \"$s2\": \"$r11\",\n        \"$s3\": \"$r12\", \"$s4\": \"$r13\", \"$s5\": \"$r14\", \"$fp\": \"$r15/$s6\",\n        \"$a0\": \"$r16\", \"$a1\": \"$r17\", \"$a2\": \"$r18\", \"$a3\": \"$r19\",\n        \"$a4\": \"$r20\", \"$a5\": \"$r21\", \"$t8\": \"$r22\", \"$t9\": \"$r23\",\n        \"$t10\": \"$r24\", \"$t11\": \"$r25\", \"$ra\": \"$r26\", \"$t12\": \"$r27/$pv\",\n        \"$at\": \"$r28\", \"$gp\": \"$r29\", \"$sp\": \"$r30\", \"$zero\": \"$r31\",\n    }\n    flag_register = None # alpha has no flags register\n    return_register = \"$v0\"\n    function_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\"]\n    syscall_register = \"$v0\"\n    syscall_parameters = [\"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\"]\n\n    bit_length = 64\n    endianness = \"little\"\n    instruction_length = 4\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x1f\\x04\\xff\\x47\" # nop\n    infloop_insn = b\"\\xff\\xff\\xff\\xc3\" # br self\n    trap_insn = b\"\\x80\\x00\\x00\\x00\" # bpt\n    ret_insn = b\"\\x01\\x80\\xfa\\x6b\" # ret\n    syscall_insn = b\"\\x83\\x00\\x00\\x00\" # callsys\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"callsys\"]\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"br\", \"bsr\", \"jsr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"jmp\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"jsr_coroutine\"]\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"bge\", \"bgt\", \"blbc\", \"blbs\", \"ble\", \"blt\", \"bne\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        taken, reason = False, \"\"\n\n        if len(ops) == 0:\n            return taken, reason\n\n        regname = ops[0]\n        regval = get_register(regname)\n        if regval is None:\n            return taken, reason\n\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        u2i = lambda a: uq(pQ(a))\n        regval = u2i(regval)\n\n        if mnemo == \"beq\":\n            taken, reason = regval == 0, \"{:s} == 0\".format(regname)\n        elif mnemo == \"bne\":\n            taken, reason = regval != 0, \"{:s} != 0\".format(regname)\n        elif mnemo == \"bge\":\n            taken, reason = regval >= 0, \"{:s} >= 0\".format(regname)\n        elif mnemo == \"bgt\":\n            taken, reason = regval > 0, \"{:s} > 0\".format(regname)\n        elif mnemo == \"ble\":\n            taken, reason = regval <= 0, \"{:s} <= 0\".format(regname)\n        elif mnemo == \"blt\":\n            taken, reason = regval < 0, \"{:s} < 0\".format(regname)\n        elif mnemo == \"blbc\":\n            taken, reason = (regval & 1) == 0, \"({:s}&1) == 0\".format(regname)\n        elif mnemo == \"blbs\":\n            taken, reason = (regval & 1) == 1, \"({:s}&1) == 1\".format(regname)\n\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$ra\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        tls = get_register(\"$unique\")\n        if tls is not None:\n            return tls\n\n        codes = [b\"\\x9e\\x00\\x00\\x00\"] # rduniq\n        ret = ExecAsm(codes).exec_code()\n        return ret[\"reg\"][\"$v0\"]\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass HPPA(Architecture):\n    \"\"\"GEF representation of HP-PA-32 architecture.\"\"\"\n\n    arch = \"HPPA\"\n    mode = \"32\"\n\n    load_condition = [\n        # Elf.EM_PARISC cannot determine whether it is 32-bit or 64-bit, so it should not be used\n        \"PARISC\",\n        \"PARISC32\",\n        \"PA-RISC\",\n        \"PA-RISC32\",\n        \"HPPA\",\n        \"HPPA32\",\n        \"HPPA1.0\",\n        \"HPPA1.1\",\n    ]\n\n    # http://ftp.parisc-linux.org/docs/arch/pa11_acd.pdf\n    all_registers = [\n        \"$r1\", \"$rp\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\",\n        \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\", \"$r16\",\n        \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\", \"$r24\",\n        \"$r25\", \"$r26\", \"$dp\", \"$ret0\", \"$ret1\", \"$sp\", \"$r31\", \"$pc\",\n        \"$flags\", \"$pcoqh\", \"$pcsqh\", \"$pcoqt\", \"$pcsqt\",\n    ]\n    alias_registers = {\n        \"$rp\": \"$r2\", \"$dp\": \"$r27\", \"$ret0\": \"$r28\", \"$ret1\": \"$r29\",\n        \"$sp\": \"$r30\",\n    }\n    flag_register = None # HPPA has no flags register\n    return_register = \"$ret0\"\n    function_parameters = [\"$r26\", \"$r25\", \"$r24\", \"$r23\"]\n    syscall_register = \"$r20\"\n    syscall_parameters = [\"$r26\", \"$r25\", \"$r24\", \"$r23\", \"$r22\", \"$r21\"]\n\n    bit_length = 32\n    endianness = \"big\"\n    instruction_length = 4\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = True\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x40\\x02\\x00\\x08\" # nop\n    infloop_insn = b\"\\xf7\\x1f\\x1f\\xe8\" # b,l,n self, r0\n    trap_insn = None\n    ret_insn = b\"\\x02\\xc0\\x40\\xe8\" # bv.n r0(rp)\n    syscall_insn = b\"\\x00\\x82\\x00\\xe4\" # be,l 100(sr2, r0), sr0, r31\n\n    def is_syscall(self, insn):\n        return insn.mnemonic == \"be,l\" and insn.operands[:4] == [\"100(sr2\", \"r0)\", \"sr0\", \"r31\"]\n\n    def is_call(self, insn):\n        if self.is_syscall(insn):\n            return False\n        if insn.mnemonic in [\"b,l\", \"b,l,n\"]: # alias for BL,n\n            return True\n        if insn.mnemonic in [\"blr\", \"blr,n\"]: # alias for BLR,n\n            return True\n        if insn.mnemonic in [\"be,l\", \"be,l,n\"]: # alias for BLE,n\n            return True\n        return False\n\n    def is_jump(self, insn):\n        if self.is_ret(insn):\n            return False\n        if self.is_conditional_branch(insn):\n            return True\n        if insn.mnemonic in [\"b,gate\", \"b,gate,n\"]: # alias for GATE,n\n            return True\n        if insn.mnemonic in [\"bv\", \"bv,n\"]: # alias for BV,n\n            return True\n        if insn.mnemonic in [\"be\", \"be,n\"]: # alias for BE,n\n            return True\n        return False\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"bv,n\" and insn.operands[-1] == \"r0(rp)\"\n\n    def is_conditional_branch(self, insn):\n        if insn.mnemonic.startswith((\"movb\", \"movib\")): # alias for MOVB,cond,n / MOVIB,cond,n\n            return True\n        if insn.mnemonic.startswith((\"cmpb\", \"cmpib\")): # alias for COMB[TF],cond,n / COMIB[TF],cond,n\n            return True\n        if insn.mnemonic.startswith((\"addb\", \"addib\")): # alias for ADDB[TF],cond,n / ADDIB[TF],cond,n\n            return True\n        if insn.mnemonic.startswith(\"bb,\"): # alias for BB,cond,n / BVB,cond,n\n            return True\n        return False\n\n    def is_branch_taken(self, insn):\n\n        def get_masked(x):\n            bits = 64 if is_64bit() else 32\n            return x & ((1 << bits) - 1)\n\n        def get_sign(x):\n            bits = 64 if is_64bit() else 32\n            return (x >> (bits - 1)) & 1\n\n        def to_signed(x):\n            bits = 64 if is_64bit() else 32\n            x &= ((1 << bits) - 1)\n            sign = 1 << (bits - 1)\n            # if sign bit set, subtract 2^bits\n            return x - (1 << bits) if (x & sign) else x\n\n        def check_cond_mov(c, name, val):\n            v = get_masked(val)\n\n            if c == 0: # never\n                taken, reason = False, \"\"\n            elif c == 1: # =\n                taken, reason = v == 0, \"{:s}==0\".format(name)\n            elif c == 2: # <\n                taken, reason = get_sign(v) == 1, \"MSB({:s})==1\".format(name)\n            elif c == 3: # OD\n                taken, reason = (v & 1) == 1, \"LSB({:s})==1\".format(name)\n            elif c == 4: # TR\n                taken, reason = True, \"Always True\"\n            elif c == 5: # <>\n                taken, reason = v != 0, \"{:s}!=0\".format(name)\n            elif c == 6: # EV\n                taken, reason = (v & 1) == 0, \"LSB({:s})==0\".format(name)\n            else:\n                taken, reason = False, \"\"\n            return taken, reason\n\n        def check_cond_cmp(c, neg, name1, val1, name2, val2):\n            v1 = get_masked(val1)\n            v2 = get_masked(val2)\n            s1 = to_signed(v1)\n            s2 = to_signed(v2)\n            res = get_masked(v1 - v2)\n\n            if c == 0: # never\n                if not neg:\n                    taken, reason = False, \"\"\n                else:\n                    taken, reason = True, \"Always True\"\n            elif c == 1: # =\n                if not neg:\n                    taken, reason = v1 == v2, \"{:s}=={:s}\".format(name1, name2)\n                else:\n                    taken, reason = v1 != v2, \"{:s}!={:s}\".format(name1, name2)\n            elif c == 2: # < (signed)\n                if not neg:\n                    taken, reason = s1 < s2, \"{:s}<{:s}\".format(name1, name2)\n                else:\n                    taken, reason = s1 >= s2, \"{:s}>={:s}\".format(name1, name2)\n            elif c == 3: # <= (signed)\n                if not neg:\n                    taken, reason = s1 <= s2, \"{:s}<={:s}\".format(name1, name2)\n                else:\n                    taken, reason = s1 > s2, \"{:s}>{:s}\".format(name1, name2)\n            elif c == 4: # < (unsigned)\n                if not neg:\n                    taken, reason = v1 < v2, \"{:s}<{:s} (unsigned)\".format(name1, name2)\n                else:\n                    taken, reason = v1 >= v2, \"{:s}>={:s} (unsigned)\".format(name1, name2)\n            elif c == 5: # <= (unsigned)\n                if not neg:\n                    taken, reason = v1 <= v2, \"{:s}<={:s} (unsigned)\".format(name1, name2)\n                else:\n                    taken, reason = v1 > v2, \"{:s}>{:s} (unsigned)\".format(name1, name2)\n            elif c == 6: # SV\n                overflow = (get_sign(v1) != get_sign(v2)) and (get_sign(v1) != get_sign(res)) # subtract overflow\n                if not neg:\n                    taken, reason = overflow, \"{:s}-{:s} overflows\".format(name1, name2)\n                else:\n                    taken, reason = not overflow, \"{:s}-{:s} does not overflow\".format(name1, name2)\n            elif c == 7: # OD\n                if not neg:\n                    taken, reason = (res & 1) == 1, \"LSB({:s}-{:s})==1\".format(name1, name2)\n                else:\n                    taken, reason = (res & 1) == 0, \"LSB({:s}-{:s})==0\".format(name1, name2)\n            return taken, reason\n\n        def check_cond_add(c, neg, name1, val1, name2, val2):\n            v1 = get_masked(val1)\n            v2 = get_masked(val2)\n            res = get_masked(v1 + v2)\n\n            if c == 0: # never\n                if not neg:\n                    taken, reason = False, \"\"\n                else:\n                    taken, reason = True, \"Always True\"\n            elif c == 1: # =\n                if not neg:\n                    taken, reason = res == 0, \"{:s}==-{:s}\".format(name1, name2)\n                else:\n                    taken, reason = res != 0, \"{:s}!=-{:s}\".format(name1, name2)\n            elif c == 2: # < (signed)\n                sres = to_signed(res)\n                if not neg:\n                    taken, reason = sres < 0, \"{:s}<-{:s} (signed)\".format(name1, name2)\n                else:\n                    taken, reason = sres >= 0, \"{:s}>=-{:s} (signed)\".format(name1, name2)\n            elif c == 3: # <= (signed)\n                sres = to_signed(res)\n                if not neg:\n                    taken, reason = sres <= 0, \"{:s}<=-{:s} (signed)\".format(name1, name2)\n                else:\n                    taken, reason = sres > 0, \"{:s}>-{:s} (signed)\".format(name1, name2)\n            elif c == 4: # NUV (unsigned)\n                full = v1 + v2 # addition overflow\n                carry = (full >> (64 if is_64bit() else 32)) & 1\n                if not neg:\n                    taken, reason = not carry, \"{:s}+{:s} does not overflow (unsigned)\".format(name1, name2)\n                else:\n                    taken, reason = carry, \"{:s}+{:s} overflows (unsigned)\".format(name1, name2)\n            elif c == 5: # ZNV (unsigned)\n                full = v1 + v2 # addition overflow\n                carry = (full >> (64 if is_64bit() else 32)) & 1\n                zero = (res == 0)\n                if not neg:\n                    taken, reason = zero or not carry, \"{:s}+{:s} is zero or no overflow (unsigned)\".format(name1, name2)\n                else:\n                    taken, reason = not zero and carry, \"{:s}+{:s} is nonzero and overflows (unsigned)\".format(name1, name2)\n            elif c == 6: # SV (signed)\n                overflow = (get_sign(v1) == get_sign(v2)) and (get_sign(v1) != get_sign(res)) # addition overflow\n                if not neg:\n                    taken, reason = overflow, \"{:s}+{:s} overflows (signed)\".format(name1, name2)\n                else:\n                    taken, reason = not overflow, \"{:s}+{:s} does not overflow (signed)\".format(name1, name2)\n            elif c == 7: # OD\n                if not neg:\n                    taken, reason = (res & 1) == 1, \"LSB({:s}+{:s})==1\".format(name1, name2)\n                else:\n                    taken, reason = (res & 1) == 0, \"LSB({:s}+{:s})==0\".format(name1, name2)\n            return taken, reason\n\n        def check_cond_bit(c, name1, val1, name2, val2):\n            bits = (64 if is_64bit() else 32) - 1\n            if val2 < 0 or val2 > bits:\n                return False, \"\"\n            v1 = get_masked(val1)\n            bit_on = ((v1 >> (bits - val2)) & 1) == 1\n\n            if c == 2: # <\n                taken, reason = bit_on, \"{:s}.bit({:s})==1\".format(name1, name2)\n            elif c == 6: # >=\n                taken, reason = not bit_on, \"{:s}.bit({:s})==0\".format(name1, name2)\n            else:\n                taken, reason = False, \"\"\n            return taken, reason\n\n        taken, reason = False, \"\"\n        if insn.mnemonic.startswith(\"movb\"): # alias for MOVB,cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            v1 = insn.operands[0] # source\n            taken, reason = check_cond_mov(c, v1, get_register(v1))\n        elif insn.mnemonic.startswith(\"movib\"): # alias for MOVIB,cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            v1 = insn.operands[0] # source\n            taken, reason = check_cond_mov(c, v1, int(v1, 16))\n        elif insn.mnemonic.startswith(\"cmpb\"): # alias for COMB[TF],cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            f = (insn.opcodes[0] >> 3) & 1 # True or False\n            v1 = insn.operands[0] # source1\n            v2 = insn.operands[1] # source2\n            taken, reason = check_cond_cmp(c, f, v1, get_register(v1), v2, get_register(v2))\n        elif insn.mnemonic.startswith(\"cmpib\"): # alias for COMIB[TF],cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            f = (insn.opcodes[0] >> 3) & 1 # True or False\n            v1 = insn.operands[0] # source1\n            v2 = insn.operands[1] # source2\n            taken, reason = check_cond_cmp(c, f, v1, int(v1, 16), v2, get_register(v2))\n        elif insn.mnemonic.startswith(\"addb\"): # alias for ADDB[TF],cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            f = (insn.opcodes[0] >> 3) & 1 # True or False\n            v1 = insn.operands[0] # source1\n            v2 = insn.operands[1] # source2\n            taken, reason = check_cond_add(c, f, v1, get_register(v1), v2, get_register(v2))\n        elif insn.mnemonic.startswith(\"addib\"): # alias for ADDIB[TF],cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            f = (insn.opcodes[0] >> 3) & 1 # True or False\n            v1 = insn.operands[0] # source1\n            v2 = insn.operands[1] # source2\n            taken, reason = check_cond_add(c, f, v1, int(v1, 16), v2, get_register(v2))\n        elif insn.mnemonic.startswith(\"bb,\"): # alias for BVB,cond,n / BB,cond,n\n            c = (insn.opcodes[2] >> 5) & 0b111\n            v1 = insn.operands[0] # source1\n            v2 = insn.operands[1] # source2\n            vbit = (insn.opcodes[0] >> 2) & 1\n            if vbit:\n                taken, reason = check_cond_bit(c, v1, get_register(v1), v2, int(v2, 16)) # bb,cond,n\n            else:\n                taken, reason = check_cond_bit(c, v1, get_register(v1), v2, get_register(v2)) # bvb,cond,n\n\n        if not taken:\n            reason = \"\"\n        return taken, reason\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            i -= len(self.function_parameters)\n            ret0 = get_register(\"$ret0\")\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = ret0 - (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp - {:#x}]\".format(sp - loc)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$rp\") & ~0b11\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        tls = get_register(\"$cr27\")\n        if tls is not None:\n            return tls\n\n        tls = get_register(\"$mpsfu_high\")\n        if tls is not None:\n            return tls\n\n        codes = [b\"\\xbc\\x08\\x60\\x03\"] # mfctl tr3, ret0\n        ret = ExecAsm(codes).exec_code()\n        return ret[\"reg\"][\"$ret0\"]\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass HPPA64(HPPA):\n    \"\"\"GEF representation of HP-PA-64 architecture.\"\"\"\n\n    arch = \"HPPA\"\n    mode = \"64\"\n\n    # qemu does not support hppa64, so this could not be tested.\n\n    load_condition = [\n    ]\n\n    bit_length = 64\n\n\nclass OR1K(Architecture):\n    \"\"\"GEF representation of OpenRISC 1000 architecture.\"\"\"\n\n    arch = \"OR1K\"\n    mode = \"OR1K\"\n\n    load_condition = [\n        Elf.EM_OPENRISC,\n        \"OPENRISC\",\n        \"OPENRISC1000\",\n        \"OR1K\",\n    ]\n\n    # https://openrisc.io/or1k.html\n    # https://sourceware.org/cgen/gen-doc/openrisc-insn.html\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$ppc\", \"$npc\", \"$sr\",\n    ]\n    alias_registers = {\n        \"$r1\": \"$sp\", \"$r2\": \"$fp\", \"$r9\": \"$lr\",\n    }\n    flag_register = \"$sr\"\n    flags_table = {\n        11: \"overflow\",\n        10: \"carry\",\n        9: \"flag\",\n    }\n    return_register = \"$r11\"\n    function_parameters = [\"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\"]\n    syscall_register = \"$r11\"\n    syscall_parameters = [\"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\"]\n\n    bit_length = 32\n    endianness = \"big\"\n    instruction_length = 4\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x00\\x00\\x00\\x15\" # l.nop 0x0\n    infloop_insn = b\"\\x00\\x00\\x00\\x00\" # l.j self\n    trap_insn = None\n    ret_insn = b\"\\x00\\x48\\x00\\x44\" # l.jr r9\n    syscall_insn = b\"\\x01\\x00\\x00\\x20\" # l.sys 0x1\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"l.sys\" and int(insn.operands[0], 0) == 0x1\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"l.bal\", \"l.jal\", \"l.jalr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"l.j\", \"l.jr\"]\n\n    def is_ret(self, insn):\n        if insn.mnemonic == \"l.jr\" and insn.operands[0] == \"r9\":\n            return True\n        if insn.mnemonic in [\"l.rfe\"]:\n            return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        return insn.mnemonic in [\"l.bf\", \"l.bnf\"]\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        val = get_register(self.flag_register)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        taken, reason = False, \"\"\n\n        flag = bool(val & (1 << flags[\"flag\"]))\n\n        if mnemo == \"l.bf\":\n            taken, reason = flag, \"F\"\n        if mnemo == \"l.bnf\":\n            taken, reason = not flag, \"!F\"\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if insn.mnemonic == \"l.jr\" and insn.operands[0] == \"r9\":\n                ra = get_register(\"$r9\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$r10\")\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass NIOS2(Architecture):\n    \"\"\"GEF representation of NiosII architecture.\"\"\"\n\n    arch = \"NIOS2\"\n    mode = \"NIOS2\"\n\n    load_condition = [\n        Elf.EM_ALTERA_NIOS2,\n        \"NIOS2\",\n        \"NIOS2:R1\",\n        \"NIOS2:R2\",\n    ]\n\n    # https://www.intel.com/content/www/us/en/docs/programmable/683836/current/introduction.html\n    # https://www.intel.co.jp/content/dam/altera-www/global/ja_JP/pdfs/literature/hb/nios2/n2cpu-nii5v1gen2-j.pdf\n    all_registers = [\n        \"$zero\", \"$at\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$et\", \"$bt\", \"$gp\", \"$sp\", \"$fp\", \"$ea\", \"$sstatus\", \"$ra\",\n        \"$pc\",\n    ]\n    alias_registers = {\n        \"$zero\": \"$r0\", \"$at\": \"$r1\", \"$et\": \"$r24\", \"$bt\": \"$r25\",\n        \"$gp\": \"$r26\", \"$sp\": \"$r27\", \"$fp\": \"$r28\", \"$ea\": \"$r29\",\n        \"$sstatus\": \"$r30\", \"$ra\": \"$r31\",\n    }\n    flag_register = None # NIOS2 has no flags register\n    return_register = \"$r2\"\n    function_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\"]\n    syscall_register = \"$r2\"\n    syscall_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = 4\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x3a\\x88\\x01\\x00\" # nop\n    infloop_insn = b\"\\x06\\xff\\x3f\\x00\" # br self\n    trap_insn = None\n    ret_insn = b\"\\x3a\\x28\\x00\\xf8\" # ret\n    syscall_insn = b\"\\x3a\\x68\\x3b\\x00\" # trap 0\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"trap\" and int(insn.operands[0], 0) == 0\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"call\", \"callr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"br\", \"jmp\", \"jmpi\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"bret\", \"eret\"]\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"bne\",\n            \"bge\", \"bgeu\", \"bgt\", \"bgtu\",\n            \"ble\", \"bleu\", \"blt\", \"bltu\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        v0 = get_register(ops[0])\n        v1 = get_register(ops[1])\n\n        pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        u2i = lambda a: ui(pI(a))\n        v0s = u2i(v0)\n        v1s = u2i(v1)\n\n        taken, reason = False, \"\"\n        if mnemo == \"beq\":\n            taken, reason = v0 == v1, \"{:s}=={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bne\":\n            taken, reason = v0 != v1, \"{:s}!={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bge\":\n            taken, reason = v0s >= v1s, \"{:s}>={:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bgeu\":\n            taken, reason = v0 >= v1, \"{:s}>={:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"bgt\":\n            taken, reason = v0s > v1s, \"{:s}>{:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bgtu\":\n            taken, reason = v0 > v1, \"{:s}>{:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"ble\":\n            taken, reason = v0s <= v1s, \"{:s}<={:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bleu\":\n            taken, reason = v0 <= v1, \"{:s}<={:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"blt\":\n            taken, reason = v0s < v1s, \"{:s}<{:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bltu\":\n            taken, reason = v0 < v1, \"{:s}<{:s} (unsigned)\".format(ops[0], ops[1])\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$ra\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n\n        def adjust_offset(x):\n            TLS_TCB_OFFSET = 0x7000\n            if x == 0:\n                return x\n            return x - TLS_TCB_OFFSET\n\n        tls = get_register(\"$r23\")\n        return adjust_offset(tls)\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass MICROBLAZE(Architecture):\n    \"\"\"GEF representation of MicroBlaze architecture.\"\"\"\n\n    arch = \"MICROBLAZE\"\n    mode = \"MICROBLAZE\"\n\n    load_condition = [\n        Elf.EM_MICROBLAZE,\n        \"MICROBLAZE\",\n    ]\n\n    # https://www.xilinx.com/content/dam/xilinx/support/documents/sw_manuals/xilinx2021_2/ug984-vivado-microblaze-ref.pdf\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$rpc\", \"$rmsr\",\n    ]\n    alias_registers = {\n        \"$r0\": \"$zero\", \"$r1\": \"$sp\", \"$r15\": \"$ra\",\n    }\n    flag_register = None\n    return_register = \"$r3\"\n    function_parameters = [\"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\", \"$r10\"]\n    syscall_register = \"$r12\"\n    syscall_parameters = [\"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\", \"$r10\"]\n\n    bit_length = 32\n    endianness = \"little / big\"\n    instruction_length = 4\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x00\\x00\\x00\\x80\" # or r0, r0, r0\n    infloop_insn = b\"\\x00\\x00\\x00\\xb8\" # bri self\n    trap_insn = None\n    ret_insn = b\"\\x08\\x00\\x0f\\xb6\" # rtsd r15, 8\n    syscall_insn = b\"\\x08\\x00\\xcc\\xb9\" # brki r14,8\n\n    def is_syscall(self, insn):\n        return insn.mnemonic == \"brki\" and insn.operands[:2] == [\"r14\", \"8\"]\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"brld\", \"brald\", \"brlid\", \"bralid\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        branch_mnemos = [\n            \"br\", \"bra\", \"brd\", \"brad\",\n            \"bri\", \"brai\", \"brid\", \"braid\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"rtsd\"]\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"beqd\", \"beqi\", \"beqid\",\n            \"bne\", \"bned\", \"bnei\", \"bneid\",\n            \"bge\", \"bged\", \"bgei\", \"bgeid\",\n            \"bgt\", \"bgtd\", \"bgti\", \"bgtid\",\n            \"ble\", \"bled\", \"blei\", \"bleid\",\n            \"blt\", \"bltd\", \"blti\", \"bltid\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, [x.split()[0] for x in insn.operands]\n        taken, reason = False, \"\"\n\n        pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        u2i = lambda a: ui(pI(a))\n\n        v0 = u2i(get_register(ops[0])) # signed\n\n        if mnemo in [\"beq\", \"beqd\", \"beqi\", \"beqid\"]:\n            taken, reason = v0 == 0, \"{:s}==0\".format(ops[0])\n        elif mnemo in [\"bne\", \"bned\", \"bnei\", \"bneid\"]:\n            taken, reason = v0 != 0, \"{:s}!=0\".format(ops[0])\n        elif mnemo in [\"bge\", \"bged\", \"bgei\", \"bgeid\"]:\n            taken, reason = v0 >= 0, \"{:s}>=0\".format(ops[0])\n        elif mnemo in [\"bgt\", \"bgtd\", \"bgti\", \"bgtid\"]:\n            taken, reason = v0 > 0, \"{:s}>0\".format(ops[0])\n        elif mnemo in [\"ble\", \"bled\", \"blei\", \"bleid\"]:\n            taken, reason = v0 <= 0, \"{:s}<=0\".format(ops[0])\n        elif mnemo in [\"blt\", \"bltd\", \"blti\", \"bltid\"]:\n            taken, reason = v0 < 0, \"{:s}<0\".format(ops[0])\n        return taken, reason\n\n    def get_ith_parameter(self, i, in_func=True):\n        if i < len(self.function_parameters):\n            reg = self.function_parameters[i]\n            val = get_register(reg)\n            key = reg\n            return key, val\n        else:\n            sp = current_arch.sp\n            sz = current_arch.ptrsize\n            loc = sp + (i * sz)\n            val = read_int_from_memory(loc)\n            key = \"[sp + {:#x}]\".format(i * sz)\n            return key, val\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$r15\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$r21\")\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass XTENSA(Architecture):\n    \"\"\"GEF representation of Xtensa architecture.\"\"\"\n\n    arch = \"XTENSA\"\n    mode = \"XTENSA\"\n\n    load_condition = [\n        Elf.EM_XTENSA,\n        \"XTENSA\",\n    ]\n\n    # https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/ip/tensilica-ip/isa-summary.pdf\n    # https://dl.espressif.com/github_assets/espressif/xtensa-isa-doc/releases/download/latest/Xtensa.pdf\n    # https://usermanual.wiki/Document/Xtensa2020ASSEMBLER20GUIDE.1231659642/html\n    all_registers = [\n        \"$a0\", \"$a1\", \"$a2\", \"$a3\", \"$a4\", \"$a5\", \"$a6\", \"$a7\",\n        \"$a8\", \"$a9\", \"$a10\", \"$a11\", \"$a12\", \"$a13\", \"$a14\", \"$a15\",\n        \"$pc\", \"$lbeg\", \"$lend\", \"$lcount\", \"$sar\", \"$litbase\", \"$ps\", \"$threadptr\",\n        \"$scompare1\", \"$acclo\", \"$acchi\", \"$expstate\",\n    ]\n    alias_registers = {\n        \"$a0\": \"$lr\", \"$a1\": \"$sp\",\n    }\n    flag_register = None\n    return_register = \"$a2\"\n    function_parameters = [\"$a10\", \"$a11\", \"$a12\", \"$a13\", \"$a14\", \"$a15\"]\n    syscall_register = \"$a2\"\n    syscall_parameters = [\"$a6\", \"$a3\", \"$a4\", \"$a5\", \"$a8\", \"$a9\"]\n\n    bit_length = 32\n    endianness = \"little / big\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x3d\\xf0\" # nop.n\n    infloop_insn = b\"\\x06\\xff\\xff\" # j self\n    trap_insn = None\n    ret_insn = b\"\\x1d\\xf0\" # retw.n\n    syscall_insn = b\"\\x00\\x50\\x00\" # syscall\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"syscall\"]\n\n    def is_call(self, insn):\n        call_mnemo = [\n            \"call0\", \"call4\", \"call8\", \"call12\",\n            \"callx0\", \"callx4\", \"callx8\", \"callx12\",\n        ]\n        return insn.mnemonic in call_mnemo\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"j\", \"jx\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"ret\", \"retw\", \"ret.n\", \"retw.n\"]\n\n    def is_conditional_branch(self, insn):\n        branch_mnemos = [\n            \"beq\", \"beqz\", \"beqz.n\", \"beqi\",\n            \"bne\", \"bnez\", \"bnez.n\", \"bnei\",\n            \"bge\", \"bgez\", \"bgei\", \"bgeu\", \"bgeui\",\n            \"blt\", \"bltz\", \"blti\", \"bltu\", \"bltui\",\n            \"bbc\", \"bbs\", \"bbci\", \"bbsi\",\n            \"bnone\", \"bany\", \"ball\", \"bnall\",\n            \"bt\", \"bf\",\n        ]\n        return insn.mnemonic in branch_mnemos\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        taken, reason = False, \"\"\n\n        pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        u2i = lambda a: ui(pI(a))\n\n        if mnemo == \"beq\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = v0 == v1, \"{:s}=={:s}\".format(ops[0], ops[1])\n        if mnemo == \"beqi\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = v0 == v1, \"{:s}=={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bne\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = v0 != v1, \"{:s}!={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bnei\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = v0 != v1, \"{:s}!={:s}\".format(ops[0], ops[1])\n        elif mnemo in [\"beqz\", \"beqz.n\"]:\n            v0 = get_register(ops[0])\n            taken, reason = v0 == 0, \"{:s}==0\".format(ops[0])\n        elif mnemo in [\"bnez\", \"bnez.n\"]:\n            v0 = get_register(ops[0])\n            taken, reason = v0 != 0, \"{:s}!=0\".format(ops[0])\n        elif mnemo == \"bge\":\n            v0 = u2i(get_register(ops[0]))\n            v1 = u2i(get_register(ops[1]))\n            taken, reason = v0 >= v1, \"{:s}>={:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bgei\":\n            v0 = u2i(get_register(ops[0]))\n            v1 = int(ops[1])\n            taken, reason = v0 >= v1, \"{:s}>={:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bgeu\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = v0 >= v1, \"{:s}>={:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"bgeui\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = v0 >= v1, \"{:s}>={:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"bgez\":\n            v0 = get_register(ops[0])\n            taken, reason = (v0 >> 31) == 0, \"({:s}>>31)==0\".format(ops[0])\n        elif mnemo == \"blt\":\n            v0 = u2i(get_register(ops[0]))\n            v1 = u2i(get_register(ops[1]))\n            taken, reason = v0 < v1, \"{:s}<{:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"blti\":\n            v0 = u2i(get_register(ops[0]))\n            v1 = int(ops[1])\n            taken, reason = v0 < v1, \"{:s}<{:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bltu\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = v0 < v1, \"{:s}<{:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"bltui\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = v0 < v1, \"{:s}<{:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"bltz\":\n            v0 = get_register(ops[0])\n            taken, reason = (v0 >> 31) == 1, \"({:s}>>31)==1\".format(ops[0])\n        elif mnemo == \"bany\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = (v0 & v1) != 0, \"({:s}&{:s})!=0\".format(ops[0], ops[1])\n        elif mnemo == \"bnone\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = (v0 & v1) == 0, \"({:s}&{:s})==0\".format(ops[0], ops[1])\n        elif mnemo == \"ball\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = (~v0 & v1) == 0, \"(~{:s}&{:s})==0\".format(ops[0], ops[1])\n        elif mnemo == \"bnall\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = (~v0 & v1) != 0, \"(~{:s}&{:s})!=0\".format(ops[0], ops[1])\n        elif mnemo == \"bt\":\n            v0 = get_register(ops[0])\n            taken, reason = v0 != 0, \"{:s}!=0\".format(ops[0])\n        elif mnemo == \"bf\":\n            v0 = get_register(ops[0])\n            taken, reason = v0 == 0, \"{:s}==0\".format(ops[0])\n        elif mnemo == \"bbs\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = ((v0 >> (v1 & 0b11111)) & 1) == 1, \"Bit ({:s}&0b11111) of {:s} is 1\".format(ops[1], ops[0])\n        elif mnemo == \"bbsi\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = ((v0 >> v1) & 1) == 1, \"Bit {:s} of {:s} is 1\".format(ops[1], ops[0])\n        elif mnemo == \"bbc\":\n            v0 = get_register(ops[0])\n            v1 = get_register(ops[1])\n            taken, reason = ((v0 >> (v1 & 0b11111)) & 1) == 0, \"Bit ({:s}&0b11111) of {:s} is 0\".format(ops[1], ops[0])\n        elif mnemo == \"bbci\":\n            v0 = get_register(ops[0])\n            v1 = int(ops[1])\n            taken, reason = ((v0 >> v1) & 1) == 0, \"Bit {:s} of {:s} is 0\".format(ops[1], ops[0])\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$a0\")\n                if insn.mnemonic in [\"retw\", \"retw.n\"]:\n                    ra &= ~(0b11 << 30)\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$threadptr\")\n\n\nclass CRIS(Architecture):\n    \"\"\"GEF representation of CRIS architecture.\"\"\"\n\n    arch = \"CRIS\"\n    mode = \"CRIS\"\n\n    load_condition = [\n        Elf.EM_CRIS,\n        \"CRIS\",\n    ]\n\n    # https://www.axis.com/dam/public/25/67/ab/etrax-100lx-programmer%E2%80%99s-manual-en-US-33419.pdf\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$sp\", \"$pc\",\n        \"$srp\", \"$ccr\",\n    ]\n    alias_registers = {\n        \"$sp\": \"$r14\", \"$pc\": \"$r15\",\n    }\n    flag_register = \"$ccr\"\n    flags_table = {\n        9: \"write-fail\",\n        3: \"negative\",\n        2: \"zero\",\n        1: \"overflow\",\n        0: \"carry\",\n    }\n    return_register = \"$r10\"\n    function_parameters = [\"$r10\", \"$r11\", \"$r12\", \"$r13\"]\n    # As of linux 4.17, CRIS is no longer supported.\n    syscall_register = \"$r9\"\n    syscall_parameters = [\"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$dcr1/mof\", \"$sp+0x4\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = None # variable length\n    has_delay_slot = True\n    has_syscall_delay_slot = True\n    has_ret_delay_slot = True\n    stack_grow_down = False\n    tls_supported = False\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x0f\\x05\" # nop\n    infloop_insn = b\"\\xff\\xe0\" # ba self\n    trap_insn = None\n    ret_insn = b\"\\x7f\\xb6\" # ret\n    syscall_insn = b\"\\x3d\\xe9\" # break 13\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"break\" and int(insn.operands[0], 0) == 13\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"jsr\", \"jsrc\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"ba\", \"jmpu\", \"jump\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"ret\"\n\n    def is_conditional_branch(self, insn):\n        conditions = [\n            \"cc\", \"cs\", \"ne\", \"eq\", \"vc\", \"vs\", \"pl\", \"mi\",\n            \"ls\", \"hi\", \"ge\", \"lt\", \"gt\", \"le\", \"wf\"\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"b{cc}\"]:\n                return True\n        return False\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        val = get_register(self.flag_register)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        taken, reason = False, \"\"\n\n        zero = bool(val & (1 << flags[\"zero\"]))\n        negative = bool(val & (1 << flags[\"negative\"]))\n        overflow = bool(val & (1 << flags[\"overflow\"]))\n        carry = bool(val & (1 << flags[\"carry\"]))\n        write_fail = bool(val & (1 << flags[\"write-fail\"]))\n\n        if mnemo == \"bcc\":\n            taken, reason = not carry, \"!C\"\n        elif mnemo == \"bcs\":\n            taken, reason = carry, \"C\"\n        elif mnemo == \"bne\":\n            taken, reason = not zero, \"!Z\"\n        elif mnemo == \"beq\":\n            taken, reason = zero, \"Z\"\n        elif mnemo == \"bvc\":\n            taken, reason = not overflow, \"!V\"\n        elif mnemo == \"bvs\":\n            taken, reason = overflow, \"V\"\n        elif mnemo == \"bpl\":\n            taken, reason = not negative, \"!N\"\n        elif mnemo == \"bmi\":\n            taken, reason = negative, \"N\"\n        elif mnemo == \"bls\":\n            taken, reason = carry or zero, \"C || Z\"\n        elif mnemo == \"bhi\":\n            taken, reason = not carry and not zero, \"!C && !Z\"\n        elif mnemo == \"bge\":\n            taken, reason = (negative and overflow) or (not negative and not overflow), \"(N && V) || (!N && !V)\"\n        elif mnemo == \"blt\":\n            taken, reason = (negative and not overflow) or (not negative and overflow), \"(N && !V) || (!N && V)\"\n        elif mnemo == \"bgt\":\n            taken = (negative and overflow and not zero) or (not negative and not overflow and not zero)\n            reason = \"(N && V && !Z) || (!N && !V && !Z)\"\n        elif mnemo == \"ble\":\n            taken, reason = zero or (negative and not overflow) or (not negative and overflow), \"Z || (N && !V) || (!N && V)\"\n        elif mnemo == \"bwf\":\n            taken, reason = write_fail, \"WF\"\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$srp\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n\nclass LOONGARCH64(Architecture):\n    \"\"\"GEF representation of Loongarch-64 architecture.\"\"\"\n\n    arch = \"LOONGARCH\"\n    mode = \"64\"\n\n    load_condition = [\n        # Elf.EM_LOONGARCH cannot determine whether it is 32 bit or 64 bit,\n        # but since GEF only supports 64 bit (LA64), so we will use it.\n        Elf.EM_LOONGARCH,\n        \"LOONGARCH\",\n        \"LOONGARCH64\",\n    ]\n\n    # https://docs.kernel.org/loongarch/introduction.html\n    # https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$orig_a0\", \"$pc\", \"$badv\",\n    ]\n    alias_registers = {\n        \"$r0\": \"$zero\", \"$r1\": \"$ra\", \"$r2\": \"$tp\", \"$r3\": \"$sp\",\n        \"$r4\": \"$a0/$v0\", \"$r5\": \"$a1/$v1\", \"$r6\": \"$a2\", \"$r7\": \"$a3\",\n        \"$r8\": \"$a4\", \"$r9\": \"$a5\", \"$r10\": \"$a6\", \"$r11\": \"$a7\",\n        \"$r12\": \"$t0\", \"$r13\": \"$t1\", \"$r14\": \"$t2\", \"$r15\": \"$t3\",\n        \"$r16\": \"$t4\", \"$r17\": \"$t5\", \"$r18\": \"$t6\", \"$r19\": \"$t7\", \"$r20\": \"$t8\",\n        \"$r21\": \"$u0\", \"$r22\": \"$fp\",\n        \"$r23\": \"$s0\", \"$r24\": \"$s1\", \"$r25\": \"$s2\", \"$r26\": \"$s3\",\n        \"$r27\": \"$s4\", \"$r28\": \"$s5\", \"$r29\": \"$s6\", \"$r30\": \"$s7\", \"$r31\": \"$s8\",\n    }\n    flag_register = None # LOONGARCH has no flags register\n    return_register = \"$r4\"\n    function_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\", \"$r10\", \"$r11\"]\n    syscall_register = \"$r11\"\n    syscall_parameters = [\"$r4\", \"$r5\", \"$r6\", \"$r7\", \"$r8\", \"$r9\"]\n\n    bit_length = 64\n    endianness = \"little\"\n    instruction_length = 4\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x00\\x00\\x40\\x03\" # andi $zero, $zero, 0x0\n    infloop_insn = b\"\\x00\\x00\\x00\\x50\" # b self\n    trap_insn = None\n    ret_insn = b\"\\x20\\x00\\x00\\x4c\" # jirl\n    syscall_insn = b\"\\x00\\x00\\x2b\\x00\" # syscall\n\n    def is_syscall(self, insn):\n        return insn.mnemonic in [\"syscall\"]\n\n    def is_call(self, insn):\n        mnemo = insn.mnemonic\n        if mnemo == \"bl\":\n            return True\n        if mnemo == \"jirl\":\n            return len(insn.operands) >= 1 and insn.operands[0] != \"$zero\"\n        return False\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        mnemo = insn.mnemonic\n        if mnemo == \"b\":\n            return True\n        if mnemo == \"jirl\":\n            return len(insn.operands) >= 1 and insn.operands[0] == \"$zero\"\n        return False\n\n    def is_ret(self, insn):\n        return insn.mnemonic == \"ret\" # gdb interpret \"jalr $zero, $ra, 0\" as \"ret\"\n\n    def is_conditional_branch(self, insn):\n        return insn.mnemonic in [\"beq\", \"bne\", \"bge\", \"bgeu\", \"blt\", \"bltu\", \"beqz\", \"bnez\"]\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        alias_inverse = {}\n        for k, v in self.alias_registers.items():\n            for alias_reg in v.split(\"/\"):\n                alias_inverse[alias_reg] = k\n\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        u2i = lambda a: uq(pQ(a))\n\n        v0 = get_register(alias_inverse.get(ops[0], ops[0]))\n        if v0 is None:\n            return False\n        v0s = u2i(v0)\n\n        if mnemo not in [\"beqz\", \"bnez\"]:\n            v1 = get_register(alias_inverse.get(ops[1], ops[1]))\n            if v1 is None:\n                return False\n            v1s = u2i(v1)\n\n        taken, reason = False, \"\"\n        if mnemo == \"beq\":\n            taken, reason = v0 == v1, \"{:s}=={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bne\":\n            taken, reason = v0 != v1, \"{:s}!={:s}\".format(ops[0], ops[1])\n        elif mnemo == \"bge\":\n            taken, reason = v0s >= v1s, \"{:s}>={:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bgeu\":\n            taken, reason = v0 >= v1, \"{:s}>={:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"blt\":\n            taken, reason = v0s < v1s, \"{:s}<{:s} (signed)\".format(ops[0], ops[1])\n        elif mnemo == \"bltu\":\n            taken, reason = v0 < v1, \"{:s}<{:s} (unsigned)\".format(ops[0], ops[1])\n        elif mnemo == \"beqz\":\n            taken, reason = v0 == 0, \"{:s}==0\".format(ops[0])\n        elif mnemo == \"bnez\":\n            taken, reason = v0 != 0, \"{:s}!=0\".format(ops[0])\n        return taken, reason\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$r1\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$r2\")\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\nclass ARC(Architecture):\n    \"\"\"GEF representation of ARC-v2-32 architecture.\"\"\"\n\n    arch = \"ARC\"\n    mode = \"32v2\"\n\n    load_condition = [\n        Elf.EM_ARC,\n        Elf.EM_ARC_COMPACT,\n        Elf.EM_ARCV2,\n        \"ARC600\",\n        \"ARC601\",\n        \"ARC700\",\n        \"ARCV2\",\n    ]\n\n    # http://me.bios.io/images/d/dd/ARCompactISA_ProgrammersReference.pdf\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$gp\", \"$fp\", \"$sp\", \"$ilink\", \"$r30\", \"$blink\",\n        \"$pc\", \"$status32\", \"$bta\", \"$lp_count\",\n    ]\n    alias_registers = {\n        \"$r25\": \"$tp\", \"$gp\": \"$r26\", \"$fp\": \"$r27\", \"$sp\": \"$r28\", \"$ilink\": \"$r29\", \"$blink\": \"$r31\",\n        \"$lp_count\": \"$r60\", \"$pc\": \"$pcl/$r63\",\n    }\n\n    flag_register = \"$status32\"\n    flags_table = {\n        0: \"halt\",\n        1: \"e1\",\n        2: \"e2\",\n        3: \"a1\",\n        4: \"a2\",\n        5: \"ae\",\n        6: \"de\",\n        7: \"user\",\n        8: \"overflow\",\n        9: \"carry\",\n        10: \"negative\",\n        11: \"zero\",\n        12: \"loop\",\n    }\n    return_register = \"$r0\"\n    function_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\"]\n    syscall_register = \"$r8\"\n    syscall_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = None # variable length\n    has_delay_slot = True # if op includes `.d`\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = True # if op includes `.d`\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\xe0\\x78\" # nop_s\n    infloop_insn = b\"\\x00\\xf0\" # b_s 0\n    infloop_insn2 = b\"\\x01\\xf0\" # b_s 2 (if $pc % 4 == 2)\n    trap_insn = None\n    ret_insn = b\"\\xe0\\x7e\" # j_s [blink]\n    syscall_insn = b\"\\x1e\\x78\" # trap_s 0\n\n    def is_syscall(self, insn):\n        if insn.mnemonic == \"trap0\":\n            return True\n        try:\n            return insn.mnemonic == \"trap_s\" and int(insn.operands[0], 0) == 0\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        if insn.mnemonic in [\"bl\", \"bl.d\", \"bl_s\", \"jl\", \"jl.d\", \"jl_s\", \"jl_s.d\"]:\n            return True\n\n        # BLcc<.d>\n        conditions = [\n            \"al\", \"ra\", \"eq\", \"z\", \"ne\", \"nz\", \"pl\", \"p\",\n            \"mi\", \"n\", \"cs\", \"c\", \"lo\", \"cc\", \"nc\", \"hs\",\n            \"vs\", \"v\", \"vc\", \"nv\", \"gt\", \"ge\", \"lt\", \"le\",\n            \"hi\", \"ls\", \"pnz\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"bl{cc}\", f\"bl{cc}.d\"]:\n                return True\n\n        # JLcc<.d>\n        conditions = [\n            \"eq\", \"ne\", \"lt\", \"ge\", \"lo\", \"hs\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"jl{cc}\", f\"jl{cc}.d\"]:\n                return True\n\n        return False\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        if insn.mnemonic in [\"b\", \"b.d\", \"b_s\"]:\n            return True\n        if insn.mnemonic in [\"j\", \"j.d\"]:\n            if insn.operands != [\"[blink]\"]:\n                return True\n        return False\n\n    def is_ret(self, insn):\n        if insn.mnemonic in [\"j\", \"j_s\", \"j_s.d\"] and insn.operands == [\"[blink]\"]:\n            return True\n        return False\n\n    def is_conditional_branch(self, insn):\n        # Bcc<.d>\n        conditions = [\n            \"al\", \"ra\", \"eq\", \"z\", \"ne\", \"nz\", \"pl\", \"p\",\n            \"mi\", \"n\", \"cs\", \"c\", \"lo\", \"cc\", \"nc\", \"hs\",\n            \"vs\", \"v\", \"vc\", \"nv\", \"gt\", \"ge\", \"lt\", \"le\",\n            \"hi\", \"ls\", \"pnz\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"b{cc}\", f\"b{cc}.d\"]:\n                return True\n\n        # BRcc<.d>\n        conditions = [\n            \"eq\", \"ne\", \"lt\", \"ge\", \"lo\", \"hs\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"br{cc}\", f\"br{cc}.d\", f\"br{cc}.nt\", f\"br{cc}.d.nt\"]:\n                return True\n        if insn.mnemonic in [\"bbit0\", \"bbit1\", \"bbit0.d\", \"bbit1.d\"]:\n            return True\n\n        # BRcc_s\n        conditions = [\n            \"eq\", \"ne\", \"gt\", \"ge\", \"lt\", \"le\", \"hi\", \"hs\", \"lo\", \"ls\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"br{cc}_s\"]:\n                return True\n\n        # Jcc<.d>, Jcc.F\n        conditions = [\n            \"eq\", \"ne\", \"lt\", \"ge\", \"lo\", \"hs\",\n        ]\n        for cc in conditions:\n            if insn.mnemonic in [f\"j{cc}\", f\"j{cc}.d\", f\"j{cc}.f\"]:\n                return True\n\n        # Jcc_s\n        if insn.mnemonic in [\"jeq_s\", \"jne_s\"]:\n            return True\n\n        return False\n\n    def is_branch_taken(self, insn):\n        mnemo = insn.mnemonic\n        ops = []\n        for op in insn.operands:\n            if op.startswith(\";\"):\n                break\n            ops.append(op)\n\n        val = get_register(self.flag_register)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n\n        zero = bool(val & (1 << flags[\"zero\"]))\n        negative = bool(val & (1 << flags[\"negative\"]))\n        overflow = bool(val & (1 << flags[\"overflow\"]))\n        carry = bool(val & (1 << flags[\"carry\"]))\n\n        if len(ops) >= 2:\n            pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n            ui = lambda a: struct.unpack(\"<i\", a)[0]\n            u2i = lambda a: ui(pI(a))\n            v0u = get_register(ops[0])\n            if v0u is None:\n                v0u = int(ops[0], 0)\n            v1u = get_register(ops[1])\n            if v1u is None:\n                v1u = int(ops[1], 0)\n            v0s = u2i(v0u)\n            v1s = u2i(v1u)\n\n        taken, reason = False, \"\"\n        if mnemo.startswith((\"beq\", \"breq\", \"jeq\")):\n            if len(ops) >= 2:\n                taken, reason = v0u == v1u, \"{:s}=={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = zero, \"Z\"\n\n        elif mnemo.startswith((\"bne\", \"brne\", \"jne\")):\n            if len(ops) >= 2:\n                taken, reason = v0u != v1u, \"{:s}!={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = not zero, \"!Z\"\n\n        elif mnemo.startswith((\"bgt\", \"brgt\")):\n            if len(ops) >= 2:\n                taken, reason = v0s > v1s, \"{:s}>{:s}\".format(ops[0], ops[1])\n            else:\n                taken = (negative and overflow and not zero) or (not negative and not overflow and not zero)\n                reason = \"(N && V && !Z) || (!N && !V && !Z)\"\n\n        elif mnemo.startswith((\"bge\", \"brge\", \"jge\")):\n            if len(ops) >= 2:\n                taken, reason = v0s >= v1s, \"{:s}>={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = (negative and overflow) or (not negative and not overflow), \"(N && V) || (!N && !V)\"\n\n        elif mnemo.startswith((\"blt\", \"brlt\", \"jlt\")):\n            if len(ops) >= 2:\n                taken, reason = v0s < v1s, \"{:s}<{:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = (negative and not overflow) or (not negative and overflow), \"(N && !V) || (!N && V)\"\n\n        elif mnemo.startswith((\"ble\", \"brle\")):\n            if len(ops) >= 2:\n                taken, reason = v0s <= v1s, \"{:s}<={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = zero or (negative and not overflow) or (not negative and overflow), \"Z || (N && !V) || (!N && V)\"\n\n        elif mnemo.startswith((\"bhi\", \"brhi\")):\n            if len(ops) >= 2:\n                taken, reason = v0u > v1u, \"{:s}>{:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = not carry and not zero, \"!C && !Z\"\n\n        elif mnemo.startswith((\"bhs\", \"brhs\", \"jhs\")):\n            if len(ops) >= 2:\n                taken, reason = v0u >= v1u, \"{:s}>={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = not carry, \"!C\"\n\n        elif mnemo.startswith((\"blo\", \"brlo\", \"jlo\")):\n            if len(ops) >= 2:\n                taken, reason = v0u < v1u, \"{:s}<{:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = carry, \"C\"\n\n        elif mnemo.startswith((\"bls\", \"brls\")):\n            if len(ops) >= 2:\n                taken, reason = v0u <= v1u, \"{:s}<={:s}\".format(ops[0], ops[1])\n            else:\n                taken, reason = carry or zero, \"C || Z\"\n\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$blink\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$r25\")\n\n    def decode_cookie(self, value, cookie):\n        return value\n\n    def encode_cookie(self, value, cookie):\n        return value\n\n\nclass ARCv3(ARC):\n    \"\"\"GEF representation of ARC-v3-32 architecture.\"\"\"\n\n    arch = \"ARC\"\n    mode = \"32v3\"\n\n    load_condition = [\n        Elf.EM_ARC_COMPACT3,\n        \"ARC64:32\",\n    ]\n\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$fp\", \"$sp\", \"$ilink\", \"$gp\", \"$blink\",\n        \"$pc\", \"$status32\", \"$bta\", \"$eret\",\n    ]\n    alias_registers = {\n        \"$fp\": \"$r27\", \"$sp\": \"$r28\", \"$ilink\": \"$r29\", \"$gp\": \"$r30\", \"$blink\": \"$r31\",\n        \"$pc\": \"$pcl/$r63\",\n    }\n\n    def get_tls(self):\n        return get_register(\"$gp\")\n\n\nclass ARC64(ARCv3):\n    \"\"\"GEF representation of ARC-v3-64 architecture.\"\"\"\n\n    arch = \"ARC\"\n    mode = \"64v3\"\n\n    load_condition = [\n        Elf.EM_ARC_COMPACT3_64,\n        \"ARC64:64\",\n    ]\n\n    bit_length = 64\n\n\nclass CSKY(Architecture):\n    \"\"\"GEF representation of C-SKY architecture.\"\"\"\n\n    arch = \"CSKY\"\n    mode = \"CSKY\"\n\n    load_condition = [\n        Elf.EM_CSKY,\n        \"CSKY\",\n        \"CSKY:CK510\",\n        \"CSKY:CK610\",\n        \"CSKY:CK801\",\n        \"CSKY:CK802\",\n        \"CSKY:CK803\",\n        \"CSKY:CK807\",\n        \"CSKY:CK810\",\n        \"CSKY:CK860\",\n        \"CSKY:ANY\",\n    ]\n\n    # https://github.com/c-sky/csky-doc/blob/master/CSKY%20Architecture%20user_guide.pdf\n    all_registers = [\n        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n        \"$r16\", \"$r17\", \"$r18\", \"$r19\", \"$r20\", \"$r21\", \"$r22\", \"$r23\",\n        \"$r24\", \"$r25\", \"$r26\", \"$r27\", \"$r28\", \"$r29\", \"$r30\", \"$r31\",\n        \"$pc\", \"$psr\", \"$hi\", \"$lo\",\n    ]\n    alias_registers = {\n        \"$r14\": \"$sp\", \"$r15\": \"$lr\", \"$r28\": \"$ds\", \"$r30\": \"$vec\",\n        \"$r31\": \"$tp\",\n    }\n    flag_register = \"$psr\"\n    flags_table = {\n        0: \"carry\",\n    }\n    return_register = \"$r0\"\n    function_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\"]\n    syscall_register = \"$r7\"\n    syscall_parameters = [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\"]\n\n    bit_length = 32\n    endianness = \"little\"\n    instruction_length = None # variable length\n    has_delay_slot = False\n    has_syscall_delay_slot = False\n    has_ret_delay_slot = False\n    stack_grow_down = False\n    tls_supported = True\n\n    keystone_support = False\n    capstone_support = False\n    unicorn_support = False\n\n    nop_insn = b\"\\x03\\x6c\" # mov r0, r0\n    infloop_insn = b\"\\x00\\x04\" # br self\n    trap_insn = b\"\\x00\\x00\" # bkpt\n    ret_insn = b\"\\x3c\\x78\" # rts\n    syscall_insn = b\"\\x00\\xc0\\x20\\x20\" # trap 0\n\n    def is_syscall(self, insn):\n        try:\n            return insn.mnemonic == \"trap\" and int(insn.operands[0], 0) == 0\n        except Exception:\n            return False\n\n    def is_call(self, insn):\n        return insn.mnemonic in [\"bsr\", \"jsri\", \"jsr\"]\n\n    def is_jump(self, insn):\n        if self.is_conditional_branch(insn):\n            return True\n        return insn.mnemonic in [\"br\", \"jmpi\", \"jmp\", \"jmpix\"]\n\n    def is_ret(self, insn):\n        return insn.mnemonic in [\"rts\"]\n\n    def is_conditional_branch(self, insn):\n        return insn.mnemonic in [\"bt\", \"bf\", \"bez\", \"bnez\", \"bhz\", \"blsz\", \"blz\", \"bhsz\"]\n\n    def is_branch_taken(self, insn):\n        mnemo, ops = insn.mnemonic, insn.operands\n        val = get_register(self.flag_register)\n        flags = {self.flags_table[k]: k for k in self.flags_table}\n        taken, reason = False, \"\"\n\n        carry = bool(val & (1 << flags[\"carry\"]))\n\n        pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        u2i = lambda a: ui(pI(a))\n\n        if mnemo == \"bt\":\n            taken, reason = carry, \"C\"\n        elif mnemo == \"bf\":\n            taken, reason = not carry, \"!C\"\n        elif mnemo == \"bez\":\n            v0 = get_register(ops[0])\n            taken, reason = v0 == 0, \"{:s}==0\".format(ops[0])\n        elif mnemo == \"bnez\":\n            v0 = get_register(ops[0])\n            taken, reason = v0 != 0, \"{:s}!=0\".format(ops[0])\n        elif mnemo == \"bhz\":\n            v0s = u2i(get_register(ops[0]))\n            taken, reason = v0s > 0, \"{:s}>0\".format(ops[0])\n        elif mnemo == \"blsz\":\n            v0s = u2i(get_register(ops[0]))\n            taken, reason = v0s <= 0, \"{:s}<=0\".format(ops[0])\n        elif mnemo == \"blz\":\n            v0s = u2i(get_register(ops[0]))\n            taken, reason = v0s < 0, \"{:s}<0\".format(ops[0])\n        elif mnemo == \"bhsz\":\n            v0s = u2i(get_register(ops[0]))\n            taken, reason = v0s >= 0, \"{:s}>=0\".format(ops[0])\n        return taken, reason\n\n    def flag_register_to_human(self, val=None):\n        if val is None:\n            reg = self.flag_register\n            val = get_register(reg)\n        return Architecture.flags_to_human(val, self.flags_table)\n\n    def get_ra(self, insn, frame):\n        ra = None\n        try:\n            if self.is_ret(insn):\n                ra = get_register(\"$r15\")\n            elif frame.older():\n                ra = frame.older().pc()\n        except gdb.error:\n            pass\n        return ra\n\n    def get_tls(self):\n        return get_register(\"$r31\")\n\n    def decode_cookie(self, value, cookie):\n        return value ^ cookie\n\n    def encode_cookie(self, value, cookie):\n        return value ^ cookie\n\n\n# The prototype for new architecture.\n#\n#class XXX(Architecture):\n#   \"\"\"GEF representation of XXX architecture.\"\"\"\n#\n#    arch = \"XXX\"\n#    mode = \"XXX\"\n#\n#    load_condition = [\n#        Elf.EM_XXX,\n#        \"XXX\",\n#    ]\n#\n#    all_registers = [\n#        \"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\",\n#        \"$r8\", \"$r9\", \"$r10\", \"$r11\", \"$r12\", \"$r13\", \"$r14\", \"$r15\",\n#        \"$pc\", \"$sr\",\n#    ]\n#    alias_registers = {\n#        \"$r15\": \"$sp\",\n#    }\n#    #flag_register = \"$flags\"\n#    #flags_table = {\n#    #    0: \"negative\",\n#    #    1: \"zero\",\n#    #}\n#    #return_register = \"$r0\"\n#    #function_parameters = [\"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\"]\n#    #syscall_register = \"$r0\"\n#    #syscall_parameters = [\"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\"]\n#\n#    bit_length = 32\n#    endianness = \"little\"\n#    #instruction_length = 4\n#    #has_delay_slot = False\n#    #has_syscall_delay_slot = False\n#    #has_ret_delay_slot = False\n#    #stack_grow_down = False\n#    #tls_supported = False\n#\n#    #keystone_support = False\n#    #capstone_support = False\n#    #unicorn_support = False\n#\n#    #nop_insn = b\"\\x00\\x00\" # nop\n#    #infloop_insn = b\"\\x11\\x11\" # bra self\n#    #trap_insn = None\n#    #ret_insn = b\"\\x22\\x22\" # ret\n#    #syscall_insn = b\"\\x33\\x33\" # ecall\n#\n#    #def is_syscall(self, insn):\n#    #    return insn.mnemonic in []\n#\n#    #def is_call(self, insn):\n#    #    return insn.mnemonic in []\n#\n#    #def is_jump(self, insn):\n#    #    if self.is_conditional_branch(insn):\n#    #        return True\n#    #    return insn.mnemonic in []\n#\n#    #def is_ret(self, insn):\n#    #    return insn.mnemonic in []\n#\n#    #def is_conditional_branch(self, insn):\n#    #    return insn.mnemonic in []\n#\n#    #def is_branch_taken(self, insn):\n#    #    mnemo = insn.mnemonic\n#    #    val = get_register(self.flag_register)\n#    #    flags = {self.flags_table[k]: k for k in self.flags_table}\n#    #    taken, reason = False, \"\"\n#    #    return taken, reason\n#\n#    #def flag_register_to_human(self, val=None):\n#    #    if val is None:\n#    #        reg = self.flag_register\n#    #        val = get_register(reg)\n#    #    return Architecture.flags_to_human(val, self.flags_table)\n#\n#    #def get_ith_parameter(self, i, in_func=True):\n#    #    if in_func:\n#    #        i += 1 # Account for RA being at the top of the stack\n#    #    sp = current_arch.sp\n#    #    sz = current_arch.ptrsize\n#    #    loc = sp + (i * sz)\n#    #    val = read_int_from_memory(loc)\n#    #    key = \"[sp + {:#x}]\".format(i * sz)\n#    #    return key, val\n#\n#    #def get_ra(self, insn, frame):\n#    #    ra = None\n#    #    try:\n#    #        if self.is_ret(insn):\n#    #            ra = get_register(\"$sr\")\n#    #        elif frame.older():\n#    #            ra = frame.older().pc()\n#    #    except gdb.error:\n#    #        pass\n#    #    return ra\n#\n#    #def get_tls(self):\n#    #    return None\n#\n#    #def decode_cookie(self, value, cookie):\n#    #    return value ^ cookie\n#\n#    #def encode_cookie(self, value, cookie):\n#    #    return value ^ cookie\n\n\ndef write_memory(addr, data):\n    \"\"\"Write `data` at address `addr`.\"\"\"\n\n    def write_memory_qemu_user(pid, addr, data, length):\n        \"\"\"Write `data` at address `addr` for qemu-user or Intel Pin.\"\"\"\n\n        def read_memory_via_proc_mem(pid, addr, length):\n            with open(\"/proc/{:d}/mem\".format(pid), \"rb\") as fd:\n                try:\n                    fd.seek(addr)\n                    return fd.read(length)\n                except OSError:\n                    return None\n\n        def write_memory_via_proc_mem(pid, addr, data, length):\n            with open(\"/proc/{:d}/mem\".format(pid), \"wb\") as fd:\n                try:\n                    fd.seek(addr)\n                    ret = fd.write(data[:length])\n                    fd.flush()\n                    gdb.execute(\"maintenance flush dcache\", to_string=True)\n                    return ret\n                except (OSError, gdb.error):\n                    return None\n\n        def write_with_check(pid, addr, data, length, offset=0):\n            before = read_memory_via_proc_mem(pid, addr + offset, length)\n            if before is None:\n                return None\n\n            ret = write_memory_via_proc_mem(pid, addr + offset, data, length)\n            after = read_memory(addr, length)\n\n            if ret:\n                if after == data[:length]:\n                    return ret\n                else:\n                    # fail, revert\n                    write_memory_via_proc_mem(pid, addr + offset, before, length)\n                    return None\n            return None\n\n        # 1. qemu-user (32bit) maps the memory at +0x10000 (fast path)\n        if is_qemu_user() and is_32bit(): # not Intel Pin\n            ret = write_with_check(pid, addr, data, length, offset=0x10000)\n            if ret:\n                return ret\n\n        # 2. we assume addr is same\n        ret = write_with_check(pid, addr, data, length)\n        if ret:\n            return ret\n\n        # 3. heuristic addr search and try use it\n        if is_qemu_user(): # not Intel Pin\n            inner_section = ProcessMap.lookup_address(addr).section\n            target_path = inner_section.path\n\n            outer_maps = ProcessMap.get_process_maps(outer=True)\n            for m in outer_maps:\n                if m.path != target_path:\n                    continue\n                offset = m.page_start - inner_section.page_start\n                ret = write_with_check(pid, addr, data, length, offset=offset)\n                if ret:\n                    return ret\n\n        raise Exception(\"Memory write error for qemu-user or Intel Pin\")\n\n    # ----\n\n    length = len(data)\n    if length == 0:\n        return 0\n\n    try:\n        gdb.selected_inferior().write_memory(addr, data, length)\n        return length\n    except gdb.MemoryError:\n        pass\n\n    # Under qemu-user/pin, you can not patch to `code` areas,\n    # so you have to patch via /proc/pid/mem\n    if is_qemu_user() or is_pin():\n        pid = Pid.get_pid()\n        if pid:\n            return write_memory_qemu_user(pid, addr, data, length)\n\n    raise Exception(\"Memory write error\")\n\n\ndef read_memory(addr, length):\n    \"\"\"Return a `length` long byte array with the copy of the process memory at `addr`.\"\"\"\n    if length == 0:\n        return b\"\"\n\n    if is_pin():\n        # Memory read of Intel Pin is very slow, so speed it up\n        try:\n            pid = Pid.get_pid()\n            fd = open(\"/proc/{:d}/mem\".format(pid), \"rb\")\n            fd.seek(addr)\n            content = fd.read(length)\n            fd.close()\n            return content\n        except Exception:\n            pass\n\n    if is_arm64() and is_qemu_system():\n        if Config.get_gef_setting(\"gef.read_memory_work_around_for_aarch64_secure_memory\"):\n            sm = QemuMonitor.get_secure_memory_map()\n            if sm:\n                target_phys = XSecureMemAddrCommand.v2p_secure(addr) # heavy\n                if target_phys:\n                    if sm.sm_base <= target_phys < sm.sm_base + sm.sm_size:\n                        target_offset = target_phys - sm.sm_base\n                        data = XSecureMemAddrCommand.read_secure_memory(sm, target_offset, length)\n                        if data:\n                            return data\n\n    # Don't include it in a try-catch, as we might expect a memory error on read_memory.\n    return gdb.selected_inferior().read_memory(addr, length).tobytes()\n\n\ndef read_int_from_memory(addr):\n    \"\"\"Return an integer read from memory.\"\"\"\n    # It works even if current_arch is None\n    sz = AddressUtil.get_memory_alignment()\n    mem = read_memory(addr, sz)\n    unpack = {2:u16, 4:u32, 8:u64}[sz]\n    return unpack(mem)\n\n\ndef read_int8_from_memory(addr):\n    \"\"\"Return a uint_8 read from memory.\"\"\"\n    mem = read_memory(addr, 1)\n    return u8(mem)\n\n\ndef read_int16_from_memory(addr):\n    \"\"\"Return a uint_16 read from memory.\"\"\"\n    mem = read_memory(addr, 2)\n    return u16(mem)\n\n\ndef read_int32_from_memory(addr):\n    \"\"\"Return a uint_32 read from memory.\"\"\"\n    mem = read_memory(addr, 4)\n    return u32(mem)\n\n\ndef read_int64_from_memory(addr):\n    \"\"\"Return a uint_64 read from memory.\"\"\"\n    mem = read_memory(addr, 8)\n    return u64(mem)\n\n\ndef read_cstring_from_memory(addr, max_length=None):\n    \"\"\"Return a C-string read from memory.\"\"\"\n    if max_length is None:\n        max_length = Config.get_gef_setting(\"context.nb_max_string_length\")\n\n    if is_kgdb():\n        # read_memory when kgdb is very slow, this is dirty hack\n        block_size = 64\n    else:\n        block_size = get_pagesize()\n\n    # first, read to page boundary\n    length = block_size - (addr % block_size)\n    try:\n        res = read_memory(addr, length)\n    except gdb.MemoryError:\n        return None\n\n    # if too short, more read\n    while len(res) < max_length:\n        if b\"\\x00\" in res:\n            break\n        try:\n            read_length = min(max_length - len(res), block_size)\n            res += read_memory(addr + len(res), read_length)\n        except gdb.MemoryError:\n            break\n\n    # check if ascii\n    res = res.split(b\"\\x00\")[0]\n    ustr = String.bytes2str(res)\n\n    if ustr and any(x not in String.STRING_PRINTABLE for x in ustr):\n        return None\n\n    if len(ustr) > max_length:\n        ustr = \"{}[...]\".format(ustr[:max_length])\n\n    return ustr\n\n\ndef read_physmem(paddr, size):\n    \"\"\"Return a `size` long byte array with the copy of the physical memory at `paddr`.\"\"\"\n\n    def transparent_read(paddr, size):\n        # switch virt/phys mode\n        orig_mode = QemuMonitor.get_current_mmu_mode()\n        try:\n            if orig_mode == \"virt\":\n                enable_phys()\n            out = read_memory(paddr, size)\n            if orig_mode == \"virt\":\n                disable_phys()\n            return out\n        except gdb.MemoryError:\n            if orig_mode == \"virt\":\n                disable_phys()\n        return None\n\n    def qemu_system_proc_mem(paddr, size):\n        qemu_system_pid = Pid.get_pid()\n        if qemu_system_pid is None:\n            return None\n        res = gdb.execute(\"monitor gpa2hva {:#x}\".format(paddr), to_string=True)\n        r = re.search(\"is (0x[0-9a-f]+)\", res)\n        if not r:\n            return None\n        virt_addr = int(r.group(1), 16)\n        try:\n            with open(\"/proc/{:d}/mem\".format(qemu_system_pid), \"rb\") as fd:\n                fd.seek(virt_addr)\n                return fd.read(size)\n        except Exception:\n            pass\n        return None\n\n    def qemu_system_use_xp(paddr, size):\n        # for older than qemu 4.1.0\n        try:\n            res = gdb.execute(\"monitor xp/{:d}xb {:#x}\".format(size, paddr), to_string=True)\n            \"\"\"\n            gef> monitor xp/16xb 0\n            0000000000000000: 0x53 0xff 0x00 0xf0 0x53 0xff 0x00 0xf0\n            0000000000000008: 0xc3 0xe2 0x00 0xf0 0x53 0xff 0x00 0xf0\n            \"\"\"\n        except gdb.error:\n            return None\n        out = b\"\"\n        for line in res.splitlines():\n            if not line:\n                continue\n            data = line.split()[1:]\n            out += bytes([int(x, 16) for x in data])\n        return out\n\n    def kgdb_use_physmap(paddr, size):\n        # Use workaround value if provided. Useful if KGDB does not expose system registers.\n        physmap = Config.get_gef_setting(\"gef.physmap_base_for_read_physmem_kgdb_work_around\")\n        if physmap == 0:\n            if is_arm64():\n                # On arm64, calculate physmap address based on PAGE_OFFSET and memstart_addr.\n                # This requires access to TCR_EL1 register to calculate PAGE_OFFSET.\n                physmap = KernelAddressHeuristicFinder.consts().physmap_base\n            elif is_x86_64():\n                physmap = KernelAddressHeuristicFinder.get_PAGE_OFFSET()\n            else:\n                return None\n            if physmap is None:\n                return None\n\n        vaddr = physmap + paddr\n        try:\n            return read_memory(vaddr, size)\n        except gdb.MemoryError:\n            return None\n\n    def kdb_use_mdp(paddr, size):\n        # for KDB; not supported by KGDB\n        # Note: `mdp` command can only handle aligned addresses.\n        paddr_aligned = paddr & ~0xf\n        read_n_line = (size + (paddr - paddr_aligned) + 15) // 16\n        try:\n            res = gdb.execute(\"monitor mdp {:#x} {:d}\".format(paddr_aligned, read_n_line), to_string=True)\n            \"\"\"\n            gef> monitor mdp 0 2\n            phys 0x0000000000000000 f000ff53f000ff53 f000ff53f000e2c3   S...S.......S...\n            phys 0x0000000000000010 f000ff54f000ff53 f000ff53f0008488   S...T.......S...\n            \"\"\"\n        except gdb.error:\n            return None\n        out = b\"\"\n        for line in res.splitlines():\n            if not line:\n                continue\n            if line.endswith(\"zero suppressed\"):\n                start, end = AddressUtil.parse_string_range(line.split(\" \")[0])\n                zlen = (end + 1) - start\n                out += b\"\\x00\" * zlen\n                continue\n            out += b\"\".join([bytes.fromhex(x)[::-1] for x in line.split()[2:4]])\n        return out[paddr & 0xf:][:size]\n\n    # ----\n\n    if size == 0:\n        return b\"\"\n\n    if is_qemu_system():\n        out = qemu_system_proc_mem(paddr, size)\n        if out:\n            return out\n        if is_supported_physmode():\n            out = transparent_read(paddr, size)\n            if out:\n                return out\n        out = qemu_system_use_xp(paddr, size)\n        if out:\n            return out\n        return None\n\n    if is_vmware():\n        return transparent_read(paddr, size)\n\n    if is_kgdb():\n        out = kgdb_use_physmap(paddr, size) # fast path\n        if out:\n            return out\n        if is_kdb():\n            return kdb_use_mdp(paddr, size) # slow path\n\n    return None\n\n\ndef write_physmem(paddr, data):\n    \"\"\"Write `data` at physical memory address `paddr`.\"\"\"\n\n    def transparent_write(paddr, data):\n        # switch virt/phys mode\n        orig_mode = QemuMonitor.get_current_mmu_mode()\n        try:\n            if orig_mode == \"virt\":\n                enable_phys()\n            out = write_memory(paddr, data)\n            if orig_mode == \"virt\":\n                disable_phys()\n            return out\n        except Exception:\n            if orig_mode == \"virt\":\n                disable_phys()\n        return None\n\n    # ----\n\n    if len(data) == 0:\n        return 0\n\n    if not is_qemu_system() and not is_vmware(): # kgdb is unsupported\n        return None\n\n    if not is_supported_physmode():\n        return None\n\n    return transparent_write(paddr, data)\n\n\n@Cache.cache_until_next\ndef is_valid_addr(addr):\n    if not hasattr(addr, \"__int__\"):\n        return False\n\n    addr = int(addr)\n    if addr < 0:\n        return False\n\n    if AddressUtil.get_vmem_end() <= addr:\n        return False\n\n    if is_qemu_system():\n        if QemuMonitor.check_gic_address(addr):\n            return False\n\n    try:\n        gdb.selected_inferior().read_memory(addr, 1)\n        return True\n    except gdb.MemoryError:\n        return False\n\n\n@Cache.cache_until_next\ndef is_valid_addr_addr(addr):\n    if is_valid_addr(addr):\n        v = read_int_from_memory(addr)\n        return is_valid_addr(v)\n    return False\n\n\n@Cache.cache_until_next\ndef is_single_link_list(addr):\n    # +------+   +------+           +------+\n    # | head |-->| next |--> ... -->| next |--> NULL\n    # +------+   +------+           +------+\n\n    seen = []\n    while True:\n        if addr == 0:\n            return True\n        if addr in seen:\n            return False\n        if not is_valid_addr(addr):\n            return False\n        seen.append(addr)\n        addr = read_int_from_memory(addr)\n\n\n@Cache.cache_until_next\ndef is_double_link_list(addr, min_len=0):\n    # +------+<-+   +------+<-+        <-+   +------+<-+   +------+\n    # | head |--|-->| next |--|--> ... --|-->| next |--|-->| head |\n    # +------+  |   +------+  |          |   +------+  |   +------+\n    # | tail |  +---| prev |  +---       +---| prev |  +---| tail |\n    # +------+      +------+                 +------+      +------+\n\n    # list next pointer\n    seen = []\n    while True:\n        if not is_valid_addr(addr):\n            return False\n        if addr in seen:\n            break\n        seen.append(addr)\n        addr = read_int_from_memory(addr)\n\n    if addr != seen[0]:\n        return False\n\n    # check prev pointer\n    for i, x in enumerate(seen):\n        p = read_int_from_memory(x + current_arch.ptrsize)\n        if p != seen[i - 1]:\n            return False\n\n    # minimum length check\n    return len(seen) > min_len\n\n\nclass QemuMonitor:\n    \"\"\"A collection of utility functions that are related to qemu-monitor.\"\"\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_gic_addrs():\n        \"\"\"Return physical addresses of ARM GIC(General Interrupt Controller).\"\"\"\n        if not is_qemu_system():\n            return []\n\n        if not is_arm32() and not is_arm64():\n            return []\n\n        try:\n            res = gdb.execute(\"monitor info mtree -f\", to_string=True)\n        except gdb.error:\n            return []\n\n        gic_list = []\n        for line in res.splitlines():\n            # gef> monitor info mtree -f # these are physical addresses\n            #   0000000008000000-0000000008000fff (prio 0, i/o): gic_dist\n            #   0000000008010000-0000000008011fff (prio 0, i/o): gic_cpu\n            if not line.startswith(\"  \"):\n                continue\n            m = re.search(r\"  ([0-9a-f]+)-([0-9a-f]+).*i/o\\): gic_(dist|cpu)\", line)\n            if not m:\n                continue\n            paddr = int(m.group(1), 16)\n            pend = int(m.group(2), 16)\n            # fix size\n            size = pend - paddr\n            if (size & 0xfff) == 0xfff:\n                size += 1\n            gic_list.append([paddr, paddr + size])\n        return gic_list\n\n    @staticmethod\n    @Cache.cache_until_next\n    def check_gic_address(vaddr):\n        gic_addrs = QemuMonitor.get_gic_addrs()\n        if not gic_addrs:\n            return False\n\n        try:\n            ret = gdb.execute(\"monitor gva2gpa {:#x}\".format(vaddr), to_string=True)\n        except gdb.error:\n            return False\n        r = re.search(r\"gpa: (0x\\S+)\", ret)\n        if not r:\n            return False\n        paddr = int(r.group(1), 16)\n\n        for s, e in gic_addrs:\n            if s <= paddr < e:\n                return True\n        return False\n\n    @staticmethod\n    def get_current_mmu_mode():\n        if is_qemu_system():\n            try:\n                response = gdb.execute(\"maintenance packet qqemu.PhyMemMode\", to_string=True, from_tty=False)\n                if 'received: \"0\"' in response:\n                    return \"virt\"\n                elif 'received: \"1\"' in response:\n                    return \"phys\"\n                else:\n                    return False\n            except gdb.error:\n                return False\n        elif is_vmware():\n            try:\n                read_memory(0, 1)\n                return \"phys\"\n            except gdb.MemoryError:\n                return \"virt\"\n        return None\n\n    @staticmethod\n    def get_secure_memory_map(verbose=False):\n        # find secure-ram base\n        ret = gdb.execute(\"monitor info mtree -f\", to_string=True)\n        for line in ret.splitlines():\n            m = re.search(r\"([0-9a-f]{16})-([0-9a-f]{16}).*: \\S+.secure-ram\", line)\n            if m:\n                secure_memory_base = int(m.group(1), 16)\n                secure_memory_size = int(m.group(2), 16) + 1 - secure_memory_base\n                if verbose:\n                    info(\"secure memory base: {:#x}-{:#x} ({:#x} bytes)\".format(\n                        secure_memory_base,\n                        secure_memory_base + secure_memory_size,\n                        secure_memory_size,\n                    ))\n                break\n        else:\n            return None\n\n        # find virtual address\n        ret = gdb.execute(\"monitor gpa2hva {:#x}\".format(secure_memory_base), to_string=True)\n        r = re.search(\"is (0x[0-9a-f]+)\", ret)\n        if not r:\n            return None\n        secure_memory_page_addr = int(r.group(1), 16)\n\n        # find target map of qemu-system's pid\n        qemu_system_pid = Pid.get_pid()\n        if qemu_system_pid is None:\n            if verbose:\n                err(\"Could not find the qemu-system pid\")\n            return None\n        maps = ProcessMap.get_process_maps_linux(qemu_system_pid)\n        for m in maps:\n            if m.page_start != secure_memory_page_addr:\n                continue\n            if m.size != secure_memory_size:\n                continue\n            if verbose:\n                info(\"secure memory page of pid {:d}: {:#x}\".format(qemu_system_pid, m.page_start))\n            m.sm_base = secure_memory_base\n            m.sm_size = secure_memory_size\n            return m\n        return None\n\n\ndef is_supported_physmode():\n    \"\"\"GDB mode determination function for physmem support.\"\"\"\n    return QemuMonitor.get_current_mmu_mode() in [\"virt\", \"phys\"]\n\n\ndef enable_phys():\n    if is_qemu_system():\n        response = gdb.execute(\"maintenance packet Qqemu.PhyMemMode:1\", to_string=True, from_tty=False)\n        response = gdb.execute(\"maintenance packet qqemu.PhyMemMode\", to_string=True, from_tty=False)\n        gdb.execute(\"maintenance flush dcache\", to_string=True)\n        return 'received: \"1\"' in response\n    elif is_vmware():\n        gdb.execute(\"monitor phys\", to_string=True)\n        gdb.execute(\"maintenance flush dcache\", to_string=True)\n        return True\n\n\ndef disable_phys():\n    if is_qemu_system():\n        response = gdb.execute(\"maintenance packet Qqemu.PhyMemMode:0\", to_string=True, from_tty=False)\n        response = gdb.execute(\"maintenance packet qqemu.PhyMemMode\", to_string=True, from_tty=False)\n        gdb.execute(\"maintenance flush dcache\", to_string=True)\n        return 'received: \"0\"' in response\n    elif is_vmware():\n        gdb.execute(\"monitor virt\", to_string=True)\n        gdb.execute(\"maintenance flush dcache\", to_string=True)\n        return True\n\n\n@Cache.cache_this_session\ndef p8(x, s=False):\n    \"\"\"Pack one byte respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.pack(\"{}B\".format(Endian.endian_str()), x)\n    else:\n        return struct.pack(\"{}b\".format(Endian.endian_str()), x)\n\n\n@Cache.cache_this_session\ndef p16(x, s=False):\n    \"\"\"Pack one word respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.pack(\"{}H\".format(Endian.endian_str()), x)\n    else:\n        return struct.pack(\"{}h\".format(Endian.endian_str()), x)\n\n\n@Cache.cache_this_session\ndef p32(x, s=False):\n    \"\"\"Pack one dword respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.pack(\"{}I\".format(Endian.endian_str()), x)\n    else:\n        return struct.pack(\"{}i\".format(Endian.endian_str()), x)\n\n\n@Cache.cache_this_session\ndef p64(x, s=False):\n    \"\"\"Pack one qword respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.pack(\"{}Q\".format(Endian.endian_str()), x)\n    else:\n        return struct.pack(\"{}q\".format(Endian.endian_str()), x)\n\n\n@Cache.cache_this_session\ndef u8(x, s=False):\n    \"\"\"Unpack one byte respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.unpack(\"{}B\".format(Endian.endian_str()), x)[0]\n    else:\n        return struct.unpack(\"{}b\".format(Endian.endian_str()), x)[0]\n\n\n@Cache.cache_this_session\ndef u16(x, s=False):\n    \"\"\"Unpack one word respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.unpack(\"{}H\".format(Endian.endian_str()), x)[0]\n    else:\n        return struct.unpack(\"{}h\".format(Endian.endian_str()), x)[0]\n\n\n@Cache.cache_this_session\ndef u32(x, s=False):\n    \"\"\"Unpack one dword respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.unpack(\"{}I\".format(Endian.endian_str()), x)[0]\n    else:\n        return struct.unpack(\"{}i\".format(Endian.endian_str()), x)[0]\n\n\n@Cache.cache_this_session\ndef u64(x, s=False):\n    \"\"\"Unpack one qword respecting the current architecture endianness.\"\"\"\n    if not s:\n        return struct.unpack(\"{}Q\".format(Endian.endian_str()), x)[0]\n    else:\n        return struct.unpack(\"{}q\".format(Endian.endian_str()), x)[0]\n\n\n@Cache.cache_this_session\ndef u128(x):\n    \"\"\"Unpack one oword respecting the current architecture endianness.\"\"\"\n    upper = struct.unpack(\"{}Q\".format(Endian.endian_str()), x[8:])[0]\n    lower = struct.unpack(\"{}Q\".format(Endian.endian_str()), x[:8])[0]\n    return (upper << 64) | lower\n\n\ndef is_ascii_string(addr):\n    \"\"\"Helper function to determine if the buffer pointed by `addr` is an ASCII string (in GDB)\"\"\"\n    try:\n        x = read_cstring_from_memory(addr)\n        return x is not None and len(x) > 0\n    except gdb.MemoryError:\n        return False\n\n\ndef is_alive():\n    \"\"\"GDB mode determination function for running.\"\"\"\n    try:\n        return gdb.selected_inferior().pid > 0\n    except gdb.error:\n        return False\n\n\ndef parse_args(f):\n    \"\"\"Decorator wrapper to parse args for command.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(self, argv, **kwargs):\n        try:\n            self.parser.exit = lambda *_: exec(\"if _: print(_[1]);\\nraise(GefUtil.ArgparseExitProxyException(_))\")\n            args = self.parser.parse_args(argv)\n        except GefUtil.ArgparseExitProxyException as e:\n            if not e.args[0]: # when --help or -h\n                self.usage(after_syntax_only=True)\n            return\n        except Exception as e:\n            err(\"Invalid argument: {}\".format(e))\n            return\n        if hasattr(args, \"help_simple\") and args.help_simple:\n            self.usage(simple=True)\n            return\n        self.args = args\n        return f(self, args, **kwargs)\n\n    return wrapper\n\n\ndef switch_to_intel_syntax(f):\n    \"\"\"Decorator to temporarily switch to Intel syntax.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if not is_x86():\n            return f(*args, **kwargs)\n\n        att = gdb.parameter(\"disassembly-flavor\") == \"att\"\n        if att:\n            gdb.execute(\"set disassembly-flavor intel\", to_string=True)\n        ret = f(*args, **kwargs)\n        if att:\n            gdb.execute(\"set disassembly-flavor att\", to_string=True)\n        return ret\n\n    return wrapper\n\n\ndef only_if_gdb_running(f):\n    \"\"\"Decorator wrapper to check if GDB is running.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if is_alive():\n            return f(*args, **kwargs)\n        else:\n            warn(\"No debugging session active\")\n            return\n\n    return wrapper\n\n\ndef only_if_gdb_target_local(f):\n    \"\"\"Decorator wrapper to check if GDB is running locally (target not remote).\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if not is_remote_debug():\n            return f(*args, **kwargs)\n        else:\n            warn(\"This command is not supported for remote sessions\")\n            return\n\n    return wrapper\n\n\ndef only_if_in_kernel(f):\n    \"\"\"Decorator wrapper to check if context is in kernel.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if is_in_kernel():\n            return f(*args, **kwargs)\n        else:\n            warn(\"Run in kernel context\")\n            return\n\n    return wrapper\n\n\ndef only_if_in_kernel_or_kpti_disabled(f):\n    \"\"\"Decorator wrapper to check if context is in kernel or kpti disabled.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n\n        def is_kpti_enabled():\n            try:\n                s = KernelAddressHeuristicFinder.get_saved_command_line()\n            except gdb.MemoryError:\n                return True\n            if s and is_valid_addr(s):\n                # You can access the kernel's .data area while in userland.\n                # This means KPTI is disabled.\n                return False\n            return True\n\n        if is_in_kernel():\n            return f(*args, **kwargs)\n        elif not is_kpti_enabled():\n            return f(*args, **kwargs)\n        else:\n            warn(\"Run in kernel context, or disable KPTI\")\n            return\n\n    return wrapper\n\n\ndef only_if_kvm_disabled(f):\n    \"\"\"Decorator wrapper to check if there is not -enable-kvm option.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if is_kvm_enabled():\n            err(\"Disable `-enable-kvm` option for qemu-system\")\n            return\n        return f(*args, **kwargs)\n\n    return wrapper\n\n\ndef only_if_smp_disabled(f):\n    \"\"\"Decorator wrapper to check if there is not -smp N option.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if is_smp_enabled():\n            err(\"Disable `-smp N` option for qemu-system\")\n            return\n        return f(*args, **kwargs)\n\n    return wrapper\n\n\ndef require_arch_set(f):\n    \"\"\"Decorator wrapper to check if current_arch is not None.\"\"\"\n\n    @functools.wraps(f)\n    def wrapper(*args, **kwargs):\n        if current_arch is not None:\n            return f(*args, **kwargs)\n        else:\n            err(\"Unsupported architecture\")\n            return\n\n    return wrapper\n\n\ndef only_if_specific_gdb_mode(mode=()):\n    \"\"\"Decorator wrapper to check if the gdb mode is specific.\"\"\"\n\n    def wrapper(f):\n\n        @functools.wraps(f)\n        def inner_f(*args, **kwargs):\n            dic = {\n                \"pin\": is_pin,\n                \"qemu-system\": is_qemu_system,\n                \"qemu-user\": is_qemu_user,\n                \"vmware\": is_vmware,\n                \"kgdb\": is_kgdb,\n                \"kdb\": is_kdb,\n                \"qiling\": is_qiling,\n                \"rr\": is_rr,\n                \"wine\": is_wine,\n            }\n            for m in mode:\n                if dic.get(m, lambda: False)():\n                    return f(*args, **kwargs)\n            warn(\"This command is not supported in this gdb mode\")\n            if \"kgdb\" in mode:\n                if is_in_kernel() and not is_qemu_system() and not is_vmware():\n                    info(\"For KGDB: Try `gef config gef.kgdb_force True`\")\n            return\n\n        return inner_f\n\n    return wrapper\n\n\ndef exclude_specific_gdb_mode(mode=()):\n    \"\"\"Decorator wrapper to check if the gdb mode is specific.\"\"\"\n\n    def wrapper(f):\n\n        @functools.wraps(f)\n        def inner_f(*args, **kwargs):\n            dic = {\n                \"pin\": is_pin,\n                \"qemu-system\": is_qemu_system,\n                \"qemu-user\": is_qemu_user,\n                \"vmware\": is_vmware,\n                \"kgdb\": is_kgdb,\n                \"kdb\": is_kdb,\n                \"qiling\": is_qiling,\n                \"rr\": is_rr,\n                \"wine\": is_wine,\n            }\n            for m in mode:\n                if dic.get(m, lambda: False)():\n                    warn(\"This command is not supported in this gdb mode\")\n                    return\n            return f(*args, **kwargs)\n\n        return inner_f\n\n    return wrapper\n\n\ndef only_if_specific_arch(arch=()):\n    \"\"\"Decorator wrapper to check if the architecture is specific.\"\"\"\n\n    def wrapper(f):\n\n        @functools.wraps(f)\n        def inner_f(*args, **kwargs):\n            dic = {\n                \"x86_32\": is_x86_32,\n                \"x86_64\": is_x86_64,\n                \"x86_16\": is_x86_16,\n                \"ARM32\": is_arm32,\n                \"ARM32M\": is_arm32_cortex_m,\n                \"ARM64\": is_arm64,\n                \"MIPS32\": is_mips32,\n                \"MIPS64\": is_mips64,\n                \"MIPSN32\": is_mipsn32,\n                \"PPC32\": is_ppc32,\n                \"PPC64\": is_ppc64,\n                \"SPARC32\": is_sparc32,\n                \"SPARC32PLUS\": is_sparc32plus,\n                \"SPARC64\": is_sparc64,\n                \"RISCV32\": is_riscv32,\n                \"RISCV64\": is_riscv64,\n                \"S390X\": is_s390x,\n                \"SH4\": is_sh4,\n                \"M68K\": is_m68k,\n                \"ALPHA\": is_alpha,\n                \"HPPA32\": is_hppa32,\n                \"HPPA64\": is_hppa64,\n                \"OR1K\": is_or1k,\n                \"NIOS2\": is_nios2,\n                \"MICROBLAZE\": is_microblaze,\n                \"XTENSA\": is_xtensa,\n                \"CRIS\": is_cris,\n                \"LOONGARCH64\": is_loongarch64,\n                \"ARC32\": is_arc32,\n                \"ARC64\": is_arc64,\n                \"CSKY\": is_csky,\n            }\n            for a in arch:\n                if dic.get(a, lambda: False)():\n                    return f(*args, **kwargs)\n            warn(\"This command is not supported on this architecture\")\n            return\n\n        return inner_f\n\n    return wrapper\n\n\ndef exclude_specific_arch(arch=()):\n    \"\"\"Decorator wrapper to check if the architecture is specific.\"\"\"\n\n    def wrapper(f):\n\n        @functools.wraps(f)\n        def inner_f(*args, **kwargs):\n            dic = {\n                \"x86_32\": is_x86_32,\n                \"x86_64\": is_x86_64,\n                \"x86_16\": is_x86_16,\n                \"ARM32\": is_arm32,\n                \"ARM32M\": is_arm32_cortex_m,\n                \"ARM64\": is_arm64,\n                \"MIPS32\": is_mips32,\n                \"MIPS64\": is_mips64,\n                \"MIPSN32\": is_mipsn32,\n                \"PPC32\": is_ppc32,\n                \"PPC64\": is_ppc64,\n                \"SPARC32\": is_sparc32,\n                \"SPARC32PLUS\": is_sparc32plus,\n                \"SPARC64\": is_sparc64,\n                \"RISCV32\": is_riscv32,\n                \"RISCV64\": is_riscv64,\n                \"S390X\": is_s390x,\n                \"SH4\": is_sh4,\n                \"M68K\": is_m68k,\n                \"ALPHA\": is_alpha,\n                \"HPPA32\": is_hppa32,\n                \"HPPA64\": is_hppa64,\n                \"OR1K\": is_or1k,\n                \"NIOS2\": is_nios2,\n                \"MICROBLAZE\": is_microblaze,\n                \"XTENSA\": is_xtensa,\n                \"CRIS\": is_cris,\n                \"LOONGARCH64\": is_loongarch64,\n                \"ARC32\": is_arc32,\n                \"ARC64\": is_arc64,\n                \"CSKY\": is_csky,\n            }\n            for a in arch:\n                if dic.get(a, lambda: False)():\n                    warn(\"This command is not supported on this architecture\")\n                    return\n            return f(*args, **kwargs)\n\n        return inner_f\n\n    return wrapper\n\n\ndef timeout(duration):\n    \"\"\"Decorator to handle timeout.\"\"\"\n\n    def wrapper(function):\n        import multiprocessing\n        queue = multiprocessing.Queue(maxsize=1)\n\n        def run_function(function, *args, **kwargs):\n            try:\n                # len(result) must be less than 0xffe8\n                result = function(*args, **kwargs)\n            except Exception as e:\n                queue.put((False, e))\n            else:\n                queue.put((True, result))\n            return\n\n        def inner_f(*args, **kwargs):\n            fargs = [function] + list(args)\n            p = multiprocessing.Process(target=run_function, args=fargs, kwargs=kwargs)\n            p.start()\n            p.join(duration)\n            if p.is_alive():\n                p.kill()\n                raise multiprocessing.TimeoutError\n            assert queue.full()\n            success, result = queue.get()\n            if success:\n                return result\n            else:\n                raise result\n\n        return inner_f\n\n    return wrapper\n\n\ndef to_unsigned_long(v):\n    \"\"\"Cast a gdb.Value to unsigned long.\"\"\"\n    mask = AddressUtil.get_vmem_end_mask()\n    return int(v.cast(gdb.Value(mask).type)) & mask\n\n\n# Don't use cache.\n# This is because there is a command that performs step execution internally.\ndef get_register(regname, use_mbed_exec=False, use_monitor=False):\n    \"\"\"Return a register's value.\"\"\"\n\n    if regname[0] in [\"%\", \"@\"]:\n        regname = \"$\" + regname[1:]\n\n    if regname[0] != \"$\":\n        regname = \"$\" + regname\n\n    try:\n        value = gdb.parse_and_eval(regname)\n        if value.type.code == gdb.TYPE_CODE_INT:\n            return to_unsigned_long(value)\n        elif value.type.name == \"vec128\":\n            if hasattr(value, \"bytes\"):\n                return u128(value.bytes)\n            else:\n                return eval(str(value[\"uint128\"]))\n        else:\n            return int(value)\n    except gdb.error:\n        if (is_hppa32() or is_hppa64()) and regname == \"$r0\":\n            return 0\n        try:\n            value = gdb.selected_frame().read_register(regname[1:])\n            return int(value)\n        except (gdb.error, ValueError):\n            pass\n\n    if use_mbed_exec and is_qemu_system() and is_arm32():\n        # Note that attempting to read a non-existent register will jump to an Undefined exception\n        try:\n            r = gdb.execute(\"read-system-register-for-qemu-arm {:s}\".format(regname), to_string=True)\n            if r:\n                return int(r.split(\"=\")[1], 16)\n        except gdb.error:\n            pass\n\n    if use_monitor and is_qemu_system() and is_x86():\n        regname = regname.lstrip(\"$\").upper()\n        res = gdb.execute(\"monitor info registers\", to_string=True)\n        r = re.search(r\"{:s}=(\\S+)\".format(regname), res)\n        if r:\n            return int(r.group(1), 16)\n\n    if use_monitor and is_vmware() and is_x86_64():\n        regname = regname.lstrip(\"$\")\n        res = gdb.execute(\"monitor r {:s}\".format(regname), to_string=True)\n        r = re.search(r\"{:s}=(\\S+)\".format(regname), res)\n        if r:\n            return int(r.group(1), 16)\n\n    if use_mbed_exec and is_kgdb() and (is_x86_64() or is_arm64()):\n        if ReadSystemRegisterForKgdbCommand.is_supported_reg(regname):\n            try:\n                r = gdb.execute(\"read-system-register-for-kgdb {:s}\".format(regname), to_string=True)\n                if r:\n                    return int(r.split(\"=\")[1], 16)\n            except gdb.error:\n                pass\n\n    return None\n\n\n@Cache.cache_this_session\ndef is_remote_debug():\n    \"\"\"GDB mode determination function for remote debugging.\"\"\"\n    try:\n        connection = gdb.selected_inferior().connection\n        if connection is None:\n            return False\n        return connection and connection.type == \"remote\"\n    except AttributeError:\n        # before gdb 11.x: AttributeError: 'gdb.Inferior' object has no attribute 'connection'\n        res = gdb.execute(\"maintenance print target-stack\", to_string=True)\n        return \"remote\" in res\n\n\n# Removed is_remote_same_host.\n# It can detect that gdb connects to a process in the same host.\n# However, it cannot detect that traffic is being redirected to another host.\n\n\n@Cache.cache_this_session\ndef is_normal_run():\n    \"\"\"GDB mode determination function for normal running.\"\"\"\n    ret = gdb.execute(\"info files\", to_string=True)\n    return \"Using the running image of child\" in ret\n\n\n@Cache.cache_this_session\ndef is_attach():\n    \"\"\"GDB mode determination function for attaching.\"\"\"\n    try:\n        return gdb.selected_inferior().was_attached\n    except AttributeError:\n        ret = gdb.execute(\"info files\", to_string=True)\n        return \"Using the running image of attached\" in ret\n\n\n@Cache.cache_this_session\ndef is_container_attach():\n    \"\"\"GDB mode determination function for attaching another namespace.\"\"\"\n    filename = gdb.current_progspace().filename\n    if filename and filename.startswith(\"target:\"):\n        return True\n    pid = Pid.get_pid()\n    if pid is None:\n        return False\n    path = \"/proc/{:d}/status\".format(pid)\n    if os.path.exists(path):\n        content = open(path, \"rb\").read()\n        r = re.search(rb\"\\nNSpid:\\s+(\\d+)\\s+(\\d+)\", content)\n        return bool(r)\n    return False\n\n\n@Cache.cache_this_session\ndef is_pin():\n    \"\"\"GDB mode determination function for pin and SDE.\"\"\"\n    if not is_remote_debug():\n        return False\n    try:\n        response = gdb.execute(\"maintenance packet qSupported\", to_string=True, from_tty=False)\n    except gdb.error as e:\n        err(\"{}\".format(e))\n        os._exit(0)\n    return \"intel.name=\" in response\n\n\n@Cache.cache_this_session\ndef is_qemu():\n    \"\"\"GDB mode determination function for qemu-user or qemu-system.\"\"\"\n    if not is_remote_debug():\n        return False\n    try:\n        response = gdb.execute(\"maintenance packet Qqemu.sstepbits\", to_string=True, from_tty=False)\n    except gdb.error as e:\n        err(\"{}\".format(e))\n        os._exit(0)\n    return \"ENABLE=\" in response\n\n\n@Cache.cache_this_session\ndef is_qemu_user():\n    \"\"\"GDB mode determination function for qemu-user gdb stub.\"\"\"\n    if is_qemu() is False:\n        return False\n    try:\n        response = gdb.execute(\"maintenance packet qOffsets\", to_string=True, from_tty=False)\n    except gdb.error as e:\n        err(\"{}\".format(e))\n        os._exit(0)\n    return \"Text=\" in response\n\n\n@Cache.cache_this_session\ndef is_qemu_system():\n    \"\"\"GDB mode determination function for qemu-system gdb stub.\"\"\"\n    if is_qemu() is False:\n        return False\n    try:\n        response = gdb.execute(\"maintenance packet qOffsets\", to_string=True, from_tty=False)\n    except gdb.error as e:\n        err(\"{}\".format(e))\n        os._exit(0)\n    return 'received: \"\"' in response\n\n\n@Cache.cache_this_session\ndef is_over_serial():\n    \"\"\"GDB mode determination function for serial device.\"\"\"\n    if not is_remote_debug():\n        return False\n    try:\n        dev = gdb.selected_inferior().connection.details\n        return dev.startswith((\"/dev/ttyS\", \"/dev/ttyAMA\", \"/dev/ttyUSB\"))\n    except AttributeError:\n        # before gdb 11.x: AttributeError: 'gdb.Inferior' object has no attribute 'connection'\n        return False\n\n\n@Cache.cache_this_session\ndef is_kgdb():\n    \"\"\"GDB mode determination function for KGDB.\"\"\"\n    # Forcing KGDB mode is useful when KGDB is being used via agent-proxy\n    # and thus GDB cannot see the serial device name.\n    if Config.get_gef_setting(\"gef.kgdb_force\") is True:\n        return True\n    return bool((is_x86_64() or is_arm64()) and is_over_serial())\n\n\n@Cache.cache_this_session\ndef kgdb_has_system_registers():\n    return Config.get_gef_setting(\"gef.kgdb_system_registers\") is True\n\n\n@Cache.cache_this_session\ndef is_kdb():\n    \"\"\"GDB mode determination function for KDB (over KGDB).\"\"\"\n    if not is_kgdb():\n        return False\n    try:\n        res = gdb.execute(\"monitor _stext\", to_string=True)\n    except gdb.error:\n        return False\n    r = re.search(r\"_stext = 0x(\\S+)\", res)\n    return bool(r)\n\n\n@Cache.cache_this_session\ndef is_vmware():\n    \"\"\"GDB mode determination function for VMware gdb stub.\"\"\"\n    if not is_remote_debug():\n        return False\n    # The `monitor help` command takes a very long time in kgdb mode.\n    # We can speed it up by making sure we're not in kgdb mode beforehand.\n    if is_over_serial() or is_kgdb():\n        return False\n    # https://xuanxuanblingbling.github.io/ctf/tools/2021/10/22/vmware/\n    try:\n        res = gdb.execute(\"monitor help r\", to_string=True)\n        return \"Dump hidden register\" in res\n    except gdb.error:\n        return False\n\n\n@Cache.cache_this_session\ndef is_qiling():\n    \"\"\"GDB mode determination function for qiling framework gdb stub.\"\"\"\n    if not is_remote_debug():\n        return False\n    pid = Pid.get_pid(remote=True)\n    if pid is None or pid < 42000:\n        return False\n    for m in ProcessMap.get_process_maps():\n        if m.path == \"[hook_mem]\":\n            return True\n    return False\n\n\n@Cache.cache_this_session\ndef is_rr():\n    \"\"\"GDB mode determination function for rr.\"\"\"\n    return Pid.get_pid_from_tcp_session(filepath=\"rr\") is not None\n\n\n@Cache.cache_this_session\ndef is_wine():\n    \"\"\"GDB mode determination function for winedbg.\"\"\"\n    return Pid.get_pid_from_tcp_session(filepath=\"wineserver\") is not None\n\n\n@Cache.cache_until_next\ndef is_in_kernel():\n    \"\"\"GDB mode determination function for kernel mode.\"\"\"\n    if not is_alive():\n        return False\n    if is_arm32_cortex_m():\n        return False\n    if is_qiling():\n        return False\n\n    # If it fails to obtain the flag register required for the judgment,\n    # it will be considered as userland.\n    if is_x86():\n        cs = get_register(\"$cs\")\n        if cs is None:\n            return False\n        return (cs & 0b11) != 3\n    elif is_arm32():\n        if is_in_secure():\n            return False\n        cpsr = get_register(current_arch.flag_register)\n        if cpsr is None:\n            return False\n        return (cpsr & 0b11111) not in [0b10000, 0b11010]\n    elif is_arm64():\n        if is_in_secure():\n            return False\n        cpsr = get_register(current_arch.flag_register)\n        if cpsr is None:\n            return False\n        return ((cpsr >> 2) & 0b11) == 1\n    elif is_riscv64() or is_riscv32():\n        priv = get_register(\"priv\")\n        if priv is None:\n            return False\n        return priv == 1\n    # All other architectures are considered userland.\n    return False\n\n\n@Cache.cache_this_session\ndef is_support_secure_world():\n    if not is_arm32() and not is_arm64():\n        return False\n    if not is_qemu_system():\n        return False\n    ret = gdb.execute(\"monitor info mtree -f\", to_string=True)\n    return \".secure-ram\" in ret\n\n\n@Cache.cache_until_next\ndef is_in_secure():\n    \"\"\"GDB mode determination function for secure world.\"\"\"\n    if not is_support_secure_world():\n        return False\n    if is_arm32():\n        scr = get_register(\"$SCR\")\n    elif is_arm64():\n        scr = get_register(\"$SCR_EL3\")\n    # In environments without a secure world:\n    # Older qemu versions did not have the SCR register. (return None)\n    # Newer qemu versions always return 0.\n    if not scr:\n        return False\n    return (scr & 0b1) == 0\n\n\n@Cache.cache_this_session\ndef is_kvm_enabled():\n    \"\"\"GDB mode determination function for KVM.\"\"\"\n    try:\n        res = gdb.execute(\"monitor info kvm\", to_string=True)\n        return \"enabled\" in res\n    except gdb.error:\n        return False\n\n\n@Cache.cache_this_session\ndef is_smp_enabled():\n    \"\"\"GDB mode determination function for smp.\"\"\"\n    try:\n        res = gdb.execute(\"monitor info cpus\", to_string=True)\n        return len(res.splitlines()) >= 2\n    except gdb.error:\n        return False\n\n\nclass Pid:\n    \"\"\"A collection of utility functions that obtains a pid.\"\"\"\n\n    @staticmethod\n    def get_tcp_sess(pid):\n        # get inode information from opened file descriptor\n        inodes = []\n        for openfd in os.listdir(\"/proc/{:d}/fd\".format(pid)):\n            try:\n                fdname = os.readlink(\"/proc/{:d}/fd/{:s}\".format(pid, openfd))\n            except (FileNotFoundError, ProcessLookupError, OSError):\n                continue\n            if fdname.startswith(\"socket:[\"):\n                inode = fdname[8:-1]\n                inodes.append(inode)\n\n        def decode(addr):\n            ip, port = addr.split(\":\")\n            import socket\n            ip = socket.inet_ntop(socket.AF_INET, bytes.fromhex(ip)[::-1])\n            port = int(port, 16)\n            return (ip, port)\n\n        # get connection information\n        sessions = []\n        with open(\"/proc/{:d}/net/tcp\".format(pid)) as fd:\n            for line in fd.readlines()[1:]:\n                _, laddr, raddr, status, _, _, _, _, _, inode = line.split()[:10]\n                if status != \"01\": # ESTABLISHED\n                    continue\n                if inode not in inodes:\n                    continue\n                laddr = decode(laddr)\n                raddr = decode(raddr)\n                sessions.append({\"laddr\": laddr, \"raddr\": raddr})\n        return sessions\n\n    @staticmethod\n    def get_all_process():\n        pids = [int(x) for x in os.listdir(\"/proc\") if x.isdigit()]\n        process = []\n        for pid in pids:\n            try:\n                filepath = os.readlink(\"/proc/{:d}/exe\".format(pid))\n            except (FileNotFoundError, ProcessLookupError, OSError):\n                continue\n            process.append({\"pid\": pid, \"filepath\": os.path.basename(filepath)})\n        return process\n\n    @staticmethod\n    def get_pid_from_name(filepath):\n        all_process = Pid.get_all_process()\n\n        # strict matching\n        candidate = [process for process in all_process if process[\"filepath\"] == filepath]\n        if len(candidate) == 1:\n            return candidate[0][\"pid\"]\n        if len(candidate) > 1: # If it cannot be uniquely identified, return None\n            return None\n\n        # relax the restrictions\n        candidate = [process for process in all_process if process[\"filepath\"].startswith(filepath)]\n        if len(candidate) == 1:\n            return candidate[0][\"pid\"]\n        if len(candidate) > 1: # If it cannot be uniquely identified, return None\n            return None\n\n        # more relax the restrictions\n        candidate = [process for process in all_process if filepath in process[\"filepath\"]]\n        if len(candidate) == 1:\n            return candidate[0][\"pid\"]\n        if len(candidate) > 1: # If it cannot be uniquely identified, return None\n            return None\n        return None\n\n    @staticmethod\n    def get_pid_from_tcp_session(filepath=None):\n        gdb_tcp_sess = [x[\"raddr\"] for x in Pid.get_tcp_sess(os.getpid())]\n        if not gdb_tcp_sess:\n            return None\n        for process in Pid.get_all_process():\n            if filepath and not process[\"filepath\"].startswith(filepath):\n                continue\n            for c in Pid.get_tcp_sess(process[\"pid\"]):\n                if c[\"laddr\"] in gdb_tcp_sess:\n                    return process[\"pid\"]\n        return None\n\n    @staticmethod\n    def get_pid_wine():\n        ws_pid = Pid.get_pid_from_tcp_session(filepath=\"wineserver\")\n        if ws_pid is None:\n            return None\n\n        def get_external_pipe_inodes(pid):\n            inodes = set()\n            if not os.path.exists(\"/proc/{:d}/\".format(pid)):\n                return inodes\n            # get inode information from opened file descriptor\n            for openfd in os.listdir(\"/proc/{:d}/fd\".format(pid)):\n                try:\n                    fdname = os.readlink(\"/proc/{:d}/fd/{:s}\".format(pid, openfd))\n                except (FileNotFoundError, ProcessLookupError, OSError):\n                    continue\n                if fdname.startswith(\"pipe:[\"):\n                    inode = fdname[6:-1]\n                    if inode in inodes:\n                        inodes.remove(inode)\n                    else:\n                        inodes.add(inode)\n            return inodes\n\n        ws_inodes = get_external_pipe_inodes(ws_pid)\n\n        gdb_pid = os.getpid()\n        for candidate_pid in range(gdb_pid - 1, ws_pid, -1):\n            candidate_inodes = get_external_pipe_inodes(candidate_pid)\n            if candidate_inodes & ws_inodes:\n                return candidate_pid\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_pid(remote=False):\n        \"\"\"Return the PID of the debuggee process.\"\"\"\n        if is_pin():\n            return Pid.get_pid_from_tcp_session()\n        elif is_qemu_user() or is_qemu_system():\n            pid = Pid.get_pid_from_tcp_session(\"qemu\") # strict way\n            if pid is None:\n                pid = Pid.get_pid_from_name(\"qemu\") # ambiguous way\n            return pid\n        elif is_wine():\n            return Pid.get_pid_wine()\n        elif remote is False and is_remote_debug():\n            return None # gdbserver etc.\n        return gdb.selected_inferior().pid\n\n    @staticmethod\n    def get_tid():\n        ptid = gdb.selected_thread().ptid\n        return ptid[1] or ptid[2]\n\n\nclass Path:\n    \"\"\"A collection of utility functions that obtains a path.\"\"\"\n\n    @staticmethod\n    def append_proc_root(filepath):\n        if filepath is None:\n            return None\n        pid = Pid.get_pid()\n        if pid is None:\n            return None\n        if pid == 0: # under gdbserver, when target exited then pid is 0\n            return None\n        prefix = \"/proc/{}/root\".format(pid)\n        relative_path = filepath.lstrip(\"/\")\n        return os.path.join(prefix, relative_path)\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_filepath(append_proc_root_prefix=True):\n        \"\"\"Return the local absolute path of the file currently debugged.\"\"\"\n        filepath = gdb.current_progspace().filename\n\n        if is_remote_debug():\n            if filepath is None:\n                return None\n            elif filepath.startswith(\"target:\"):\n                return None\n            elif filepath.startswith(\".gnu_debugdata for target:\"):\n                return None\n            else:\n                return filepath\n        else:\n            # inferior probably did not have name, extract cmdline from info proc\n            if filepath is None:\n                filepath = Path.get_filepath_from_info_proc()\n                if append_proc_root_prefix:\n                    # maybe different mnt namespace, so use /proc/<PID>/root\n                    filepath = Path.append_proc_root(filepath)\n            # not remote, but different PID namespace and attaching by pid. it shows with `target:`\n            elif filepath.startswith(\"target:\"):\n                # /proc/PID/root is not given when used for purposes such as comparing with entry in vmmap\n                filepath = filepath[len(\"target:\"):]\n                if append_proc_root_prefix:\n                    # maybe different mnt namespace, so use /proc/<PID>/root\n                    filepath = Path.append_proc_root(filepath)\n            # normal path\n            return filepath\n\n    @staticmethod\n    def get_filepath_from_info_proc():\n        try:\n            response = gdb.execute(\"info proc\", to_string=True)\n        except gdb.error:\n            return None\n        for x in response.splitlines():\n            if x.startswith(\"exe = \"):\n                return x.split(\" = \")[1].replace(\"'\", \"\")\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_filename():\n        \"\"\"Return the full filename of the file currently debugged.\"\"\"\n        filename = Path.get_filepath()\n        if filename is None:\n            return None\n        return os.path.basename(filename)\n\n    @staticmethod\n    def read_remote_file(filepath, as_byte=True):\n        tmp_name = os.path.join(GEF_TEMP_DIR, \"read_remote_file.tmp\")\n        try:\n            gdb.execute(\"remote get {!r} {!r}\".format(filepath, tmp_name), to_string=True)\n        except gdb.error:\n            return \"\"\n        if as_byte:\n            data = open(tmp_name, \"rb\").read()\n        else:\n            data = open(tmp_name, \"r\").read()\n        os.unlink(tmp_name)\n        return data\n\n\nclass ProcessMap:\n    \"\"\"A collection of utility functions that obtains a process map.\"\"\"\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_process_maps_linux(pid, remote=False):\n        \"\"\"Parse the Linux process `/proc/pid/maps` file.\"\"\"\n\n        if Config.get_gef_setting(\"context.disable_vmmap\"):\n            return []\n\n        # open & read maps\n        proc_map_file = \"/proc/{:d}/maps\".format(pid)\n        if remote:\n            data = Path.read_remote_file(proc_map_file, as_byte=False)\n            if not data:\n                return []\n            lines = data.splitlines()\n        else:\n            if not os.path.exists(proc_map_file):\n                return []\n            lines = open(proc_map_file, \"r\").readlines()\n\n        # tls and $sp of each threads\n        extra_info = []\n        if is_x86():\n            tls_list = []\n            orig_thread = gdb.selected_thread()\n            orig_frame = gdb.selected_frame()\n            if orig_thread: # orig_thread may be None if under winedbg\n                for thread in gdb.selected_inferior().threads():\n                    thread.switch() # change thread\n                    # note: for speed up, do not use current_arch.get_tls()\n                    tls = get_register(\"$fs_base\" if is_x86_64() else \"$gs_base\") # get tls address\n                    tls_list.append([thread.num, tls, current_arch.sp])\n                orig_thread.switch() # revert thread\n                orig_frame.select()\n                extra_info = sorted(tls_list)\n\n                # When using gdbserver, thread.num may start from 2 even though there is no thread.\n                # This is confusing, so if there is only the main thread, force it to 1.\n                if len(extra_info) == 1:\n                    extra_info[0][0] = 1\n\n        # parse\n        maps = []\n        for line in lines:\n            line = line.replace(\"\\t\", \" \") # for qiling framework\n            line = line.strip()\n            addr, perm, off, _, rest = line.split(\" \", 4)\n            addr_start, addr_end = [int(x, 16) for x in addr.split(\"-\")]\n            rest = rest.split(\" \", 1)\n            if len(rest) == 1:\n                pathname = \"\"\n            else:\n                pathname = rest[1].lstrip()\n            inode = int(rest[0])\n\n            for th_num, tls_addr, _ in extra_info:\n                if tls_addr and addr_start <= tls_addr < addr_end:\n                    pathname += \"<tls-th{:d}>\".format(th_num)\n                    break\n\n            for th_num, _, stack_addr in extra_info:\n                if th_num > 1 and stack_addr and addr_start <= stack_addr < addr_end:\n                    pathname += \"<stack-th{:d}>\".format(th_num)\n                    break\n\n            off = int(off, 16)\n            perm = Permission.from_process_maps(perm)\n            sect = Section(\n                page_start=addr_start, page_end=addr_end,\n                offset=off, permission=perm, inode=inode, path=pathname,\n            )\n            maps.append(sect)\n        return maps\n\n    # get_explored_regions (used at qemu-user mode) is very slow,\n    # Because it repeats read_memory many times to find the upper and lower bounds of the page.\n    # Cache.cache_until_next is ineffective due to frequent resets (each time the `stepi` runs).\n    # Fortunately, memory maps rarely change.\n    # The cache is cleared and rechecked when the `vmmap` command is called explicitly.\n    @staticmethod\n    @Cache.cache_this_session\n    def get_explored_regions():\n        \"\"\"Return sections from auxv exploring.\"\"\"\n\n        if Config.get_gef_setting(\"context.disable_vmmap\"):\n            return []\n\n        if current_arch is None:\n            return []\n\n        def is_valid_addr_fast(addr):\n            try:\n               gdb.selected_inferior().read_memory(addr, 1)\n               return True\n            except gdb.MemoryError:\n                return False\n\n        def get_region_start_end(addr):\n            addr &= get_pagesize_mask_high()\n            if not is_valid_addr_fast(addr):\n                return None, None\n            region_start = addr\n            region_end = addr + get_pagesize()\n\n            nonlocal regions\n            end_addrs = [r.page_end for r in regions]\n            start_addrs = [r.page_start for r in regions]\n\n            # up search\n            lower_bound = 0\n            while True:\n                if region_start <= lower_bound:\n                    break\n                if region_start in end_addrs:\n                    break\n                if not is_valid_addr_fast(region_start - get_pagesize()):\n                    break\n                region_start -= get_pagesize()\n\n            upper_bound = 1 << AddressUtil.get_memory_alignment(in_bits=True)\n            # down search\n            while True:\n                if region_end >= upper_bound:\n                    break\n                if region_end in start_addrs:\n                    break\n                if not is_valid_addr_fast(region_end):\n                    break\n                region_end += get_pagesize()\n            return region_start, region_end\n\n        def make_regions(addr, label, perm=\"rw-\"):\n            if addr is None:\n                return []\n            # check if already in region\n            nonlocal regions\n            for rg in regions:\n                if rg.page_start <= addr < rg.page_end:\n                    return []\n            # make region\n            start, end = get_region_start_end(addr)\n            if start is None:\n                return []\n            perm = Permission.from_process_maps(perm)\n            sect = Section(page_start=start, page_end=end, permission=perm, path=label)\n            return [sect]\n\n        def get_ehdr(addr):\n            upper_bound = 1 << AddressUtil.get_memory_alignment(in_bits=True)\n            for _ in range(128):\n                if addr < 0 or addr > upper_bound:\n                    return None\n                try:\n                    e_magic = read_memory(addr, 4)\n                except gdb.MemoryError:\n                    return None\n                if e_magic == b\"\\x7fELF\":\n                    return Elf.get_elf(addr)\n                addr -= get_pagesize()\n            return None\n\n        def parse_region_from_ehdr(addr, label):\n            elf = get_ehdr(addr & get_pagesize_mask_high())\n            if elf is None:\n                return []\n\n            pages = []\n            for phdr in elf.phdrs:\n                if not phdr.p_memsz:\n                    continue\n\n                vaddr = phdr.p_vaddr\n                if elf.is_pie():\n                    vaddr += elf.addr\n                vaddr_end = vaddr + phdr.p_memsz\n\n                offset = phdr.p_offset\n                flags = phdr.p_flags\n\n                # align\n                vaddr &= get_pagesize_mask_high()\n                offset &= get_pagesize_mask_high()\n                vaddr_end = (vaddr_end + get_pagesize_mask_low()) & get_pagesize_mask_high()\n\n                # add per pages\n                for page_addr in range(vaddr, vaddr_end, get_pagesize()):\n                    # check already exist\n                    for i, page in enumerate(pages):\n                        if page[\"vaddr\"] == page_addr:\n                            # found, so fix flags\n                            if page[\"flags\"] & Elf.Phdr.PF_X: # already has PF_X\n                                flags |= Elf.Phdr.PF_X\n                            pages[i][\"flags\"] = flags # overwrite, because RELRO\n                            break\n                    else:\n                        # not found, so add new page\n                        page = {\n                            \"vaddr\": page_addr,\n                            \"memsize\": get_pagesize(),\n                            \"flags\": flags,\n                            \"offset\": offset + (page_addr - vaddr),\n                        }\n                        pages.append(page)\n\n            pages = sorted(pages, key=lambda x: x[\"vaddr\"])\n\n            # merge contiguous\n            prev = pages[0]\n            for page in pages[1:]:\n                prev_vend = prev[\"vaddr\"] + prev[\"memsize\"]\n                if prev[\"flags\"] == page[\"flags\"] and prev_vend == page[\"vaddr\"]:\n                    prev[\"memsize\"] += page[\"memsize\"]\n                    pages.remove(page)\n                else:\n                    prev = page\n\n            # page -> section\n            sects = []\n            for page in pages:\n                perm = Permission.from_process_maps(ElfInfoCommand.pflags[page[\"flags\"]].lower())\n                page_start = page[\"vaddr\"]\n                page_end = page[\"vaddr\"] + page[\"memsize\"]\n                off = page[\"offset\"]\n                sect = Section(\n                    page_start=page_start, page_end=page_end,\n                    offset=off, permission=perm, path=label,\n                )\n                sects.append(sect)\n            return sects\n\n        def get_linker(addr):\n            if addr is None:\n                return None\n\n            # get interp\n            elf = get_ehdr(addr & get_pagesize_mask_high())\n            phdr = elf.get_phdr(Elf.Phdr.PT_INTERP)\n            if phdr is None:\n                return None\n\n            vaddr = phdr.p_vaddr\n            if elf.is_pie():\n                vaddr += elf.addr\n\n            linker = read_cstring_from_memory(vaddr)\n            return linker\n\n        def get_link_map(addr):\n            if addr is None:\n                return None\n\n            # get dynamic\n            elf = get_ehdr(addr & get_pagesize_mask_high())\n            phdr = elf.get_phdr(Elf.Phdr.PT_DYNAMIC)\n            if phdr is None:\n                return None\n\n            vaddr = phdr.p_vaddr\n            vaddr_end = vaddr + phdr.p_memsz\n            if elf.is_pie():\n                vaddr += elf.addr\n                vaddr_end += elf.addr\n\n            # search DT_DEBUG\n            for tag_addr in range(vaddr, vaddr_end, current_arch.ptrsize * 2):\n                tag = read_int_from_memory(tag_addr)\n                if tag == 21: # DT_DEBUG\n                    dt_debug = read_int_from_memory(tag_addr + current_arch.ptrsize)\n                    break\n            else:\n                # not found\n                return None\n\n            # get link_map\n            try:\n                link_map = read_int_from_memory(dt_debug + current_arch.ptrsize)\n            except gdb.MemoryError:\n                return None\n            return link_map\n\n        def get_filepath_wrapper():\n            filepath = Path.get_filepath()\n            if filepath:\n                return filepath\n            filepath = gdb.current_progspace().filename\n            if filepath and filepath.startswith(\"target:\"):\n                filepath = filepath[7:]\n            return filepath\n\n        def parse_region_from_link_map(link_map):\n            current = link_map\n            new_regions = []\n            while True:\n                l_addr = read_int_from_memory(current + current_arch.ptrsize * 0)\n                l_name = read_int_from_memory(current + current_arch.ptrsize * 1)\n                l_next = read_int_from_memory(current + current_arch.ptrsize * 3)\n                name = read_cstring_from_memory(l_name)\n                if not name:\n                    name = get_filepath_wrapper() or \"[code]\"\n                new_regions += parse_region_from_ehdr(l_addr, name)\n                if l_next == 0:\n                    break\n                current = l_next\n            return new_regions\n\n        def parse_auxv():\n            auxv = Auxv.get_auxiliary_values()\n            if not auxv:\n                return []\n\n            new_regions = []\n            codebase = auxv.get(\"AT_PHDR\", None) or auxv.get(\"AT_ENTRY\", None)\n\n            # plan1: from link_map info (code, all loaded shared library)\n            link_map = get_link_map(codebase)\n            if link_map:\n                new_regions += parse_region_from_link_map(link_map)\n\n            # plan2: use each auxv info (for code, linker)\n            else:\n                # code\n                if \"AT_PHDR\" in auxv:\n                    new_regions += parse_region_from_ehdr(auxv[\"AT_PHDR\"], get_filepath_wrapper() or \"[code]\")\n                elif \"AT_ENTRY\" in auxv:\n                    new_regions += parse_region_from_ehdr(auxv[\"AT_ENTRY\"], get_filepath_wrapper() or \"[code]\")\n                # linker\n                if \"AT_BASE\" in auxv:\n                    new_regions += parse_region_from_ehdr(auxv[\"AT_BASE\"], get_linker(codebase) or \"[linker]\")\n\n            # vdso\n            if \"AT_SYSINFO_EHDR\" in auxv:\n                new_regions += parse_region_from_ehdr(auxv[\"AT_SYSINFO_EHDR\"], \"[vdso]\")\n            elif \"AT_SYSINFO\" in auxv:\n                new_regions += parse_region_from_ehdr(auxv[\"AT_SYSINFO\"], \"[vdso]\")\n            return new_regions\n\n        def parse_stack_register():\n            # get permission\n            stack_permission = \"rw-\" # default\n            auxv = Auxv.get_auxiliary_values()\n            if auxv and \"AT_PHDR\" in auxv:\n                elf = get_ehdr(auxv[\"AT_PHDR\"] & get_pagesize_mask_high())\n                phdr = elf.get_phdr(Elf.Phdr.PT_GNU_STACK)\n                if phdr:\n                    stack_permission = ElfInfoCommand.pflags[phdr.p_flags].lower()\n                else:\n                    stack_permission = \"rwx\" # no GNU_STACK phdr means no-NX\n            # add region\n            return make_regions(current_arch.sp, \"[stack]\", stack_permission)\n\n        def parse_registers_and_stack():\n            queue = set()\n\n            # registers\n            for regname in current_arch.all_registers:\n                v = get_register(regname)\n                if v is None:\n                    continue\n                queue.add(v & get_pagesize_mask_high())\n\n            # walk value from stack top\n            sp = current_arch.sp\n            if sp is not None:\n                try:\n                    data = read_memory(sp & get_pagesize_mask_high(), get_pagesize())\n                    data = slice_unpack(data, current_arch.ptrsize)\n                    queue |= {d & get_pagesize_mask_high() for d in set(data)}\n                except gdb.MemoryError:\n                    pass\n\n            # contiguous areas are removed from the queue\n            merged_queue = []\n            for addr in sorted(queue):\n                if not is_valid_addr(addr):\n                    continue\n                if addr - get_pagesize() in merged_queue:\n                    continue\n                merged_queue.append(addr)\n\n            # add regions\n            new_regions = []\n            for addr in merged_queue:\n                skip = False\n                for rg in new_regions:\n                    if rg.page_start <= addr < rg.page_end:\n                        skip = True\n                if not skip:\n                    new_regions += make_regions(addr, \"<explored>\")\n            return new_regions\n\n        # ----\n\n        regions = []\n        regions += parse_auxv()\n        regions += parse_stack_register()\n\n        # walk from known map, because qemu may maps extra regions (?)\n        for r in regions.copy():\n            regions += make_regions(r.page_start - 1, \"<explored>\", str(r.permission))\n            regions += make_regions(r.page_end + 1, \"<explored>\", str(r.permission))\n\n        regions += parse_registers_and_stack()\n\n        # ok\n        regions = sorted(regions, key=lambda x: x.page_start)\n\n        return regions\n\n    @staticmethod\n    def get_process_maps_from_info_proc():\n        if Config.get_gef_setting(\"context.disable_vmmap\"):\n            return []\n\n        res = gdb.execute(\"info proc mappings\", to_string=True)\n\n        \"\"\"\n        process 2897541\n        Mapped address spaces:\n\n                  Start Addr           End Addr       Size     Offset  Perms  objfile\n                    0x400000           0x478000    0x78000        0x0  r-xp   /tmp/a.out\n                    0x478000           0x48c000    0x14000        0x0  ---p\n                    0x48c000           0x492000     0x6000    0x7c000  rw-p   /tmp/a.out\n                    0x492000           0x498000     0x6000        0x0  rw-p\n              0x400000000000     0x400000001000     0x1000        0x0  ---p\n              0x400000001000     0x400000801000   0x800000        0x0  rw-p   [stack]\n              0x400000801000     0x400000802000     0x1000        0x0  r-xp\n        \"\"\"\n        maps = []\n        for line in res.splitlines()[4:]:\n            line = line.strip()\n            addr_start, addr_end, size, offset, perm, *path = line.split()\n            addr_start = int(addr_start, 16)\n            addr_end = int(addr_end, 16)\n            size = int(size, 16)\n            offset = int(offset, 16)\n            perm = Permission.from_process_maps(perm)\n            if len(path) == 1:\n                path = path[0]\n            else:\n                path = \"\"\n            sect = Section(\n                page_start=addr_start, page_end=addr_end,\n                offset=offset, permission=perm, inode=None, path=path,\n            )\n            maps.append(sect)\n        return maps\n\n    __gef_use_info_proc_mappings__ = None # the flag to use `info proc mappings`\n\n    @staticmethod\n    def get_process_maps_heuristic():\n        if Config.get_gef_setting(\"context.disable_vmmap\"):\n            return []\n\n        if ProcessMap.__gef_use_info_proc_mappings__ is None:\n            try:\n                res = gdb.execute(\"info proc mappings\", to_string=True)\n                if \"warning\" in res:\n                    ProcessMap.__gef_use_info_proc_mappings__ = False\n                elif \"Perms\" not in res: # xtensa-linux-gdb\n                    ProcessMap.__gef_use_info_proc_mappings__ = False\n                else: # for core files\n                    ProcessMap.__gef_use_info_proc_mappings__ = True\n            except gdb.error:\n                ProcessMap.__gef_use_info_proc_mappings__ = False\n\n        # fast path\n        if ProcessMap.__gef_use_info_proc_mappings__ is True:\n            res = ProcessMap.get_process_maps_from_info_proc() # don't use cache\n            if res:\n                return res\n            # something is wrong\n            ProcessMap.__gef_use_info_proc_mappings__ = False\n\n        # slow path\n        return ProcessMap.get_explored_regions() # use cache\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_process_maps(outer=False):\n        \"\"\"Return the mapped memory sections.\"\"\"\n        if Config.get_gef_setting(\"context.disable_vmmap\"):\n            return []\n\n        if is_qemu_user():\n            if outer:\n                pid = Pid.get_pid()\n                if pid:\n                    return ProcessMap.get_process_maps_linux(pid)\n                return []\n            else: # scan heuristic\n                return ProcessMap.get_process_maps_heuristic()\n\n        elif is_pin():\n            pid = Pid.get_pid()\n            if pid:\n                return ProcessMap.get_process_maps_linux(pid)\n\n        elif is_qemu_system():\n            return []\n\n        elif is_wine():\n            # Wine loads the EXE at Wine's own virtual address space.\n            # For typical pwner use cases, Wine itself and its libraries should also be displayed.\n            # However, Wine's `monitor mem` does not show them, so this approach is not used.\n            # Resolving Wine's PID and retrieving its memory maps is more reliable.\n            pid = Pid.get_pid()\n            if pid:\n                return ProcessMap.get_process_maps_linux(pid)\n            return []\n\n        elif is_remote_debug():\n            remote_pid = Pid.get_pid(remote=True)\n            if remote_pid:\n                return ProcessMap.get_process_maps_linux(remote_pid, remote=True)\n\n        elif is_rr():\n            return ProcessMap.get_process_maps_from_info_proc()\n\n        else: # normal pattern\n            pid = Pid.get_pid()\n            if pid:\n                r = ProcessMap.get_process_maps_linux(pid)\n                if r:\n                    return r\n\n        return ProcessMap.get_process_maps_heuristic()\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_process_maps_exclude_special_regions(outer=False, allow_vdso=False, allow_vsyscall=False):\n        \"\"\"Return the mapped memory sections,\n        exclude [vvar], [vvar_vclock], [vdso], [vsyscall], [sigpage], etc.\"\"\"\n        vmmap = ProcessMap.get_process_maps(outer)\n        if vmmap == []:\n            return vmmap\n\n        valid_maps = []\n        for m in vmmap:\n            if \"[vvar]\" in m.path:\n                continue\n            if \"[vvar_vclock]\" in m.path:\n                continue\n            if \"[vdso]\" in m.path:\n                if not allow_vdso:\n                    continue\n            if \"[vsyscall]\" in m.path:\n                if not allow_vsyscall:\n                    continue\n            if \"[sigpage]\" in m.path: # ARM\n                continue\n            if \"[vectors]\" in m.path: # ARM\n                continue\n            valid_maps.append(m)\n        return valid_maps\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_loaded_files():\n        files = set()\n        for m in ProcessMap.get_process_maps():\n            if not m.path:\n                continue\n            if m.path.startswith((\"<\", \"[\")):\n                continue\n            if not os.path.exists(m.path):\n                continue\n            files.add(m.path)\n        return files\n\n    # `info files` called from get_info_files is heavy processing.\n    # Moreover, AddressUtil.recursive_dereference causes each address to be resolved every time.\n    # Cache.cache_until_next is ineffective due to frequent resets (each time the `stepi` runs).\n    # Fortunately, zone information rarely changes.\n    # The cache is retained until explicitly cleared.\n    @staticmethod\n    @Cache.cache_this_session\n    def get_info_files():\n        \"\"\"Retrieve all the files loaded by debuggee.\"\"\"\n        lines = gdb.execute(\"info files\", to_string=True).splitlines()\n        info_files = []\n        seen = []\n        for line in lines:\n            line = line.strip()\n            if not line:\n                break\n            if not line.startswith(\"0x\"):\n                continue\n            if line in seen:\n                continue\n            seen.append(line)\n\n            blobs = [x.strip() for x in line.split(\" \")]\n            addr_start = int(blobs[0], 16)\n            addr_end = int(blobs[2], 16)\n            if len(blobs) > 4:\n                section_name = blobs[4]\n            else:\n                section_name = \"\"\n            if \"system-supplied DSO\" in line:\n                filepath = \"[vdso]\"\n            elif len(blobs) == 7:\n                filepath = blobs[6]\n            else:\n                filepath = Path.get_filepath(append_proc_root_prefix=False)\n            Zone = collections.namedtuple(\"Zone\", [\"name\", \"zone_start\", \"zone_end\", \"filename\"])\n            info = Zone(section_name, addr_start, addr_end, filepath)\n            info_files.append(info)\n        return info_files\n\n    @staticmethod\n    @Cache.cache_until_next\n    def process_lookup_address(addr):\n        \"\"\"Look up for an address in memory. Return an Address object if found, None otherwise.\"\"\"\n        if not is_alive():\n            err(\"Process is not running\")\n            return None\n        if is_qemu_system() or is_vmware() or is_kgdb():\n            return None\n        for sect in ProcessMap.get_process_maps():\n            if sect.page_start <= addr < sect.page_end:\n                return sect\n        return None\n\n    @staticmethod\n    @Cache.cache_until_next\n    def process_lookup_path(names, perm_mask=Permission.ALL):\n        \"\"\"Look up for paths in the process memory mapping.\n        Return a Section object of the load base address if found, None otherwise.\"\"\"\n        if not is_alive():\n            err(\"Process is not running\")\n            return None\n        if isinstance(names, str):\n            names = (names,) # make tuple to iterate\n        for sect in ProcessMap.get_process_maps():\n            for name in names:\n                if name in sect.path and sect.permission.value & perm_mask:\n                    return sect\n        return None\n\n    @staticmethod\n    @Cache.cache_until_next\n    def file_lookup_address(addr):\n        \"\"\"Look up for a file by its address. Return a Zone object if found, None otherwise.\"\"\"\n        if is_qemu_system() or is_vmware() or is_kgdb():\n            # If FGKASLR is enabled, there are too many sections and it will take a long time, so skip them.\n            return None\n        for info in ProcessMap.get_info_files():\n            if info.zone_start <= addr < info.zone_end:\n                return info\n        return None\n\n    @staticmethod\n    @Cache.cache_until_next\n    def lookup_address(addr):\n        \"\"\"Try to find the address in the process address space. Return an Address object with caching.\"\"\"\n        return Address(addr)\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_section_base_address(name):\n        if name is None:\n            return None\n        section = ProcessMap.process_lookup_path(name)\n        if section:\n            return section.page_start\n        # Fail, retry with real path\n        section = ProcessMap.process_lookup_path(os.path.realpath(name))\n        if section:\n            return section.page_start\n        return None\n\n    @staticmethod\n    def get_section_base_address_by_list(names):\n        for name in names:\n            page_start = ProcessMap.get_section_base_address(name)\n            if page_start is not None:\n                return page_start\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_codebase():\n        filepath = Path.get_filepath(append_proc_root_prefix=is_container_attach())\n        bin_base = ProcessMap.get_section_base_address(filepath)\n        if bin_base is not None:\n            return bin_base\n\n        filepath = Path.get_filepath_from_info_proc()\n        bin_base = ProcessMap.get_section_base_address(filepath)\n        return bin_base\n\n\nclass EventHandler:\n    \"\"\"A collection of handler functions that are called when the specified events occur.\"\"\"\n\n    @staticmethod\n    def continue_handler(_event):\n        \"\"\"GDB event handler for new object continue cases.\"\"\"\n        return\n\n    __gef_check_once__ = True # the flag to process only once at startup\n    __gef_check_disabled_bp__ = False # the flag to remove unnecessary breakpoints\n\n    @staticmethod\n    def hook_stop_handler(event):\n        \"\"\"GDB event handler for stop cases.\"\"\"\n        Cache.reset_gef_caches()\n\n        # There appears to be a bug on some architectures (e.g., i386) where temporary breakpoints\n        # are not deleted even after being hit. The conditions under which this occurs are unknown,\n        # so any remaining breakpoints are removed manually by GEF.\n        if EventHandler.__gef_check_disabled_bp__:\n            for bp in gdb.breakpoints():\n                if not bp.visible and bp.temporary:\n                    if not bp.enabled:\n                        bp.delete()\n            EventHandler.__gef_check_disabled_bp__ = False\n\n        # when kgdb, assume x86-64 if /dev/ttyS\n        if EventHandler.__gef_check_once__:\n            if is_over_serial():\n                dev = gdb.selected_inferior().connection.details\n                if dev.startswith(\"/dev/ttyS\"):\n                    gdb.execute(\"set architecture i386:x86-64:intel\", to_string=True)\n                else:\n                    # In the case of /dev/ttyAMA, it is not clear whether it is ARM64 or ARM32.\n                    # In some cases, /dev/ttyUSB is used.\n                    pass\n                Cache.reset_gef_caches()\n\n        # GEF will resolve the architecture if it is unknown.\n        if current_arch is None:\n            set_arch(get_arch())\n\n        # set `c`, `ni` and `si` command hooks for qemu-user and pin\n        if EventHandler.__gef_check_once__:\n            if is_qemu_user() or is_pin():\n                gdb.execute(\"define c\\ncontinue-for-qemu-user\\nend\")\n                if is_or1k() or is_cris():\n                    gdb.execute(\"define si\\nstepi-for-qemu-user\\nend\")\n                    gdb.execute(\"define ni\\nnexti-for-qemu-user\\nend\")\n\n        # disable for cortex-m\n        if EventHandler.__gef_check_once__:\n            if is_arm32_cortex_m():\n                gdb.execute(\"gef config context.disable_vmmap True\")\n                gdb.execute(\"gef config context.disable_auxv True\")\n\n        # If the silent command is specified for a breakpoint, skip `context` command.\n        context_flag = True\n        if isinstance(event, gdb.BreakpointEvent):\n            if event.breakpoint.is_valid() and event.breakpoint.enabled:\n                if event.breakpoint.commands:\n                    if event.breakpoint.commands.startswith(\"silent\"):\n                        context_flag = False\n        if context_flag:\n            gdb.execute(\"context\")\n\n        # Message if file is not loaded.\n        if EventHandler.__gef_check_once__:\n            if not (is_qemu_system() or is_kgdb() or is_vmware()):\n                if not gdb.current_progspace().filename:\n                    err(\"Missing info about architecture, please set: `file /path/to/target_binary`\")\n                    err(\"If the architecture isn't automatically detected, use: `set architecture YOUR_ARCH`\")\n            EventHandler.__gef_check_once__ = False\n        return\n\n    @staticmethod\n    def new_objfile_handler(_event):\n        \"\"\"GDB event handler for new object file cases.\"\"\"\n        Cache.reset_gef_caches(all=True)\n        if current_arch is None:\n            set_arch(get_arch())\n\n        # delayed breakpoint for brva\n        if BreakRelativeVirtualAddressCommand.delayed_bp_set is False and is_alive():\n            if not (is_qemu_system() or is_kgdb() or is_vmware()):\n                codebase = ProcessMap.get_codebase()\n                if codebase:\n                    for offset in BreakRelativeVirtualAddressCommand.delayed_breakpoints:\n                        gdb.execute(\"b *{:#x}\".format(codebase + offset))\n                    BreakRelativeVirtualAddressCommand.delayed_bp_set = True\n        return\n\n    @staticmethod\n    def exit_handler(_event):\n        \"\"\"GDB event handler for exit cases.\"\"\"\n        Cache.reset_gef_caches(all=True)\n        return\n\n    @staticmethod\n    def memchanged_handler(_event):\n        \"\"\"GDB event handler for mem changes cases.\"\"\"\n        Cache.reset_gef_caches()\n        return\n\n    @staticmethod\n    def regchanged_handler(_event):\n        \"\"\"GDB event handler for reg changes cases.\"\"\"\n        Cache.reset_gef_caches()\n        return\n\n\nclass UnicornKeystoneCapstone:\n    \"\"\"A collection of utility functions that are related to unicorn, keystone, and capstone.\"\"\"\n\n    @staticmethod\n    def get_generic_arch(module, prefix, arch, mode, big_endian, to_string):\n        \"\"\"Retrieve architecture and mode from the arguments for use for the holy\n        capstone/keystone/unicorn trinity.\"\"\"\n        if isinstance(mode, tuple):\n            modes = list(mode)\n        else:\n            modes = [mode]\n\n        if big_endian:\n            modes.append(\"BIG_ENDIAN\")\n        else:\n            modes.append(\"LITTLE_ENDIAN\")\n\n        if to_string:\n            # arch\n            arch = \"{:s}.{:s}_ARCH_{:s}\".format(module.__name__, prefix, arch)\n            # mode\n            tmp = []\n            for m in modes:\n                if not m:\n                    tmp.append(\"0\")\n                else:\n                    tmp.append(\"{:s}.{:s}_MODE_{:s}\".format(module.__name__, prefix, m))\n            mode = \" + \".join(tmp)\n        else:\n            # arch\n            arch = getattr(module, \"{:s}_ARCH_{:s}\".format(prefix, arch))\n            # mode\n            mode = 0\n            for m in modes:\n                if m:\n                    mode |= getattr(module, \"{:s}_MODE_{:s}\".format(prefix, m))\n        return arch, mode\n\n    @staticmethod\n    @ModuleLoader.load_unicorn\n    def get_unicorn_arch(arch=None, mode=None, endian=None, to_string=False):\n        if (arch, mode, endian) == (None, None, None):\n            arch = current_arch.arch\n            mode = current_arch.mode\n            endian = Endian.is_big_endian()\n        if arch is None:\n            arch = current_arch.arch\n        if (arch, mode) == (\"RISCV\", \"32\"):\n            mode = \"RISCV32\"\n        elif (arch, mode) == (\"RISCV\", \"64\"):\n            mode = \"RISCV64\"\n        elif (arch, mode) == (\"PPC\", \"32\"):\n            mode = \"PPC32\"\n        elif (arch, mode) == (\"PPC\", \"64\"):\n            mode = \"PPC64\"\n        elif (arch, mode) == (\"SPARC\", \"32\"):\n            mode = \"SPARC32\"\n        elif (arch, mode) == (\"SPARC\", \"32PLUS\"):\n            mode = \"SPARC32\"\n        elif (arch, mode) == (\"SPARC\", \"64\"):\n            mode = \"SPARC64\"\n        elif (arch, mode) == (\"MIPS\", \"32\"):\n            mode = \"MIPS32\"\n        elif (arch, mode) == (\"MIPS\", \"64\"):\n            mode = \"MIPS64\"\n        elif arch == \"S390X\":\n            mode = None\n        elif arch == \"M68K\":\n            mode = None\n        return UnicornKeystoneCapstone.get_generic_arch(\n            sys.modules[\"unicorn\"], \"UC\", arch, mode, endian, to_string,\n        )\n\n    @staticmethod\n    @ModuleLoader.load_capstone\n    def get_capstone_arch(arch=None, mode=None, endian=None, to_string=False):\n        if (arch, mode, endian) == (None, None, None):\n            arch = current_arch.arch\n            mode = current_arch.mode\n            endian = Endian.is_big_endian()\n        if arch is None:\n            arch = current_arch.arch\n        # hacky patch for applying to capstone's mode\n        if arch == \"ARM64\":\n            if sys.modules[\"capstone\"].cs_version()[0] == 6:\n                arch = \"AARCH64\"\n        elif (arch, mode) == (\"RISCV\", \"32\"):\n            mode = (\"RISCV32\", \"RISCVC\")\n        elif (arch, mode) == (\"RISCV\", \"64\"):\n            mode = (\"RISCV64\", \"RISCVC\")\n        elif (arch, mode) == (\"SPARC\", \"32\"):\n            mode = \"\"\n        elif (arch, mode) == (\"SPARC\", \"32PLUS\"):\n            mode = \"\"\n        elif (arch, mode) == (\"SPARC\", \"64\"):\n            mode = \"V9\"\n        elif (arch, mode) == (\"MIPS\", \"32\"):\n            mode = \"MIPS32\"\n        elif (arch, mode) == (\"MIPS\", \"64\"):\n            mode = \"MIPS64\"\n        elif arch == \"S390X\":\n            if sys.modules[\"capstone\"].cs_version()[0] == 6:\n                arch, mode = \"SYSTEMZ\", None\n            else:\n                arch, mode = \"SYSZ\", None\n        elif arch == \"M68K\":\n            mode = \"M68K_060\"\n        elif (arch, mode) == (\"LOONGARCH\", \"64\"): # capstone v6.x~\n            mode = \"LOONGARCH64\"\n        elif (arch, mode) == (\"LOONGARCH\", \"32\"): # capstone v6.x~\n            mode = \"LOONGARCH32\"\n        elif arch == \"ALPHA\": # capstone v6.x~\n            mode = None\n        elif (arch, mode) == (\"HPPA\", \"64\"): # capstone v6.x~\n            mode = \"HPPA_20\"\n        elif (arch, mode) == (\"HPPA\", \"32\"): # capstone v6.x~\n            mode = \"HPPA_11\"\n        return UnicornKeystoneCapstone.get_generic_arch(\n            sys.modules[\"capstone\"], \"CS\", arch, mode, endian, to_string,\n        )\n\n    @staticmethod\n    @ModuleLoader.load_keystone\n    def get_keystone_arch(arch=None, mode=None, endian=None, to_string=False):\n        if (arch, mode, endian) == (None, None, None):\n            arch = current_arch.arch\n            mode = current_arch.mode\n            endian = Endian.is_big_endian()\n        if arch is None:\n            arch = current_arch.arch\n        # hacky patch for applying to capstone's mode\n        if arch == \"ARM64\":\n            mode = None\n        elif (arch, mode) == (\"PPC\", \"32\"):\n            mode = \"PPC32\"\n        elif (arch, mode) == (\"PPC\", \"64\"):\n            mode = \"PPC64\"\n        elif (arch, mode) == (\"SPARC\", \"32\"):\n            mode = \"SPARC32\"\n        elif (arch, mode) == (\"SPARC\", \"32PLUS\"):\n            mode = \"SPARC32\"\n        elif (arch, mode) == (\"SPARC\", \"64\"):\n            mode = \"SPARC64\"\n        elif (arch, mode) == (\"MIPS\", \"32\"):\n            mode = \"MIPS32\"\n        elif (arch, mode) == (\"MIPS\", \"64\"):\n            mode = \"MIPS64\"\n        elif arch == \"S390X\":\n            arch, mode = \"SYSTEMZ\", None\n        return UnicornKeystoneCapstone.get_generic_arch(\n            sys.modules[\"keystone\"], \"KS\", arch, mode, endian, to_string,\n        )\n\n    @staticmethod\n    @ModuleLoader.load_unicorn\n    def get_unicorn_registers(to_string=False, add_sse=False):\n        \"Return a dict matching the Unicorn identifier for a specific register.\"\n        unicorn = sys.modules[\"unicorn\"]\n        regs = {}\n\n        if current_arch is not None:\n            arch = current_arch.arch.lower()\n        else:\n            raise OSError(\"Oops\")\n\n        const = getattr(unicorn, \"{}_const\".format(arch))\n\n        extra_regs = []\n        if add_sse:\n            if is_x86():\n                extra_regs = [\"$xmm{:d}\".format(i) for i in range(16)]\n        if is_arm64():\n            extra_regs = [\"$tpidr_el0\"] # for tls\n        if is_arm32():\n            extra_regs = [\"$c13_c0_3\"] # for tls\n\n        for reg in current_arch.all_registers + extra_regs:\n            if arch == \"ppc\" and reg.startswith(\"$r\"):\n                regname = \"UC_{:s}_REG_{:s}\".format(arch.upper(), reg.lstrip(\"$r\").upper())\n            elif arch == \"arm64\" and reg == \"$cpsr\":\n                regname = \"UC_ARM64_REG_PSTATE\"\n            else:\n                regname = \"UC_{:s}_REG_{:s}\".format(arch.upper(), reg.lstrip(\"$\").upper())\n            try:\n                getattr(const, regname)\n            except AttributeError:\n                continue\n            if to_string:\n                regs[reg] = \"{:s}.{:s}\".format(const.__name__, regname)\n            else:\n                regs[reg] = getattr(const, regname)\n        return regs\n\n    @staticmethod\n    @ModuleLoader.load_keystone\n    def keystone_assemble(code, arch, mode, *args, **kwargs):\n        \"\"\"Assembly encoding function based on keystone.\"\"\"\n        import multiprocessing\n        keystone = sys.modules[\"keystone\"]\n        code = String.str2bytes(code)\n        addr = kwargs.get(\"addr\", 0x1000)\n\n        # `asm \"[]\"` returns no response\n        @timeout(duration=1)\n        def ks_asm(code, addr):\n            return ks.asm(code, addr)\n\n        try:\n            ks = keystone.Ks(arch, mode)\n            enc, cnt = ks_asm(code, addr)\n        except keystone.KsError as e:\n            err(\"Keystone assembler error: {!s}\".format(e))\n            return None\n        except multiprocessing.TimeoutError:\n            err(\"Keystone assembler timeout error\")\n            return None\n\n        if cnt == 0:\n            return \"\"\n\n        enc = bytearray(enc)\n        if \"raw\" not in kwargs:\n            s = binascii.hexlify(enc)\n            enc = b\"\\\\x\" + b\"\\\\x\".join([s[i : i + 2] for i in range(0, len(s), 2)])\n            enc = enc.decode(\"utf-8\")\n\n        return enc\n\n\ndef is_64bit():\n    \"\"\"GDB mode determination function for 64-bit architecture.\"\"\"\n    return AddressUtil.ptr_width() == 8\n\n\ndef is_32bit():\n    \"\"\"GDB mode determination function for 32-bit architecture.\"\"\"\n    return AddressUtil.ptr_width() == 4\n\n\ndef is_emulated32():\n    \"\"\"GDB mode determination function for 32-bit architecture on 64-bit environment.\"\"\"\n    if is_64bit():\n        return False\n\n    if is_qemu_user():\n        # This case cannot be determined\n        return False\n\n    if is_qemu_system():\n        # corner case (e.g., using qemu-system-x86_64, but process is executed as 32bit mode)\n        # is not able to be detected\n        return True\n\n    for m in ProcessMap.get_process_maps():\n        # native x86:\n        # 0xbffdf000 0xc0000000 0x021000 0x000000 rw- [stack]\n        # emulated x86 on x86_64\n        # 0xfffdd000 0xffffe000 0x021000 0x000000 rw- [stack]\n        # native arm:\n        # 0xbefdf000 0xbf000000 0x021000 0x000000 rw- [stack]\n        # emulated arm on aarch64\n        # 0xfffcf000 0xffff0000 0x021000 0x000000 rw- [stack]\n        if m.path == \"[stack]\":\n            return (m.page_start >> 28) == 0xf\n    else:\n        return False # by default it considers on native\n\n\ndef is_x86_64():\n    \"\"\"Architecture determination function for x86-64.\"\"\"\n    return current_arch and current_arch.arch == \"X86\" and current_arch.mode == \"64\"\n\n\ndef is_x86_32():\n    \"\"\"Architecture determination function for x86-32.\"\"\"\n    return current_arch and current_arch.arch == \"X86\" and current_arch.mode == \"32\"\n\n\ndef is_x86_16():\n    \"\"\"Architecture determination function for x86-16.\"\"\"\n    return current_arch and current_arch.arch == \"X86\" and current_arch.mode == \"16\"\n\n\ndef is_x86():\n    \"\"\"Architecture determination function for x86-32 or x86-64 or x86_16.\"\"\"\n    return is_x86_32() or is_x86_64() or is_x86_16()\n\n\ndef is_arm32():\n    \"\"\"Architecture determination function for ARM 32 bit (Cortex-A).\"\"\"\n    return current_arch and current_arch.arch == \"ARM\" and not current_arch.is_cortex_m()\n\n\ndef is_arm32_cortex_m():\n    \"\"\"Architecture determination function for ARM 32 bit (Cortex-M).\"\"\"\n    return current_arch and current_arch.arch == \"ARM\" and current_arch.is_cortex_m()\n\n\ndef is_arm64():\n    \"\"\"Architecture determination function for ARM 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"ARM64\"\n\n\ndef is_mips32():\n    \"\"\"Architecture determination function for mips 32 bit (o32 ABI).\"\"\"\n    return current_arch and current_arch.arch == \"MIPS\" and current_arch.mode == \"32\"\n\n\ndef is_mips64():\n    \"\"\"Architecture determination function for mips 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"MIPS\" and current_arch.mode == \"64\"\n\n\ndef is_mipsn32():\n    \"\"\"Architecture determination function for mips 32 bit (n32 ABI).\"\"\"\n    return current_arch and current_arch.arch == \"MIPS\" and current_arch.mode == \"n32\"\n\n\ndef is_ppc32():\n    \"\"\"Architecture determination function for powerpc 32 bit.\"\"\"\n    return current_arch and current_arch.arch == \"PPC\" and current_arch.mode == \"32\"\n\n\ndef is_ppc64():\n    \"\"\"Architecture determination function for powerpc 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"PPC\" and current_arch.mode == \"64\"\n\n\ndef is_sparc32():\n    \"\"\"Architecture determination function for sparc 32 bit.\"\"\"\n    return current_arch and current_arch.arch == \"SPARC\" and current_arch.mode == \"32\"\n\n\ndef is_sparc32plus():\n    \"\"\"Architecture determination function for sparc 32 bit (v8+).\"\"\"\n    return current_arch and current_arch.arch == \"SPARC\" and current_arch.mode == \"32PLUS\"\n\n\ndef is_sparc64():\n    \"\"\"Architecture determination function for sparc 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"SPARC\" and current_arch.mode == \"64\"\n\n\ndef is_riscv32():\n    \"\"\"Architecture determination function for RISC-V 32 bit.\"\"\"\n    return current_arch and current_arch.arch == \"RISCV\" and current_arch.mode == \"32\"\n\n\ndef is_riscv64():\n    \"\"\"Architecture determination function for RISC-V 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"RISCV\" and current_arch.mode == \"64\"\n\n\ndef is_s390x():\n    \"\"\"Architecture determination function for s390x.\"\"\"\n    return current_arch and current_arch.arch == \"S390X\"\n\n\ndef is_sh4():\n    \"\"\"Architecture determination function for sh4.\"\"\"\n    return current_arch and current_arch.arch == \"SH4\"\n\n\ndef is_m68k():\n    \"\"\"Architecture determination function for m68k.\"\"\"\n    return current_arch and current_arch.arch == \"M68K\"\n\n\ndef is_alpha():\n    \"\"\"Architecture determination function for alpha.\"\"\"\n    return current_arch and current_arch.arch == \"ALPHA\"\n\n\ndef is_hppa32():\n    \"\"\"Architecture determination function for HP-PA 32 bit.\"\"\"\n    return current_arch and current_arch.arch == \"HPPA\" and current_arch.mode == \"32\"\n\n\ndef is_hppa64():\n    \"\"\"Architecture determination function for HP-PA 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"HPPA\" and current_arch.mode == \"64\"\n\n\ndef is_or1k():\n    \"\"\"Architecture determination function for OpenRISC 1000.\"\"\"\n    return current_arch and current_arch.arch == \"OR1K\"\n\n\ndef is_nios2():\n    \"\"\"Architecture determination function for Nios II.\"\"\"\n    return current_arch and current_arch.arch == \"NIOS2\"\n\n\ndef is_microblaze():\n    \"\"\"Architecture determination function for Microblaze.\"\"\"\n    return current_arch and current_arch.arch == \"MICROBLAZE\"\n\n\ndef is_xtensa():\n    \"\"\"Architecture determination function for Xtensa.\"\"\"\n    return current_arch and current_arch.arch == \"XTENSA\"\n\n\ndef is_cris():\n    \"\"\"Architecture determination function for CRIS.\"\"\"\n    return current_arch and current_arch.arch == \"CRIS\"\n\n\ndef is_loongarch64():\n    \"\"\"Architecture determination function for Loongarch 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"LOONGARCH\" and current_arch.mode == \"64\"\n\n\ndef is_arc32():\n    \"\"\"Architecture determination function for ARC 32 bit.\"\"\"\n    return current_arch and current_arch.arch == \"ARC\" and current_arch.mode in [\"32v2\", \"32v3\"]\n\n\ndef is_arc64():\n    \"\"\"Architecture determination function for ARC 64 bit.\"\"\"\n    return current_arch and current_arch.arch == \"ARC\" and current_arch.mode == \"64v3\"\n\n\ndef is_csky():\n    \"\"\"Architecture determination function for csky.\"\"\"\n    return current_arch and current_arch.arch == \"CSKY\"\n\n\n@Cache.cache_until_next\ndef get_arch():\n    \"\"\"Return the binary's architecture.\"\"\"\n    if is_alive():\n        try:\n            arch = gdb.selected_frame().architecture()\n            name = arch.name()\n            # check i386 or i8086\n            if name != \"i386\":\n                return name\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            # Resolve by moving to the slow path.\n            pass\n\n    # slow path\n    arch_str = gdb.execute(\"show architecture\", to_string=True).strip()\n\n    # The target architecture is set automatically (currently i386)\n    # The target architecture is set to \"auto\" (currently \"i386\").\n    # The target architecture is assumed to be mips\n    # The target architecture is set to \"mips\".\n\n    if \"The target architecture is set automatically (currently \" in arch_str:\n        arch_str = arch_str.split(\"(currently \", 1)[1]\n        arch_str = arch_str.split(\")\", 1)[0]\n    elif 'The target architecture is set to \"auto\" (currently \"' in arch_str:\n        arch_str = arch_str.split('(currently \"', 1)[1]\n        arch_str = arch_str.split('\")', 1)[0]\n    elif \"The target architecture is assumed to be \" in arch_str:\n        arch_str = arch_str.replace(\"The target architecture is assumed to be \", \"\")\n    elif \"The target architecture is set to \" in arch_str:\n        arch_str = arch_str.split('\"')[1]\n    else:\n        # Unknown, we throw an exception to be safe\n        raise RuntimeError(\"Unknown architecture: {}\".format(arch_str))\n    return arch_str\n\n\ndef set_arch(arch_str=None):\n    \"\"\"Set the current architecture.\n    If an arch is explicitly specified, use that one, otherwise try to parse it out of the current target.\n    If that fails, and default is specified, select and set that arch.\n    Return the selected arch, or raise an OSError.\"\"\"\n    global current_arch\n\n    # get defined arch\n    arches = {}\n    queue = Architecture.__subclasses__()\n    while queue:\n        cls = queue.pop(0)\n        for lc in cls.load_condition:\n            arches[lc] = cls\n        queue.extend(cls.__subclasses__())\n\n    # Determined from the specified arch string\n    if arch_str:\n        key = arch_str.upper()\n\n    else:\n        # Determined from loaded ELF\n        elf = Elf.get_elf()\n        if elf is None or not elf.is_valid():\n            raise OSError(\"Could not determine architecture.\")\n\n        if elf.e_machine not in [Elf.EM_MIPS, Elf.EM_RISCV, Elf.EM_PARISC]:\n            key = elf.e_machine\n\n        else:\n            # On some architectures, it is not possible to determine whether it is 32-bit or 64-bit\n            # from the ELF header e_machine. so we use the detection result of gdb.\n            key = get_arch().upper()\n\n    # Even if it is determined to be MIPS64, if it is in 32-bit mode, it is n32.\n    if key in MIPS64.load_condition and is_32bit():\n        key = \"MIPSN32\"\n\n    if key not in arches:\n        err(\"Specified arch {!s} is not supported\".format(key))\n        info(\"A generic mode with minimal functionality will be applied\")\n        return\n\n    current_arch = arches[key]()\n    Cache.reset_gef_caches(all=True)\n    return\n\n\nclass Auxv:\n    \"\"\"A collection of utility functions that are related to ELF Auxiliary Vectors.\"\"\"\n\n    @staticmethod\n    def get_auxiliary_walk(offset=0):\n        \"\"\"Find AUXV by walking stack.\"\"\"\n\n        if Config.get_gef_setting(\"context.disable_auxv\"):\n            return None\n\n        if current_arch.sp is None:\n            return None\n\n        if is_in_kernel():\n            return None\n\n        # do not use get_pagesize(), get_pagesize_mask_high(), etc.\n        # because get_pagesize() -> Auxv.get_auxiliary_values() -> Auxv.get_auxiliary_walk()\n        page_size = 0x1000\n        addr = current_arch.sp & ~(page_size - 1)\n\n        # check readable or not\n        if not is_valid_addr(addr):\n            return None\n\n        # find stack bottom\n        try:\n            while True:\n                if b\"\\x7fELF\" == read_memory(addr, 4):\n                    break\n                addr += page_size\n        except gdb.MemoryError: # if read error, that is stack bottom\n            pass\n        current = addr - current_arch.ptrsize * 2 - offset\n\n        # check readable or not again\n        if not is_valid_addr(current):\n            # something is wrong, maybe stack is pivoted\n            return None\n\n        # find auxv end\n        while True:\n            a = read_int_from_memory(current)\n            b = read_int_from_memory(current + current_arch.ptrsize)\n            if a == b == 0:\n                break\n            current -= current_arch.ptrsize * 2\n\n        # skip dummy null if exist\n        for _ in range(1024):\n            a = read_int_from_memory(current)\n            if a == 7: # AT_BASE\n                break\n            current -= current_arch.ptrsize * 2\n        else:\n            return None\n\n        # find auxv start\n        auxv_keys = AuxvCommand.AT_CONSTANTS.keys()\n        while read_int_from_memory(current) in auxv_keys:\n            current -= current_arch.ptrsize * 2\n        current += current_arch.ptrsize * 2\n\n        # parse auxv\n        res = {}\n        while True:\n            key = read_int_from_memory(current)\n            val = read_int_from_memory(current + current_arch.ptrsize)\n            if key not in AuxvCommand.AT_CONSTANTS:\n                break\n            res[AuxvCommand.AT_CONSTANTS[key]] = val\n            if key == 0:\n                break\n            current += current_arch.ptrsize * 2\n\n        # test\n        if \"AT_ENTRY\" not in res:\n            return None\n        if \"AT_PHDR\" not in res:\n            return None\n        if \"AT_RANDOM\" not in res:\n            return None\n        if \"AT_BASE\" not in res:\n            return None\n        if \"AT_NULL\" not in res:\n            return None\n\n        return res\n\n    # Auxv.get_auxiliary_values (under qemu-user mode) is very slow,\n    # Because it may call Auxv.get_auxiliary_walk that repeats read_memory many times to find the auxv value.\n    # Cache.cache_until_next is ineffective due to frequent resets (each time the `stepi` runs).\n    # Fortunately, auxv rarely changes.\n    # The cache is retained until explicitly cleared.\n    @staticmethod\n    @Cache.cache_this_session\n    def get_auxiliary_values(force_heuristic=False):\n        \"\"\"Retrieve the auxiliary values of the current execution.\n        Return None if not running, or a dict() of values.\"\"\"\n\n        if Config.get_gef_setting(\"context.disable_auxv\"):\n            return None\n\n        if not is_alive():\n            return None\n\n        if is_in_kernel():\n            return None\n\n        if is_qemu_system() or is_kgdb() or is_vmware() or is_wine():\n            return None\n\n        def fast_path():\n            try:\n                result = gdb.execute(\"info auxv\", to_string=True)\n            except gdb.error:\n                return None\n            res = {}\n            for line in result.splitlines():\n                tmp = line.split()\n                auxv_type = tmp[1]\n                if auxv_type in (\"AT_PLATFORM\", \"AT_EXECFN\", \"AT_BASE_PLATFORM\"):\n                    m = re.match(\"^.+?(0x[0-9a-f]+)\", line)\n                    res[auxv_type] = int(m.group(1), 0)\n                else:\n                    res[auxv_type] = int(tmp[-1], 0)\n            return res\n\n        def slow_path():\n            if current_arch is None:\n                return None\n            for offset in [0, current_arch.ptrsize]:\n                res = Auxv.get_auxiliary_walk(offset)\n                if res:\n                    return res\n            return None\n\n        # ----\n\n        if force_heuristic:\n            return slow_path()\n\n        return fast_path() or slow_path()\n\n\n@Cache.cache_this_session\ndef get_pagesize():\n    \"\"\"Get the page size from auxiliary values.\"\"\"\n    auxval = Auxv.get_auxiliary_values()\n    if not auxval or \"AT_PAGESZ\" not in auxval:\n        return 0x1000\n    return auxval[\"AT_PAGESZ\"]\n\n\n@Cache.cache_this_session\ndef get_pagesize_mask_low():\n    \"\"\"Get the page size mask from auxiliary values.\"\"\"\n    auxval = Auxv.get_auxiliary_values()\n    if not auxval or \"AT_PAGESZ\" not in auxval:\n        return 0xfff\n    return auxval[\"AT_PAGESZ\"] - 1\n\n\n@Cache.cache_this_session\ndef get_pagesize_mask_high():\n    \"\"\"Get the page size mask from auxiliary values.\"\"\"\n    auxval = Auxv.get_auxiliary_values()\n    if not auxval or \"AT_PAGESZ\" not in auxval:\n        return ~0xfff\n    return ~(auxval[\"AT_PAGESZ\"] - 1)\n\n\ndef only_if_events_supported(event_type):\n    \"\"\"Decorator for checking if GDB supports events without crashing.\"\"\"\n\n    def wrap(f):\n\n        def wrapped_f(*args, **kwargs):\n            if hasattr(gdb.events, event_type):\n                return f(*args, **kwargs)\n            warn(\"GDB events cannot be set\")\n\n        return wrapped_f\n\n    return wrap\n\n\nclass EventHooking:\n    \"\"\"A collection of utility functions that hook up specified events.\"\"\"\n\n    @staticmethod\n    @only_if_events_supported(\"cont\")\n    def gef_on_continue_hook(func):\n        return gdb.events.cont.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"cont\")\n    def gef_on_continue_unhook(func):\n        return gdb.events.cont.disconnect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"stop\")\n    def gef_on_stop_hook(func):\n        return gdb.events.stop.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"stop\")\n    def gef_on_stop_unhook(func):\n        return gdb.events.stop.disconnect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"exited\")\n    def gef_on_exit_hook(func):\n        return gdb.events.exited.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"exited\")\n    def gef_on_exit_unhook(func):\n        return gdb.events.exited.disconnect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"new_objfile\")\n    def gef_on_new_hook(func):\n        return gdb.events.new_objfile.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"new_objfile\")\n    def gef_on_new_unhook(func):\n        return gdb.events.new_objfile.disconnect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"memory_changed\")\n    def gef_on_memchanged_hook(func):\n        return gdb.events.memory_changed.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"memory_changed\")\n    def gef_on_memchanged_unhook(func):\n        return gdb.events.memory_changed.disconnect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"register_changed\")\n    def gef_on_regchanged_hook(func):\n        return gdb.events.register_changed.connect(func)\n\n    @staticmethod\n    @only_if_events_supported(\"register_changed\")\n    def gef_on_regchanged_unhook(func):\n        return gdb.events.register_changed.disconnect(func)\n\n\n#\n# Commands\n#\n\n\ndef register_command(cls):\n    \"\"\"Decorator for registering new GEF (sub-)command to GDB.\"\"\"\n    global __gef_commands__\n    __gef_commands__.append(cls)\n    return cls\n\n\ndef register_priority_command(cls):\n    \"\"\"Decorator for registering new command with priority, meaning that it must\n    loaded before the other generic commands.\"\"\"\n    global __gef_commands__\n    __gef_commands__.insert(0, cls)\n    return cls\n\n\nclass GenericCommand(gdb.Command):\n    \"\"\"This is an abstract class for invoking commands, should not be instantiated.\"\"\"\n\n    __metaclass__ = abc.ABCMeta\n\n    @property\n    @abc.abstractmethod\n    def _cmdline_(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def _syntax_(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def _example_(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def _note_(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def _repeat_(self):\n        pass\n\n    @property\n    @abc.abstractmethod\n    def _aliases_(self):\n        pass\n\n    @abc.abstractmethod\n    def do_invoke(self, argv):\n        pass\n\n    def __init__(self, *args, **kwargs):\n\n        def tab(lines):\n            return \"\\n\".join([\"  \" + line for line in lines.splitlines()])\n\n        self.__doc__ += \"\\n\"\n\n        if self._syntax_:\n            self.__doc__ += \"\\n\"\n            self.__doc__ += Color.colorify(\"Syntax:\", \"bold yellow\")\n            self.__doc__ += \"\\n\"\n            self.__doc__ += self._syntax_.strip()\n            self.__doc__ += \"\\n\"\n\n        if self._example_:\n            self.__doc__ += \"\\n\"\n            self.__doc__ += Color.colorify(\"Example:\", \"bold yellow\")\n            self.__doc__ += \"\\n\"\n            self.__doc__ += tab(self._example_.strip())\n            self.__doc__ += \"\\n\"\n\n        if self._note_:\n            self.__doc__ += \"\\n\"\n            self.__doc__ += Color.colorify(\"Note:\", \"bold yellow\")\n            self.__doc__ += \"\\n\"\n            self.__doc__ += tab(self._note_.strip())\n            self.__doc__ += \"\\n\"\n\n        if hasattr(self._aliases_, \"__iter__\") and self._aliases_:\n            self.__doc__ += \"\\n\"\n            self.__doc__ += Color.colorify(\"Aliases:\", \"bold yellow\")\n            self.__doc__ += \"\\n\"\n            self.__doc__ += tab(str(self._aliases_))\n            self.__doc__ += \"\\n\"\n\n        self.repeat_count = 0\n        self.last_command = None\n\n        command_type = kwargs.get(\"command\", gdb.COMMAND_NONE)\n        complete_type = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        prefix = kwargs.get(\"prefix\", False)\n\n        if complete_type == \"use_user_complete\":\n            super().__init__(self._cmdline_, command_type, prefix=prefix)\n        else:\n            super().__init__(self._cmdline_, command_type, complete_type, prefix)\n        return\n\n    def invoke(self, args, from_tty): # noqa\n        try:\n            argv = gdb.string_to_argv(args)\n            if self._repeat_:\n                self.set_repeat_count(argv, from_tty)\n            else:\n                self.dont_repeat()\n            self.do_invoke(argv)\n        except Exception:\n            # Since we are intercepting cleaning exceptions here, commands preferably should avoid\n            # catching generic Exception, but rather specific ones. This is allows a much cleaner use.\n            GefUtil.show_last_exception()\n        return\n\n    def usage(self, simple=False, after_syntax_only=False):\n\n        def tab(lines):\n            return \"\\n\".join([\"  \" + line for line in lines.splitlines()])\n\n        if not after_syntax_only:\n            gef_print(Color.colorify(\"Syntax:\", \"bold yellow\"))\n            gef_print(self._syntax_.strip())\n\n        if self._example_:\n            gef_print(\"\")\n            gef_print(Color.colorify(\"Example:\", \"bold yellow\"))\n            gef_print(tab(self._example_.strip()))\n\n        if self._note_:\n            if not simple:\n                gef_print(\"\")\n                gef_print(Color.colorify(\"Note:\", \"bold yellow\"))\n                gef_print(tab(self._note_.strip()))\n\n        if self._aliases_:\n            gef_print(\"\")\n            gef_print(Color.colorify(\"Aliases:\", \"bold yellow\"))\n            gef_print(\"  \" + str(self._aliases_))\n\n        this_command_key = self._cmdline_.replace(\"-\", \"_\").replace(\" \", \"_\").split()\n        configs = [k for k in Config.__gef_config__.keys() if k.split(\".\")[:-1] == this_command_key]\n        if configs:\n            gef_print(\"\")\n            gef_print(Color.colorify(\"Configs:\", \"bold yellow\"))\n            max_width = max(len(x) for x in configs)\n            for key in configs:\n                value, _types, desc = Config.__gef_config__[key]\n                gef_print(\"  {:{:d}} : {:s} [{}]\".format(key, max_width, desc, value))\n        return\n\n    def add_setting(self, name, value, description=\"\"):\n        # make sure settings are always associated to the root command\n        # which derives from GenericCommand directly.\n        if \"GenericCommand\" not in [x.__name__ for x in self.__class__.__bases__]:\n            return\n\n        # sanitize\n        class_name = self.__class__._cmdline_\n        class_name = class_name.replace(\" \", \"_\")\n        # gdb's user complete feature does not work well if \"-\" is included.\n        class_name = class_name.replace(\"-\", \"_\")\n\n        # add\n        key = \"{:s}.{:s}\".format(class_name, name)\n        Config.__gef_config__[key] = [value, type(value), description]\n        Config.__gef_config_orig__[key] = [value, type(value), description] # for debugging\n\n        # reset cache\n        Cache.reset_gef_caches()\n        return\n\n    def set_repeat_count(self, argv, from_tty):\n        if not from_tty:\n            self.repeat_count = 0\n            return\n\n        command = gdb.execute(\"show commands\", to_string=True).strip().split(\"\\n\")[-1]\n        self.repeat_count = self.repeat_count + 1 if self.last_command == command else 0\n        self.last_command = command\n        return\n\n    def quiet_print(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            gef_print(msg)\n        return\n\n    def quiet_ok(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            ok(msg)\n        return\n\n    def quiet_info(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            info(msg)\n        return\n\n    def quiet_warn(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            warn(msg)\n        return\n\n    def quiet_err(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            err(msg)\n        return\n\n    def verbose_info(self, msg):\n        if hasattr(self.args, \"verbose\") and self.args.verbose:\n            info(msg)\n        return\n\n    def verbose_err(self, msg):\n        if hasattr(self.args, \"verbose\") and self.args.verbose:\n            err(msg)\n        return\n\n\nclass BufferingOutput:\n    \"\"\"A collection of utility functions that append a messages to self.out.\"\"\"\n\n    def info_add_out(self, msg):\n        msg = \"{} {}\".format(Color.colorify(\"[+]\", \"bold blue\"), msg)\n        self.out.append(msg)\n        return\n\n    def warn_add_out(self, msg):\n        msg = \"{} {}\".format(Color.colorify(\"[*]\", \"bold yellow\"), msg)\n        self.out.append(msg)\n        return\n\n    def err_add_out(self, msg):\n        msg = \"{} {}\".format(Color.colorify(\"[!]\", \"bold red\"), msg)\n        self.out.append(msg)\n        return\n\n    def quiet_info_add_out(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            msg = \"{} {}\".format(Color.colorify(\"[+]\", \"bold blue\"), msg)\n            self.out.append(msg)\n        return\n\n    def quiet_add_out(self, msg):\n        if not hasattr(self.args, \"quiet\") or not self.args.quiet:\n            self.out.append(msg)\n        return\n\n    def verbose_add_out(self, msg):\n        if hasattr(self.args, \"verbose\") and self.args.verbose:\n            self.out.append(msg)\n        return\n\n    def print_output(self, check_terminal_size=False, skip_color=False):\n        if not hasattr(self, \"out\"):\n            return\n        if not self.out:\n            return\n\n        def do_check_term_size(lines):\n            # rough check\n            t_height, t_width = GefUtil.get_terminal_size()\n            if len(lines) > t_height:\n                return not self.args.no_pager\n\n            # detailed check\n            h = 0\n            for element in lines:\n                for line in element.splitlines():\n                    line = Color.remove_color(line)\n                    h += (len(line) // t_width) + 1\n                    if h > t_height:\n                        return not self.args.no_pager\n            return False\n\n        if not check_terminal_size:\n            less = not self.args.no_pager\n        else:\n            less = do_check_term_size(self.out)\n\n        gef_print(\"\\n\".join(self.out), less=less, skip_color=skip_color)\n        return\n\n\n# Copy/paste this template for new command\n# @register_command\n# class TemplateCommand(GenericCommand):\n#     \"\"\"TemplateCommand: description here will be seen in the help menu for the command.\"\"\"\n#\n#     _cmdline_ = \"template-fake\"\n#     _category_ = \"99. GEF Maintenance Command\"\n#     _aliases_ = [\"tpl-fk\"]\n#\n#     parser = argparse.ArgumentParser(prog=_cmdline_)\n#     _syntax_ = parser.format_help()\n#\n#     _example_ = \"...\"\n#     _note_ = \"...\"\n#\n#     def __init__(self):\n#         super().__init__(complete=gdb.COMPLETE_FILENAME)\n#         return\n#\n#     @parse_args\n#     def do_invoke(self, args):\n#         return\n\n\n@register_priority_command\nclass GefThemeCommand(GenericCommand, BufferingOutput):\n    \"\"\"Customize GEF appearance.\"\"\"\n\n    _cmdline_ = \"theme\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"key\", metavar=\"KEY\", nargs=\"?\", help=\"color theme key.\")\n    parser.add_argument(\"value\", metavar=\"VALUE\", nargs=\"*\", help=\"color theme value.\")\n    parser.add_argument(\"-c\", \"--color-sample\", action=\"store_true\", help=\"print available name of colors.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                         # show all theme settings\",\n        \"{0:s} address_code            # show specified theme setting\",\n        \"{0:s} address_code bold cyan  # set new theme\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        'GDB 17 do not allow multiple color specifications (such as \"bold red\"). This bug had fixed in GDB 18.',\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__()\n        self.add_setting(\"context_title_line\", \"cyan\", \"Color of the borders in context window\")\n        self.add_setting(\"context_title_message\", \"cyan\", \"Color of the title in context window\")\n        self.add_setting(\"default_title_line\", \"cyan\", \"Default color of borders\")\n        self.add_setting(\"default_title_message\", \"cyan\", \"Default color of title\")\n        self.add_setting(\"table_heading\", \"bold blue\", \"Color of the column headings to tables (e.g., vmmap)\")\n        self.add_setting(\"context_code_past\", \"bright_black\", \"Color to display past code\")\n        self.add_setting(\"context_code_future\", \"\", \"Color to display future code\")\n        self.add_setting(\"disassemble_address\", \"\", \"Color of address when disassembling\")\n        self.add_setting(\"disassemble_address_highlight\", \"bold green\", \"Color of address when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_opcode\", \"white\", \"Color of location when disassembling\")\n        self.add_setting(\"disassemble_opcode_highlight\", \"bold white\", \"Color of location when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_mnemonic_normal\", \"yellow\", \"Color of normal mnemonic when disassembling\")\n        self.add_setting(\"disassemble_mnemonic_normal_highlight\", \"bold bright_yellow\",\n                         \"Color of normal mnemonic when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_mnemonic_branch\", \"bold bright_yellow\", \"Color of branch mnemonic when disassembling\")\n        self.add_setting(\"disassemble_mnemonic_branch_highlight\", \"bold bright_yellow\",\n                         \"Color of branch mnemonic when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_operands_normal\", \"cyan\", \"Color of normal operands when disassembling\")\n        self.add_setting(\"disassemble_operands_normal_highlight\", \"bold cyan\",\n                         \"Color of normal operands when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_operands_const\", \"bright_blue\", \"Color of const operands when disassembling\")\n        self.add_setting(\"disassemble_operands_const_highlight\", \"bold bright_blue\",\n                         \"Color of const operands when disassembling (=$pc)\")\n        self.add_setting(\"disassemble_operands_symbol\", \"white\", \"Color of symbol operands when disassembling)\")\n        self.add_setting(\"disassemble_operands_symbol_highlight\", \"bold white\",\n                         \"Color of symbol operands when disassembling (=$pc)\")\n        self.add_setting(\"dereference_string\", \"yellow\", \"Color of dereferenced string\")\n        self.add_setting(\"dereference_base_address\", \"cyan\", \"Color of dereferenced address\")\n        self.add_setting(\"dereference_register_value\", \"bold blue\", \"Color of dereferenced register\")\n        self.add_setting(\"registers_register_name\", \"blue\", \"Color of the register name in the register window\")\n        self.add_setting(\"registers_value_changed\", \"bold red\", \"Color of the changed register in the register window\")\n        self.add_setting(\"address_stack\", \"magenta\", \"Color to use when a stack address is found\")\n        self.add_setting(\"address_heap\", \"bright_blue\", \"Color to use when a heap address is found\")\n        self.add_setting(\"address_code\", \"red\", \"Color to use when a code address is found\")\n        self.add_setting(\"address_writable\", \"green\", \"Color to use when a writable address is found\")\n        self.add_setting(\"address_readonly\", \"white\", \"Color to use when a read-only address is found\")\n        self.add_setting(\"address_rwx\", \"underline\", \"Color to use when a RWX address is found\")\n        self.add_setting(\"address_valid_but_none\", \"bright_black\", \"Color to use when a --- address is found\")\n        self.add_setting(\"source_current_line\", \"bold green\", \"Color to use for the current code line in the source window\")\n        self.add_setting(\"heap_arena_label\", \"bold cyan underline\", \"Color of the arena label used heap\")\n        self.add_setting(\"heap_chunk_label\", \"bold cyan underline\", \"Color of the chunk label used heap\")\n        self.add_setting(\"heap_label_active\", \"bold green underline\", \"Color of the (active) label used heap\")\n        self.add_setting(\"heap_label_inactive\", \"bold red underline\", \"Color of the (inactive) label used heap\")\n        self.add_setting(\"heap_chunk_address_used\", \"bright_black\", \"Color of the chunk address used heap\")\n        self.add_setting(\"heap_chunk_address_freed\", \"bold yellow\", \"Color of the freed chunk address used heap\")\n        self.add_setting(\"heap_chunk_used\", \"bright_black\", \"Color of the used chunk used heap\")\n        self.add_setting(\"heap_chunk_freed\", \"yellow\", \"Color of the freed chunk used heap\")\n        self.add_setting(\"heap_chunk_size\", \"bold magenta\", \"Color of the size used heap\")\n        self.add_setting(\"heap_chunk_flag_prev_inuse\", \"bold red\", \"Color of the prev_in_use flag used heap\")\n        self.add_setting(\"heap_chunk_flag_non_main_arena\", \"bold yellow\", \"Color of the non_main_arena flag used heap\")\n        self.add_setting(\"heap_chunk_flag_is_mmapped\", \"bold blue\", \"Color of the is_mmapped flag used heap\")\n        self.add_setting(\"heap_freelist_hint\", \"bold blue\", \"Color of the freelist hint used heap\")\n        self.add_setting(\"heap_page_address\", \"bold\", \"Color of the page address used heap\")\n        self.add_setting(\"heap_management_address\", \"bright_blue\", \"Color of the management address used heap\")\n        self.add_setting(\"heap_corrupted_msg\", \"bold red\", \"Color of the corrupted message used heap\")\n        return\n\n    def show_all_config(self):\n        self.out.append(titlify(\"settings\"))\n\n        settings = []\n        for x in Config.__gef_config__:\n            if x.startswith(\"theme.\"):\n                settings.append(x.split(\".\", 1)[1])\n\n        for setting in sorted(settings):\n            value = Config.get_gef_setting(\"theme.{:s}\".format(setting))\n            if value:\n                value = Color.colorify(value, value)\n                self.out.append(\"{:40s}: {:s}\".format(setting, value))\n            else:\n                self.out.append(\"{:40s}: {:s}\".format(setting, \"None\"))\n        return\n\n    def show_color_sample(self):\n\n        def list_all_color_sample(mod):\n            i = 0\n            line = \"\"\n            for k, v in Color.colors.items():\n                if k.endswith(\"_off\") or k == \"normal\":\n                    continue\n                line += (\"{}{:20s}{}  \".format(mod + v, k, Color.colors[\"normal\"]))\n\n                if k in [\"blink\", \"cyan\", \"bright_white\", \"_black\"]: # group terminators\n                    self.out.append(line)\n                    line = \"\"\n                    i = 0\n                    continue\n\n                if i % 5 == 4:\n                    self.out.append(line)\n                    line = \"\"\n                i += 1\n\n        self.out.append(titlify(\"defined colors\"))\n        list_all_color_sample(\"\")\n\n        self.out.append(titlify(\"defined colors (bold)\"))\n        list_all_color_sample(Color.colors[\"bold\"])\n\n        self.out.append(titlify(\"defined colors (highlight)\"))\n        list_all_color_sample(Color.colors[\"highlight\"])\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n\n        # show all\n        if args.key is None:\n            self.show_all_config()\n            if args.color_sample:\n                self.show_color_sample()\n            else:\n                self.out.append(\"* use --color-sample to see available color name\")\n            self.print_output(check_terminal_size=True)\n            return\n\n        # show one\n        key = \"theme.{:s}\".format(args.key)\n        if key not in Config.__gef_config__:\n            err(\"Invalid key\")\n            return\n        if args.value == []:\n            value = Config.get_gef_setting(key)\n            value = Color.colorify(value, value)\n            gef_print(\"{:40s}: {:s}\".format(args.key, value))\n            return\n\n        # set\n        val = [x for x in args.value if x in Color.colors]\n        gdb.execute(\"gef config theme.{:s} {!r}\".format(args.key, \" \".join(val)))\n        return\n\n\n@register_command\nclass HighlightCommand(GenericCommand):\n    \"\"\"The base command to highlight user-defined text matches, which modifies GEF output universally.\"\"\"\n\n    _cmdline_ = \"highlight\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"add\")\n    subparsers.add_parser(\"remove\")\n    subparsers.add_parser(\"list\")\n    subparsers.add_parser(\"clear\")\n    _syntax_ = parser.format_help()\n\n    highlight_table = {}\n\n    @staticmethod\n    def highlight_text(text):\n        \"\"\"Highlight text using highlight_table { match -> color } settings.\n\n        If RegEx is enabled it will create a match group around all items in the\n        highlight_table and wrap the specified color in the highlight_table\n        around those matches.\n\n        If RegEx is disabled, split by ANSI codes and 'colorify' each match found\n        within the specified string.\"\"\"\n        if not HighlightCommand.highlight_table:\n            return text\n\n        if Config.get_gef_setting(\"highlight.regex\"):\n            for match, color in HighlightCommand.highlight_table.items():\n                text = re.sub(\"(\" + match + \")\", Color.colorify(\"\\\\1\", color), text)\n            return text\n\n        ansiSplit = re.split(r\"(\\033\\[[\\d;]*m)\", text)\n        for match, color in HighlightCommand.highlight_table.items():\n            for index, val in enumerate(ansiSplit):\n                found = val.find(match)\n                if found > -1:\n                    ansiSplit[index] = val.replace(match, Color.colorify(match, color))\n                    break\n            text = \"\".join(ansiSplit)\n            ansiSplit = re.split(r\"(\\033\\[[\\d;]*m)\", text)\n        return \"\".join(ansiSplit)\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        self.add_setting(\"regex\", False, \"Enable regex highlighting\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass HighlightListCommand(GenericCommand):\n    \"\"\"Display the current highlight table with matches to colors.\"\"\"\n\n    _cmdline_ = \"highlight list\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def print_highlight_table(self):\n        if not HighlightCommand.highlight_table:\n            err(\"No matches found\")\n            return\n\n        left_pad = max(map(len, HighlightCommand.highlight_table.keys()))\n        for match, color in sorted(HighlightCommand.highlight_table.items()):\n            # do not use gef_print because the color will be overwrite\n            print(\"{!s} | {!s}\".format(\n                Color.colorify(match.ljust(left_pad), color),\n                Color.colorify(color, color),\n            ))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.print_highlight_table()\n        return\n\n\n@register_command\nclass HighlightClearCommand(GenericCommand):\n    \"\"\"Clear the highlight table.\"\"\"\n\n    _cmdline_ = \"highlight clear\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        HighlightCommand.highlight_table.clear()\n        return\n\n\n@register_command\nclass HighlightAddCommand(GenericCommand):\n    \"\"\"Add a match to the highlight table.\"\"\"\n\n    _cmdline_ = \"highlight add\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"match\", metavar=\"MATCH\", help=\"the keyword phrase to highlight.\")\n    parser.add_argument(\"color\", metavar=\"COLOR\", nargs=\"+\", help=\"the color used to highlight.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"call   rcx\" bold yellow',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"use config `gef config highlight.regex true` if need regex.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    def do_invoke(self, args):\n        for a in args.color:\n            if a not in Color.colors.keys():\n                err(\"Invalid color\")\n                return\n        HighlightCommand.highlight_table[args.match] = \" \".join(args.color)\n        return\n\n\n@register_command\nclass HighlightRemoveCommand(GenericCommand):\n    \"\"\"Remove a match in the highlight table.\"\"\"\n\n    _cmdline_ = \"highlight remove\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"match\", metavar=\"MATCH\", help=\"the keyword phrase to remove from highlight.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"call   rcx\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    def do_invoke(self, args):\n        HighlightCommand.highlight_table.pop(args.match, None)\n        return\n\n\nclass SimpleInternalTemporaryBreakpoint(gdb.Breakpoint):\n    \"\"\"A simple wrapper that takes into account the bug where temporary breakpoints isn't deleted after it is hit.\"\"\"\n\n    def __init__(self, loc):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=True, temporary=True)\n        return\n\n    def stop(self):\n        EventHandler.__gef_check_disabled_bp__ = True\n        self.enabled = False\n\n        Cache.reset_gef_caches()\n        return True\n\n\nclass SecondBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint which sets a 2nd breakpoint, when hit.\"\"\"\n\n    def __init__(self, loc, second_loc):\n        self.second_loc = second_loc\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=True, temporary=True)\n        return\n\n    def stop(self):\n        EventHandler.__gef_check_disabled_bp__ = True\n        self.enabled = False\n\n        Cache.reset_gef_caches()\n        SimpleInternalTemporaryBreakpoint(loc=self.second_loc)\n        return True\n\n\n@register_command\nclass NextiForQemuUserCommand(GenericCommand):\n    \"\"\"`ni` wrapper for some specific architectures (OpenRISC 1000 and CRIS).\"\"\"\n\n    _cmdline_ = \"nexti-for-qemu-user\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"args\", metavar=\"ARGS\", nargs=\"*\",\n                        help=\"An array of arguments to pass as is to the nexti command. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Only when qemu-user with specific architecture, the `ni` command is redirected to `nexti-for-qemu-user`.\",\n        \"This setting is done only once, when `hook_stop_handler` is called for the first time.\",\n        \"\",\n        \"Target architecture:\",\n        \"  OpenRISC 1000: branch operations don't work well, so GEF uses breakpoints to simulate.\",\n        \"  CRIS: si/ni commands don't work well. so GEF uses breakpoints to simulate.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def ni_set_bp_for_branch(self):\n        target = None\n        delay_slot = False\n\n        try:\n            frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            frame = None\n\n        insn = get_insn()\n        insn_next = get_insn_next()\n\n        if insn and current_arch.is_jump(insn):\n            target = ContextCodeCommand.get_branch_addr(insn)\n            delay_slot = current_arch.has_delay_slot\n        elif insn and current_arch.is_ret(insn):\n            target = current_arch.get_ra(insn, frame)\n            delay_slot = current_arch.has_ret_delay_slot\n\n        if target is None:\n            return\n\n        # something wrong if infinity loop on CRIS architecture\n        if is_cris() and target == insn.address:\n            SecondBreakpoint(loc=insn_next.address, second_loc=target)\n            return\n\n        SimpleInternalTemporaryBreakpoint(loc=target)\n        if delay_slot:\n            SimpleInternalTemporaryBreakpoint(loc=insn_next.address)\n        return\n\n    def ni_set_bp_next(self):\n        insn_next = get_insn_next()\n        SimpleInternalTemporaryBreakpoint(loc=insn_next.address)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-user\",))\n    @only_if_specific_arch(arch=(\"OR1K\", \"CRIS\"))\n    def do_invoke(self, args):\n        if is_cris():\n            self.ni_set_bp_for_branch()\n            self.ni_set_bp_next()\n            gdb.execute(\"c\") # use c wrapper\n            return\n\n        if is_or1k():\n            self.ni_set_bp_for_branch()\n\n        cmd = \"nexti \" + \" \".join(args.args)\n        try:\n            gdb.execute(cmd.rstrip())\n        except gdb.error:\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            if str(exc_value).startswith(\"Cannot access memory at address\"):\n                if is_valid_addr(current_arch.pc):\n                    gdb.execute(\"xuntil --from-wrapper\")\n                else:\n                    err(exc_value)\n            else:\n                err(exc_value)\n        return\n\n\n@register_command\nclass StepiForQemuUserCommand(GenericCommand):\n    \"\"\"`si` wrapper for some specific architectures (OpenRISC 1000 and CRIS).\"\"\"\n\n    _cmdline_ = \"stepi-for-qemu-user\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"args\", metavar=\"ARGS\", nargs=\"*\",\n                        help=\"An array of arguments to pass as is to the stepi command. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Only when qemu-user with specific architecture, the `si` command is redirected to `stepi-for-qemu-user`.\",\n        \"This setting is done only once, when `hook_stop_handler` is called for the first time.\",\n        \"\",\n        \"Target architecture:\",\n        \"  OpenRISC 1000: branch operations don't work well, so GEF uses breakpoints to simulate.\",\n        \"  CRIS: si/ni commands don't work well. so GEF uses breakpoints to simulate.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def si_set_bp_for_branch(self):\n        target = None\n        delay_slot = False\n\n        try:\n            frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            frame = None\n\n        insn = get_insn()\n        insn_next = get_insn_next()\n\n        if insn and (current_arch.is_jump(insn) or current_arch.is_call(insn)): # si also stops at `call` target\n            target = ContextCodeCommand.get_branch_addr(insn)\n            delay_slot = current_arch.has_delay_slot\n        elif insn and current_arch.is_ret(insn):\n            target = current_arch.get_ra(insn, frame)\n            delay_slot = current_arch.has_ret_delay_slot\n\n        if target is None:\n            return\n\n        # something wrong if infinity loop on CRIS architecture\n        if is_cris() and target == insn.address:\n            SecondBreakpoint(loc=insn_next.address, second_loc=target)\n            return\n\n        SimpleInternalTemporaryBreakpoint(loc=target)\n        if delay_slot:\n            SimpleInternalTemporaryBreakpoint(loc=insn_next.address)\n        return\n\n    def si_set_bp_next(self):\n        insn_next = get_insn_next()\n        SimpleInternalTemporaryBreakpoint(loc=insn_next.address)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-user\",))\n    @only_if_specific_arch(arch=(\"OR1K\", \"CRIS\"))\n    def do_invoke(self, args):\n        if is_cris():\n            self.si_set_bp_for_branch()\n            self.si_set_bp_next()\n            gdb.execute(\"c\") # use c wrapper\n            return\n\n        if is_or1k():\n            self.si_set_bp_for_branch()\n\n        cmd = \"stepi \" + \" \".join(args.args)\n        try:\n            gdb.execute(cmd.rstrip())\n        except gdb.error:\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            if str(exc_value).startswith(\"Cannot access memory at address\"):\n                if is_valid_addr(current_arch.pc):\n                    gdb.execute(\"xuntil --from-wrapper\")\n                else:\n                    err(exc_value)\n            else:\n                err(exc_value)\n        return\n\n\n@register_command\nclass ContinueForQemuUserCommand(GenericCommand):\n    \"\"\"`c` wrapper to resolve the Ctrl+C problem for qemu-user or Intel Pin.\"\"\"\n\n    _cmdline_ = \"continue-for-qemu-user\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"args\", metavar=\"ARGS\", nargs=\"*\",\n                        help=\"An array of arguments to pass as is to the continue command. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Only when qemu-user or pin, the `c` command is redirected to `continue-for-qemu-user`.\",\n        \"This setting is done only once, when hook_stop_handler is called for the first time.\",\n        \"Nested `c` command causes a problem, so in that case gef executes the original continue command instead.\",\n        \"Internally, SIGINT is monitored in a forked child process (default) or another thread.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    nested = False\n\n    def __init__(self):\n        super().__init__()\n        # In the previous old implementation, Ctrl+C signal was monitored by thread. It was quite stable.\n        # However, if you use this method before libc.so is loaded, gdb will crash on non-x86 architectures.\n        # This is because the code executes gdb.execute(\"continue\") in a non-main thread.\n        # However, signals can only be monitored in the main thread, so there was no way to avoid this.\n        # In the new implementation, Ctrl+C signal is monitored by forked child process.\n        # It seems to work well so far, but there may be cases where it doesn't work properly.\n        self.add_setting(\"use_fork\", True, \"Ctrl+C is monitored by forked process. If False, monitored by thread.\")\n        return\n\n    def continue_for_qemu_thread(self):\n        import signal\n        import threading\n        thread_started = False\n        thread_finished = False\n\n        pid = Pid.get_pid()\n\n        def continue_thread():\n            nonlocal thread_started, thread_finished\n            thread_started = True\n            try:\n                gdb.execute(\"continue\")\n            except gdb.error:\n                exc_type, exc_value, exc_traceback = sys.exc_info()\n                err(exc_value)\n            thread_finished = True\n            return\n\n        def sig_handler(_signum, _frame):\n            # do not use get_pid() in this func.\n            # get_pid() uses `maintenance packet` command internally,\n            # but it cannot be used when the non-static program is running.\n            os.kill(pid, signal.SIGTRAP)\n            return\n\n        th = threading.Thread(target=continue_thread, daemon=True)\n        th.start()\n        while thread_started is False:\n            time.sleep(0.1)\n        old = signal.signal(signal.SIGINT, sig_handler)\n        while thread_finished is False:\n            time.sleep(0.1)\n        th.join()\n        signal.signal(signal.SIGINT, old)\n        return\n\n    def pid_is_alive(self, pid):\n        try:\n            os.kill(pid, 0)\n        except OSError:\n            return False\n        return True\n\n    def continue_for_qemu_fork(self):\n        import signal\n\n        parent_pid = Pid.get_pid()\n        child_pid = os.fork()\n\n        if child_pid == 0:\n\n            # child\n            def sig_handler(_signum, _frame):\n                nonlocal signal_monitoring\n                os.kill(parent_pid, signal.SIGTRAP)\n                signal_monitoring = False\n                return\n\n            signal_monitoring = True\n            old = signal.signal(signal.SIGINT, sig_handler)\n            while signal_monitoring:\n                time.sleep(0.1)\n            signal.signal(signal.SIGINT, old)\n            os._exit(0)\n\n        # parent\n        try:\n            gdb.execute(\"continue\")\n        except gdb.error:\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            err(exc_value)\n\n        # clean up\n        try:\n            if self.pid_is_alive(child_pid):\n                os.kill(child_pid, signal.SIGKILL)\n            os.waitpid(child_pid, os.WNOHANG)\n        except (ProcessLookupError, ChildProcessError):\n            pass\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-user\", \"pin\"))\n    def do_invoke(self, args):\n        if is_qemu_user() or is_pin():\n            if Pid.get_pid():\n                if not self.nested:\n                    self.nested = True\n                    if Config.get_gef_setting(\"continue_for_qemu_user.use_fork\"):\n                        self.continue_for_qemu_fork()\n                    else:\n                        self.continue_for_qemu_thread()\n                    self.nested = False\n                    return\n\n        # fall back to original continue command\n        try:\n            cmd = \"continue \" + \" \".join(args.args)\n            gdb.execute(cmd.rstrip())\n        except gdb.error:\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            err(exc_value)\n        return\n\n\n@register_command\nclass StepiForKGDBCommand(GenericCommand):\n    \"\"\"`si` wrapper for AArch64 KGDB that avoids stepping into pending IRQ handlers.\"\"\"\n\n    _cmdline_ = \"stepi-for-kgdb\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Only for AArch64 + kgdb.\",\n        \"Temporarily masks IRQ before `stepi`, then restores the original state\",\n        \"unless the stepped instruction intentionally modified DAIF.I.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        old_cpsr = get_register(\"$cpsr\")\n        try:\n            instr = read_int32_from_memory(current_arch.pc)\n        except gdb.error:\n            err(\"Memory read error\")\n            return\n\n        irq_mask_bit = 0x80 # DAIF.I\n        gdb.execute(\"set $cpsr = {:#x}\".format(old_cpsr | irq_mask_bit), to_string=True)\n\n        try:\n            gdb.execute(\"stepi\", from_tty=True)\n        except gdb.error:\n            gdb.execute(\"set $cpsr = {:#x}\".format(old_cpsr), to_string=True)\n            raise\n\n        if old_cpsr & irq_mask_bit:\n            return\n\n        new_cpsr = get_register(\"$cpsr\")\n\n        # If the stepped instruction itself modified DAIF.I, preserve that result.\n        if (instr & 0xffff_f0ff) == 0xd503_40df: # MSR DAIFSet/DAIFClr, #imm\n            if (instr & 0x200) == 0:\n                new_cpsr &= ~irq_mask_bit\n        elif (instr & 0xffff_ffe0) == 0xd51b_4220: # MSR DAIF, Xn\n            regval = get_register(\"$x{:d}\".format(instr & 0x1f))\n            if (regval & irq_mask_bit) == 0:\n                new_cpsr &= ~irq_mask_bit\n        else:\n            new_cpsr &= ~irq_mask_bit\n\n        gdb.execute(\"set $cpsr = {:#x}\".format(new_cpsr), to_string=True)\n        return\n\n\n@register_command\nclass UpCommand(GenericCommand):\n    \"\"\"`up` wrapper.\"\"\"\n\n    _cmdline_ = \"up\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n    _repeat_ = True\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"n\", metavar=\"N\", nargs=\"?\", type=int, default=1,\n                        help=\"Number of frames to move. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    def do_up(self, current_frame):\n        # check if target frame is available\n        n = self.args.n\n        while current_frame and n:\n            if not current_frame.is_valid():\n                break\n            current_frame = current_frame.older()\n            n -= 1\n\n        # go to target frame\n        if n == 0 and current_frame:\n            current_frame.select()\n\n        # back up\n        nb_lines_before = Config.get_gef_setting(\"context_trace.nb_lines_before\")\n        nb_lines = Config.get_gef_setting(\"context_trace.nb_lines\")\n\n        # change temporarily\n        Config.set_gef_setting(\"context_trace.nb_lines_before\", 0x100)\n        Config.set_gef_setting(\"context_trace.nb_lines\", 0x100)\n\n        # print\n        gdb.execute(\"context trace -i\")\n\n        # restore\n        Config.set_gef_setting(\"context_trace.nb_lines_before\", nb_lines_before)\n        Config.set_gef_setting(\"context_trace.nb_lines\", nb_lines)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            current_frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            err(\"Failed to get frame information\")\n            return\n\n        self.do_up(current_frame)\n        return\n\n\n@register_command\nclass DownCommand(GenericCommand):\n    \"\"\"`down` wrapper.\"\"\"\n\n    _cmdline_ = \"down\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n    _repeat_ = True\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"n\", metavar=\"N\", nargs=\"?\", type=int, default=1,\n                        help=\"Number of frames to move. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    def do_down(self, current_frame):\n        # check if target frame is available\n        n = self.args.n\n        while current_frame and n:\n            if not current_frame.is_valid():\n                break\n            current_frame = current_frame.newer()\n            n -= 1\n\n        # go to target frame\n        if n == 0 and current_frame:\n            current_frame.select()\n\n        # back up\n        nb_lines_before = Config.get_gef_setting(\"context_trace.nb_lines_before\")\n        nb_lines = Config.get_gef_setting(\"context_trace.nb_lines\")\n\n        # change temporarily\n        Config.set_gef_setting(\"context_trace.nb_lines_before\", 0x100)\n        Config.set_gef_setting(\"context_trace.nb_lines\", 0x100)\n\n        # print\n        gdb.execute(\"context trace -i\")\n\n        # restore\n        Config.set_gef_setting(\"context_trace.nb_lines_before\", nb_lines_before)\n        Config.set_gef_setting(\"context_trace.nb_lines\", nb_lines)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            current_frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            err(\"Failed to get frame information\")\n            return\n\n        self.do_down(current_frame)\n        return\n\n\n@register_command\nclass HistoryCommand(GenericCommand, BufferingOutput):\n    \"\"\"Show gdb command history easily.\"\"\"\n\n    _cmdline_ = \"history\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_history(self):\n        history = {}\n        line_idx = 0\n        prev_ret = None\n        while True:\n            ret = gdb.execute(\"show commands {:d}\".format(line_idx), to_string=True)\n            for line in ret.splitlines():\n                line_idx = int(line.split()[0])\n                if line_idx in history:\n                    continue\n                history[line_idx] = line\n\n            if prev_ret == ret:\n                break\n            prev_ret = ret\n        return list(history.values())\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = self.get_history()\n        self.print_output(skip_color=True)\n        return\n\n\n@register_command\nclass DisplayTypeCommand(GenericCommand, BufferingOutput):\n    \"\"\"Make it easier to use `ptype /ox TYPE` and `p ((TYPE*) ADDRESS)[0]`.\"\"\"\n\n    _cmdline_ = \"dt\"\n    _category_ = \"02-h. Process Information - Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"type\", metavar=\"TYPE\", help=\"the type name.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address to apply the type.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\",\n                        help=\"override `context.smart_cpp_function_name = True` temporarily.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"struct malloc_state\"       # shortcut for `ptype /ox struct malloc_state`',\n        '{0:s} \"struct malloc_state\" $rsp  # shortcut for `p ((struct malloc_state*) $rsp)[0]`',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command is designed for several purposes.\",\n        \"1. When displaying very large struct, you may want to go through a pager because the results will not fit on one screen.\",\n        \"   However, using a pager, the color information disappears. This command calls the pager with preserving colors.\",\n        \"2. When `ptype /ox TYPE`, interpreting member type recursively often result is too long and difficult to read.\",\n        \"   This command keeps result compact by displaying only top-level members.\",\n        \"3. When `p ((TYPE*) ADDRESS)[0]` for large struct, the gdb setting of `max-value-size` is too small to display.\",\n        \"   This command adjusts it automatically.\",\n        \"4. When debugging a binary written in the Golang, the offset information of the type is not displayed.\",\n        \"   This command also displays the offset.\",\n        \"5. When debugging a binary written in the Golang, the `p ((TYPE*) ADDRESS)[0]` command will be broken.\",\n        \"   This is because the Golang helper script is automatically loaded and overwrites the behavior of `p` command.\",\n        \"   This command creates the display results on the python side, so we can display it without any problems.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def dump_type(self, tp, args_type):\n        if tp.code == gdb.TYPE_CODE_STRUCT:\n            type_prefix = \"struct\"\n        elif tp.code == gdb.TYPE_CODE_UNION:\n            type_prefix = \"union\"\n        elif tp.code == gdb.TYPE_CODE_ENUM:\n            type_prefix = \"enum\"\n        else:\n            err(\"{:s} is not struct or union\".format(tp.name or args_type))\n            return False\n\n        self.out = [\n            \"{:s} {:s} {{\".format(type_prefix, Instruction.smartify_text(tp.name or args_type)),\n            \"    /* offset | size   */\",\n        ]\n        for name, field in tp.items():\n            if tp.code in [gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION]:\n                if hasattr(field, \"bitpos\") and hasattr(field.type, \"sizeof\"):\n                    offsz_str = \"/* {:#06x} | {:#06x} */\".format(field.bitpos // 8, field.type.sizeof)\n                elif hasattr(field.type, \"sizeof\"):\n                    offsz_str = \"/*        | {:#06x} */\".format(field.type.sizeof)\n                elif hasattr(field, \"bitpos\"):\n                    offsz_str = \"/* {:#06x} |        */\".format(field.bitpos // 8)\n                else:\n                    offsz_str = \"/*        |        */\"\n                type_str = Instruction.smartify_text(str(field.type))\n                name_str = Color.cyanify(Instruction.smartify_text(name))\n                if field.bitsize == 0:\n                    msg = \"    {:s}    {} {:s};\".format(offsz_str, type_str, name_str)\n                else:\n                    msg = \"    {:s}    {} {:s} : {:d};\".format(offsz_str, type_str, name_str, field.bitsize)\n            else: # gdb.TYPE_CODE_ENUM\n                offsz_str = \"/* {:#06x} | {:#06x} */\".format(0, 4)\n                type_str = \"int\"\n                name_str = Color.cyanify(Instruction.smartify_text(name))\n                msg = \"    {:s}    {} {:s} = {:#x};\".format(offsz_str, type_str, name_str, field.enumval)\n            self.out.append(msg)\n        self.out.append(\"}} // total: {:#x} bytes\".format(tp.sizeof))\n        return True\n\n    def apply_type(self, tp, args_address):\n        if not is_valid_addr(args_address):\n            err(\"Memory read error\")\n            return False\n\n        # change setting\n        if tp.sizeof > 2200: # 2200 is default value of max-value-size\n            gdb.execute(\"set max-value-size {:#x}\".format(tp.sizeof))\n\n        v = gdb.Value(args_address)\n        s = v.cast(tp.pointer()).dereference()\n        self.out = s.format_string(styling=True).splitlines()\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        # lookup type\n        tp = GefUtil.cached_lookup_type(args.type)\n        if not args.type.startswith((\"struct\", \"union\", \"enum\")):\n            if tp is None:\n                tp = GefUtil.cached_lookup_type(\"struct {:s}\".format(args.type))\n            if tp is None:\n                tp = GefUtil.cached_lookup_type(\"union {:s}\".format(args.type))\n            if tp is None:\n                tp = GefUtil.cached_lookup_type(\"enum {:s}\".format(args.type))\n\n        if tp is None:\n            err(\"Could not find {:s}\".format(args.type))\n            return\n\n        # remove pointer\n        while str(tp).endswith(\"*\"):\n            tp = tp.target()\n\n        # check if valid type\n        if tp.code not in [gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION, gdb.TYPE_CODE_ENUM]:\n            err(\"{:s} is not struct or union or enum\".format(tp.name or args.type))\n            return\n\n        # change setting temporarily\n        if args.smart:\n            old_smart_setting = Config.get_gef_setting(\"context.smart_cpp_function_name\")\n            Config.set_gef_setting(\"context.smart_cpp_function_name\", True)\n\n        # doit\n        if args.address is None:\n            ret = self.dump_type(tp, args.type)\n        else:\n            ret = self.apply_type(tp, args.address)\n\n        if ret:\n            self.print_output(check_terminal_size=True)\n\n        # revert setting\n        if args.smart:\n            Config.set_gef_setting(\"context.smart_cpp_function_name\", old_smart_setting)\n        return\n\n\n@register_command\nclass BreakRelativeVirtualAddressCommand(GenericCommand):\n    \"\"\"Set a breakpoint at relative offset from codebase.\"\"\"\n\n    _cmdline_ = \"break-rva\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n    _aliases_ = [\"brva\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"offset\", metavar=\"OFFSET\", type=AddressUtil.parse_address,\n                        help=\"the offset from codebase to set a breakpoint.\")\n    _syntax_ = parser.format_help()\n\n    delayed_breakpoints = set()\n    delayed_bp_set = False\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        elf = Elf.get_elf()\n        if elf is None or not elf.is_valid():\n            err(\"Invalid ELF\")\n            return\n\n        if not elf.is_pie():\n            err(\"Non-PIE ELF is unsupported\")\n            return\n\n        if is_alive():\n            codebase = ProcessMap.get_codebase()\n            if codebase is None:\n                gef_print(\"Could not find the codebase\")\n                return\n            gdb.execute(\"b *{:#x}\".format(codebase + args.offset))\n        else:\n            # use delayed breakpoints\n            BreakRelativeVirtualAddressCommand.delayed_breakpoints.add(args.offset)\n            info(\"Add delayed breakpoint to codebase+{:#x}\".format(args.offset))\n        return\n\n\n@register_command\nclass PrintFormatCommand(GenericCommand):\n    \"\"\"Print bytes format in high level languages.\"\"\"\n\n    _cmdline_ = \"print-format\"\n    _category_ = \"07-c. Misc - Generation\"\n    _aliases_ = [\"pf\", \"gethex\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", dest=\"format\", default=\"hex\",\n                        choices=[\"py\", \"c\", \"js\", \"asm\", \"hex\", \"hexn\", \"hexs\", \"hexsn\"],\n                        help=\"the output format. (default: %(default)s)\")\n    parser.add_argument(\"-b\", dest=\"bitlen\", type=int, default=8, choices=[8, 16, 32, 64],\n                        help=\"the size of bit. (default: %(default)s)\")\n    group = parser.add_mutually_exclusive_group(required=False)\n    group.add_argument(\"-l\", dest=\"length\", type=AddressUtil.parse_address, default=256,\n                        help=\"the length of array. (default: %(default)s)\")\n    group.add_argument(\"-t\", dest=\"to_addr\", type=AddressUtil.parse_address,\n                        help=\"specify the end address instead of the length.\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address of data to dump.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -f py -b 8 -l 256 $rsp\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        '\"hexn\" means hex with new-line.',\n        '\"hexs\" means hex with separator.',\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def extract_memory(self):\n        unit_size = self.args.bitlen // 8\n        if self.args.to_addr is not None:\n            end_addr = self.args.to_addr\n        else:\n            end_addr = self.args.location + self.args.length * unit_size\n\n        bit_format = {8: \"<B\", 16: \"<H\", 32: \"<I\", 64: \"<Q\"}[self.args.bitlen]\n        data = []\n        for address in range(self.args.location, end_addr, unit_size):\n            try:\n                mem = read_memory(address, unit_size)\n            except gdb.MemoryError:\n                err(\"Memory read error\")\n                return None\n            value = struct.unpack(bit_format, mem)[0]\n            data.append(value)\n        return data\n\n    def parse_data(self, data):\n        if self.args.format in [\"hexs\", \"hexsn\"]:\n            separator = \" \"\n        else:\n            separator = \"\"\n\n        sdata = \"\"\n        if self.args.format in [\"hexn\", \"hexsn\"]:\n            for i, x in enumerate(data):\n                sdata += \"{:02x}{:s}\".format(x, separator)\n                if (i % 16) == 15:\n                    sdata += \"\\n\"\n        elif self.args.format in [\"hex\", \"hexs\"]:\n            for x in data:\n                sdata += \"{:02x}{:s}\".format(x, separator)\n        else:\n            for i, x in enumerate(data):\n                if (i % 8) == 0:\n                    sdata += \"    \"\n                sdata += \"{:#0{}x}, \".format(x, self.args.bitlen // 4 + 2)\n                if (i % 8) == 7:\n                    sdata += \"\\n\"\n        sdata = sdata.rstrip()\n        return sdata\n\n    def make_format(self, sdata):\n        if self.args.format == \"py\":\n            out = \"buf = [\\n{:s}\\n]\".format(sdata)\n        elif self.args.format == \"c\":\n            c_type = {8: \"char\", 16: \"short\", 32: \"int\", 64: \"long long\"}\n            out = \"unsigned {:s} buf[] = {{\\n{:s}\\n}};\".format(c_type[self.args.bitlen], sdata)\n        elif self.args.format == \"js\":\n            out = \"var buf = [\\n{:s}\\n];\".format(sdata)\n        elif self.args.format == \"asm\":\n            asm_type = {8: \"db\", 16: \"dw\", 32: \"dd\", 64: \"dq\"}\n            out = \"buf {:s}\\n{:s}\".format(asm_type[self.args.bitlen], sdata)\n        elif self.args.format in [\"hex\", \"hexn\", \"hexs\", \"hexsn\"]:\n            out = sdata\n        return out\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.format in [\"hex\", \"hexn\", \"hexs\", \"hexsn\"] and args.bitlen != 8:\n            err(\"{:s} must be bit == 8\".format(args.format))\n            return\n\n        data = self.extract_memory()\n        if data is None:\n            return\n        sdata = self.parse_data(data)\n        out = self.make_format(sdata)\n        gef_print(out)\n        return\n\n\n@register_command\nclass CanaryCommand(GenericCommand):\n    \"\"\"Display the canary value of the current process from auxv information.\"\"\"\n\n    _cmdline_ = \"canary\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    @Cache.cache_this_session\n    def gef_read_canary():\n        \"\"\"Read the canary of a running process using Auxiliary Vector.\n        Return a tuple of (canary, location) if found, None otherwise.\"\"\"\n        if is_in_kernel():\n            return None\n\n        try:\n            auxval = Auxv.get_auxiliary_values()\n            if not auxval:\n                return None\n            canary_location = auxval[\"AT_RANDOM\"]\n            canary = read_int_from_memory(canary_location)\n            canary &= ~0xff\n            return canary, canary_location\n        except (KeyError, gdb.MemoryError):\n            return None\n\n    def dump_canary(self):\n        res = CanaryCommand.gef_read_canary()\n        if not res:\n            err(\"Failed to get the canary\")\n            return\n\n        canary, location = res\n        gef_print(titlify(\"Canary value\"))\n        info(\"Found AT_RANDOM at {!s}, reading {:d} bytes\".format(\n            ProcessMap.lookup_address(location), current_arch.ptrsize,\n        ))\n        info(\"The canary is {:s}\".format(Color.colorify_hex(canary, \"bold\")))\n\n        gef_print(titlify(\"Found canaries\"))\n        vmmap = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True)\n        unpack = u32 if current_arch.ptrsize == 4 else u64\n        sp = current_arch.sp\n        printed_flag_sp = False\n        for m in vmmap:\n            if not (m.permission & Permission.READ):\n                continue\n            if not (m.permission & Permission.WRITE):\n                continue\n            try:\n                data = read_memory(m.page_start, m.page_end - m.page_start)\n            except gdb.MemoryError:\n                continue\n            prev_addr = -1\n            for pos in range(0, m.page_end - m.page_start, current_arch.ptrsize):\n                addr = m.page_start + pos\n                d = data[pos: pos + current_arch.ptrsize]\n                if canary != unpack(d):\n                    continue\n                if m.path == \"\":\n                    path = \"unknown\"\n                else:\n                    path = m.path\n                if prev_addr <= sp <= addr:\n                    if printed_flag_sp is False:\n                        info(\"(Stack pointer is at {!s})\".format(ProcessMap.lookup_address(sp)))\n                        printed_flag_sp = True\n                if path == \"[stack]\":\n                    info(\"Found at {!s} in {!r} (sp{:+#x})\".format(\n                        ProcessMap.lookup_address(addr), path, addr - sp,\n                    ))\n                else:\n                    info(\"Found at {!s} in {!r}\".format(ProcessMap.lookup_address(addr), path))\n                prev_addr = addr\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.dump_canary()\n        return\n\n\n@register_command\nclass AuxvCommand(GenericCommand):\n    \"\"\"Display ELF auxiliary vectors.\"\"\"\n\n    _cmdline_ = \"auxv\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--force-heuristic\", action=\"store_true\", help=\"use heuristic detection.\")\n    _syntax_ = parser.format_help()\n\n    AT_CONSTANTS = {\n        0  : \"AT_NULL\",              # End of vector\n        1  : \"AT_IGNORE\",            # Entry should be ignored\n        2  : \"AT_EXECFD\",            # File descriptor of program\n        3  : \"AT_PHDR\",              # Program headers for program\n        4  : \"AT_PHENT\",             # Size of program header entry\n        5  : \"AT_PHNUM\",             # Number of program headers\n        6  : \"AT_PAGESZ\",            # System page size\n        7  : \"AT_BASE\",              # Base address of interpreter\n        8  : \"AT_FLAGS\",             # Flags\n        9  : \"AT_ENTRY\",             # Entry point of program\n        10 : \"AT_NOTELF\",            # Program is not ELF\n        11 : \"AT_UID\",               # Real uid\n        12 : \"AT_EUID\",              # Effective uid\n        13 : \"AT_GID\",               # Real gid\n        14 : \"AT_EGID\",              # Effective gid\n        15 : \"AT_PLATFORM\",          # String identifying platform\n        16 : \"AT_HWCAP\",             # Machine dependent hints about processor capabilities\n        17 : \"AT_CLKTCK\",            # Frequency of times()\n        18 : \"AT_FPUCW\",             #\n        19 : \"AT_DCACHEBSIZE\",       #\n        20 : \"AT_ICACHEBSIZE\",       #\n        21 : \"AT_UCACHEBSIZE\",       #\n        22 : \"AT_IGNOREPPC\",         # A special ignored type value for PPC, for glibc compatibility\n        23 : \"AT_SECURE\",            #\n        24 : \"AT_BASE_PLATFORM\",     # String identifying real platforms\n        25 : \"AT_RANDOM\",            # Address of 16 random bytes\n        26 : \"AT_HWCAP2\",            # extension of AT_HWCAP\n        27 : \"AT_RSEQ_FEATURE_SIZE\", # seq supported feature size\n        28 : \"AT_RSEQ_ALIGN\",        # rseq allocation alignment\n        31 : \"AT_EXECFN\",            # Filename of executable\n        32 : \"AT_SYSINFO\",           #\n        33 : \"AT_SYSINFO_EHDR\",      #\n        34 : \"AT_L1I_CACHESHAPE\",    #\n        35 : \"AT_L1D_CACHESHAPE\",    #\n        36 : \"AT_L2_CACHESHAPE\",     #\n        37 : \"AT_L3_CACHESHAPE\",     #\n        40 : \"AT_L1I_CACHESIZE\",     #\n        41 : \"AT_L1I_CACHEGEOMETRY\", #\n        42 : \"AT_L1D_CACHESIZE\",     #\n        43 : \"AT_L1D_CACHEGEOMETRY\", #\n        44 : \"AT_L2_CACHESIZE\",      #\n        45 : \"AT_L2_CACHEGEOMETRY\",  #\n        46 : \"AT_L3_CACHESIZE\",      #\n        47 : \"AT_L3_CACHEGEOMETRY\",  #\n        51 : \"AT_MINSIGSTKSZ\",       # stack needed for signal delivery\n    }\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        auxval = Auxv.get_auxiliary_values(args.force_heuristic)\n        if not auxval:\n            return None\n\n        reverse_AT_CONSTS = {v: \"{:#04x}\".format(k) for k, v in self.AT_CONSTANTS.items()}\n\n        gef_print(titlify(\"ELF auxiliary vector\"))\n        fmt = \"{:6s} {:22s} {:s}\"\n        legend = [\"Const\", \"Name\", \"Value\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        for k, v in auxval.items():\n            num = reverse_AT_CONSTS.get(k, \"?\")\n            additional_message = \"\"\n            if k == \"AT_NULL\":\n                additional_message = \" (End of vector)\"\n            elif k in [\"AT_EXECFN\", \"AT_PLATFORM\"]:\n                s = read_cstring_from_memory(v)\n                if s is None:\n                    s = \"Cannot access memory\"\n                s = Color.yellowify(repr(s))\n                additional_message = \" -> {:s}\".format(s)\n            elif k in [\"AT_RANDOM\"]:\n                try:\n                    if is_64bit():\n                        s1 = read_int_from_memory(v + current_arch.ptrsize * 0)\n                        s2 = read_int_from_memory(v + current_arch.ptrsize * 1)\n                        additional_message = \" -> {:#018x}, {:#018x}\".format(s1, s2)\n                    else:\n                        s1 = read_int_from_memory(v + current_arch.ptrsize * 0)\n                        s2 = read_int_from_memory(v + current_arch.ptrsize * 1)\n                        s3 = read_int_from_memory(v + current_arch.ptrsize * 2)\n                        s4 = read_int_from_memory(v + current_arch.ptrsize * 3)\n                        additional_message = \" -> {:#010x}, {:#010x}, {:#010x}, {:#010x}\".format(\n                            s1, s2, s3, s4,\n                        )\n                except gdb.MemoryError:\n                    s = Color.yellowify(repr(\"Cannot access memory\"))\n                    additional_message = \" -> {:s}\".format(s)\n\n            if is_valid_addr(v):\n                v = str(ProcessMap.lookup_address(v))\n            else:\n                v = hex(v)\n            gef_print(\"{:6s} {:22s} {:s}{:s}\".format(num, k + \":\", v, additional_message))\n        return\n\n\n@register_command\nclass ArgvCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display the program's argv array.\"\"\"\n\n    _cmdline_ = \"argv\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"print all elements. (default: outputs up to 100)\")\n    parser.add_argument(\"-i\", \"--increase-limit\", action=\"store_true\",\n                        help=\"increase rounding limit from 128 bytes to 4096 bytes.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_address_from_symbol(self, symbol):\n        try:\n            return AddressUtil.parse_address(symbol)\n        except Exception:\n            return None\n\n    def print_from_mem(self, array):\n        fmt = \"{:3s} {:{:d}s}  {:{:d}s} -> {:s}\"\n        legend = [\n            \"#\",\n            \"ArrAddr\", AddressUtil.get_format_address_width(),\n            \"StrAddr\", AddressUtil.get_format_address_width(),\n            \"String\",\n        ]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        max_size = get_pagesize() if self.args.increase_limit else 128\n\n        i = 0\n        while True:\n            pos = array + i * current_arch.ptrsize\n            addr = read_int_from_memory(pos)\n            if addr == 0:\n                break\n            if not self.args.verbose and i >= 100:\n                self.out.append(\"...\")\n                break\n\n            s = read_cstring_from_memory(addr, get_pagesize())\n            s = Color.yellowify(repr(s))\n            if len(s) > max_size:\n                s = s[:max_size] + \"[...]\"\n\n            self.out.append(\"{:03d} {!s}: {!s} -> {:s}\".format(\n                i,\n                ProcessMap.lookup_address(pos),\n                ProcessMap.lookup_address(addr),\n                s,\n            ))\n            i += 1\n        return\n\n    def print_from_proc(self, filename):\n        fmt = \"{:3s} {:s}\"\n        legend = [\"#\", \"String\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        max_size = get_pagesize() if self.args.increase_limit else 128\n\n        lines = open(filename, \"rb\").read()\n        lines = String.bytes2str(lines)\n        for i, elem in enumerate(lines.split(\"\\0\")):\n            if not elem:\n                break\n            if not self.args.verbose and i >= 100:\n                self.out.append(\"...\")\n                break\n\n            if len(elem) > max_size:\n                elem = elem[:max_size] + \"[...]\"\n            self.out.append(\"{:03d} {!s}\".format(i, elem))\n        return\n\n    def dump_dl_argv(self):\n        paddr = self.get_address_from_symbol(\"&_dl_argv\")\n        addr = self.get_address_from_symbol(\"_dl_argv\")\n        if paddr and addr:\n            self.out.append(titlify(\"ARGV from _dl_argv\"))\n            self.info_add_out(\"_dl_argv @ {}\".format(ProcessMap.lookup_address(paddr)))\n            self.print_from_mem(addr)\n            return\n        elif addr == 0:\n            self.err_add_out(\"_dl_argv is 0x0\")\n        else:\n            self.err_add_out(\"Could not find _dl_argv\")\n        return\n\n    def dump_libc_argv(self):\n        paddr = self.get_address_from_symbol(\"&__libc_argv\")\n        addr = self.get_address_from_symbol(\"__libc_argv\")\n        if paddr and addr:\n            self.out.append(titlify(\"ARGV from __libc_argv\"))\n            self.info_add_out(\"__libc_argv @ {}\".format(ProcessMap.lookup_address(paddr)))\n            self.print_from_mem(addr)\n        elif addr == 0:\n            self.err_add_out(\"__libc_argv is 0x0\")\n        else:\n            self.err_add_out(\"Could not find __libc_argv\")\n        return\n\n    def dump_proc_cmdline(self):\n        if is_remote_debug():\n            return\n        self.out.append(titlify(\"ARGV from /proc/{:d}/cmdline\".format(Pid.get_pid())))\n        self.print_from_proc(\"/proc/{:d}/cmdline\".format(Pid.get_pid()))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.out = []\n        self.dump_dl_argv()\n        self.dump_libc_argv()\n        self.dump_proc_cmdline()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass EnvpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display initial envp from __environ@ld, or modified envp from last_environ@libc.\"\"\"\n\n    _cmdline_ = \"envp\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"print all elements. (default: outputs up to 100)\")\n    parser.add_argument(\"-i\", \"--increase-limit\", action=\"store_true\",\n                        help=\"increase rounding limit from 128 bytes to 4096 bytes.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_address_from_symbol(self, symbol):\n        try:\n            return AddressUtil.parse_address(symbol)\n        except Exception:\n            return None\n\n    def print_from_mem(self, array):\n        fmt = \"{:3s} {:{:d}s}  {:{:d}s} -> {:s}\"\n        legend = [\n            \"#\",\n            \"ArrAddr\", AddressUtil.get_format_address_width(),\n            \"StrAddr\", AddressUtil.get_format_address_width(),\n            \"String\",\n        ]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        max_size = get_pagesize() if self.args.increase_limit else 128\n\n        i = 0\n        while True:\n            pos = array + i * current_arch.ptrsize\n            addr = read_int_from_memory(pos)\n            if addr == 0:\n                break\n            if not self.args.verbose and i >= 100:\n                self.out.append(\"...\")\n                break\n\n            s = read_cstring_from_memory(addr, get_pagesize())\n            s = Color.yellowify(repr(s))\n            if len(s) > max_size:\n                s = s[:max_size] + \"[...]\"\n\n            self.out.append(\"{:03d} {!s}: {!s} -> {:s}\".format(\n                i,\n                ProcessMap.lookup_address(pos),\n                ProcessMap.lookup_address(addr),\n                s,\n            ))\n            i += 1\n        return\n\n    def print_from_proc(self, filename):\n        fmt = \"{:3s} {:s}\"\n        legend = [\"#\", \"Name=Value\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        max_size = get_pagesize() if self.args.increase_limit else 128\n\n        lines = open(filename, \"rb\").read()\n        lines = String.bytes2str(lines)\n        for i, elem in enumerate(lines.split(\"\\0\")):\n            if not elem:\n                break\n            if not self.args.verbose and i >= 100:\n                self.out.append(\"...\")\n                break\n            elem = re.sub(r\"^(.*?=)\", Color.boldify(\"\\\\1\"), elem)\n            if len(elem) > max_size:\n                elem = elem[:max_size] + \"[...]\"\n            self.out.append(\"{:03d} {:s}\".format(i, elem))\n        return\n\n    def dump_environ(self):\n        self.out.append(titlify(\"ENVP from __environ\"))\n        paddr = self.get_address_from_symbol(\"&__environ\")\n        addr = self.get_address_from_symbol(\"__environ\")\n        if paddr and addr:\n            self.info_add_out(\"__environ @ {}\".format(ProcessMap.lookup_address(paddr)))\n            self.print_from_mem(addr)\n        elif addr == 0:\n            self.err_add_out(\"___environ is 0x0\")\n        else:\n            self.err_add_out(\"Could not find __environ\")\n        return\n\n    def dump_last_environ(self):\n        self.out.append(titlify(\"ENVP from last_environ (for putenv, etc.)\"))\n        paddr = self.get_address_from_symbol(\"&last_environ\")\n        addr = self.get_address_from_symbol(\"last_environ\")\n        if paddr and addr:\n            self.info_add_out(\"last_environ @ {}\".format(ProcessMap.lookup_address(paddr)))\n            self.print_from_mem(addr)\n        elif addr == 0:\n            self.err_add_out(\"last_environ is 0x0\")\n        else:\n            self.err_add_out(\"Could not find last_environ\")\n        return\n\n    def dump_proc_environ(self):\n        if is_remote_debug():\n            return\n        self.out.append(titlify(\"ENVP from /proc/{:d}/environ\".format(Pid.get_pid())))\n        self.print_from_proc(\"/proc/{:d}/environ\".format(Pid.get_pid()))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.out = []\n        self.dump_environ()\n        self.dump_last_environ()\n        self.dump_proc_environ()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass DumpArgsCommand(GenericCommand):\n    \"\"\"Dump arguments of current function.\"\"\"\n\n    _cmdline_ = \"dumpargs\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n    _aliases_ = [\"args\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-c\", \"--count\", type=AddressUtil.parse_address,\n                        help=\"number of arguments to guess.\")\n    parser.add_argument(\"-o\", \"--out-of-function\", action=\"store_true\",\n                        help=\"assume here is out of the function.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        gef_print(titlify(\"info args (snapshot)\"))\n        gdb.execute(\"info args\")\n\n        gef_print(titlify(\"guessed arguments (current value)\"))\n        ret = gdb.execute(\"info args\", to_string=True).strip()\n        if args.count is not None:\n            count = args.count\n        elif \"No symbol table info available\" in ret:\n            count = len(current_arch.function_parameters)\n        else:\n            count = len(ret.splitlines())\n\n        for i in range(count):\n            key, val = current_arch.get_ith_parameter(i, in_func=not args.out_of_function)\n\n            width = len(key)\n            while width % 4:\n                width += 1\n            gef_print(\"{:>{:d}s} = {:s}\".format(key, width, AddressUtil.recursive_dereference_to_string(val)))\n        return\n\n\n@register_command\nclass VdsoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Disassemble the text area of vdso smartly.\"\"\"\n\n    _cmdline_ = \"vdso\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # get map entry\n        maps = ProcessMap.get_process_maps()\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        for entry in maps:\n            if entry.path == \"[vdso]\":\n                break\n        else:\n            err(\"Could not find the vdso\")\n            return\n\n        # get dump area\n        elf = Elf.get_elf(entry.page_start)\n        if elf is None or not elf.is_valid():\n            err(\"Failed to parse\")\n            return\n        shdr = elf.get_shdr(\".text\")\n\n        text_start = entry.page_start + shdr.sh_addr\n        text_size = shdr.sh_size\n        text_end = text_start + text_size\n\n        # disassemble\n        try:\n            __import__(\"capstone\")\n            ret = gdb.execute(\"capstone-disassemble {:#x} -l {:#x}\".format(text_start, text_size), to_string=True)\n            result_lines = ret.splitlines()\n        except ImportError:\n            gen = Disasm.gdb_disassemble(text_start, end_pc=text_end - 1)\n            result_lines = [str(x) for x in gen]\n\n        self.out = []\n        for line in result_lines:\n            if int(Color.remove_color(line.split()[0]), 16) < text_end:\n                self.out.append(line)\n            else:\n                break\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass VvarCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the vvar area (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"vvar\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def read(self, addr, size):\n        if is_x86_64():\n            block_size = 128\n            dynamic_read = current_arch.read128\n        elif is_x86_32():\n            block_size = 28\n            dynamic_read = current_arch.read28\n\n        out = b\"\"\n        pos = 0\n        while pos < size:\n            out += dynamic_read(addr + pos)\n            pos += block_size\n        return out[:size]\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        # get map entry\n        maps = ProcessMap.get_process_maps()\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        for entry in maps:\n            if entry.path == \"[vvar]\":\n                break\n        else:\n            err(\"Could not find the vvar\")\n            return\n\n        # dump\n        # arch/x86/include/asm/vvar.h\n        self.out = []\n        start = entry.page_start + 128 # DECLARE_VVAR(128, struct vdso_data, _vdso_data)\n        size = 0x180 # >= sizeof(struct vdso_data)\n        data = self.read(start, size)\n        hex_data = hexdump(data, base=start, unit=current_arch.ptrsize)\n        self.out.extend(hex_data.splitlines())\n\n        # print\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass IouringDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the iouring area (x64 only).\"\"\"\n\n    _cmdline_ = \"iouring-dump\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def read(self, addr, size):\n        block_size = 128\n        dynamic_read = current_arch.read128\n\n        out = b\"\"\n        pos = 0\n        while pos < size:\n            out += dynamic_read(addr + pos)\n            pos += block_size\n        return out[:size]\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        # get map entry\n        maps = ProcessMap.get_process_maps()\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        # get anon_inode:[io_uring]\n        iouring_entries = []\n        for entry in maps:\n            if entry.path == \"anon_inode:[io_uring]\":\n                iouring_entries.append(entry)\n\n        # dump\n        self.out = []\n        for entry in iouring_entries:\n            if entry.offset in [0, 0x0800_0000]: # IORING_OFF_SQ_RING ,IORING_OFF_CQ_RING\n                self.out.append(titlify(\"struct io_rings: {:#x}\".format(entry.page_start)))\n            elif entry.offset == 0x1000_0000: # IORING_OFF_SQES\n                self.out.append(titlify(\"struct io_uring_sqe: {:#x}\".format(entry.page_start)))\n\n            data = self.read(entry.page_start, entry.size)\n            hex_data = hexdump(data, base=entry.page_start, unit=current_arch.ptrsize)\n            hex_data_merged = HexdumpCommand.merge_lines(hex_data.splitlines(), nb_skip_merge=0x10)\n            self.out.extend(hex_data_merged)\n\n        # print\n        if not self.out:\n            err(\"Could not find io_uring region\")\n            return\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PidCommand(GenericCommand):\n    \"\"\"Display the local PID or remote PID.\"\"\"\n\n    _cmdline_ = \"pid\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        pid = Pid.get_pid()\n        if pid:\n            if is_qemu_user() or is_qemu_system():\n                gef_print(\"Local qemu PID: {:d}\".format(pid))\n            else:\n                gef_print(\"Local PID: {:d}\".format(pid))\n            return\n\n        if is_remote_debug():\n            pid = Pid.get_pid(remote=True)\n            if pid:\n                gef_print(\"Remote PID: {:d}\".format(pid))\n                return\n\n        err(\"Failed to get pid\")\n        return\n\n\n@register_command\nclass TidCommand(GenericCommand):\n    \"\"\"Display the Thread ID.\"\"\"\n\n    _cmdline_ = \"tid\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        ptid = gdb.selected_thread().ptid\n        gef_print(\"TID: {:d}\".format(ptid[1] or ptid[2]))\n        return\n\n\n@register_command\nclass FilenameCommand(GenericCommand):\n    \"\"\"Display current debugged filename.\"\"\"\n\n    _cmdline_ = \"filename\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        filepath = Path.get_filepath()\n        if filepath:\n            gef_print(repr(filepath))\n            return\n\n        elif is_remote_debug():\n            filepath = gdb.current_progspace().filename\n            if filepath and filepath.startswith(\"target:\"):\n                filepath = filepath[7:]\n            if filepath:\n                gef_print(repr(filepath))\n                return\n\n        err(\"Failed to get filename\")\n        return\n\n\n@register_command\nclass ProcInfoCommand(GenericCommand):\n    \"\"\"Extend the info given by GDB `info proc`.\"\"\"\n\n    _cmdline_ = \"proc-info\"\n    _category_ = \"02-a. Process Information - General\"\n    _aliases_ = [\"pr\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def get_state_of(self, pid):\n        try:\n            status = open(\"/proc/{:d}/status\".format(pid), \"r\").read()\n        except (FileNotFoundError, OSError):\n            return {}\n        res = {}\n        for line in status.splitlines():\n            key, value = line.split(\":\", 1)\n            res[key.strip()] = value.strip()\n        return res\n\n    def get_stat_of(self, pid):\n        try:\n            stat = open(\"/proc/{:d}/stat\".format(pid), \"r\").read()\n        except (FileNotFoundError, OSError):\n            return []\n        try:\n            name = re.search(r\"\\((.+)\\)\", stat).group(1)\n        except IndexError:\n            name = \"???\"\n        other = re.sub(r\"\\(.+\\) \", \"\", stat).split()\n        res = [int(other[0]), name, other[1]] + [int(x) for x in other[2:]]\n        return res\n\n    def get_cmdline_of(self, pid):\n        try:\n            cmdline = open(\"/proc/{:d}/cmdline\".format(pid), \"r\").read()\n        except (FileNotFoundError, OSError):\n            return \"\"\n        return cmdline.replace(\"\\0\", \" \").strip()\n\n    def get_process_path_of(self, pid):\n        try:\n            return os.readlink(\"/proc/{:d}/exe\".format(pid))\n        except (FileNotFoundError, OSError):\n            return \"Not found\"\n\n    def get_process_cwd(self, pid):\n        try:\n            return os.readlink(\"/proc/{:d}/cwd\".format(pid))\n        except (FileNotFoundError, OSError):\n            return \"Not found\"\n\n    def get_process_root(self, pid):\n        try:\n            return os.readlink(\"/proc/{:d}/root\".format(pid))\n        except (FileNotFoundError, OSError):\n            return \"Not found\"\n\n    def get_thread_ids(self, pid):\n        try:\n            tids = os.listdir(\"/proc/{:d}/task\".format(pid))\n            return [int(x) for x in tids]\n        except (FileNotFoundError, OSError):\n            return []\n\n    def get_children_pids(self, pid):\n        try:\n            ps = GefUtil.which(\"ps\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return []\n\n        # Trick: If there are no child processes, `ps` exit code will be non-zero,\n        # causing a subprocess.CalledProcessError exception to be raised.\n        cmd = [ps, \"-o\", \"pid\", \"--ppid\", str(pid), \"--noheaders\"]\n        try:\n            return [int(x) for x in GefUtil.gef_execute_external(cmd, as_list=True)]\n        except (subprocess.CalledProcessError, ValueError):\n            return []\n\n    def get_uid_map(self, pid):\n        try:\n            uid_map = open(\"/proc/{:d}/uid_map\".format(pid), \"r\").read().strip()\n        except (FileNotFoundError, OSError):\n            return []\n        return slicer([int(x) for x in uid_map.split()], 3)\n\n    def get_gid_map(self, pid):\n        try:\n            gid_map = open(\"/proc/{:d}/gid_map\".format(pid), \"r\").read().strip()\n        except (FileNotFoundError, OSError):\n            return []\n        return slicer([int(x) for x in gid_map.split()], 3)\n\n    def get_tty_str(self, major, minor):\n        try:\n            devices = open(\"/proc/devices\", \"r\").read()\n        except (FileNotFoundError, OSError):\n            return \"Not found\"\n        for line in devices.splitlines():\n            if not line or line.endswith(\":\"):\n                continue\n            n, name = line.strip().split()\n            if major == int(n):\n                if not name.startswith(\"/dev\"):\n                    name = os.path.join(\"/dev\", name)\n                break\n        else:\n            return \"Not found\"\n\n        def get_major_minor(name):\n            devnum = os.stat(name).st_rdev\n            major = (devnum >> 8) & 0xff\n            minor = devnum & 0xff\n            return major, minor\n\n        if not os.path.exists(name):\n            return \"Not found\"\n\n        if os.path.islink(name):\n            return \"Not found\"\n\n        if os.path.isfile(name):\n            if get_major_minor(name) == (major, minor):\n                return name\n\n        if os.path.isdir(name):\n            for path in GefUtil.walk(name):\n                if get_major_minor(path) == (major, minor):\n                    return path\n        return \"Not found\"\n\n    def show_info_proc(self):\n        gef_print(titlify(\"Process Information\"))\n\n        pid = Pid.get_pid()\n        executable = self.get_process_path_of(pid)\n        cmdline = self.get_cmdline_of(pid)\n        cwd = self.get_process_cwd(pid)\n        root = self.get_process_root(pid)\n        gef_print(\"{:30s}  ->  {:d}\".format(\"PID\", pid))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", executable))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", cmdline))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Current Working Directory\", cwd))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Root Directory\", root))\n        uids = re.sub(r\"\\s+\", \" : \", self.get_state_of(pid)[\"Uid\"])\n        gids = re.sub(r\"\\s+\", \" : \", self.get_state_of(pid)[\"Gid\"])\n        gef_print(\"{:30s}  ->  {:s}\".format(\"  RUID:EUID:SavedUID:FSUID\", uids))\n        gef_print(\"{:30s}  ->  {:s}\".format(\"  RGID:EGID:SavedGID:FSGID\", gids))\n        seccomp_n = self.get_state_of(pid)[\"Seccomp\"]\n        seccomp_s = {\"0\": \"Disabled\", \"1\": \"Strict\", \"2\": \"CustomFilter\"}[seccomp_n]\n        gef_print(\"{:30s}  ->  {:s} ({:s})\".format(\"  Seccomp Mode\", seccomp_n, seccomp_s))\n        return\n\n    def show_info_proc_extra(self):\n        gef_print(titlify(\"Process Information Additional\"))\n\n        pid = Pid.get_pid()\n        stat = self.get_stat_of(pid)\n        pgid = stat[4]\n        pgid_exec = self.get_process_path_of(pgid)\n        pgid_cmdline = self.get_cmdline_of(pgid)\n        gef_print(\"{:30s}  ->  {:d}\".format(\"Process Group ID\", pgid))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", pgid_exec))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", pgid_cmdline))\n        sid = stat[5]\n        sid_exec = self.get_process_path_of(sid)\n        sid_cmdline = self.get_cmdline_of(sid)\n        gef_print(\"{:30s}  ->  {:d}\".format(\"Session ID\", sid))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", sid_exec))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", sid_cmdline))\n        tpgid = stat[7]\n        tpgid_exec = self.get_process_path_of(tpgid)\n        tpgid_cmdline = self.get_cmdline_of(tpgid)\n        gef_print(\"{:30s}  ->  {:d}\".format(\"TTY Process Group ID\", tpgid))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", tpgid_exec))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", tpgid_cmdline))\n        ttynr = stat[6]\n        major, minor = (ttynr >> 8) & 0xff, ((ttynr >> 20) << 8) | (ttynr & 0xff)\n        ttystr = self.get_tty_str(major, minor)\n        gef_print(\"{:30s}  ->  {:d} ({!r})\".format(\"  TTY Device Number\", ttynr, ttystr))\n        return\n\n    def show_parent(self):\n        gef_print(titlify(\"Parent Process Information\"))\n        ppid = int(self.get_state_of(Pid.get_pid())[\"PPid\"])\n        ppid_exec = self.get_process_path_of(ppid)\n        ppid_cmdline = self.get_cmdline_of(ppid)\n        gef_print(\"{:30s}  ->  {:d}\".format(\"Parent PID\", ppid))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", ppid_exec))\n        gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", ppid_cmdline))\n        return\n\n    def show_childs(self):\n        gef_print(titlify(\"Child Process Information\"))\n\n        children = self.get_children_pids(Pid.get_pid())\n        if not children:\n            gef_print(\"No child process\")\n            return\n\n        for i, cpid in enumerate(children, start=1):\n            cpid_exec = self.get_process_path_of(cpid)\n            cpid_cmdline = self.get_cmdline_of(cpid)\n            gef_print(\"{:30s}  ->  {:d}\".format(\"Child {:d} PID\".format(i), cpid))\n            gef_print(\"{:30s}  ->  {!r}\".format(\"  Executable\", cpid_exec))\n            gef_print(\"{:30s}  ->  {!r}\".format(\"  Command Line\", cpid_cmdline))\n        return\n\n    def show_info_thread(self):\n        gef_print(titlify(\"Thread Information\"))\n\n        pid = Pid.get_pid()\n        nthreads = self.get_state_of(pid)[\"Threads\"]\n        tgid = self.get_state_of(pid)[\"Tgid\"]\n        gef_print(\"{:30s}  ->  {:s}\".format(\"Num of Threads\", nthreads))\n        gef_print(\"{:30s}  ->  {:s}\".format(\"Thread Group ID\", tgid))\n        tids = self.get_thread_ids(pid)\n        gef_print(\"{:30s}  ->  {!r}\".format(\"Thread ID List\", tids))\n        return\n\n    def show_info_proc_ns(self):\n        gef_print(titlify(\"Namespace Information\"))\n\n        pid = Pid.get_pid()\n        gdb_pid = os.getpid()\n        ns_symbols = [\"cgroup\", \"ipc\", \"mnt\", \"net\", \"pid\", \"time\", \"user\", \"uts\"]\n        for ns in ns_symbols:\n            if not os.path.exists(\"/proc/{:d}/ns/{:s}\".format(pid, ns)):\n                continue\n            if not os.path.exists(\"/proc/{:d}/ns/{:s}\".format(gdb_pid, ns)):\n                continue\n            sym1 = os.readlink(\"/proc/{:d}/ns/{:s}\".format(pid, ns))\n            sym2 = os.readlink(\"/proc/{:d}/ns/{:s}\".format(gdb_pid, ns))\n            m = \"{:s} namespace separation\".format(ns.upper())\n            gef_print(\"{:30s}  ->  {!s}\".format(m, sym1 != sym2))\n\n        gef_print(titlify(\"Pid Namespace Information\"))\n        state = self.get_state_of(pid)\n        if len(state[\"NSpid\"].split()) > 1:\n            gef_print(\"{:30s}  ->  {:s}\".format(\n                \"Host PID  : Namespace PID\", re.sub(r\"\\s+\", \" : \", state[\"NSpid\"]),\n            ))\n            gef_print(\"{:30s}  ->  {:s}\".format(\n                \"Host PGID : Namespace PGID\", re.sub(r\"\\s+\", \" : \", state[\"NSpgid\"]),\n            ))\n            gef_print(\"{:30s}  ->  {:s}\".format(\n                \"Host SID  : Namespace SID\", re.sub(r\"\\s+\", \" : \", state[\"NSsid\"]),\n            ))\n            gef_print(\"{:30s}  ->  {:s}\".format(\n                \"Host TGID : Namespace TGID\", re.sub(r\"\\s+\", \" : \", state[\"NStgid\"]),\n            ))\n        else:\n            gef_print(\"{:30s}\".format(\"No pid namespace\"))\n\n        gef_print(titlify(\"User Namespace Information\"))\n        for u in self.get_uid_map(pid):\n            gef_print(\"{:30s}  ->  [{:#x} : {:#x} : {:#x}]\".format(\n                \"UID_MAP [NameSpace:Host:Range]\", u[0], u[1], u[2],\n            ))\n        for g in self.get_gid_map(pid):\n            gef_print(\"{:30s}  ->  [{:#x} : {:#x} : {:#x}]\".format(\n                \"GID_MAP [NameSpace:Host:Range]\", g[0], g[1], g[2],\n            ))\n        return\n\n    def get_state_string(self, proto, state):\n        if proto in [\"tcp\", \"tcp6\"]:\n            dic = {\n                0x01: \"ESTABLISHED\",\n                0x02: \"SYN_SENT\",\n                0x03: \"SYN_RECV\",\n                0x04: \"FIN_WAIT1\",\n                0x05: \"FIN_WAIT2\",\n                0x06: \"TIME_WAIT\",\n                0x07: \"CLOSE\",\n                0x08: \"CLOSE_WAIT\",\n                0x09: \"LAST_ACK\",\n                0x0a: \"LISTEN\",\n                0x0b: \"CLOSING\",\n                0x0c: \"NEW_SYN_RECV\",\n                0x0d: \"BOUND_INACTIVE\",\n            }\n        elif proto in [\"udp\", \"udp6\"]:\n            dic = {\n                0x07: \"LISTEN\",\n            }\n        elif proto in [\"unix\"]:\n            dic = {\n                0x00: \"FREE\",\n                0x01: \"LISTEN\", # \"UNCONNECTED\"\n                0x02: \"CONNECTING\",\n                0x03: \"CONNECTED\",\n                0x04: \"DISCONNECTING\",\n            }\n        else:\n            return str(int(state, 16))\n        return dic.get(int(state, 16), \"???\")\n\n    def get_proto_string(self, proto):\n        # proto string (for raw/raw6)\n        dic = {\n            0x00: \"IP\",\n            0x01: \"ICMP\",\n            0x02: \"IGMP\",\n            0x04: \"IPIP\",\n            0x06: \"TCP\",\n            0x08: \"EGP\",\n            0x0c: \"PUP\",\n            0x11: \"UDP\",\n            0x16: \"IDP\",\n            0x1d: \"TP\",\n            0x21: \"DCCP\",\n            0x29: \"IPV6\",\n            0x2b: \"ROUTING\",\n            0x2c: \"FRAGMENT\",\n            0x2e: \"RSVP\",\n            0x2f: \"GRE\",\n            0x32: \"ESP\",\n            0x33: \"AH\",\n            0x3a: \"ICMPV6\",\n            0x3b: \"NONE\",\n            0x3c: \"DSTOPTS\",\n            0x5c: \"MTP\",\n            0x5e: \"BEETPH\",\n            0x62: \"ENCAP\",\n            0x67: \"PIM\",\n            0x6c: \"COMP\",\n            0x73: \"L2TP\",\n            0x84: \"SCTP\",\n            0x87: \"MH\",\n            0x88: \"UDPLITE\",\n            0x89: \"MPLS\",\n            0x8f: \"ETHERNET\",\n            0x90: \"AGGFRAG\",\n            0xff: \"RAW\",\n            0x100: \"SMC\",\n            0x106: \"MPTCP\",\n        }\n        return dic.get(proto, str(proto))\n\n    def parse_ip_port(self, addr, proto):\n        # tcp/udp: return (ip, port)\n        # other: return (ip, proto)\n\n        ip, port = addr.split(\":\")\n\n        import socket\n        if len(ip) == 8: # ipv4\n            # 0100007F -> 127.0.0.1\n            ip = bytes.fromhex(ip)[::-1]\n            ip = socket.inet_ntop(socket.AF_INET, ip)\n        else: # ipv6\n            # 00000000000000000000000001000000 -> ::1\n            ip = bytes.fromhex(ip)\n            ip = b\"\".join([x[::-1] for x in slicer(ip, 4)])\n            ip = socket.inet_ntop(socket.AF_INET6, ip)\n            ip = \"[{:s}]\".format(ip)\n\n        if proto in [\"tcp\", \"tcp6\", \"udp\", \"udp6\"]:\n            port = int(port, 16)\n            return ip, port # str, int\n\n        # other protocol\n        real_proto = self.get_proto_string(int(port, 16))\n        return ip, real_proto # str, str\n\n    def get_extra_info(self):\n        # e.g., inode -> \"[tcp]           127.0.0.1:34588 -> 127.0.0.1:5001 (ESTABLISHED)\"\n\n        # get all sockets\n        pid = Pid.get_pid()\n        sockets = {}\n        path = \"/proc/{:d}/fd\".format(pid)\n        for fname in os.listdir(path):\n            fullpath = os.path.join(path, fname)\n            if os.path.islink(fullpath) and os.readlink(fullpath).startswith(\"socket:\"):\n                inode = os.readlink(fullpath).replace(\"socket:\", \"\")[1:-1]\n                sockets[int(inode)] = fname\n        if not sockets:\n            return sockets\n\n        # get entries\n        protocols = [\"tcp\", \"udp\", \"tcp6\", \"udp6\", \"unix\", \"raw\", \"raw6\"]\n        entries = {}\n        for prot in protocols:\n            lines = open(f\"/proc/{pid}/net/{prot}\", \"r\").readlines()\n            entries[prot] = [x.split() for x in lines[1:]]\n\n        extra_info = {}\n        for proto, proto_entries in entries.items():\n            for proto_entry in proto_entries:\n                # parse\n                if proto in [\"tcp\", \"tcp6\", \"udp\", \"udp6\", \"raw\", \"raw6\"]:\n                    _, local, remote, state, _, _, _, _, _, inode, *_ = proto_entry\n                elif proto == \"unix\":\n                    _, _, _, _, _, state, inode, *path = proto_entry\n                    path = path[0] if path else \"\"\n\n                # check if socket\n                inode = int(inode)\n                if inode not in sockets:\n                    continue\n\n                # get state\n                state = self.get_state_string(proto, state)\n\n                # make extra info\n                if proto in [\"tcp\", \"tcp6\", \"udp\", \"udp6\"]:\n                    local = self.parse_ip_port(local, proto)\n                    if state == \"LISTEN\":\n                        extra_info[inode] = \"{:14s}  {:s}:{:d} ({:s})\".format(\n                            \"[{:s}]\".format(proto),\n                            *local, state,\n                        )\n                    else:\n                        remote = self.parse_ip_port(remote, proto)\n                        extra_info[inode] = \"{:14s}  {:s}:{:d} -> {:s}:{:d} ({:s})\".format(\n                            \"[{:s}]\".format(proto),\n                            *local, *remote, state,\n                        )\n                elif proto in [\"raw\", \"raw6\"]:\n                    local = self.parse_ip_port(local, proto)\n                    remote = self.parse_ip_port(remote, proto)\n                    extra_info[inode] = \"{:14s}  {:s} -> {:s} (st={:s})\".format(\n                        \"[{:s}/{:s}]\".format(proto, local[1]),\n                        local[0], remote[0], state,\n                    )\n                elif proto == \"unix\":\n                    extra_info[inode] = \"{:14s}  {!r} ({:s})\".format(\n                        \"[{:s}]\".format(proto),\n                        path, state,\n                    )\n        return extra_info\n\n    def show_fds(self):\n        gef_print(titlify(\"File Descriptors\"))\n\n        pid = Pid.get_pid()\n        path = \"/proc/{:d}/fd\".format(pid)\n\n        gef_print(\"{:30s}  ->  {:s}\".format(\"Num of FD slots\", self.get_state_of(pid)[\"FDSize\"]))\n        items = os.listdir(path)\n        if not items:\n            gef_print(\"No FD opened\")\n            return\n\n        extra_info = self.get_extra_info()\n\n        for fname in items:\n            fullpath = os.path.join(path, fname)\n            if os.path.islink(fullpath):\n                content = os.readlink(fullpath)\n                if content.startswith(\"socket:[\"):\n                    inode = int(content.replace(\"socket:\", \"\")[1:-1])\n                    extra = extra_info.get(inode, \"\")\n                    gef_print(\"{:30s}  ->  {:s}  {:s}\".format(fullpath, content, extra))\n                else:\n                    gef_print(\"{:30s}  ->  {:s}\".format(fullpath, content))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_gdb_target_local\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\"))\n    def do_invoke(self, args):\n        self.show_info_proc()\n        self.show_info_proc_extra()\n        self.show_parent()\n        self.show_childs()\n        self.show_info_thread()\n        self.show_info_proc_ns()\n        self.show_fds()\n        return\n\n\n@register_command\nclass FileDescriptorsCommand(GenericCommand):\n    \"\"\"Display opened file descriptors.\"\"\"\n\n    _cmdline_ = \"fds\"\n    _category_ = \"02-a. Process Information - General\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def fd_dump(self):\n        pid = Pid.get_pid()\n        if not pid:\n            err(\"Could not find the local pid\")\n            return\n        path = \"/proc/{:d}/fd\".format(pid)\n\n        items = os.listdir(path)\n        if not items:\n            err(\"No FD opened\")\n            return\n\n        for fname in items:\n            fullpath = os.path.join(path, fname)\n            if os.path.islink(fullpath):\n                gef_print(\"{:32s}  ->  {:s}\".format(fullpath, os.readlink(fullpath)))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.fd_dump()\n        return\n\n\n@register_command\nclass ProcDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump each file under `/proc/PID`.\"\"\"\n\n    _cmdline_ = \"proc-dump\"\n    _category_ = \"02-a. Process Information - General\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def dump_environ(self, path):\n        data = open(path, \"rb\").read()\n        for line in sorted(data.split(b\"\\0\")):\n            if line:\n                line = String.bytes2str(line)\n                key, val = line.split(\"=\", 1)\n                self.out.append(\"{:s}={:s}\".format(Color.boldify(key), val))\n        return\n\n    def dump_cmdline(self, path):\n        data = open(path, \"rb\").read()\n        for line in data.split(b\"\\0\"):\n            if line:\n                self.out.append(String.bytes2str(line))\n        return\n\n    def dump_auxv(self, path):\n        data = open(path, \"rb\").read()\n        data = slice_unpack(data, current_arch.ptrsize)\n        for i in range(0, len(data), 2):\n            typ = data[i]\n            val = data[i + 1]\n            self.out.append(\"{:#8x}: {:#x}\".format(typ, val))\n        return\n\n    def dump_syscall(self, path):\n        data = String.bytes2str(open(path, \"rb\").read())\n        self.out.append(data.strip())\n\n        self.out.append(\"----- parsed -----\")\n\n        if int(data.split()[0]) < 0:\n            tag = [\"NR\", \"sp\", \"pc\"]\n        else:\n            tag = [\"NR\", \"arg1\", \"arg2\", \"arg3\", \"arg4\", \"arg5\", \"arg6\", \"sp\", \"pc\"]\n\n        for i, elem in enumerate(data.split()):\n            if i < len(tag):\n                elem_name = tag[i]\n            else:\n                elem_name = \"???\"\n            elem_name = Color.boldify(\"{:4s}\".format(elem_name))\n\n            if i == 0: # NR\n                nr = int(elem)\n                syscall_table = get_syscall_table()\n                if syscall_table is None:\n                    self.out.append(\"Could not find the syscall table\")\n                    return\n                if nr >= 0 and syscall_table and nr in syscall_table.nr_table:\n                    syscall_name = syscall_table.nr_table[nr].name\n                    self.out.append(\"{:2d} {:s}: {:s} ({:s})\".format(i + 1, elem_name, elem, syscall_name))\n                else:\n                    self.out.append(\"{:2d} {:s}: {:s}\".format(i + 1, elem_name, elem))\n            else: # argN, sp, pc\n                address = int(elem, 0)\n                sym = Symbol.get_symbol_string(address)\n                elem = \"{!s}{:s}\".format(ProcessMap.lookup_address(address), sym)\n                self.out.append(\"{:2d} {:s}: {:s}\".format(i + 1, elem_name, elem))\n        return\n\n    def dump_stat(self, path):\n        data = String.bytes2str(open(path, \"rb\").read())\n        self.out.append(data.strip())\n\n        self.out.append(\"----- parsed -----\")\n\n        tag = [\n            \"pid\", \"comm\", \"state\", \"ppid\", \"pgrp\", \"session\", \"tty_nr\", \"tpgid\", \"flags\",\n            \"minflt\", \"cminflt\", \"majflt\", \"cmajflt\", \"utime\", \"stime\", \"cutime\", \"cstime\",\n            \"priority\", \"nice\", \"num_threads\", \"itrealvalue\", \"starttime\", \"vsize\",\n            \"rss\", \"rsslim\", \"startcode\", \"endcode\", \"startstack\", \"kstkesp\", \"kstkeip\",\n            \"signal\", \"blocked\", \"sigignore\", \"sigcatch\", \"wchan\", \"nswap\", \"cnswap\",\n            \"exit_signal\", \"processor\", \"rt_priority\", \"policy\", \"delayacct_blkio_ticks\",\n            \"guest_time\", \"cguest_time\", \"start_data\", \"end_data\", \"start_brk\",\n            \"arg_start\", \"arg_end\", \"env_startr\", \"env_end\", \"exit_code\",\n        ]\n\n        max_width = max(len(x) for x in tag)\n        lpos = data.find(\"(\")\n        rpos = data.rfind(\")\") + 1\n        data = [data[:lpos].strip(), data[lpos:rpos]] + data[rpos:].split()\n\n        for i, elem in enumerate(data):\n            if i < len(tag):\n                elem_name = tag[i]\n            else:\n                elem_name = \"???\"\n            elem_name = Color.boldify(\"{:{:d}s}\".format(elem_name, max_width))\n\n            if i + 1 in [25, 26, 27, 28, 29, 30, 45, 46, 47, 48, 49, 50, 51]:\n                address = int(elem)\n                sym = Symbol.get_symbol_string(address)\n                elem = \"{!s}{:s}\".format(ProcessMap.lookup_address(address), sym)\n            elif i + 1 in [23, 33, 34]:\n                elem = hex(int(elem))\n            self.out.append(\"{:2d} {:s}: {:s}\".format(i + 1, elem_name, elem))\n        return\n\n    def dump_statm(self, path):\n        data = String.bytes2str(open(path, \"rb\").read())\n        self.out.append(data.strip())\n\n        self.out.append(\"----- parsed -----\")\n\n        tag = [\"size\", \"resident\", \"shared\", \"text\", \"lib\", \"data\", \"dt\"]\n        max_width = max(len(x) for x in tag)\n\n        for i, elem in enumerate(data.split()):\n            if i < len(tag):\n                elem_name = tag[i]\n            else:\n                elem_name = \"???\"\n            elem_name = Color.boldify(\"{:{:d}s}\".format(elem_name, max_width))\n            self.out.append(\"{:2d} {:s}: {:s}\".format(i + 1, elem_name, elem))\n        return\n\n    def dump_status(self, path):\n        try:\n            column_command = GefUtil.which(\"column\")\n        except FileNotFoundError as e:\n            self.out.append(\"{}\".format(e))\n            return\n\n        ret = GefUtil.gef_execute_external([column_command, \"-s:\", \"-t\", path], as_list=True)\n        for line in ret:\n            r = line.split(maxsplit=1)\n            if len(r) == 2:\n                k, v = r[0], r[1]\n            else:\n                k, v = r[0], \"\"\n            k = k.strip() + \":\"\n            v = v.replace(\"\\t\", \"\").strip()\n            self.out.append(\"{:30s} {:s}\".format(k, v))\n        return\n\n    def dump_rt_acct(self, path):\n        try:\n            hexdump_command = GefUtil.which(\"hexdump\")\n        except FileNotFoundError as e:\n            self.out.append(\"{}\".format(e))\n            return\n\n        ret = GefUtil.gef_execute_external([hexdump_command, \"-C\", path], as_list=True)\n        self.out.extend(ret)\n        return\n\n    def dump_mounts(self, path):\n        try:\n            column_command = GefUtil.which(\"column\")\n        except FileNotFoundError as e:\n            self.out.append(\"{}\".format(e))\n            return\n\n        ret = GefUtil.gef_execute_external([column_command, \"-t\", path], as_list=True)\n        self.out.extend(ret)\n        return\n\n    def dump_raw(self, path):\n        try:\n            column_command = GefUtil.which(\"column\")\n        except FileNotFoundError as e:\n            self.out.append(\"{}\".format(e))\n            return\n\n        data = open(path, \"rb\").read()\n        data = data.replace(b\"tx_queue \", b\"tx_queue:\")\n        data = data.replace(b\" tr \", b\" tr:\")\n        tmp_fd, tmp_filename = GefUtil.mkstemp(prefix=\"proc-dump\")\n        os.fdopen(tmp_fd, \"wb\").write(data)\n        ret = GefUtil.gef_execute_external([column_command, \"-t\", tmp_filename], as_list=True)\n        os.unlink(tmp_filename)\n        self.out.extend(ret)\n        return\n\n    def dump_dev(self, path):\n        try:\n            column_command = GefUtil.which(\"column\")\n        except FileNotFoundError as e:\n            self.out.append(\"{}\".format(e))\n            return\n\n        data = open(path, \"rb\").read()\n        data = data.replace(b\"|\", b\" |\")\n        data = re.sub(rb\"\\|\\s*Receive\", b\"|Receive\", data)\n        data = re.sub(rb\"\\|\\s*Transmit\", b\"|Transmit\", data)\n\n        tmp_fd, tmp_filename = GefUtil.mkstemp(prefix=\"proc-dump\")\n        os.fdopen(tmp_fd, \"wb\").write(data)\n        ret = GefUtil.gef_execute_external([column_command, \"-t\", tmp_filename], as_list=True)\n        os.unlink(tmp_filename)\n\n        wrong = ret[0].rfind(\"|\")\n        rright = ret[1].rfind(\"|\")\n        lright = ret[1].find(\"|\")\n        ret[0] = (ret[0][:wrong] + \" \" * (rright - wrong) + ret[0][wrong:]).rstrip()\n\n        ret[0] = re.sub(r\"\\|(\\S+)\", \"| \\\\1 \", ret[0])\n        ret[1] = re.sub(r\"\\|(\\S+)\", \"| \\\\1 \", ret[1])\n        for i in range(2, len(ret)):\n            ret[i] = ret[i][:lright] + \"  \" + ret[i][lright:]\n            ret[i] = ret[i][:rright] + \"  \" + ret[i][rright:]\n\n        self.out.extend(ret)\n        return\n\n    def dump_igmp(self, path):\n        fd = open(path, \"rb\")\n        for line in fd.readlines():\n            self.out.append(String.bytes2str(line.rstrip())) # no-lstrip\n        return\n\n    def dump_netstat(self, path):\n        data = String.bytes2str(open(path, \"rb\").read())\n        table = [line.split() for line in data.splitlines()]\n        for idx in range(0, len(table), 2):\n            for i, (k, v) in enumerate(zip(*table[idx:idx + 2])):\n                if i == 0:\n                    self.out.append(\"{:s}\".format(k))\n                else:\n                    self.out.append(\"  {:30s} {:s}\".format(k + \":\", v))\n        return\n\n    def dump_default(self, path):\n        if not os.access(path, os.R_OK):\n            self.out.append(\"{:s} No permission to read\".format(Color.colorify(\"[!]\", \"bold red\")))\n            return\n\n        try:\n            fd = open(path, \"rb\")\n        except OSError:\n            self.out.append(\"{:s} Failed to open\".format(Color.colorify(\"[!]\", \"bold red\")))\n            return\n\n        try:\n            for line in fd.readlines():\n                self.out.append(String.bytes2str(line).strip())\n        except OSError:\n            self.out.append(\"{:s} Parse failed\".format(Color.colorify(\"[!]\", \"bold red\")))\n        return\n\n    def proc_dump(self):\n        pid = Pid.get_pid()\n        for root, dirs, files in os.walk(\"/proc/{:d}/\".format(pid)):\n            files = sorted(files)\n\n            if \"task\" in dirs:\n                dirs.remove(\"task\") # in-place change to skip /proc/<pid>/task/\n\n            for f in files:\n                path = os.path.join(root, f)\n                self.out.append(titlify(path))\n\n                if os.path.islink(path):\n                    self.out.append(Color.colorify(\"{:s} -> {:s}\".format(path, os.readlink(path)), \"blue\"))\n                    continue\n\n                if f in [\"pagemap\", \"mem\"]:\n                    self.out.append(\"{:s} skipped\".format(Color.colorify(\"[*]\", \"bold yellow\"))) # too large\n                    continue\n\n                if f == \"environ\":\n                    self.dump_environ(path)\n                    continue\n\n                if f in [\"cmdline\", \"context\"]:\n                    self.dump_cmdline(path)\n                    continue\n\n                if f == \"auxv\":\n                    self.dump_auxv(path)\n                    continue\n\n                if f == \"syscall\":\n                    self.dump_syscall(path)\n                    continue\n\n                if f == \"stat\":\n                    self.dump_stat(path)\n                    continue\n\n                if f == \"statm\":\n                    self.dump_statm(path)\n                    continue\n\n                if f == \"rt_acct\":\n                    self.dump_rt_acct(path)\n                    continue\n\n                if f == \"status\":\n                    self.dump_status(path)\n                    continue\n\n                if f in [\"mounts\", \"mountinfo\", \"mountstats\", \"unix\", \"protocols\"]:\n                    self.dump_mounts(path)\n                    continue\n\n                if f in [\"raw\", \"tcp\", \"udp\", \"icmp\", \"raw6\", \"tcp6\", \"udp6\", \"icmp6\", \"udplite\", \"udplite6\"]:\n                    self.dump_raw(path)\n                    continue\n\n                if f == \"dev\":\n                    self.dump_dev(path)\n                    continue\n\n                if f in [\"igmp\", \"fib_trie\", \"wireless\"]:\n                    self.dump_igmp(path)\n                    continue\n\n                if f in [\"netstat\", \"snmp\"]:\n                    self.dump_netstat(path)\n                    continue\n\n                self.dump_default(path)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_gdb_target_local\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.out = []\n        self.proc_dump()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass CapabilityCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display the capabilities of the debugging process.\"\"\"\n\n    _cmdline_ = \"capability\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"also display detailed bit information other than cap_eff.\")\n    _syntax_ = parser.format_help()\n\n    def get_thread_ids(self, pid):\n        try:\n            tids = os.listdir(\"/proc/{:d}/task\".format(pid))\n            return [int(x) for x in tids]\n        except (FileNotFoundError, OSError):\n            return []\n\n    def print_cap_details(self, name, cap):\n        bit_info = [\n            [40, \"CAP_CHECKPOINT_RESTORE\", \"Update /proc/sys/kernel/ns_last_pid; read /proc/[another_pid]/map_files; etc.\"],\n            [39, \"CAP_BPF\", \"Allow privileged BPF operations\"],\n            [38, \"CAP_PERFMON\", \"Allow various performance-monitoring mechanisms; allow perf_event_open(2); allow some BPF operations\"],\n            [37, \"CAP_AUDIT_READ\", \"Allow reading the audit log via a multicast netlink socket\"],\n            [36, \"CAP_BLOCK_SUSPEND\", \"Allow features that can block system suspend\"],\n            [35, \"CAP_WAKE_ALARM\", \"Trigger something that will wake up the system\"],\n            [34, \"CAP_SYSLOG\", \"Allow privileged syslog(2) operations; View kernel addresses exposed via /proc even if kptr_restrict=1\"],\n            [33, \"CAP_MAC_ADMIN\", \"Allow MAC configuration or state changes\"],\n            [32, \"CAP_MAC_OVERRIDE\", \"Override MAC\"],\n            [31, \"CAP_SETFCAP\", \"Set arbitrary capabilities on a file\"],\n            [30, \"CAP_AUDIT_CONTROL\", \"Enable/disable kernel audit; change audit filter rules; retrieve audit status and filter rules\"],\n            [29, \"CAP_AUDIT_WRITE\", \"Write records to kernel audit log\"],\n            [28, \"CAP_LEASE\", \"Establish leases\"],\n            [27, \"CAP_MKNOD\", \"Create special files using mknod(2)\"],\n            [26, \"CAP_SYS_TTY_CONFIG\", \"Allow vhangup(2); allow various privileged ioctl(2) operations on virtual terminals\"],\n            [25, \"CAP_SYS_TIME\", \"Set system clock; set real-time (hardware) clock\"],\n            [24, \"CAP_SYS_RESOURCE\", \"Override disk quota limits; override RLIMIT_NPROC resource limit; etc.\"],\n            [23, \"CAP_SYS_NICE\", \"Lower the process nice value and change the nice value for arbitrary processes; etc.\"],\n            [22, \"CAP_SYS_BOOT\", \"Allow reboot(2) and kexec_load(2)\"],\n            [21, \"CAP_SYS_ADMIN\", \"Allow various privileges operations\"],\n            [20, \"CAP_SYS_PACCT\", \"Allow acct(2)\"],\n            [19, \"CAP_SYS_PTRACE\", \"Trace arbitrary processes using ptrace(2); etc.\"],\n            [18, \"CAP_SYS_CHROOT\", \"Allow chroot(2); change mount namespaces using setns(2)\"],\n            [17, \"CAP_SYS_RAWIO\", \"Perform I/O port operations; etc.\"],\n            [16, \"CAP_SYS_MODULE\", \"Load and unload kernel modules\"],\n            [15, \"CAP_IPC_OWNER\", \"Bypass permission checks for operations on SystemV IPC objects\"],\n            [14, \"CAP_IPC_LOCK\", \"Lock memory; allocate memory using huge pages\"],\n            [13, \"CAP_NET_RAW\", \"Use RAW and PACKET sockets; bind to any address for transparent proxying\"],\n            [12, \"CAP_NET_ADMIN\", \"Perform various network-related operations\"],\n            [11, \"CAP_NET_BROADCAST\", \"(Unused) Make socket broadcasts, and listen to multicast\"],\n            [10, \"CAP_NET_BIND_SERVICE\", \"Bind a socket to Internet domain privileged ports (less than 1024)\"],\n            [9, \"CAP_LINUX_IMMUTABLE\", \"Set the FS_APPEND_FL and FS_IMMUTABLE_FL inode flags\"],\n            [8, \"CAP_SETPCAP\", \"Add any capability from the calling thread's bounding set to its inheritable set; etc.\"],\n            [7, \"CAP_SETUID\", \"Make arbitrary manipulations of process UIDs; etc.\"],\n            [6, \"CAP_SETGID\", \"Make arbitrary manipulations of process GIDs and supplementary GID list; etc.\"],\n            [5, \"CAP_KILL\", \"Bypass permission checks for sending signals\"],\n            [4, \"CAP_FSETID\", \"Don't clear SUID and SGID bits when a file is modified; etc.\"],\n            [3, \"CAP_FOWNER\", \"Bypass permission checks whether FSUID == file UID; set ACLs; etc.\"],\n            [2, \"CAP_DAC_READ_SEARCH\", \"Bypass permission checks of file read, dir read/exec; etc.\"],\n            [1, \"CAP_DAC_OVERRIDE\", \"Bypass permission checks of file read/write/exec\"],\n            [0, \"CAP_CHOWN\", \"Make arbitrary changes to file UIDs and GIDs\"],\n        ]\n        out = BitInfo(name, 64, bit_info).make_out(cap)\n        self.out.append(titlify(\"\"))\n        self.out.extend(out)\n        self.out.append(titlify(\"\"))\n        return\n\n    def print_capability_from_pid(self):\n        pid = Pid.get_pid()\n        if pid is None:\n            return\n\n        tids = self.get_thread_ids(pid)\n        for tid in tids:\n            self.out.append(titlify(\"Thread capability set [PID={:d}, TID={:d}]\".format(pid, tid)))\n            try:\n                status_path = \"/proc/{:d}/task/{:d}/status\".format(pid, tid)\n                status = open(status_path, \"r\").read()\n            except (FileNotFoundError, OSError):\n                self.err_add_out(\"Failed to get the information of capability from {:s}\".format(status_path))\n                continue\n\n            caps = {}\n            m = re.search(r\"CapInh:\\s+(.+)\", status)\n            if m:\n                caps[\"cap_inh\"] = int(m.group(1), 16)\n            m = re.search(r\"CapPrm:\\s+(.+)\", status)\n            if m:\n                caps[\"cap_prm\"] = int(m.group(1), 16)\n            m = re.search(r\"CapEff:\\s+(.+)\", status)\n            if m:\n                caps[\"cap_eff\"] = int(m.group(1), 16)\n            m = re.search(r\"CapBnd:\\s+(.+)\", status)\n            if m:\n                caps[\"cap_bnd\"] = int(m.group(1), 16)\n            m = re.search(r\"CapAmb:\\s+(.+)\", status)\n            if m:\n                caps[\"cap_amb\"] = int(m.group(1), 16)\n\n            if \"cap_prm\" in caps:\n                msg = \"Capability set that Effective and Inheritable are allowed to have\"\n                self.out.append(\"Permitted  : {:#018x} - {:s}\".format(caps[\"cap_prm\"], msg))\n                if self.args.verbose:\n                    self.print_cap_details(\"cap_prm\", caps[\"cap_prm\"])\n            if \"cap_inh\" in caps:\n                msg = \"Capability set that can be inherited when execve(2)\"\n                self.out.append(\"Inheritable: {:#018x} - {:s}\".format(caps[\"cap_inh\"], msg))\n                if self.args.verbose:\n                    self.print_cap_details(\"cap_inh\", caps[\"cap_inh\"])\n            if \"cap_amb\" in caps:\n                msg = \"Capability set that inherited when execve(2) not suid/sgid program\"\n                self.out.append(\"Ambient    : {:#018x} - {:s}\".format(caps[\"cap_amb\"], msg))\n                if self.args.verbose:\n                    self.print_cap_details(\"cap_amb\", caps[\"cap_amb\"])\n            if \"cap_eff\" in caps:\n                msg = \"Capability set that kernel actually uses to determine privileges\"\n                self.out.append(\"Effective  : {:#018x} - {:s}\".format(caps[\"cap_eff\"], msg))\n                if self.args.verbose:\n                    self.print_cap_details(\"cap_eff\", caps[\"cap_eff\"])\n            if \"cap_bnd\" in caps:\n                msg = \"Capability set that limits the capabilities set that can be acquired\"\n                self.out.append(\"Bounding   : {:#018x} - {:s}\".format(caps[\"cap_bnd\"], msg))\n                if self.args.verbose:\n                    self.print_cap_details(\"cap_bnd\", caps[\"cap_bnd\"])\n        return\n\n    def print_capability_from_file(self):\n        filepath = Path.get_filepath()\n        if filepath is None:\n            return\n\n        self.out.append(titlify(\"File capability set [{:s}]\".format(filepath)))\n        try:\n            raw_caps = os.getxattr(filepath, \"security.capability\")\n        except OSError:\n            self.err_add_out(\"No data available\")\n            return\n\n        caps = {}\n        magic = struct.unpack(\"<I\", raw_caps[:4])[0]\n        caps[\"magic\"] = magic & ~1\n        caps[\"cap_eff\"] = magic & 1\n        if caps[\"magic\"] == 0x0100_0000:\n            cap_prm, cap_inh = struct.unpack(\"<II\", raw_caps[4:12])\n        elif caps[\"magic\"] == 0x0200_0000:\n            cap_prm_low, cap_inh_low, cap_prm_high, cap_inh_high = struct.unpack(\"<IIII\", raw_caps[4:20])\n            cap_prm = (cap_prm_high << 32) | cap_prm_low\n            cap_inh = (cap_inh_high << 32) | cap_inh_low\n        elif caps[\"magic\"] == 0x0300_0000:\n            cap_prm_low, cap_inh_low, cap_prm_high, cap_inh_high, rootid = struct.unpack(\"<IIIII\", raw_caps[4:24])\n            cap_prm = (cap_prm_high << 32) | cap_prm_low\n            cap_inh = (cap_inh_high << 32) | cap_inh_low\n            caps[\"rootid\"] = rootid\n        else:\n            self.err_add_out(\"Invalid magic values: {:#x}\".format(magic))\n            return\n        caps[\"cap_prm\"] = cap_prm\n        caps[\"cap_inh\"] = cap_inh\n\n        if \"magic\" in caps:\n            msg = \"Magic number: ver1: 0x01000000, ver2:0x02000000, ver3:0x03000000\"\n            self.out.append(\"Magic      : {:#010x} - {:s}\".format(caps[\"magic\"], msg))\n        if \"cap_eff\" in caps:\n            msg = \"If 1, new cap_prm are added to new cap_eff after execve(2)\"\n            self.out.append(\"Effective  : {:#03x} - {:s}\".format(caps[\"cap_eff\"], msg))\n        if \"cap_prm\" in caps:\n            msg = \"Capability set that permitted to the thread, regardless of the thread's cap_inh\"\n            self.out.append(\"Permitted  : {:#018x} - {:s}\".format(caps[\"cap_prm\"], msg))\n            if self.args.verbose:\n                self.print_cap_details(\"cap_prm\", caps[\"cap_prm\"])\n        if \"cap_inh\" in caps:\n            msg = \"Capability set that is ANDed with thread cap_inh to determine cap_inh after execve(2)\"\n            self.out.append(\"Inheritable: {:#018x} - {:s}\".format(caps[\"cap_inh\"], msg))\n            if self.args.verbose:\n                self.print_cap_details(\"cap_inh\", caps[\"cap_inh\"])\n        if \"rootid\" in caps:\n            msg = \"UID of root in user namespace\"\n            self.out.append(\"Root ID    : {:#010x} - {:s}\".format(caps[\"rootid\"], msg))\n        return\n\n    @parse_args\n    @only_if_gdb_target_local\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.out = []\n        self.print_capability_from_pid()\n        self.print_capability_from_file()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass SmartMemoryDumpCommand(GenericCommand):\n    \"\"\"Dump the memory of the entire process smartly.\"\"\"\n\n    _cmdline_ = \"smart-memory-dump\"\n    _category_ = \"03-f. Memory - Dump/Load\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-p\", \"--prefix\", default=\"\",\n                        help=\"use this name for the dump destination file prefix. (default: '')\")\n    parser.add_argument(\"-s\", \"--suffix\", default=\"\",\n                        help=\"use this name for the dump destination file suffix. (default: '')\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP include filter.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP exclude filter.\")\n    parser.add_argument(\"-c\", \"--commit\", action=\"store_true\", help=\"actually perform the dump.\")\n    parser.add_argument(\"-m\", \"--max-region-size\", type=AddressUtil.parse_address, default=0x1000_0000,\n                        help=\"maximum size of dump region. (default: %(default)#x; 0: infinity)\")\n    _syntax_ = parser.format_help()\n\n    def do_dump(self, filepath, start, size):\n        if self.args.max_region_size and self.args.max_region_size < size:\n            warn(\"Too large, so skip: {:s}\".format(filepath))\n            return\n\n        size_str = GefUtil.get_size_str(size)\n\n        if self.args.commit:\n            # make dir\n            if not os.path.exists(os.path.dirname(filepath)):\n                os.mkdir(os.path.dirname(filepath))\n\n            # read\n            try:\n                data = read_memory(start, size)\n            except gdb.MemoryError:\n                warn(\"Memory read error; skipped: {:s} ({:s})\".format(filepath, size_str))\n                return\n\n            # write\n            open(filepath, \"wb\").write(data)\n            info(\"Saved to {:s} ({:s})\".format(filepath, size_str))\n        else:\n            info(\"It will be saved to {:s} ({:s})\".format(filepath, size_str))\n        return\n\n    def smart_memory_dump(self, maps, prefix, suffix):\n        dirpath = os.path.join(GEF_TEMP_DIR, \"mem-dump-\" + GefUtil.now_str())\n        width = current_arch.ptrsize * 2\n        total_size = 0\n\n        for entry in maps:\n            if isinstance(entry, list):\n                start = entry[0]\n                end = entry[0] + entry[1]\n                size = entry[1]\n                perm = entry[2].lower()\n                path = \"\"\n            else:\n                start = entry.page_start\n                end = entry.page_end\n                size = end - start\n                perm = str(entry.permission)\n\n                if not entry.path.startswith((\"[\", \"<\")):\n                    path = os.path.basename(entry.path)\n                else:\n                    path = entry.path\n                    path = path.replace(\"[\", \"\").replace(\"]\", \"\") # consider [heap], [stack], [vdso]\n                    path = path.replace(\"<\", \"\").replace(\">\", \"\") # consider <tls-th1>, <explored>\n                path = path.replace(\" \", \"_\") # consider deleted case. e.g., /path/to/file (deleted)\n\n            dumpfile_name = \"{:s}{:0{:d}x}-{:0{:d}x}_{:s}_{:s}{:s}.raw\".format(\n                prefix, start, width, end, width, perm, path, suffix,\n            )\n            filepath = os.path.join(dirpath, dumpfile_name)\n\n            # filtering\n            if self.args.filter and not any(filt.search(dumpfile_name) for filt in self.args.filter):\n                continue\n            if self.args.exclude and any(ex.search(dumpfile_name) for ex in self.args.exclude):\n                continue\n\n            # dump\n            self.do_dump(filepath, start, size)\n            total_size += size\n\n        info(\"Total size: {:s}\".format(GefUtil.get_size_str(total_size)))\n\n        if not self.args.commit:\n            info(\"The directory name is replaced with the latest timestamp\")\n            warn('This dry run mode skips dumping; add \"--commit\" to proceed')\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if is_qemu_system():\n            maps = Kernel.get_maps()\n        else:\n            maps = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True)\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        prefix = self.args.prefix\n        if prefix:\n            prefix = prefix + \"_\"\n\n        suffix = self.args.suffix\n        if suffix:\n            suffix = \"_\" + suffix\n\n        self.smart_memory_dump(maps, prefix, suffix)\n        return\n\n\n@register_command\nclass HijackFdCommand(GenericCommand):\n    \"\"\"Redirect the file descriptor during execution.\"\"\"\n\n    _cmdline_ = \"hijack-fd\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"old_fd\", metavar=\"OLD_FD\", type=int, help=\"file descriptor number to redirect.\")\n    parser.add_argument(\"new_output\", metavar=\"NEW_OUTPUT\", type=str, help=\"the location redirected data is stored.\")\n    parser.add_argument(\"--fd-adjust-connect\", type=int, default=0,\n                        help=\"slide value when `connect` syscall result and the actual opened FD differ (for old qemu-user).\")\n    parser.add_argument(\"--fd-adjust-dup3\", type=int, default=0,\n                        help=\"slide value when `dup3` syscall result and the actual opened FD differ (for old qemu-user).\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 2 /tmp/gef/stderr.txt\",\n        \"{0:s} 2 localhost:8000  # determined as the socket by the presence of `:`.\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def call_syscall(self, syscall_name, args):\n        args = \" \".join([hex(x) if x >= 0 else str(x) for x in args])\n        cmd = \"call-syscall {:s} {:s}\".format(syscall_name, args)\n        self.quiet_info(cmd)\n        res = gdb.execute(cmd, to_string=True)\n        output_line = res.splitlines()[-1]\n        self.quiet_info(output_line)\n        return int(output_line.split()[2], 0)\n\n    def write_stack(self, data):\n        data = String.str2bytes(data)\n\n        # get stack address\n        vmmap = ProcessMap.get_process_maps()\n        stack_addrs = [entry.page_start for entry in vmmap if entry.path == \"[stack]\"]\n        if len(stack_addrs) == 0:\n            err(\"Could not find the stack\")\n            return None, None\n        stack_addr = stack_addrs[0]\n\n        # read original contents\n        try:\n            original_contents = read_memory(stack_addr, len(data))\n        except gdb.MemoryError:\n            err(\"Failed to read stack\")\n            return None, None\n\n        self.quiet_info(\"Original contents: {!s} @ {:#x}\".format(original_contents, stack_addr))\n        self.quiet_info(\"Overwrite data: {!s}\".format(data))\n\n        # overwrite it\n        try:\n            write_memory(stack_addr, data)\n        except Exception:\n            err(\"Failed to write stack\")\n            return None, None\n\n        # read again and check\n        if read_memory(stack_addr, len(data)) != data:\n            err(\"Failed to write stack\")\n            return None, None\n\n        return stack_addr, original_contents\n\n    def get_fd_from_file_open(self):\n        # call open\n        stack_addr, original_contents = self.write_stack(self.args.new_output + \"\\0\")\n        if stack_addr is None:\n            return None\n\n        self.quiet_info(\"Trying to open {:s}\".format(Color.boldify(self.args.new_output)))\n\n        AT_FDCWD = -100\n        flags = self.O_APPEND | self.O_CREAT | self.O_RDWR\n        mode = 0o666\n        # open does not exist in aarch64. So use openat instead of open.\n        open_fd = self.call_syscall(\"openat\", [AT_FDCWD, stack_addr, flags, mode])\n        write_memory(stack_addr, original_contents) # revert\n\n        if AddressUtil.is_msb_on(open_fd):\n            err(\"Failed to open {:s}\".format(self.args.new_output))\n            return None\n\n        self.quiet_info(\"Opened {:s} with 0o666 as fd #{:d}\".format(Color.boldify(self.args.new_output), open_fd))\n        return open_fd\n\n    def get_fd_from_connect_server(self):\n        import socket\n        address = socket.gethostbyname(self.args.new_output.split(\":\")[0])\n        port = int(self.args.new_output.split(\":\")[1])\n\n        # call socket\n        sock_fd = self.call_syscall(\"socket\", [self.AF_INET, self.SOCK_STREAM, 0])\n        if AddressUtil.is_msb_on(sock_fd):\n            err(\"Failed to create socket\")\n            return None\n        self.quiet_info(\"Created socket fd #{:d}\".format(sock_fd))\n\n        # call connect (Also supports big endian)\n        sockaddr_in = p16(self.AF_INET) + struct.pack(\"<H\", socket.htons(port)) + socket.inet_aton(address)\n        stack_addr, original_contents = self.write_stack(sockaddr_in)\n        if stack_addr is None:\n            return None\n\n        self.quiet_info(\"Trying to connect to {:s}\".format(Color.boldify(self.args.new_output)))\n        connect_result = self.call_syscall(\"connect\", [sock_fd - self.args.fd_adjust_connect, stack_addr, 16])\n        write_memory(stack_addr, original_contents) # revert\n\n        if AddressUtil.is_msb_on(connect_result):\n            err(\"Failed to connect to {:s}:{:d}\".format(address, port))\n            return\n\n        self.quiet_info(\"Connected to {:s} as fd #{:d}\".format(Color.boldify(self.args.new_output), sock_fd))\n        return sock_fd\n\n    def hijack_fd(self):\n        if \":\" in self.args.new_output:\n            new_fd = self.get_fd_from_connect_server()\n        else:\n            new_fd = self.get_fd_from_file_open()\n        if new_fd is None:\n            return\n\n        # call dup3\n        # dup2 does not exist in aarch64. So use dup3 instead of dup2.\n        dup3_result = self.call_syscall(\"dup3\", [new_fd - self.args.fd_adjust_dup3, self.args.old_fd, 0])\n        if dup3_result - self.args.fd_adjust_dup3 != self.args.old_fd:\n            err(\"Failed to dup3 (result {:d} != fd #{:d})\".format(dup3_result, self.args.old_fd))\n            return\n        self.quiet_info(\"Duplicated fd #{:d} -> #{:d}\".format(new_fd, self.args.old_fd))\n\n        # call close\n        close_result = self.call_syscall(\"close\", [new_fd])\n        if AddressUtil.is_msb_on(close_result):\n            err(\"Failed to close fd #{:d}\".format(new_fd))\n            return\n        self.quiet_info(\"Closed extra fd #{:d}\".format(new_fd))\n\n        ok(\"Success\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        # In old version of qemu, the file descriptor was sometimes shifted by a\n        # constant value on i386 (fd returned by the syscall == actual opened fd + 80).\n        # This had been hard-coded as a workaround, but the issue appears to be fixed,\n        # so it should now be specified via a command argument.\n        # Currently supported: dup3, connect\n\n        self.AF_INET = 2\n        self.SOCK_STREAM = 1\n        self.O_APPEND = 0o2000\n        self.O_CREAT = 0o100\n        self.O_RDWR = 0o2\n        # some architecture use different consts.\n        if is_mips32() or is_mips64() or is_mipsn32():\n            # /usr/mipsel-linux-gnu/include/bits/socket_type.h\n            # /usr/mips64el-linux-gnuabi64/include/bits/socket_type.h\n            self.SOCK_STREAM = 2\n            # /usr/mipsel-linux-gnu/include/bits/fcntl.h\n            # /usr/mips64el-linux-gnuabi64/include/bits/fcntl.h\n            self.O_APPEND = 0x0008\n            self.O_CREAT = 0x0100\n        elif is_sparc32() or is_sparc32plus() or is_sparc64():\n            # sparcv8--uclibc--stable-2022.08-1/sparc-buildroot-linux-uclibc/sysroot/usr/include/bits/fcntl.h\n            # sparc64--glibc--stable-2022.08-1/sparc64-buildroot-linux-gnu/sysroot/usr/include/bits/fcntl.h\n            self.O_APPEND = 0x0008\n            self.O_CREAT = 0x0200\n        elif is_alpha():\n            # /usr/alpha-linux-gnu/include/bits/fcntl.h\n            self.O_APPEND = 0o0010\n            self.O_CREAT = 0o1000\n        elif is_hppa32() or is_hppa64():\n            # /usr/hppa-linux-gnu/include/bits/fcntl.h\n            self.O_APPEND = 0o0010\n            self.O_CREAT = 0o0400\n\n        self.hijack_fd()\n        return\n\n\n@register_command\nclass ScanSectionCommand(GenericCommand):\n    \"\"\"Find memory addresses mapped across different regions.\"\"\"\n\n    _cmdline_ = \"scan-section\"\n    _category_ = \"03-a. Memory - Search\"\n    _aliases_ = [\"peek-pointers\", \"leakfind\", \"p2p\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"haystack\", metavar=\"HAYSTACK\", nargs=\"?\", help=\"where to search for the needle.\")\n    parser.add_argument(\"needle\", metavar=\"NEEDLE\", nargs=\"?\", help=\"what to search for.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} stack binary                        # scan binary address from stack\",\n        \"{0:s} stack libc                          # scan libc address from stack\",\n        \"{0:s} stack heap                          # scan heap address from stack\",\n        \"{0:s} heap libc                           # scan libc address from heap\",\n        \"{0:s} 0x555555772000-0x555555774000 libc  # support address range\",\n        \"{0:s} any any\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def scan(self, haystack, needle):\n        needle_sections = []\n        haystack_sections = []\n\n        if haystack and \"0x\" in haystack:\n            try:\n                start, end = AddressUtil.parse_string_range(haystack)\n                haystack_sections.append((start, end, \"\"))\n            except ValueError:\n                pass\n\n        if needle and \"0x\" in needle:\n            try:\n                start, end = AddressUtil.parse_string_range(needle)\n                needle_sections.append((start, end))\n            except ValueError:\n                pass\n\n        for sect in ProcessMap.get_process_maps():\n            if haystack is None or haystack in sect.path:\n                haystack_sections.append((sect.page_start, sect.page_end, os.path.basename(sect.path)))\n            if needle is None or needle in sect.path:\n                needle_sections.append((sect.page_start, sect.page_end))\n\n        for hstart, hend, hname in haystack_sections:\n            try:\n                mem = read_memory(hstart, hend - hstart)\n            except gdb.MemoryError:\n                continue\n\n            for i, target in enumerate(slice_unpack(mem, current_arch.ptrsize)):\n                for nstart, nend in needle_sections:\n                    if not (nstart <= target < nend):\n                        continue\n                    # match\n                    deref = AddressUtil.recursive_dereference_to_string(hstart + i * current_arch.ptrsize)\n                    if hname != \"\":\n                        name = Color.colorify(hname, \"yellow\")\n                        gef_print(\"{:s}: {:s}\".format(name, deref))\n                    else:\n                        gef_print(\" {:s}\".format(deref))\n                    break\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        haystack = args.haystack\n        needle = args.needle\n\n        info(\"Searching for addresses in '{:s}' that point to '{:s}'\".format(\n            Color.yellowify(haystack), Color.yellowify(needle),\n        ))\n\n        if haystack == \"any\":\n            haystack = None\n        elif haystack in [\"binary\", \"bin\"]:\n            haystack = Path.get_filepath(append_proc_root_prefix=False)\n            if is_qemu_user() and haystack is None:\n                haystack = \"[code]\"\n\n        if needle == \"any\":\n            needle = None\n        elif needle in [\"binary\", \"bin\"]:\n            needle = Path.get_filepath(append_proc_root_prefix=False)\n            if is_qemu_user() and needle is None:\n                needle = \"[code]\"\n\n        self.scan(haystack, needle)\n        return\n\n\n@register_command\nclass FindSyscallCommand(GenericCommand, BufferingOutput):\n    \"\"\"Find the syscall gadget.\"\"\"\n\n    _cmdline_ = \"find-syscall\"\n    _category_ = \"03-a. Memory - Search\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"section\", metavar=\"SECTION_OR_START_ADDR\", nargs=\"?\",\n                        help=\"section name or starting address of search range.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\",\n                        help=\"search range size. valid only when a start address is specified.\")\n    parser.add_argument(\"-b\", \"--nb-insns-before\", type=AddressUtil.parse_address, default=0,\n                        help=\"the number of previous lines when print syscall instruction.\")\n    parser.add_argument(\"-s\", \"--max-region-size\", type=AddressUtil.parse_address, default=0x1000_0000,\n                        help=\"maximum search region size. (default: %(default)#x; 0: infinity)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} libc                   # search syscall from libc .text\",\n        \"{0:s} binary                 # 'binary' means the area executable itself (usermode only)\",\n        \"{0:s} 0x400000-0x404000      # search syscall from specific range\",\n        \"{0:s} 0x400000 0x4000        # another valid format\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def print_section(self, section):\n        if isinstance(section, Address):\n            section = section.section\n        if section is None:\n            return\n        title = \"In \"\n        if section.path:\n            title += \"'{}' \".format(Color.blueify(section.path))\n        title += \"{:#x}-{:#x} [{}] ({:#x} bytes)\".format(\n            section.page_start, section.page_end,\n            section.permission, section.page_end - section.page_start,\n        )\n        self.info_add_out(title)\n        return\n\n    def print_loc(self, loc):\n        if is_x86():\n            show_opcodes_size = Config.get_gef_setting(\"context_code.show_opcodes_size_x64_x86\")\n        else:\n            show_opcodes_size = Config.get_gef_setting(\"context_code.show_opcodes_size\")\n\n        nb_lines = 1\n\n        # fix loc and nb_lines\n        if self.args.nb_insns_before > 0:\n             a = Disasm.gdb_get_nth_previous_instruction_address(loc, self.args.nb_insns_before)\n             if a is not None:\n                loc = a\n                nb_lines += self.args.nb_insns_before\n\n        # disasm\n        res = Disasm.gdb_disassemble(loc, nb_lines)\n        if res:\n            for insn in res:\n                self.out.append(insn.colored_text(show_opcodes_size))\n\n        # add blank line\n        if self.args.nb_insns_before > 0:\n            self.out.append(\"\")\n        return\n\n    def read_data(self, chunk_addr, size, end_address):\n        read_size = min(size, end_address - chunk_addr)\n        try:\n            mem = read_memory(chunk_addr, read_size)\n        except (gdb.MemoryError, ValueError, OverflowError):\n            # cannot access memory this range. It doesn't make sense to try any more\n            self.err_add_out(\"skip due to memory access error\")\n            return None\n        return mem\n\n    def search_pattern_by_address(self, pattern, start_address, end_address):\n        \"\"\"Search for a pattern within a range defined by arguments.\"\"\"\n        step = 0x400 * get_pagesize()\n        locations = []\n\n        old_mem = b\"\"\n        tqdm = GefUtil.get_tqdm()\n        for chunk_addr in tqdm(range(start_address, end_address, step), leave=False):\n            # read\n            mem = self.read_data(chunk_addr, step, end_address)\n            if mem is None:\n                break\n\n            # cases where step boundaries are crossed\n            if old_mem and mem:\n                ofs = len(pattern) - 1\n                tmp = old_mem[-ofs:] + mem[:ofs]\n                r = tmp.find(pattern)\n                if r >= 0:\n                    locations.append(chunk_addr - ofs + r)\n\n            # normal case\n            for match in re.finditer(pattern, mem):\n                start = chunk_addr + match.start()\n                locations.append(start)\n\n            old_mem = mem\n        return locations\n\n    def process_by_address(self, pattern, start_address, end_address):\n        info(\"Searching for {:s} in {:#x}-{:#x}\".format(\n            Color.yellowify(pattern), start_address, end_address,\n        ))\n        ret = self.search_pattern_by_address(pattern, start_address, end_address)\n        for loc in ret:\n            self.print_loc(loc)\n        return\n\n    def process_by_section(self, pattern, section_name=None):\n        \"\"\"Search for a pattern within selected (or whole) memory.\"\"\"\n\n        if section_name is None:\n            self.info_add_out(\"Searching for {:s} in {:s}\".format(Color.yellowify(pattern), \"whole memory\"))\n        else:\n            self.info_add_out(\"Searching for {:s} in {:s}\".format(Color.yellowify(pattern), section_name))\n\n        maps_generator = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True)\n\n        for section in maps_generator:\n            # too big\n            if self.args.max_region_size != 0:\n                if section.size >= self.args.max_region_size:\n                    self.quiet_info_add_out(\n                        \"{:#x}-{:#x} is skipped due to size ({:#x}) >= MAX_REGION_SIZE ({:#x})\".format(\n                            section.page_start, section.page_end,\n                            section.size, self.args.max_region_size,\n                        )\n                    )\n                    continue\n\n            # permission filter\n            if not section.is_executable():\n                continue\n\n            # specific section name filter\n            if section_name and section_name not in section.path:\n                continue\n\n            # search\n            self.print_section(section)\n            start = section.page_start\n            end = section.page_end\n            ret = self.search_pattern_by_address(pattern, start, end) # search\n            for loc in ret:\n                self.print_loc(loc)\n\n            # check process is alive\n            if not is_alive():\n                self.err_add_out(\"The process is dead\")\n                break\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if not current_arch.syscall_insn:\n            err(\"Unsupported arch\")\n            return\n\n        pattern = current_arch.syscall_insn\n        self.out = []\n\n        if args.section and args.size:\n            # the case `find-syscall 0x400000 0x4000`\n            try:\n                start = int(args.section, 16)\n                end = start + int(args.size, 16)\n            except ValueError:\n                self.usage()\n                return\n            self.process_by_address(pattern, start, end)\n\n        elif args.section and re.match(r\"(0x)?[0-9a-fA-F]+-(0x)?[0-9a-fA-F]+\", args.section):\n            # the case `find-syscall 0x400000-0x404000` etc.\n            try:\n                start, end = AddressUtil.parse_string_range(args.section)\n            except ValueError:\n                self.usage()\n                return\n            self.process_by_address(pattern, start, end)\n\n        elif args.section:\n            # search from specific section\n            if args.section in [\"binary\", \"bin\"]:\n                section_name = Path.get_filepath(append_proc_root_prefix=False)\n            else:\n                section_name = args.section\n            self.process_by_section(pattern, section_name)\n\n        else:\n            # search whole memory\n            self.process_by_section(pattern)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass SearchPatternCommand(GenericCommand):\n    \"\"\"Search for a pattern in memory.\"\"\"\n\n    _cmdline_ = \"search-pattern\"\n    _category_ = \"03-a. Memory - Search\"\n    _aliases_ = [\"xfind\", \"xf\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group1 = parser.add_mutually_exclusive_group()\n    group1.add_argument(\"--hex\", action=\"store_true\",\n                       help=\"interpret PATTERN as hex. invalid characters are ignored.\")\n    group1.add_argument(\"--hex-regex\", action=\"store_true\",\n                       help=\"interpret PATTERN as hex with REGEX-style. space is ignored.\")\n    parser.add_argument(\"-d\", \"--disable-utf16\", action=\"store_true\",\n                        help=\"disable utf16 search if PATTERN is ascii string.\")\n    parser.add_argument(\"-b\", \"--big\", action=\"store_true\",\n                        help=\"interpret PATTERN as big endian if PATTERN is 0xXXXXXXXX style.\")\n    parser.add_argument(\"-a\", \"--aligned\", type=AddressUtil.parse_address, default=1,\n                        help=\"alignment unit. (default: %(default)s)\")\n    parser.add_argument(\"-p\", \"--perm\", default=\"r??\",\n                        help=\"the filter by permission. (default: %(default)s)\")\n    parser.add_argument(\"-i\", \"--interval\", type=AddressUtil.parse_address,\n                        help=\"the interval to skip searching from the last found position within the same section.\")\n    parser.add_argument(\"-l\", \"--limit\", type=AddressUtil.parse_address,\n                        help=\"the limit of the search result.\")\n    parser.add_argument(\"-s\", \"--max-region-size\", type=AddressUtil.parse_address, default=0x1000_0000,\n                        help=\"maximum search region size. (default: %(default)#x; 0: infinity)\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat START_ADDR as a physical address (available in qemu-system).\")\n    group2 = parser.add_mutually_exclusive_group()\n    group2.add_argument(\"-k\", \"--kernel-only\", action=\"store_true\",\n                        help=\"search from kernel area (available in qemu-system).\")\n    group2.add_argument(\"-u\", \"--user-only\", action=\"store_true\",\n                        help=\"search from user area (available in qemu-system).\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"shows the section currently being searched.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"suppress warnings.\")\n    parser.add_argument(\"-Q\", \"--quiet-region\", action=\"store_true\", help=\"suppress region information.\")\n    parser.add_argument(\"-S\", \"--quiet-symbol\", action=\"store_true\", help=\"not shown even if symbol exists.\")\n    parser.add_argument(\"pattern\", metavar=\"PATTERN\",\n                        help='search target value. \"double-escaped string\" or 0xXXXXXXXX style.')\n    parser.add_argument(\"section\", metavar=\"SECTION_OR_START_ADDR\", nargs=\"?\",\n                        help=\"section name or starting address of search range.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\",\n                        help=\"search range size. valid only when a start address is specified.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} ABCD                        # search for 'ABCD' from whole memory\",\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x42\\\\\\\\x43\\\\\\\\x44\"      # double-escaped string is also valid',\n        '{0:s} --hex \"41 42 43 44\"         # another valid format',\n        '{0:s} --hex-regex \"4[0-9]424344\"  # hex regex search',\n        \"{0:s} 0x44434241                  # search for 0x44434241 (='ABCD') from whole memory\",\n        \"{0:s} 0x555555554000 stack        # search for 0x555555554000 (6byte) from stack\",\n        \"{0:s} 0x0000555555554000 stack    # search for 0x0000555555554000 (8byte) from stack\",\n        \"{0:s} AAAA binary                 # 'binary' means the area executable itself (usermode only)\",\n        \"{0:s} AAAA 0x400000-0x404000      # search for 'AAAA' from specific range\",\n        \"{0:s} AAAA 0x400000 0x4000        # another valid format\",\n        \"{0:s} AAAA heap --aligned 16      # search for 'AAAA' with 16-byte alignment\",\n        \"{0:s} AAAA -p r?-                 # search for 'AAAA' from r-- or rw-, but not from r-x or rwx\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"To efficiently search large memory regions, the search is usually performed internally by dividing\",\n        \"the region into chunks. The chunk size is 0x10 pages for qemu-system, and 0x400 pages for others.\",\n        \"\",\n        \"However, when the --hex-regex option is enabled, this chunked search is disabled,\",\n        \"because it is difficult to implement regular expression searches that span multiple chunks.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def is_aligned(self, addr):\n        a = self.args.aligned or 1\n        return (a <= 1) or (addr % a == 0)\n\n    def accept_match(self, start_addr, locations):\n        # alignment\n        if not self.is_aligned(start_addr):\n            return False\n\n        # interval\n        if self.args.interval:\n            if locations:\n                last_loc = locations[-1]\n                if start_addr < last_loc[0] + self.args.interval:\n                    return False\n        return True\n\n    def check_limit(self):\n        if self.args.limit:\n            if self.args.limit <= self.found_count:\n                return True\n        return False\n\n    def print_section(self, section):\n        if self.args.quiet_region:\n            return\n        if isinstance(section, Address):\n            section = section.section\n        if section is None:\n            return\n        title = \"In \"\n        if section.path:\n            title += \"'{}' \".format(Color.blueify(section.path))\n        title += \"{:#x}-{:#x} [{}] ({:#x} bytes)\".format(\n            section.page_start, section.page_end, section.permission,\n            section.page_end - section.page_start,\n        )\n        ok(title)\n        return\n\n    def print_loc(self, loc):\n        if self.args.aligned and loc[0] % self.args.aligned:\n            return\n        h = hexdump(loc[1], 0x10, base=loc[0], show_symbol=not self.args.quiet_symbol)\n        gef_print(\"  {:s}\".format(h))\n        return\n\n    def read_data(self, chunk_addr, size, end_address):\n        read_size = min(size, end_address - chunk_addr)\n        try:\n            if self.args.phys:\n                mem = read_physmem(chunk_addr, read_size)\n            else:\n                mem = read_memory(chunk_addr, read_size)\n        except (gdb.MemoryError, ValueError, OverflowError):\n            # cannot access memory this range. It doesn't make sense to try any more\n            if self.args.verbose:\n                err(\"Skip due to memory access error\")\n            return None\n        return mem\n\n    def search_pattern_by_address(self, pattern, start_address, end_address):\n        \"\"\"Search for a pattern within a range defined by arguments.\"\"\"\n        if isinstance(pattern, str):\n            pattern = String.str2bytes(pattern)\n\n        if self.args.hex_regex:\n            step = end_address - start_address\n        elif is_qemu_system():\n            step = 0x10 * get_pagesize()\n        else:\n            step = 0x400 * get_pagesize()\n\n        locations = []\n        old_mem = b\"\"\n        tqdm = GefUtil.get_tqdm(self.args.verbose)\n        for chunk_addr in tqdm(range(start_address, end_address, step), leave=False):\n            # read\n            mem = self.read_data(chunk_addr, step, end_address)\n            if mem is None:\n                break\n\n            # for regex\n            if self.args.hex_regex:\n                mem = mem.hex().encode()\n\n            # cases where step boundaries are crossed\n            if not self.args.hex_regex and old_mem and mem:\n                # Considering cases where the step size boundary is crossed,\n                # the check is performed within the range of -ofs to ofs size.\n                \"\"\"\n                pattern \"ABCD\"\n                ofs = len(pattern) - 1 = 3\n\n                The scope of consideration is limited to this range.\n                 <-- step --> <-- step -->\n                | ...   xxxA | BCDxxx ... |\n                | ...  xxxAB | CDxxx  ... |\n                | ... xxxABC | Dxxx   ... |\n                         <------->\n                       -ofs     ofs\n                \"\"\"\n                ofs = len(pattern) - 1\n                tmp_mem = old_mem[-ofs:] + mem[:ofs]\n                r = tmp_mem.find(pattern)\n                if r >= 0:\n                    if self.accept_match(chunk_addr - ofs + r, locations):\n                        # read dump data\n                        data = (old_mem[-ofs:] + mem)[r:][:0x10]\n\n                        # add\n                        locations.append((chunk_addr - ofs + r, data))\n                        self.found_count += 1\n\n                        # loop check\n                        if self.check_limit():\n                            info(\"Limit reached, no more matches shown\")\n                            return locations\n                # fall through\n\n            # normal case\n            for match in re.finditer(pattern, mem):\n                if self.args.hex_regex:\n                    if match.start() % 2:\n                        continue\n                    start_pos = match.start() // 2\n                else:\n                    start_pos = match.start()\n                start = chunk_addr + start_pos\n\n                # check filter\n                if not self.accept_match(start, locations):\n                    continue\n\n                # read dump data\n                if self.args.hex_regex:\n                    data = bytes.fromhex(mem.decode())[start_pos:][:0x10]\n                else:\n                    data = mem[start_pos:][:0x10]\n                if len(data) < 0x10:\n                    lack = self.read_data(chunk_addr + step, 0x10 - len(data), end_address)\n                    if lack:\n                        data += lack\n\n                # add\n                locations.append((start, data))\n                self.found_count += 1\n\n                # loop check\n                if self.check_limit():\n                    info(\"Limit reached, no more matches shown\")\n                    return locations\n\n            old_mem = mem\n\n        return locations\n\n    def process_by_address(self, patterns, start, end):\n        extra = \" (phys)\" if self.args.phys else \"\"\n        for pattern in patterns:\n            if not pattern:\n                continue\n\n            info(\"Searching for '{:s}' in {:#x}-{:#x}{:s}\".format(\n                Color.yellowify(pattern), start, end, extra,\n            ))\n\n            self.found_count = 0\n            ret = self.search_pattern_by_address(pattern, start, end)\n            for found_loc in ret:\n                self.print_loc(found_loc)\n        return\n\n    def get_process_maps_qemu_system(self):\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --disable-color\")\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n        res = list(filter(lambda line: \"*\" not in line, res))\n        for line in res:\n            if is_x86() and \"ACCESSED\" not in line:\n                continue\n\n            # extract\n            lines = line.split()\n            addr_start, addr_end = [int(x, 16) for x in lines[0].split(\"-\")]\n\n            # non valid addr\n            if not is_valid_addr(addr_start):\n                continue\n\n            # parse\n            if is_x86():\n                perm = Permission.from_process_maps(lines[5][1:].lower())\n            elif is_arm32():\n                perm = line.split(\"/\")[-1][:3]\n                perm = Permission.from_process_maps(perm.lower())\n            elif is_arm64():\n                perm = line.split(\"/\")[-1][:3]\n                perm = Permission.from_process_maps(perm.lower())\n            yield Section(page_start=addr_start, page_end=addr_end, permission=perm)\n        return None\n\n    def search_pattern_by_section(self, pattern, section_name=None):\n        \"\"\"Search for a pattern within selected (or whole) memory.\"\"\"\n        if is_qemu_system():\n            maps_generator = self.get_process_maps_qemu_system()\n        else:\n            maps_generator = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True)\n\n        for section in maps_generator:\n            # user or kernel memory address filter\n            if self.args.user_only:\n                if AddressUtil.is_msb_on(section.page_start):\n                    continue\n            if self.args.kernel_only:\n                if not AddressUtil.is_msb_on(section.page_start):\n                    continue\n\n            # too big\n            if self.args.max_region_size != 0:\n                if section.size >= self.args.max_region_size:\n                    self.quiet_info(\n                        \"{:#x}-{:#x} is skipped due to size ({:#x}) >= MAX_REGION_SIZE ({:#x})\".format(\n                            section.page_start, section.page_end,\n                            section.size, self.args.max_region_size,\n                        )\n                    )\n                    continue\n\n            # permission filter\n            if not section.is_readable():\n                continue\n            if self.args.perm[1] in \"wW\" and not section.is_writable():\n                continue\n            if self.args.perm[1] in \"-_\" and section.is_writable():\n                continue\n            if self.args.perm[2] in \"xX\" and not section.is_executable():\n                continue\n            if self.args.perm[2] in \"-_\" and section.is_executable():\n                continue\n\n            # specific section name filter\n            if section_name and section_name not in section.path:\n                continue\n\n            # verbose: always print section before search\n            if self.args.verbose:\n                self.print_section(section)\n            # search\n            ret = self.search_pattern_by_address(pattern, section.page_start, section.page_end)\n            # default: print section if only found\n            if not self.args.verbose:\n                if ret:\n                    self.print_section(section)\n\n            # print\n            for loc in ret:\n                self.print_loc(loc)\n\n            # loop check\n            if not is_alive():\n                err(\"The process is dead\")\n                break\n            if self.check_limit():\n                info(\"Limit reached, no more matches shown\")\n                break\n        return\n\n    def process_by_section(self, patterns, section_name=None):\n        extra = \" (phys)\" if self.args.phys else \"\"\n        for pattern in patterns:\n            if not pattern:\n                continue\n\n            if section_name is None:\n                area = \"whole memory\"\n            else:\n                area = section_name\n\n            gef_print(titlify(\"\"))\n            info(\"Searching for '{:s}' in {:s}{:s}\".format(\n                Color.yellowify(pattern), area, extra,\n            ))\n            self.found_count = 0\n            self.search_pattern_by_section(pattern, section_name)\n        return\n\n    def create_patterns(self):\n        if self.args.hex_regex:\n            pattern = self.args.pattern.lower().replace(\" \", \"\")\n            return (pattern,)\n\n        # create normal pattern\n        if self.args.hex: # \"41414141\" -> \"\\x41\\x41\\x41\\x41\"\n            pattern = re.sub(r\"[^0-9a-fA-F]\", \"\", self.args.pattern)\n            if len(pattern) % 2 != 0:\n                err(\"Hex pattern length is odd\")\n                return None\n            pattern = \"\".join([\"\\\\x\" + x for x in slicer(pattern, 2)])\n        elif String.is_hex(self.args.pattern): # \"0x41414141\" -> \"\\x41\\x41\\x41\\x41\"\n            if self.args.big or Endian.is_big_endian():\n                pattern = \"\".join([\"\\\\x\" + x for x in slicer(self.args.pattern[2:], 2)])\n            else:\n                pattern = \"\".join([\"\\\\x\" + x for x in slicer(self.args.pattern[2:], 2)[::-1]])\n        else:\n            pattern = self.args.pattern\n\n        def isascii(string):\n            val = codecs.escape_decode(string)[0]\n            return all(0x20 <= c < 0x7f for c in val)\n\n        # create utf16 pattern\n        pattern_utf16 = None\n        if not self.args.disable_utf16:\n            if isascii(pattern) and \"\\\\\" not in pattern:\n                pattern_utf16 = \"\".join([x + \"\\\\x00\" for x in pattern])\n        return (pattern, pattern_utf16)\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.kernel_only or args.user_only:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode (qemu-system only)\")\n                return\n\n        # check permission\n        if args.phys:\n            info(\"Permission is ignored\")\n        else:\n            if len(args.perm) != 3:\n                err(\"Invalid permission length\")\n                return\n            if args.perm[0] not in \"rR\":\n                err(\"Permission needs to start by `r`\")\n                return\n            if args.perm[1] not in \"wW-_?\" or args.perm[2] not in \"xX-_?\":\n                err(\"Invalid permission\")\n                return\n\n        # check parameters\n        if args.interval and args.interval <= 0:\n            err(\"Invalid interval value\")\n            return\n        if args.limit and args.limit <= 0:\n            err(\"Invalid limit value\")\n            return\n        if args.max_region_size and args.max_region_size < 0x1000:\n            err(\"Invalid max-region-size\")\n            return\n\n        # prepare pattern\n        patterns = self.create_patterns()\n        if patterns is None:\n            return\n\n        if args.section and args.size:\n            # the case `find AAAA 0x400000 0x4000`\n            try:\n                start = int(args.section, 16)\n                end = start + int(args.size, 16)\n            except ValueError:\n                self.usage()\n                return\n            self.process_by_address(patterns, start, end)\n\n        elif args.section and re.match(r\"(0x)?[0-9a-fA-F]+-(0x)?[0-9a-fA-F]+\", args.section):\n            # the case `find AAAA 0x400000-0x404000`\n            try:\n                start, end = AddressUtil.parse_string_range(args.section)\n            except ValueError:\n                self.usage()\n                return\n            self.process_by_address(patterns, start, end)\n\n        else:\n            if args.phys:\n                err(\"--phys mode needs address information\")\n                return\n\n            if args.section:\n                # search from specific section\n                if is_qemu_system() or is_kgdb() or is_vmware():\n                    err(\"Unsupported\")\n                    return\n                if args.section in [\"binary\", \"bin\"]:\n                    section_name = Path.get_filepath(append_proc_root_prefix=False)\n                else:\n                    section_name = args.section\n                self.process_by_section(patterns, section_name)\n\n            else:\n                # search whole memory\n                self.process_by_section(patterns)\n        return\n\n\n@register_command\nclass PtrDemangleCommand(GenericCommand):\n    \"\"\"Demangle a mangled value by PTR_MANGLE.\"\"\"\n\n    _cmdline_ = \"ptr-demangle\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"value\", metavar=\"VALUE\", nargs=\"?\", type=AddressUtil.parse_address,\n                       help=\"the value to demangle.\")\n    group.add_argument(\"--source\", action=\"store_true\",\n                       help=\"shows the source instead of displaying demangled value.\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_cookie():\n        if is_in_kernel():\n            return None\n        if is_arm32_cortex_m():\n            return None\n        if is_qiling():\n            return None\n\n        try:\n            if is_x86_64():\n                tls = current_arch.get_tls()\n                cookie = read_int_from_memory(tls + 0x30)\n                return cookie\n            elif is_x86_32():\n                tls = current_arch.get_tls()\n                cookie = read_int_from_memory(tls + 0x18)\n                return cookie\n            elif is_arm32() or is_arm64():\n                cookie_ptr = AddressUtil.parse_address(\"&__pointer_chk_guard_local\")\n                cookie = read_int_from_memory(cookie_ptr)\n                return cookie\n        except (gdb.error, OverflowError):\n            pass\n\n        # generic\n        try:\n            auxv = Auxv.get_auxiliary_values()\n            if auxv is None:\n                Cache.reset_gef_caches()\n                auxv = Auxv.get_auxiliary_values()\n            if auxv and \"AT_RANDOM\" in auxv:\n                if is_s390x():\n                    cookie = read_int_from_memory(auxv[\"AT_RANDOM\"]) & 0x00ff_ffff_ffff_ffff\n                else:\n                    cookie = read_int_from_memory(auxv[\"AT_RANDOM\"] + current_arch.ptrsize)\n                if cookie != 0:\n                    return cookie\n        except gdb.error:\n            pass\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @exclude_specific_arch(arch=(\"SPARC32\", \"XTENSA\", \"CRIS\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.source:\n            s = GefUtil.get_source(current_arch.decode_cookie)\n            gef_print(s)\n            return\n\n        cookie = self.get_cookie()\n        if cookie is None:\n            return\n        info(\"Cookie is {:s}\".format(Color.colorify_hex(cookie, \"bold\")))\n\n        decoded = current_arch.decode_cookie(args.value, cookie)\n        decoded = ProcessMap.lookup_address(decoded)\n        decoded_sym = Symbol.get_symbol_string(decoded.value)\n        if is_valid_addr(decoded.value):\n            valid_msg = Color.colorify(\"valid\", \"bold green\")\n        else:\n            valid_msg = Color.colorify(\"invalid\", \"bold red\")\n        info(\"Decoded value is {!s}{:s} [{:s}]\".format(decoded, decoded_sym, valid_msg))\n        return\n\n\n@register_command\nclass PtrMangleCommand(GenericCommand):\n    \"\"\"Mangle a pointer value by PTR_MANGLE.\"\"\"\n\n    _cmdline_ = \"ptr-mangle\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"value\", metavar=\"VALUE\", nargs=\"?\", type=AddressUtil.parse_address,\n                       help=\"the value to mangle.\")\n    group.add_argument(\"--source\", action=\"store_true\",\n                       help=\"shows the source instead of displaying mangled value.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @exclude_specific_arch(arch=(\"SPARC32\", \"XTENSA\", \"CRIS\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.source:\n            s = GefUtil.get_source(current_arch.encode_cookie)\n            gef_print(s)\n            return\n\n        cookie = PtrDemangleCommand.get_cookie()\n        if cookie is None:\n            return\n        info(\"Cookie is {:s}\".format(Color.colorify_hex(cookie, \"bold\")))\n\n        encoded = current_arch.encode_cookie(args.value, cookie)\n        info(\"Encoded value is {:#x}\".format(encoded))\n        return\n\n\n@register_command\nclass SearchMangledPtrCommand(GenericCommand):\n    \"\"\"Search for mangled values in RW memory.\"\"\"\n\n    _cmdline_ = \"search-mangled-ptr\"\n    _category_ = \"02-f. Process Information - Security\"\n    _aliases_ = [\"cookie\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"shows the section currently being searched.\")\n    _syntax_ = parser.format_help()\n\n    def print_section(self, section):\n        if isinstance(section, Address):\n            section = section.section\n\n        if section is None:\n            return\n\n        title = \"In \"\n        if section.path:\n            title += \"'{}' \".format(Color.blueify(section.path))\n\n        title += \"({:#x}-{:#x} [{}])\".format(section.page_start, section.page_end, section.permission)\n        ok(title)\n        return\n\n    def print_loc(self, addr, value, decoded):\n        addr_sym = Symbol.get_symbol_string(addr)\n        decoded = ProcessMap.lookup_address(decoded)\n        decoded_sym = Symbol.get_symbol_string(decoded.value)\n\n        if is_valid_addr(decoded.value):\n            valid_msg = Color.colorify(\"valid\", \"bold green\")\n        else:\n            valid_msg = Color.colorify(\"invalid\", \"bold red\")\n\n        base_address_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n        width = AddressUtil.get_format_address_width()\n        addr = Color.colorify(\"{:#0{:d}x}\".format(addr, width), base_address_color)\n\n        gef_print(\"  {:s}{:s}: {:#x} (={!s}{:s}) [{:s}]\".format(addr, addr_sym, value, decoded, decoded_sym, valid_msg))\n        return\n\n    def search_mangled_ptr(self, start_address, end_address, cookie):\n        \"\"\"Search for a mangled pointer within a range defined by arguments.\"\"\"\n        if is_qemu_system():\n            step = get_pagesize()\n        else:\n            step = 0x400 * get_pagesize()\n        locations = []\n\n        for chunk_addr in range(start_address, end_address, step):\n            if chunk_addr + step > end_address:\n                chunk_size = end_address - chunk_addr\n            else:\n                chunk_size = step\n\n            try:\n                mem = read_memory(chunk_addr, chunk_size)\n            except gdb.MemoryError:\n                # cannot access memory this range. It doesn't make sense to try any more\n                break\n\n            for i, value in enumerate(slice_unpack(mem, current_arch.ptrsize)):\n                decoded = current_arch.decode_cookie(value, cookie)\n                if not is_valid_addr(decoded):\n                    continue\n                addr = chunk_addr + i * current_arch.ptrsize\n                locations.append((addr, value, decoded))\n            del mem\n        return locations\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @exclude_specific_arch(arch=(\"SPARC32\", \"XTENSA\", \"CRIS\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # init\n        cookie = PtrDemangleCommand.get_cookie()\n        if cookie is None:\n            return\n        info(\"Cookie is {:s}\".format(Color.colorify_hex(cookie, \"bold\")))\n\n        # check\n        if current_arch.decode_cookie(0, 1) == 0:\n            err(\"In this architecture, the value is not encrypted with cookies\")\n            return\n\n        # search\n        maps_generator = ProcessMap.get_process_maps()\n        for section in maps_generator:\n            if not section.permission & Permission.READ:\n                continue\n            if not section.permission & Permission.WRITE:\n                continue\n            if args.verbose:\n                self.print_section(section) # verbose: always print section before search\n\n            start = section.page_start\n            end = section.page_end\n            ret = self.search_mangled_ptr(start, end, cookie)\n\n            if ret:\n                if not args.verbose:\n                    self.print_section(section) # default: print section if found\n\n            for addr, value, decoded in ret:\n                self.print_loc(addr, value, decoded)\n\n            if not is_alive():\n                err(\"The process is dead\")\n                break\n        return\n\n\n@register_command\nclass SearchCfiGadgetsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Search for CFI-valid, controllable gadgets in the executable area.\"\"\"\n\n    _cmdline_ = \"search-cfi-gadgets\"\n    _category_ = \"03-a. Memory - Search\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def find_endbr(self, start, end):\n        if is_x86_32():\n            endbr = b\"\\xf3\\x0f\\x1e\\xfb\" # endbr32\n        else:\n            endbr = b\"\\xf3\\x0f\\x1e\\xfa\" # endbr64\n\n        data = read_memory(start, end - start)\n\n        pos = -1\n        addrs = []\n        while True:\n            pos = data.find(endbr, pos + 1)\n            if pos == -1:\n                break\n            addrs.append(start + pos)\n        return addrs\n\n    def filter_gadgets(self, endbr_addrs):\n        filtered_addrs = []\n\n        for addr in endbr_addrs:\n            start = addr\n            inscount = 0\n            valid = True\n\n            while True:\n                insn = get_insn(addr)\n                inscount += 1\n                length = len(insn.opcodes)\n                addr += length\n\n                if current_arch.is_ret(insn):\n                    break\n\n                if current_arch.is_call(insn):\n                    if insn.operands[0].startswith(\"0x\"):\n                        valid = False\n                    break\n\n                if current_arch.is_jump(insn):\n                    if insn.operands[0].startswith(\"0x\"):\n                        valid = False\n\n                    # If the GOT cannot be modified, you can jump directly to the jump destination,\n                    # so there is no need to consider it in practice.\n                    elif inscount == 2 and \"[rip\" in insn.operands[0]:\n                        # 0x555555558630 f30f1efa     <free@plt+0x0> endbr64\n                        # 0x555555558634 ff2536e90100 <free@plt+0x4> jmp QWORD PTR [rip+0x1e936] # 0x555555576f70\n                        r = re.search(r\"# (0x\\w+)\", insn.operands[0])\n                        if r:\n                            v = ProcessMap.lookup_address(int(r.group(1), 16))\n                            if not v.section.is_writable():\n                                valid = False\n                    break\n\n                if \"XMMWORD\" in \"\".join(insn.operands):\n                    valid = False\n                    break\n\n            if valid:\n                filtered_addrs.append([start, inscount])\n        return filtered_addrs\n\n    def disasm_addrs(self, candidates):\n        try:\n            __import__(\"capstone\")\n            for start, inscount in candidates:\n                res = gdb.execute(\"capstone-disassemble {:#x} --length {:d}\".format(start, inscount), to_string=True)\n                self.out.append(res)\n        except ImportError:\n            for start, inscount in candidates:\n                self.out.extend([str(x) for x in Disasm.gdb_disassemble(start, nb_insn=inscount)])\n        return\n\n    def exec_search(self):\n        # get map entry\n        maps = ProcessMap.get_process_maps()\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        for entry in maps:\n            if not entry.is_executable():\n                continue\n            if entry.path in [\"[vsyscall]\"]:\n                continue\n\n            info(\"Search from {:s}\".format(entry.path))\n            self.out.append(titlify(entry.path))\n            addrs = self.find_endbr(entry.page_start, entry.page_end)\n            filtered_addrs = self.filter_gadgets(addrs)\n            self.disasm_addrs(filtered_addrs)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        # get saved filename (for caching)\n        filepath = Path.get_filepath()\n        if filepath is None:\n            output_path = \"\"\n        else:\n            output_file = \"cfi_{:s}.txt\".format(os.path.basename(filepath))\n            output_path = os.path.join(GEF_TEMP_DIR, output_file)\n\n        if os.path.exists(output_path) and not args.rescan:\n            # read previous output\n            info(\"A previously used file found, will be reused\")\n            self.out = open(output_path).read().splitlines()\n        else:\n            # doit\n            self.out = []\n            self.exec_search()\n            # save\n            if output_path:\n                open(output_path, \"w\").write(\"\\n\".join(self.out).rstrip())\n\n        # output\n        self.print_output()\n        return\n\n\n@register_command\nclass EditFlagsCommand(GenericCommand):\n    \"\"\"Edit flags in a human friendly way.\"\"\"\n\n    _cmdline_ = \"edit-flags\"\n    _category_ = \"04-b. Register - Modify\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"flagname\", metavar=\"[FLAGNAME(+|-|~) ...]\", nargs=\"*\", help=\"the flag name to edit.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show the bit information of the flag register.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}             # show the flag register\",\n        \"{0:s} zero+       # set ZERO flag\",\n        \"{0:s} direction-  # unset DIRECTION flag\",\n        \"{0:s} sign~       # toggle SIGN flag\",\n        \"{0:s} -v          # verbose output\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def edit_flags(self, flag_names):\n        for flag in flag_names:\n            if len(flag) < 2:\n                err(\"Too short length of the name\")\n                return\n\n            if flag[-1] not in (\"+\", \"-\", \"~\"):\n                err(\"Invalid action for flag '{:s}'\".format(flag))\n                return\n\n        for flag in flag_names:\n            action = flag[-1]\n            name = flag[:-1].lower()\n\n            if is_x86():\n                dic = {\n                    \"id\": \"identification\",\n                    \"ac\": \"align\",\n                    \"vm\": \"virtualx86\",\n                    \"rf\": \"resume\",\n                    \"nt\": \"nested\",\n                    \"of\": \"overflow\",\n                    \"df\": \"direction\",\n                    \"if\": \"interrupt\",\n                    \"tf\": \"trap\",\n                    \"sf\": \"sign\",\n                    \"zf\": \"zero\",\n                    \"af\": \"adjust\",\n                    \"pf\": \"parity\",\n                    \"cf\": \"carry\",\n                }\n                if name in dic:\n                    name = dic[name]\n\n            if name not in current_arch.flags_table.values():\n                err(\"Invalid flag name '{:s}'\".format(flag[:-1]))\n                continue\n\n            for off in current_arch.flags_table:\n                if current_arch.flags_table[off] != name:\n                    continue\n\n                old_flag = get_register(current_arch.flag_register)\n                if action == \"+\":\n                    new_flags = old_flag | (1 << off)\n                elif action == \"-\":\n                    new_flags = old_flag & ~(1 << off)\n                else:\n                    new_flags = old_flag ^ (1 << off)\n\n                gdb.execute(\"set ({:s}) = {:#x}\".format(current_arch.flag_register, new_flags))\n        return\n\n    def verbose_x86(self):\n        eflags = get_register(\"$eflags\")\n        gef_print(\"{:s}  {:s}\".format(BitInfo.bits_split(eflags, 32), Color.boldify(\"MASK\")))\n\n        def c(msg):\n            mask = int(msg.split()[0], 16)\n            if eflags & mask:\n                color = \"bold\"\n            else:\n                color = \"\"\n            return Color.colorify(msg, color)\n\n        elements = [\n            \"|| |||| |||| |||| |||| |||+- \" + c(\"0x000001 [CF]   Carry flag\"),\n            \"|| |||| |||| |||| |||| ||+-- \" + c(\"0x000002        Reserved (always 1)\"),\n            \"|| |||| |||| |||| |||| |+--- \" + c(\"0x000004 [PF]   Parity flag\"),\n            \"|| |||| |||| |||| |||| +---- \" + c(\"0x000008        Reserved (always 0)\"),\n            \"|| |||| |||| |||| ||||\",\n            \"|| |||| |||| |||| |||+------ \" + c(\"0x000010 [AF]   Adjust flag (for BCD calc)\"),\n            \"|| |||| |||| |||| ||+------- \" + c(\"0x000020        Reserved (always 0)\"),\n            \"|| |||| |||| |||| |+-------- \" + c(\"0x000040 [ZF]   Zero flag\"),\n            \"|| |||| |||| |||| +--------- \" + c(\"0x000080 [SF]   Sign flag\"),\n            \"|| |||| |||| ||||\",\n            \"|| |||| |||| |||+----------- \" + c(\"0x000100 [TF]   Trap flag (single step)\"),\n            \"|| |||| |||| ||+------------ \" + c(\"0x000200 [IF]   Interrupt enable flag\"),\n            \"|| |||| |||| |+------------- \" + c(\"0x000400 [DF]   Direction flag\"),\n            \"|| |||| |||| +-------------- \" + c(\"0x000800 [OF]   Overflow flag\"),\n            \"|| |||| ||||\",\n            \"|| |||| ||++---------------- \" + c(\"0x003000 [IOPL] I/O privilege level (2bit)\"),\n            \"|| |||| |+------------------ \" + c(\"0x004000 [NT]   Nested task flag\"),\n            \"|| |||| +------------------- \" + c(\"0x008000        Reserved (always 0)\"),\n            \"|| ||||\",\n            \"|| |||+--------------------- \" + c(\"0x010000 [RF]   Resume flag\"),\n            \"|| ||+---------------------- \" + c(\"0x020000 [VM]   Virtual 8086 mode flag\"),\n            \"|| |+----------------------- \" + c(\"0x040000 [AC]   Alignment check flag\"),\n            \"|| +------------------------ \" + c(\"0x080000 [VIF]  Virtual interrupt flag\"),\n            \"||\",\n            \"|+-------------------------- \" + c(\"0x100000 [VIP]  Virtual interrupt pending\"),\n            \"+--------------------------- \" + c(\"0x200000 [ID]   Able to use CPUID instruction\"),\n        ]\n        gef_print(\"\\n\".join([\" \" * 14 + e for e in elements]))\n        return\n\n    def verbose_arm32(self):\n        cpsr = get_register(\"$cpsr\")\n        gef_print(\"{:s}  {:s}\".format(BitInfo.bits_split(cpsr, 32), Color.boldify(\"MASK\")))\n\n        def c(msg):\n            mask = int(msg.split()[0], 16)\n            if cpsr & mask:\n                color = \"bold\"\n            else:\n                color = \"\"\n            return Color.colorify(msg, color)\n\n        elements = [\n            \"|||| |||| |||| |||| |||| |||| |||+-++++- \" + c(\"0x0000001f [M]  Mode field (5bit)\"),\n            \"|||| |||| |||| |||| |||| |||| |||        \" + \"  User:0b10000 FIQ:0b10001 IRQ:0b10010\",\n            \"|||| |||| |||| |||| |||| |||| |||        \" + \"  Supervisor:0b10011 Monitor:0b10110 Abort:0b10111\",\n            \"|||| |||| |||| |||| |||| |||| |||        \" + \"  Hyp:0b11010 Undefined:0b11011 System:0b11111\",\n            \"|||| |||| |||| |||| |||| |||| |||\",\n            \"|||| |||| |||| |||| |||| |||| ||+------- \" + c(\"0x00000020 [T]  Thumb execution state bit\"),\n            \"|||| |||| |||| |||| |||| |||| |+-------- \" + c(\"0x00000040 [F]  FIQ mask bit\"),\n            \"|||| |||| |||| |||| |||| |||| +--------- \" + c(\"0x00000080 [I]  IRQ mask bit\"),\n            \"|||| |||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||| |||+----------- \" + c(\"0x00000100 [A]  Asynchronous abort mask bit\"),\n            \"|||| |||| |||| |||| |||| ||+------------ \" + c(\"0x00000200 [E]  Endianness execution state bit\"),\n            \"|||| |++------------++++-++------------- \" + c(\"0x0600fc00 [IT] If-Then execution state bits for Thumb IT instruction\"),\n            \"|||| |  | |||| ||||\",\n            \"|||| |  | |||| ++++--------------------- \" + c(\"0x000f0000 [GE] Greater than or Equal flags for SIMD instruction\"),\n            \"|||| |  | ||||\",\n            \"|||| |  | ++++-------------------------- \" + c(\"0x00f00000      Reserved\"),\n            \"|||| |  |\",\n            \"|||| |  +------------------------------- \" + c(\"0x01000000 [J]  Jazelle bit\"),\n            \"|||| +---------------------------------- \" + c(\"0x08000000 [Q]  Cumulative saturation bit\"),\n            \"||||\",\n            \"|||+------------------------------------ \" + c(\"0x10000000 [V]  Overflow condition flag\"),\n            \"||+------------------------------------- \" + c(\"0x20000000 [C]  Carry condition flag\"),\n            \"|+-------------------------------------- \" + c(\"0x40000000 [Z]  Zero condition flag\"),\n            \"+--------------------------------------- \" + c(\"0x80000000 [N]  Negative condition flag\"),\n        ]\n        gef_print(\"\\n\".join([\" \" * 2 + e for e in elements]))\n        return\n\n    def verbose_arm64(self):\n        cpsr = get_register(\"$cpsr\")\n        gef_print(\"{:s}  {:s}\".format(BitInfo.bits_split(cpsr, 32), Color.boldify(\"MASK\")))\n\n        def c(msg):\n            mask = int(msg.split()[0], 16)\n            if cpsr & mask:\n                color = \"bold\"\n            else:\n                color = \"\"\n            return Color.colorify(msg, color)\n\n        elements_aarch64_state = [\n            \"|||| |||| |||| |||| |||| |||| |||| ||++- \" + c(\"0x00000003 [M.SP]  Selected stack pointer (2bit)\"),\n            \"|||| |||| |||| |||| |||| |||| |||| ++--- \" + c(\"0x0000000c [M.EL]  Exception level (2bit)\"),\n            \"|||| |||| |||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||| |||| |||+------ \" + c(\"0x00000010 [M.S]   Execution state (AArch64:0, AArch32:1)\"),\n            \"|||| |||| |||| |||| |||| |||| ||+------- \" + c(\"0x00000020         Reserved (always 0)\"),\n            \"|||| |||| |||| |||| |||| |||| |+-------- \" + c(\"0x00000040 [F]     FIQ interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| |||| +--------- \" + c(\"0x00000080 [I]     IRQ interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||| |||+----------- \" + c(\"0x00000100 [A]     SError interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| ||+------------ \" + c(\"0x00000200 [D]     Debug exception mask bit\"),\n            \"|||| |||| |||| |||| |||| ++------------- \" + c(\"0x00000c00 [BTYPE] Branch Type Indicator if FEAT_BTI is implemented\"),\n            \"|||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||+---------------- \" + c(\"0x00001000 [SSBS]  Speculative Store Bypass if FEAT_SSBS is implemented\"),\n            \"|||| |||| |||| ++++-+++----------------- \" + c(\"0x000fe000         Reserved\"),\n            \"|||| |||| ||||\",\n            \"|||| |||| |||+-------------------------- \" + c(\"0x00100000 [IL]    Illegal execution state\"),\n            \"|||| |||| ||+--------------------------- \" + c(\"0x00200000 [SS]    Software step flag\"),\n            \"|||| |||| |+---------------------------- \" + c(\"0x00400000 [PAN]   Privileged Access Never if FEAT_PAN is implemented\"),\n            \"|||| |||| +----------------------------- \" + c(\"0x00800000 [UAO]   User Access Override if FEAT_UAO is implemented\"),\n            \"|||| ||||\",\n            \"|||| |||+------------------------------- \" + c(\"0x01000000 [DIT]   Data Independent Timing if FEAT_DIT is implemented\"),\n            \"|||| ||+-------------------------------- \" + c(\"0x02000000 [TCO]   Tag Check Override if FEAT_MTE is implemented\"),\n            \"|||| ++--------------------------------- \" + c(\"0x0c000000         Reserved\"),\n            \"||||\",\n            \"|||+------------------------------------ \" + c(\"0x10000000 [V]     Overflow condition flag\"),\n            \"||+------------------------------------- \" + c(\"0x20000000 [C]     Carry condition flag\"),\n            \"|+-------------------------------------- \" + c(\"0x40000000 [Z]     Zero condition flag\"),\n            \"+--------------------------------------- \" + c(\"0x80000000 [N]     Negative condition flag\"),\n        ]\n\n        elements_aarch32_state = [\n            \"|||| |||| |||| |||| |||| |||| |||| ++++- \" + c(\"0x0000000f [M.A32] AArch32 mode (4bit)\"),\n            \"|||| |||| |||| |||| |||| |||| ||||       \" + \"   User:0b0000 FIQ:0b0001 IRQ:0b0010\",\n            \"|||| |||| |||| |||| |||| |||| ||||       \" + \"   Supervisor:0b0011 Monitor:0b0110 Abort:0b0111\",\n            \"|||| |||| |||| |||| |||| |||| ||||       \" + \"   Hyp:0b1010 Undefined:0b1011 System:0b1111\",\n            \"|||| |||| |||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||| |||| |||+------ \" + c(\"0x00000010 [M.S]   Execution state (AAch64:0, AArch32:1)\"),\n            \"|||| |||| |||| |||| |||| |||| ||+------- \" + c(\"0x00000020 [T]     T32 instruction set (Thumb) state bit\"),\n            \"|||| |||| |||| |||| |||| |||| |+-------- \" + c(\"0x00000040 [F]     FIQ interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| |||| +--------- \" + c(\"0x00000080 [I]     IRQ interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| ||||\",\n            \"|||| |||| |||| |||| |||| |||+----------- \" + c(\"0x00000100 [A]     SError interrupt mask bit\"),\n            \"|||| |||| |||| |||| |||| ||+------------ \" + c(\"0x00000200 [E]     Endianness execution state bit\"),\n            \"|||| |++------------++++-++------------- \" + c(\"0x0600fc00 [IT]    If-Then execution state bits for Thumb IT instruction\"),\n            \"|||| |  | |||| ||||\",\n            \"|||| |  | |||| ++++--------------------- \" + c(\"0x000f0000 [GE]    Greater than or Equal flags for SIMD instruction\"),\n            \"|||| |  | ||||\",\n            \"|||| |  | |||+-------------------------- \" + c(\"0x00100000 [IL]    Illegal execution state\"),\n            \"|||| |  | ||+--------------------------- \" + c(\"0x00200000 [SS]    Software step flag\"),\n            \"|||| |  | |+---------------------------- \" + c(\"0x00400000 [PAN]   Privileged Access Never if FEAT_PAN is implemented\"),\n            \"|||| |  | +----------------------------- \" + c(\"0x00800000 [SSBS]  Speculative Store Bypass if FEAT_SBSS is implemented\"),\n            \"|||| |  |\",\n            \"|||| |  +------------------------------- \" + c(\"0x01000000 [DIT]   Data Independent Timing if FEAT_DIT is implemented\"),\n            \"|||| +---------------------------------- \" + c(\"0x08000000 [Q]     Overflow or saturation flag\"),\n            \"||||\",\n            \"|||+------------------------------------ \" + c(\"0x10000000 [V]     Overflow condition flag\"),\n            \"||+------------------------------------- \" + c(\"0x20000000 [C]     Carry condition flag\"),\n            \"|+-------------------------------------- \" + c(\"0x40000000 [Z]     Zero condition flag\"),\n            \"+--------------------------------------- \" + c(\"0x80000000 [N]     Negative condition flag\"),\n        ]\n\n        if ((cpsr >> 4) & 1) == 0:\n            elements = elements_aarch64_state\n        else:\n            elements = elements_aarch32_state\n\n        gef_print(\"\\n\".join([\" \" * 2 + e for e in elements]))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.flag_register is None:\n            warn(\"This command is not supported on this architecture\")\n            return\n\n        self.edit_flags(args.flagname)\n\n        gef_print(current_arch.flag_register_to_human())\n        if args.verbose:\n            if is_x86():\n                self.verbose_x86()\n            elif is_arm32():\n                self.verbose_arm32()\n            elif is_arm64():\n                self.verbose_arm64()\n        return\n\n\n@register_command\nclass KillThreadsCommand(GenericCommand):\n    \"\"\"Invoke pthread_exit(0) for a specific THREAD_ID.\"\"\"\n\n    _cmdline_ = \"killthreads\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"thread_id\", metavar=\"THREAD_ID\", nargs=\"*\", type=int, help=\"the thread id (not TID) to kill.\")\n    parser.add_argument(\"-a\", \"--all\", action=\"store_true\", help=\"kill all threads except current thread.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=int, default=[], help=\"the thread id not to kill.\")\n    parser.add_argument(\"-c\", \"--commit\", action=\"store_true\", help=\"commit to kill.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} 2 3   # kill threads that `Thread Id` is 2 or 3',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"qemu-user\", \"kgdb\", \"vmware\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        # print tid list and exit\n        if not args.all and not args.thread_id and not args.exclude:\n            info(\"Non-current `Thread Id`(s) from the list are available\")\n            gdb.execute(\"context-threads -i -1\")\n            return\n\n        # list target thread id\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        target_threads = []\n        for th in gdb.selected_inferior().threads():\n            if th.num == orig_thread.num:\n                continue\n            if args.all:\n                if th.num not in args.exclude:\n                    target_threads.append(th)\n                continue\n            elif args.thread_id:\n                if th.num in args.thread_id:\n                    if th.num not in args.exclude:\n                        target_threads.append(th)\n                continue\n            else:\n                if th.num not in args.exclude:\n                    target_threads.append(th)\n                continue\n        target_threads = sorted(target_threads, key=lambda x: x.num)\n        gef_print(\"target Thread Id(s) to kill: {}\".format([th.num for th in target_threads]))\n\n        # kill\n        if args.commit:\n            # backup\n            sched_lock = gdb.parameter(\"scheduler-locking\")\n            # change temporarily\n            gdb.execute(\"set scheduler-locking on\", to_string=True)\n            # kill\n            for th in target_threads:\n                th.switch()\n                try:\n                    gdb.execute(\"call pthread_exit(0)\")\n                except gdb.error:\n                    pass\n            # restore\n            orig_thread.switch()\n            orig_frame.select()\n            gdb.execute(\"set scheduler-locking {:s}\".format(sched_lock), to_string=True)\n        else:\n            warn('This dry run mode skips killing; add \"--commit\" to proceed')\n        return\n\n\n@register_command\nclass CallSyscallCommand(GenericCommand):\n    \"\"\"A wrapper for calling syscall easily.\"\"\"\n\n    _cmdline_ = \"call-syscall\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"syscall_name\", metavar=\"SYSCALL_NAME\", help=\"system call name to invoke.\")\n    parser.add_argument(\"syscall_args\", metavar=\"SYSCALL_ARG\", nargs=\"*\", type=AddressUtil.parse_address,\n                        help=\"arguments of system call.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} write 1 \"*(void**)($rsp+0x18)\" 15',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch is None:\n            err(\"current_arch is not set\")\n            return\n\n        syscall_table = get_syscall_table()\n        if syscall_table is None:\n            err(\"The syscall table does not exist\")\n            return\n\n        # get syscall entry\n        for nr, entry in syscall_table.nr_table.items():\n            if is_x86_64() and nr >= 0x4000_0000:\n                continue\n            if args.syscall_name == entry.name:\n                break\n        else:\n            err(\"Could not find the system call `{:s}`\".format(args.syscall_name))\n            return\n\n        # length check\n        if len(args.syscall_args) != len(entry.args_full):\n            err(\"Argument count mismatch\")\n            params = \"(\" + \", \".join(entry.args_full) + \");\"\n            gef_print(\"Prototype: {:s}{:s}\".format(Color.boldify(args.syscall_name), params))\n            return\n\n        # title\n        title = \"{:s}({:s})\".format(args.syscall_name, \", \".join([\"{:#x}\".format(x) for x in args.syscall_args]))\n        gef_print(titlify(title))\n\n        ret = ExecSyscall(nr, args.syscall_args).exec_code()\n\n        if isinstance(current_arch.return_register, list):\n            for ret_regs in current_arch.return_register:\n                gef_print(\"{:s} = {:#x}\".format(ret_regs, ret[\"reg\"][ret_regs]))\n        else:\n            gef_print(\"{:s} = {:#x}\".format(current_arch.return_register, ret[\"reg\"][current_arch.return_register]))\n        return\n\n\n@register_command\nclass MmapMemoryCommand(GenericCommand):\n    \"\"\"Allocate a new memory.\"\"\"\n\n    _cmdline_ = \"mmap\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address, default=None,\n                        help=\"the address to allocate. (default: %(default)s)\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address, default=get_pagesize(),\n                        help=\"the size to allocate. (default: %(default)s)\")\n    parser.add_argument(\"permission\", metavar=\"PERMISSION\", nargs=\"?\", default=\"rwx\",\n                        help=\"the permission to allocate. `_` is interpreted as `-`. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x10000 0x1000 r-x\",\n        \"{0:s} 0 0x1000 _wx        # '_' means '-'\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    # On the CRIS architecture, setting a value to a register using the gdb `set` command will cause strange behavior.\n    # So even if the assembly code is correct, it should not use this command.\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        # syscall name (mmap or mmap2 or arch-specific)\n        syscall_table = get_syscall_table()\n        if syscall_table is None:\n            err(\"The syscall table does not exist\")\n            return\n\n        mmap_syscall_name = None\n        for entry in syscall_table.nr_table.values():\n            if \"mmap\" not in entry.name:\n                continue\n            if len(entry.arg_regs) != 6:\n                continue\n            mmap_syscall_name = entry.name\n            break\n        if mmap_syscall_name is None:\n            err(\"Could not find the mmap syscall\")\n            return\n\n        # location\n        if args.location and args.location % get_pagesize():\n            err(\"Address is not a multiple of {:#x}\".format(get_pagesize()))\n            return\n\n        # size\n        if args.size < 0 or AddressUtil.get_vmem_end() <= args.size:\n            err(\"Invalid size\")\n            return\n        if args.size % get_pagesize():\n            err(\"Size is not a multiple of {:#x}\".format(get_pagesize()))\n            return\n\n        # permission\n        if len(args.permission) != 3:\n            err(\"Invalid permission\")\n            return\n        if re.match(r\"[-_r][-_w][-_x]\", args.permission):\n            perm = Permission.NONE\n            if args.permission[0] == \"r\":\n                perm |= Permission.READ\n            if args.permission[1] == \"w\":\n                perm |= Permission.WRITE\n            if args.permission[2] == \"x\":\n                perm |= Permission.EXECUTE\n        else:\n            err(\"Invalid permission\")\n            return\n\n        # flags\n        flags = 0x22 # MAP_ANONYMOUS | MAP_PRIVATE\n        if args.location is not None:\n            flags |= 0x10 # MAP_FIXED\n        if is_mips32() or is_mips64() or is_mipsn32():\n            flags |= 0x800 # MAP_DENYWRITE (why?)\n\n        # doit\n        cmd = \"call-syscall {:s} {:#x} {:#x} {:#x} {:#x} -1 0\".format(\n            mmap_syscall_name, args.location or 0, args.size, perm, flags,\n        )\n        gdb.execute(cmd)\n        Cache.reset_gef_caches()\n        return\n\n\n@register_command\nclass MunmapMemoryCommand(GenericCommand):\n    \"\"\"Unmap a mapped memory.\"\"\"\n\n    _cmdline_ = \"munmap\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to unmap.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size to unmap.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $sp                    # unmap whole stack area\",\n        \"{0:s} 0x7ffffffde000 0x1000  # unmap specified area\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"By default, the entire map containing the specified address is freed.\",\n        \"If a size is specified, the area from the specified address to that size will be unmapped.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    # On the CRIS architecture, setting a value to a register using the gdb `set` command will cause strange behavior.\n    # So even if the assembly code is correct, it should not use this command.\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        # location\n        sect = ProcessMap.process_lookup_address(args.location)\n        if sect is None:\n            err(\"Unmapped address\")\n            return\n\n        # size\n        if args.size is not None:\n            if args.location % get_pagesize():\n                err(\"Address is not a multiple of {:#x}\".format(get_pagesize()))\n                return\n            if args.location < 0:\n                err(\"Invalid address\")\n                return\n            if args.size % get_pagesize():\n                err(\"Size is not a multiple of {:#x}\".format(get_pagesize()))\n                return\n            if args.size < 0 or AddressUtil.get_vmem_end() <= args.size:\n                err(\"Invalid size\")\n                return\n            # not estimation\n            location = args.location\n            size = args.size\n        else:\n            # use estimation\n            location = sect.page_start\n            size = sect.page_end - sect.page_start\n\n        # doit\n        cmd = \"call-syscall munmap {:#x} {:#x}\".format(location, size)\n        gdb.execute(cmd)\n        Cache.reset_gef_caches()\n        return\n\n\n@register_command\nclass MprotectCommand(GenericCommand):\n    \"\"\"Change a page permission (default: RWX).\"\"\"\n\n    _cmdline_ = \"mprotect\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to change the permission.\")\n    parser.add_argument(\"permission\", metavar=\"PERMISSION\", nargs=\"?\", default=\"rwx\",\n                        help=\"the permission you set to the LOCATION. (default: %(default)s)\")\n    parser.add_argument(\"-s\", \"--size\", type=AddressUtil.parse_address,\n                        help=\"the size to change the permission (0x1000 align).\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $sp rwx\",\n        \"{0:s} 0x7ffff7e1b000 ___           # '_' means '-'\",\n        \"{0:s} 0x7ffff7e1b000 ___ -s 0x1000 # change only first 0x1000 bytes\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"By default, the permissions will be changed for the entire map including the specified address.\",\n        \"If a size is specified, the permissions will only be changed for the range of the specified address up to the size.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    # On the CRIS architecture, setting a value to a register using the gdb `set` command will cause strange behavior.\n    # So even if the assembly code is correct, it should not use this command.\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"rr\", \"wine\"))\n    @exclude_specific_arch(arch=(\"CRIS\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        # location\n        sect = ProcessMap.process_lookup_address(args.location)\n        if sect is None:\n            err(\"Unmapped address\")\n            return\n\n        # size\n        if args.size is not None:\n            if args.location % get_pagesize():\n                err(\"Address is not a multiple of {:#x}\".format(get_pagesize()))\n                return\n            if args.location < 0:\n                err(\"Invalid address\")\n                return\n            if args.size % get_pagesize():\n                err(\"Size is not a multiple of {:#x}\".format(get_pagesize()))\n                return\n            if args.size < 0 or AddressUtil.get_vmem_end() <= args.size:\n                err(\"Invalid size\")\n                return\n            # not estimation\n            location = args.location\n            size = args.size\n        else:\n            # use estimation\n            location = sect.page_start\n            size = sect.page_end - sect.page_start\n\n        # permission\n        if re.match(r\"[-_r][-_w][-_x]\", args.permission):\n            perm = Permission.NONE\n            if args.permission[0] == \"r\":\n                perm |= Permission.READ\n            if args.permission[1] == \"w\":\n                perm |= Permission.WRITE\n            if args.permission[2] == \"x\":\n                perm |= Permission.EXECUTE\n        else:\n            err(\"Invalid permission\")\n            return\n\n        # doit\n        cmd = \"call-syscall mprotect {:#x} {:#x} {:#x}\".format(location, size, perm)\n        gdb.execute(cmd)\n        Cache.reset_gef_caches()\n        return\n\n\n@register_command\nclass ReadSystemRegisterForKgdbCommand(GenericCommand):\n    \"\"\"Read system register for kgdb / kdb.\"\"\"\n\n    _cmdline_ = \"read-system-register-for-kgdb\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"reg_name\", metavar=\"REGISTER_NAME\", nargs=\"?\", help=\"register name to read a value.\")\n    group.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"show the supported register names.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} cr0\",\n        \"{0:s} TTBR0_EL1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    REGISTER_DICT = {\n        \"x64\": {\n            \"cr0\": {\n                \"sym\": [\n                    \"native_read_cr0\",\n                ],\n                \"insn\": [\n                    [\"$rax\", b\"\\x0f\\x20\\xc0\"], # mov rax, cr0\n                ],\n            },\n            \"cr2\": {\n                \"sym\": [\n                    \"native_read_cr2\",\n                    \"pv_native_read_cr2\",\n                ],\n                \"insn\": [\n                    [\"$rax\", b\"\\x0f\\x20\\xd0\"], # mov rax, cr2\n                ],\n            },\n            \"cr3\": {\n                \"sym\": [\n                    \"native_read_cr3\",\n                    \"__native_read_cr3\",\n                ],\n                \"insn\": [\n                    [\"$rax\", b\"\\x0f\\x20\\xd8\"], # mov rax, cr3\n                ],\n            },\n            \"cr4\": {\n                \"sym\": [\n                    \"native_read_cr4\",\n                    \"cr4_init\",\n                ],\n                \"insn\": [\n                    [\"$rax\", b\"\\x0f\\x20\\xe0\"], # mov rax, cr4\n                ],\n            },\n        },\n        \"arm64\": {\n            \"TTBR0_EL1\": {\n                \"sym\": [\n                    \"mte_cpu_setup\", # 5.19~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x00 + i]) + b\"\\x20\\x38\\xd5\"] for i in range(30)], # mrs x0, TTBR0_EL1\n            },\n            \"TTBR1_EL1\": {\n                \"sym\": [\n                    \"mte_cpu_setup\", # 5.19~\n                    \"__sdei_asm_entry_trampoline\", # 4.16~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x20 + i]) + b\"\\x20\\x38\\xd5\"] for i in range(30)], # mrs x0, TTBR1_EL1\n            },\n            \"TCR_EL1\": {\n                \"sym\": [\n                    \"cpu_do_suspend\", # 3.14~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x40 + i]) + b\"\\x20\\x38\\xd5\"] for i in range(30)], # mrs x0, TCR_EL1\n            },\n            \"SCTLR_EL1\": {\n                \"sym\": [\n                    \"cpu_enable_pan\", # 4.3~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x00 + i]) + b\"\\x10\\x38\\xd5\"] for i in range(30)], # mrs x0, SCTLR_EL1\n            },\n            \"ID_AA64MMFR0_EL1\": {\n                \"sym\": [\n                    \"__cpuinfo_store_cpu\", # 3.17~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x00 + i]) + b\"\\x07\\x38\\xd5\"] for i in range(30)], # mrs x0, ID_AA64MMFR0_EL1\n            },\n            \"ID_AA64MMFR1_EL1\": {\n                \"sym\": [\n                    \"__cpuinfo_store_cpu\", # 3.17~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x20 + i]) + b\"\\x07\\x38\\xd5\"] for i in range(30)], # mrs x0, ID_AA64MMFR1_EL1\n            },\n            \"ID_AA64MMFR2_EL1\": {\n                \"sym\": [\n                    \"__cpuinfo_store_cpu\", # 3.17~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x40 + i]) + b\"\\x07\\x38\\xd5\"] for i in range(30)], # mrs x0, ID_AA64MMFR2_EL1\n            },\n            \"VBAR_EL1\": {\n                \"sym\": [\n                    \"cpu_do_suspend\", # 3.14~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x00 + i]) + b\"\\xc0\\x38\\xd5\"] for i in range(30)], # mrs x0, VBAR_EL1\n            },\n            \"SP_EL0\": {\n                \"sym\": [\n                    \"cpu_die_early\", # 4.6~\n                    \"sched_setaffinity\", # 3.7~\n                ],\n                \"insn\": [[f\"$x{i}\", bytes([0x00 + i]) + b\"\\x41\\x38\\xd5\"] for i in range(30)], # mrs x0, SP_EL0\n            },\n        },\n    }\n\n    @staticmethod\n    def get_supported_regs():\n        if not is_alive():\n            return []\n\n        if is_x86_64():\n            dic = ReadSystemRegisterForKgdbCommand.REGISTER_DICT[\"x64\"]\n        elif is_arm64():\n            dic = ReadSystemRegisterForKgdbCommand.REGISTER_DICT[\"arm64\"]\n        else:\n            return []\n\n        # filter if sym is defined or not\n        regs = []\n        for k, v in dic.items():\n            if not v[\"sym\"]:\n                continue\n            regs.append(k)\n        return regs\n\n    @staticmethod\n    def is_supported_reg(reg_name):\n        regs = [r.lower() for r in ReadSystemRegisterForKgdbCommand.get_supported_regs()]\n        return reg_name.lstrip(\"$\").lower() in regs\n\n    def complete(self, text, word): # noqa\n        regs = ReadSystemRegisterForKgdbCommand.get_supported_regs()\n        if text.strip() in regs:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in regs if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in regs if s and s.startswith(text.strip())]\n\n    @Cache.cache_this_session\n    def get_stub_address(self, reg_name):\n        if not is_alive():\n            return None\n        if is_x86_64():\n            dic = ReadSystemRegisterForKgdbCommand.REGISTER_DICT[\"x64\"]\n        elif is_arm64():\n            dic = ReadSystemRegisterForKgdbCommand.REGISTER_DICT[\"arm64\"]\n        else:\n            return None\n\n        reg_name = reg_name.lstrip(\"$\")\n\n        # In kgdb mode, direct modification (patching) of text memory is not permitted.\n        # Therefore, we instead utilize legitimate kernel-provided symbols and mechanisms\n        # to achieve the same goal.\n        # This implementation locates the address where the target instruction is used,\n        # executes that instruction exactly once, and captures the resulting value.\n\n        # TODO: Implement an alternative approach using the direct physical mapping (physmap)\n        # to allow patching via physical address, or execute hand-crafted assembly\n        # to obtain the value directly (without symbol).\n\n        d = dic.get(reg_name.lower(), None) or dic.get(reg_name.upper(), None)\n        if not d:\n            return None\n\n        for symbol in d[\"sym\"]:\n            # resolve symbol\n            if is_kdb():\n                address = Symbol.get_symbol_by_monitor(symbol)\n            else:\n                address = Symbol.get_ksymaddr(symbol)\n            if address is None:\n                continue\n            try:\n                data = read_memory(address, 0x100)\n            except gdb.MemoryError:\n                continue\n            if not data:\n                continue\n\n            for return_register, byte_code in d[\"insn\"]:\n                # adjust offset\n                index = data.find(byte_code)\n                if index >= 0:\n                    return address + index, return_register\n        return None\n\n    def execute_stub(self, stub_address, return_register):\n        codes = []\n        regs = {\n            \"$pc\": stub_address,\n            return_register: 0xdead_beef,\n        }\n        use_bp = False\n\n        if is_arm64():\n            # Step execution often fails due to an interrupt on ARM64\n            # but succeeds with the use of breakpoints.\n            use_bp = True\n\n        # It may fail on the first run, possibly due to gdb cache, but succeed on the second run.\n        for _ in range(2):\n            ret = ExecAsm(codes, regs=regs, step=1, use_bp=use_bp).exec_code()\n            if abs(ret[\"reg\"][\"$pc\"] - stub_address) > 0x10:\n                return None\n            if ret[\"reg\"][return_register] != 0xdead_beef:\n                return ret[\"reg\"][return_register]\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_64\", \"ARM64\"))\n    def do_invoke(self, args):\n        if current_arch is None:\n            err(\"current_arch is not set\")\n            return\n\n        if args.list:\n            for reg in ReadSystemRegisterForKgdbCommand.get_supported_regs():\n                gef_print(reg)\n            return\n\n        if not ReadSystemRegisterForKgdbCommand.is_supported_reg(args.reg_name):\n            err(\"Unsupported register\")\n            return\n\n        ret = self.get_stub_address(args.reg_name)\n        if ret is None:\n            err(\"Failed to get the target stub\")\n            return\n\n        ret = self.execute_stub(*ret)\n        if ret is not None:\n            gef_print(\"{:s} = {:#x}\".format(args.reg_name, ret))\n        return\n\n\n@register_command\nclass ReadSystemRegisterForQemuArmCommand(GenericCommand):\n    \"\"\"Read system register for old qemu-system-arm.\"\"\"\n\n    _cmdline_ = \"read-system-register-for-qemu-arm\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"reg_name\", metavar=\"REGISTER_NAME\", help=\"register name to read a value.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} TTBR0\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Attempting to read a non-existing register raises an undefined exception.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    # thanks to https://github.com/gdelugre/ida-arm-system-highlight\n    # Extracted from the XML specifications for v8.7-A (2021-06).\n    AARCH32_COPROC_REGISTERS = {\n        (\"p15\", \"c0\", 0, \"c0\", 0): (\"MIDR\", \"Main ID Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 1): (\"CTR\", \"Cache Type Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 2): (\"TCMTR\", \"TCM Type Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 3): (\"TLBTR\", \"TLB Type Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 5): (\"MPIDR\", \"Multiprocessor Affinity Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 6): (\"REVIDR\", \"Revision ID Register\"),\n\n        # Aliases\n        (\"p15\", \"c0\", 0, \"c0\", 4): (\"MIDR\", \"Main ID Register\"),\n        (\"p15\", \"c0\", 0, \"c0\", 7): (\"MIDR\", \"Main ID Register\"),\n\n        # CPUID registers\n        (\"p15\", \"c0\", 0, \"c1\", 0): (\"ID_PFR0\", \"Processor Feature Register 0\"),\n        (\"p15\", \"c0\", 0, \"c1\", 1): (\"ID_PFR1\", \"Processor Feature Register 1\"),\n        (\"p15\", \"c0\", 0, \"c3\", 4): (\"ID_PFR2\", \"Processor Feature Register 2\"),\n        (\"p15\", \"c0\", 0, \"c1\", 2): (\"ID_DFR0\", \"Debug Feature Register 0\"),\n        (\"p15\", \"c0\", 0, \"c1\", 3): (\"ID_AFR0\", \"Auxiliary Feature Register 0\"),\n        (\"p15\", \"c0\", 0, \"c1\", 4): (\"ID_MMFR0\", \"Memory Model Feature Register 0\"),\n        (\"p15\", \"c0\", 0, \"c1\", 5): (\"ID_MMFR1\", \"Memory Model Feature Register 1\"),\n        (\"p15\", \"c0\", 0, \"c1\", 6): (\"ID_MMFR2\", \"Memory Model Feature Register 2\"),\n        (\"p15\", \"c0\", 0, \"c1\", 7): (\"ID_MMFR3\", \"Memory Model Feature Register 3\"),\n        (\"p15\", \"c0\", 0, \"c2\", 6): (\"ID_MMFR4\", \"Memory Model Feature Register 4\"),\n        (\"p15\", \"c0\", 0, \"c3\", 6): (\"ID_MMFR5\", \"Memory Model Feature Register 5\"),\n        (\"p15\", \"c0\", 0, \"c2\", 0): (\"ID_ISAR0\", \"Instruction Set Attribute Register 0\"),\n        (\"p15\", \"c0\", 0, \"c2\", 1): (\"ID_ISAR1\", \"Instruction Set Attribute Register 1\"),\n        (\"p15\", \"c0\", 0, \"c2\", 2): (\"ID_ISAR2\", \"Instruction Set Attribute Register 2\"),\n        (\"p15\", \"c0\", 0, \"c2\", 3): (\"ID_ISAR3\", \"Instruction Set Attribute Register 3\"),\n        (\"p15\", \"c0\", 0, \"c2\", 4): (\"ID_ISAR4\", \"Instruction Set Attribute Register 4\"),\n        (\"p15\", \"c0\", 0, \"c2\", 5): (\"ID_ISAR5\", \"Instruction Set Attribute Register 5\"),\n        (\"p15\", \"c0\", 0, \"c2\", 7): (\"ID_ISAR6\", \"Instruction Set Attribute Register 6\"),\n\n        (\"p15\", \"c0\", 1, \"c0\", 0): (\"CCSIDR\", \"Current Cache Size ID Register\"),\n        (\"p15\", \"c0\", 1, \"c0\", 2): (\"CCSIDR2\", \"Current Cache Size ID Register 2\"),\n        (\"p15\", \"c0\", 1, \"c0\", 1): (\"CLIDR\", \"Cache Level ID Register\"),\n        (\"p15\", \"c0\", 1, \"c0\", 7): (\"AIDR\", \"Auxiliary ID Register\"),\n        (\"p15\", \"c0\", 2, \"c0\", 0): (\"CSSELR\", \"Cache Size Selection Register\"),\n        (\"p15\", \"c0\", 4, \"c0\", 0): (\"VPIDR\", \"Virtualization Processor ID Register\"),\n        (\"p15\", \"c0\", 4, \"c0\", 5): (\"VMPIDR\", \"Virtualization Multiprocessor ID Register\"),\n\n        # System control registers\n        (\"p15\", \"c1\", 0, \"c0\", 0): (\"SCTLR\", \"System Control Register\"),\n        (\"p15\", \"c1\", 0, \"c0\", 1): (\"ACTLR\", \"Auxiliary Control Register\"),\n        (\"p15\", \"c1\", 0, \"c0\", 3): (\"ACTLR2\", \"Auxiliary Control Register 2\"),\n        (\"p15\", \"c1\", 0, \"c0\", 2): (\"CPACR\", \"Architectural Feature Access Control Register\"),\n        (\"p15\", \"c1\", 0, \"c1\", 0): (\"SCR\", \"Secure Configuration Register\"),\n        (\"p15\", \"c1\", 0, \"c1\", 1): (\"SDER\", \"Secure Debug Enable Register\"),\n        (\"p15\", \"c1\", 0, \"c3\", 1): (\"SDCR\", \"Secure Debug Control Register\"),\n        (\"p15\", \"c1\", 0, \"c1\", 2): (\"NSACR\", \"Non-Secure Access Control Register\"),\n        (\"p15\", \"c1\", 4, \"c0\", 0): (\"HSCTLR\", \"Hyp System Control Register\"),\n        (\"p15\", \"c1\", 4, \"c0\", 1): (\"HACTLR\", \"Hyp Auxiliary Control Register\"),\n        (\"p15\", \"c1\", 4, \"c0\", 3): (\"HACTLR2\", \"Hyp Auxiliary Control Register 2\"),\n        (\"p15\", \"c1\", 4, \"c1\", 0): (\"HCR\", \"Hyp Configuration Register\"),\n        (\"p15\", \"c1\", 4, \"c1\", 4): (\"HCR2\", \"Hyp Configuration Register 2\"),\n        (\"p15\", \"c1\", 4, \"c1\", 1): (\"HDCR\", \"Hyp Debug Control Register\"),\n        (\"p15\", \"c1\", 4, \"c1\", 2): (\"HCPTR\", \"Hyp Architectural Feature Trap Register\"),\n        (\"p15\", \"c1\", 4, \"c1\", 3): (\"HSTR\", \"Hyp System Trap Register\"),\n        (\"p15\", \"c1\", 4, \"c1\", 7): (\"HACR\", \"Hyp Auxiliary Configuration Register\"),\n\n        # Translation Table Base Registers\n        (\"p15\", \"c2\", 0, \"c0\", 0): (\"TTBR0\", \"Translation Table Base Register 0\"),\n        (\"p15\", \"c2\", 0, \"c0\", 1): (\"TTBR1\", \"Translation Table Base Register 1\"),\n        (\"p15\", \"c2\", 4, \"c0\", 2): (\"HTCR\", \"Hyp Translation Control Register\"),\n        (\"p15\", \"c2\", 4, \"c1\", 2): (\"VTCR\", \"Virtualization Translation Control Register\"),\n        (\"p15\", \"c2\", 0, \"c0\", 2): (\"TTBCR\", \"Translation Table Base Control Register\"),\n        (\"p15\", \"c2\", 0, \"c0\", 3): (\"TTBCR2\", \"Translation Table Base Control Register 2\"),\n\n        # Domain Access Control registers\n        (\"p15\", \"c3\", 0, \"c0\", 0): (\"DACR\", \"Domain Access Control Register\"),\n\n        # Fault Status registers\n        (\"p15\", \"c5\", 0, \"c0\", 0): (\"DFSR\", \"Data Fault Status Register\"),\n        (\"p15\", \"c5\", 0, \"c0\", 1): (\"IFSR\", \"Instruction Fault Status Register\"),\n        (\"p15\", \"c5\", 0, \"c1\", 0): (\"ADFSR\", \"Auxiliary Data Fault Status Register\"),\n        (\"p15\", \"c5\", 0, \"c1\", 1): (\"AIFSR\", \"Auxiliary Instruction Fault Status Register\"),\n        (\"p15\", \"c5\", 4, \"c1\", 0): (\"HADFSR\", \"Hyp Auxiliary Data Fault Status Register\"),\n        (\"p15\", \"c5\", 4, \"c1\", 1): (\"HAIFSR\", \"Hyp Auxiliary Instruction Fault Status Register\"),\n        (\"p15\", \"c5\", 4, \"c2\", 0): (\"HSR\", \"Hyp Syndrome Register\"),\n\n        # Fault Address registers\n        (\"p15\", \"c6\", 0, \"c0\", 0): (\"DFAR\", \"Data Fault Address Register\"),\n        (\"p15\", \"c6\", 0, \"c0\", 1): (\"N/A\", \"Watchpoint Fault Address\"), # ARM11\n        (\"p15\", \"c6\", 0, \"c0\", 2): (\"IFAR\", \"Instruction Fault Address Register\"),\n        (\"p15\", \"c6\", 4, \"c0\", 0): (\"HDFAR\", \"Hyp Data Fault Address Register\"),\n        (\"p15\", \"c6\", 4, \"c0\", 2): (\"HIFAR\", \"Hyp Instruction Fault Address Register\"),\n        (\"p15\", \"c6\", 4, \"c0\", 4): (\"HPFAR\", \"Hyp IPA Fault Address Register\"),\n\n        # Cache maintenance registers\n        (\"p15\", \"c7\", 0, \"c0\", 4): (\"NOP\", \"No Operation / Wait For Interrupt\"),\n        (\"p15\", \"c7\", 0, \"c1\", 0): (\"ICIALLUIS\", \"Instruction Cache Invalidate All to PoU, Inner Shareable\"),\n        (\"p15\", \"c7\", 0, \"c1\", 6): (\"BPIALLIS\", \"Branch Predictor Invalidate All, Inner Shareable\"),\n        (\"p15\", \"c7\", 0, \"c4\", 0): (\"PAR\", \"Physical Address Register\"),\n        (\"p15\", \"c7\", 0, \"c5\", 0): (\"ICIALLU\", \"Instruction Cache Invalidate All to PoU\"),\n        (\"p15\", \"c7\", 0, \"c5\", 1): (\"ICIMVAU\", \"Instruction Cache line Invalidate by VA to PoU\"),\n        (\"p15\", \"c7\", 0, \"c5\", 2): (\"N/A\", \"Invalidate all instruction caches by set/way\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c5\", 4): (\"CP15ISB\", \"Instruction Synchronization Barrier System instruction\"),\n        (\"p15\", \"c7\", 0, \"c5\", 6): (\"BPIALL\", \"Branch Predictor Invalidate All\"),\n        (\"p15\", \"c7\", 0, \"c5\", 7): (\"BPIMVA\", \"Branch Predictor Invalidate by VA\"),\n        (\"p15\", \"c7\", 0, \"c6\", 0): (\"N/A\", \"Invalidate entire data cache\"),\n        (\"p15\", \"c7\", 0, \"c6\", 1): (\"DCIMVAC\", \"Data Cache line Invalidate by VA to PoC\"),\n        (\"p15\", \"c7\", 0, \"c6\", 2): (\"DCISW\", \"Data Cache line Invalidate by Set/Way\"),\n        (\"p15\", \"c7\", 0, \"c7\", 0): (\"N/A\", \"Invalidate instruction cache and data cache\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c8\", 0): (\"ATS1CPR\", \"Address Translate Stage 1 Current state PL1 Read\"),\n        (\"p15\", \"c7\", 0, \"c8\", 1): (\"ATS1CPW\", \"Address Translate Stage 1 Current state PL1 Write\"),\n        (\"p15\", \"c7\", 0, \"c8\", 2): (\"ATS1CUR\", \"Address Translate Stage 1 Current state Unprivileged Read\"),\n        (\"p15\", \"c7\", 0, \"c8\", 3): (\"ATS1CUW\", \"Address Translate Stage 1 Current state Unprivileged Write\"),\n        (\"p15\", \"c7\", 0, \"c8\", 4): (\"ATS12NSOPR\", \"Address Translate Stages 1 and 2 Non-secure Only PL1 Read\"),\n        (\"p15\", \"c7\", 0, \"c8\", 5): (\"ATS12NSOPW\", \"Address Translate Stages 1 and 2 Non-secure Only PL1 Write\"),\n        (\"p15\", \"c7\", 0, \"c8\", 6): (\"ATS12NSOUR\", \"Address Translate Stages 1 and 2 Non-secure Only Unprivileged Read\"),\n        (\"p15\", \"c7\", 0, \"c8\", 7): (\"ATS12NSOUW\", \"Address Translate Stages 1 and 2 Non-secure Only Unprivileged Write\"),\n        (\"p15\", \"c7\", 0, \"c9\", 0): (\"ATS1CPRP\", \"Address Translate Stage 1 Current state PL1 Read PAN\"),\n        (\"p15\", \"c7\", 0, \"c9\", 1): (\"ATS1CPWP\", \"Address Translate Stage 1 Current state PL1 Write PAN\"),\n        (\"p15\", \"c7\", 0, \"c10\", 0): (\"N/A\", \"Clean entire data cache\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c10\", 1): (\"DCCMVAC\", \"Data Cache line Clean by VA to PoC\"),\n        (\"p15\", \"c7\", 0, \"c10\", 2): (\"DCCSW\", \"Data Cache line Clean by Set/Way\"),\n        (\"p15\", \"c7\", 0, \"c10\", 3): (\"N/A\", \"Test and clean data cache\"), # ARM9\n        (\"p15\", \"c7\", 0, \"c10\", 4): (\"CP15DSB\", \"Data Synchronization Barrier System instruction\"),\n        (\"p15\", \"c7\", 0, \"c10\", 5): (\"CP15DMB\", \"Data Memory Barrier System instruction\"),\n        (\"p15\", \"c7\", 0, \"c10\", 6): (\"N/A\", \"Read Cache Dirty Status Register\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c11\", 1): (\"DCCMVAU\", \"Data Cache line Clean by VA to PoU\"),\n        (\"p15\", \"c7\", 0, \"c12\", 4): (\"N/A\", \"Read Block Transfer Status Register\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c12\", 5): (\"N/A\", \"Stop Prefetch Range\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c13\", 1): (\"NOP\", \"No Operation / Prefetch Instruction Cache Line\"),\n        (\"p15\", \"c7\", 0, \"c14\", 0): (\"N/A\", \"Clean and invalidate entire data cache\"), # ARM11\n        (\"p15\", \"c7\", 0, \"c14\", 1): (\"DCCIMVAC\", \"Data Cache line Clean and Invalidate by VA to PoC\"),\n        (\"p15\", \"c7\", 0, \"c14\", 2): (\"DCCISW\", \"Data Cache line Clean and Invalidate by Set/Way\"),\n        (\"p15\", \"c7\", 0, \"c14\", 3): (\"N/A\", \"Test, clean, and invalidate data cache\"), # ARM9\n        (\"p15\", \"c7\", 4, \"c8\", 0): (\"ATS1HR\", \"Address Translate Stage 1 Hyp mode Read\"),\n        (\"p15\", \"c7\", 4, \"c8\", 1): (\"ATS1HW\", \"Stage 1 Hyp mode write\"),\n\n        # TLB maintenance operations\n        (\"p15\", \"c8\", 0, \"c3\", 0): (\"TLBIALLIS\", \"TLB Invalidate All, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c3\", 1): (\"TLBIMVAIS\", \"TLB Invalidate by VA, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c3\", 2): (\"TLBIASIDIS\", \"TLB Invalidate by ASID match, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c3\", 3): (\"TLBIMVAAIS\", \"TLB Invalidate by VA, All ASID, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c3\", 5): (\"TLBIMVALIS\", \"TLB Invalidate by VA, Last level, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c3\", 7): (\"TLBIMVAALIS\", \"TLB Invalidate by VA, All ASID, Last level, Inner Shareable\"),\n        (\"p15\", \"c8\", 0, \"c5\", 0): (\"ITLBIALL\", \"Instruction TLB Invalidate All\"),\n        (\"p15\", \"c8\", 0, \"c5\", 1): (\"ITLBIMVA\", \"Instruction TLB Invalidate by VA\"),\n        (\"p15\", \"c8\", 0, \"c5\", 2): (\"ITLBIASID\", \"Instruction TLB Invalidate by ASID match\"),\n        (\"p15\", \"c8\", 0, \"c6\", 0): (\"DTLBIALL\", \"Data TLB Invalidate All\"),\n        (\"p15\", \"c8\", 0, \"c6\", 1): (\"DTLBIMVA\", \"Data TLB Invalidate by VA\"),\n        (\"p15\", \"c8\", 0, \"c6\", 2): (\"DTLBIASID\", \"Data TLB Invalidate by ASID match\"),\n        (\"p15\", \"c8\", 0, \"c7\", 0): (\"TLBIALL\", \"TLB Invalidate All\"),\n        (\"p15\", \"c8\", 0, \"c7\", 1): (\"TLBIMVA\", \"TLB Invalidate by VA\"),\n        (\"p15\", \"c8\", 0, \"c7\", 2): (\"TLBIASID\", \"TLB Invalidate by ASID match\"),\n        (\"p15\", \"c8\", 0, \"c7\", 3): (\"TLBIMVAA\", \"TLB Invalidate by VA, All ASID\"),\n        (\"p15\", \"c8\", 0, \"c7\", 5): (\"TLBIMVAL\", \"TLB Invalidate by VA, Last level\"),\n        (\"p15\", \"c8\", 0, \"c7\", 7): (\"TLBIMVAAL\", \"TLB Invalidate by VA, All ASID, Last level\"),\n        (\"p15\", \"c8\", 4, \"c0\", 1): (\"TLBIIPAS2IS\", \"TLB Invalidate by Intermediate Physical Address, Stage 2, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c0\", 5): (\"TLBIIPAS2LIS\", \"TLB Invalidate by Intermediate Physical Address, Stage 2, Last level, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c3\", 0): (\"TLBIALLHIS\", \"TLB Invalidate All, Hyp mode, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c3\", 1): (\"TLBIMVAHIS\", \"TLB Invalidate by VA, Hyp mode, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c3\", 4): (\"TLBIALLNSNHIS\", \"TLB Invalidate All, Non-Secure Non-Hyp, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c3\", 5): (\"TLBIMVALHIS\", \"TLB Invalidate by VA, Last level, Hyp mode, Inner Shareable\"),\n        (\"p15\", \"c8\", 4, \"c4\", 1): (\"TLBIIPAS2\", \"TLB Invalidate by Intermediate Physical Address, Stage 2\"),\n        (\"p15\", \"c8\", 4, \"c4\", 5): (\"TLBIIPAS2L\", \"TLB Invalidate by Intermediate Physical Address, Stage 2, Last level\"),\n        (\"p15\", \"c8\", 4, \"c7\", 0): (\"TLBIALLH\", \"TLB Invalidate All, Hyp mode\"),\n        (\"p15\", \"c8\", 4, \"c7\", 1): (\"TLBIMVAH\", \"TLB Invalidate by VA, Hyp mode\"),\n        (\"p15\", \"c8\", 4, \"c7\", 4): (\"TLBIALLNSNH\", \"TLB Invalidate All, Non-Secure Non-Hyp\"),\n        (\"p15\", \"c8\", 4, \"c7\", 5): (\"TLBIMVALH\", \"TLB Invalidate by VA, Last level, Hyp mode\"),\n\n        (\"p15\", \"c9\", 0, \"c0\", 0): (\"N/A\", \"Data Cache Lockdown\"), # ARM11\n        (\"p15\", \"c9\", 0, \"c0\", 1): (\"N/A\", \"Instruction Cache Lockdown\"), # ARM11\n        (\"p15\", \"c9\", 0, \"c1\", 0): (\"N/A\", \"Data TCM Region\"), # ARM11\n        (\"p15\", \"c9\", 0, \"c1\", 1): (\"N/A\", \"Instruction TCM Region\"), # ARM11\n        (\"p15\", \"c9\", 1, \"c0\", 2): (\"L2CTLR\", \"L2 Control Register\"),\n        (\"p15\", \"c9\", 1, \"c0\", 3): (\"L2ECTLR\", \"L2 Extended Control Register\"),\n\n        # Performance monitor registers\n        (\"p15\", \"c9\", 0, \"c12\", 0): (\"PMCR\", \"Performance Monitors Control Register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 1): (\"PMCNTENSET\", \"Performance Monitor Count Enable Set Register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 2): (\"PMCNTENCLR\", \"Performance Monitor Control Enable Clear Register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 3): (\"PMOVSR\", \"Performance Monitors Overflow Flag Status Register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 4): (\"PMSWINC\", \"Performance Monitors Software Increment register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 5): (\"PMSELR\", \"Performance Monitors Event Counter Selection Register\"),\n        (\"p15\", \"c9\", 0, \"c12\", 6): (\"PMCEID0\", \"Performance Monitors Common Event Identification register 0\"),\n        (\"p15\", \"c9\", 0, \"c12\", 7): (\"PMCEID1\", \"Performance Monitors Common Event Identification register 1\"),\n        (\"p15\", \"c9\", 0, \"c13\", 0): (\"PMCCNTR\", \"Performance Monitors Cycle Count Register\"),\n        (\"p15\", \"c9\", 0, \"c13\", 1): (\"PMXEVTYPER\", \"Performance Monitors Selected Event Type Register\"),\n        (\"p15\", \"c9\", 0, \"c13\", 2): (\"PMXEVCNTR\", \"Performance Monitors Selected Event Count Register\"),\n        (\"p15\", \"c9\", 0, \"c14\", 0): (\"PMUSERENR\", \"Performance Monitors User Enable Register\"),\n        (\"p15\", \"c9\", 0, \"c14\", 1): (\"PMINTENSET\", \"Performance Monitors Interrupt Enable Set register\"),\n        (\"p15\", \"c9\", 0, \"c14\", 2): (\"PMINTENCLR\", \"Performance Monitors Interrupt Enable Clear register\"),\n        (\"p15\", \"c9\", 0, \"c14\", 3): (\"PMOVSSET\", \"Performance Monitors Overflow Flag Status Set register\"),\n        (\"p15\", \"c9\", 0, \"c14\", 4): (\"PMCEID2\", \"Performance Monitors Common Event Identification register 2\"),\n        (\"p15\", \"c9\", 0, \"c14\", 5): (\"PMCEID3\", \"Performance Monitors Common Event Identification register 3\"),\n        (\"p15\", \"c9\", 0, \"c14\", 6): (\"PMMIR\", \"Performance Monitors Machine Identification Register\"),\n        (\"p15\", \"c14\", 0, \"c8\", 0): (\"PMEVCNTR0\", \"Performance Monitors Event Count Register 0\"),\n        (\"p15\", \"c14\", 0, \"c8\", 1): (\"PMEVCNTR1\", \"Performance Monitors Event Count Register 1\"),\n        (\"p15\", \"c14\", 0, \"c8\", 2): (\"PMEVCNTR2\", \"Performance Monitors Event Count Register 2\"),\n        (\"p15\", \"c14\", 0, \"c8\", 3): (\"PMEVCNTR3\", \"Performance Monitors Event Count Register 3\"),\n        (\"p15\", \"c14\", 0, \"c8\", 4): (\"PMEVCNTR4\", \"Performance Monitors Event Count Register 4\"),\n        (\"p15\", \"c14\", 0, \"c8\", 5): (\"PMEVCNTR5\", \"Performance Monitors Event Count Register 5\"),\n        (\"p15\", \"c14\", 0, \"c8\", 6): (\"PMEVCNTR6\", \"Performance Monitors Event Count Register 6\"),\n        (\"p15\", \"c14\", 0, \"c8\", 7): (\"PMEVCNTR7\", \"Performance Monitors Event Count Register 7\"),\n        (\"p15\", \"c14\", 0, \"c9\", 0): (\"PMEVCNTR8\", \"Performance Monitors Event Count Register 8\"),\n        (\"p15\", \"c14\", 0, \"c9\", 1): (\"PMEVCNTR9\", \"Performance Monitors Event Count Register 9\"),\n        (\"p15\", \"c14\", 0, \"c9\", 2): (\"PMEVCNTR10\", \"Performance Monitors Event Count Register 10\"),\n        (\"p15\", \"c14\", 0, \"c9\", 3): (\"PMEVCNTR11\", \"Performance Monitors Event Count Register 11\"),\n        (\"p15\", \"c14\", 0, \"c9\", 4): (\"PMEVCNTR12\", \"Performance Monitors Event Count Register 12\"),\n        (\"p15\", \"c14\", 0, \"c9\", 5): (\"PMEVCNTR13\", \"Performance Monitors Event Count Register 13\"),\n        (\"p15\", \"c14\", 0, \"c9\", 6): (\"PMEVCNTR14\", \"Performance Monitors Event Count Register 14\"),\n        (\"p15\", \"c14\", 0, \"c9\", 7): (\"PMEVCNTR15\", \"Performance Monitors Event Count Register 15\"),\n        (\"p15\", \"c14\", 0, \"c10\", 0): (\"PMEVCNTR16\", \"Performance Monitors Event Count Register 16\"),\n        (\"p15\", \"c14\", 0, \"c10\", 1): (\"PMEVCNTR17\", \"Performance Monitors Event Count Register 17\"),\n        (\"p15\", \"c14\", 0, \"c10\", 2): (\"PMEVCNTR18\", \"Performance Monitors Event Count Register 18\"),\n        (\"p15\", \"c14\", 0, \"c10\", 3): (\"PMEVCNTR19\", \"Performance Monitors Event Count Register 19\"),\n        (\"p15\", \"c14\", 0, \"c10\", 4): (\"PMEVCNTR20\", \"Performance Monitors Event Count Register 20\"),\n        (\"p15\", \"c14\", 0, \"c10\", 5): (\"PMEVCNTR21\", \"Performance Monitors Event Count Register 21\"),\n        (\"p15\", \"c14\", 0, \"c10\", 6): (\"PMEVCNTR22\", \"Performance Monitors Event Count Register 22\"),\n        (\"p15\", \"c14\", 0, \"c10\", 7): (\"PMEVCNTR23\", \"Performance Monitors Event Count Register 23\"),\n        (\"p15\", \"c14\", 0, \"c11\", 0): (\"PMEVCNTR24\", \"Performance Monitors Event Count Register 24\"),\n        (\"p15\", \"c14\", 0, \"c11\", 1): (\"PMEVCNTR25\", \"Performance Monitors Event Count Register 25\"),\n        (\"p15\", \"c14\", 0, \"c11\", 2): (\"PMEVCNTR26\", \"Performance Monitors Event Count Register 26\"),\n        (\"p15\", \"c14\", 0, \"c11\", 3): (\"PMEVCNTR27\", \"Performance Monitors Event Count Register 27\"),\n        (\"p15\", \"c14\", 0, \"c11\", 4): (\"PMEVCNTR28\", \"Performance Monitors Event Count Register 28\"),\n        (\"p15\", \"c14\", 0, \"c11\", 5): (\"PMEVCNTR29\", \"Performance Monitors Event Count Register 29\"),\n        (\"p15\", \"c14\", 0, \"c11\", 6): (\"PMEVCNTR30\", \"Performance Monitors Event Count Register 30\"),\n        (\"p15\", \"c14\", 0, \"c12\", 0): (\"PMEVTYPER0\", \"Performance Monitors Event Type Register 0\"),\n        (\"p15\", \"c14\", 0, \"c12\", 1): (\"PMEVTYPER1\", \"Performance Monitors Event Type Register 1\"),\n        (\"p15\", \"c14\", 0, \"c12\", 2): (\"PMEVTYPER2\", \"Performance Monitors Event Type Register 2\"),\n        (\"p15\", \"c14\", 0, \"c12\", 3): (\"PMEVTYPER3\", \"Performance Monitors Event Type Register 3\"),\n        (\"p15\", \"c14\", 0, \"c12\", 4): (\"PMEVTYPER4\", \"Performance Monitors Event Type Register 4\"),\n        (\"p15\", \"c14\", 0, \"c12\", 5): (\"PMEVTYPER5\", \"Performance Monitors Event Type Register 5\"),\n        (\"p15\", \"c14\", 0, \"c12\", 6): (\"PMEVTYPER6\", \"Performance Monitors Event Type Register 6\"),\n        (\"p15\", \"c14\", 0, \"c12\", 7): (\"PMEVTYPER7\", \"Performance Monitors Event Type Register 7\"),\n        (\"p15\", \"c14\", 0, \"c13\", 0): (\"PMEVTYPER8\", \"Performance Monitors Event Type Register 8\"),\n        (\"p15\", \"c14\", 0, \"c13\", 1): (\"PMEVTYPER9\", \"Performance Monitors Event Type Register 9\"),\n        (\"p15\", \"c14\", 0, \"c13\", 2): (\"PMEVTYPER10\", \"Performance Monitors Event Type Register 10\"),\n        (\"p15\", \"c14\", 0, \"c13\", 3): (\"PMEVTYPER11\", \"Performance Monitors Event Type Register 11\"),\n        (\"p15\", \"c14\", 0, \"c13\", 4): (\"PMEVTYPER12\", \"Performance Monitors Event Type Register 12\"),\n        (\"p15\", \"c14\", 0, \"c13\", 5): (\"PMEVTYPER13\", \"Performance Monitors Event Type Register 13\"),\n        (\"p15\", \"c14\", 0, \"c13\", 6): (\"PMEVTYPER14\", \"Performance Monitors Event Type Register 14\"),\n        (\"p15\", \"c14\", 0, \"c13\", 7): (\"PMEVTYPER15\", \"Performance Monitors Event Type Register 15\"),\n        (\"p15\", \"c14\", 0, \"c14\", 0): (\"PMEVTYPER16\", \"Performance Monitors Event Type Register 16\"),\n        (\"p15\", \"c14\", 0, \"c14\", 1): (\"PMEVTYPER17\", \"Performance Monitors Event Type Register 17\"),\n        (\"p15\", \"c14\", 0, \"c14\", 2): (\"PMEVTYPER18\", \"Performance Monitors Event Type Register 18\"),\n        (\"p15\", \"c14\", 0, \"c14\", 3): (\"PMEVTYPER19\", \"Performance Monitors Event Type Register 19\"),\n        (\"p15\", \"c14\", 0, \"c14\", 4): (\"PMEVTYPER20\", \"Performance Monitors Event Type Register 20\"),\n        (\"p15\", \"c14\", 0, \"c14\", 5): (\"PMEVTYPER21\", \"Performance Monitors Event Type Register 21\"),\n        (\"p15\", \"c14\", 0, \"c14\", 6): (\"PMEVTYPER22\", \"Performance Monitors Event Type Register 22\"),\n        (\"p15\", \"c14\", 0, \"c14\", 7): (\"PMEVTYPER23\", \"Performance Monitors Event Type Register 23\"),\n        (\"p15\", \"c14\", 0, \"c15\", 0): (\"PMEVTYPER24\", \"Performance Monitors Event Type Register 24\"),\n        (\"p15\", \"c14\", 0, \"c15\", 1): (\"PMEVTYPER25\", \"Performance Monitors Event Type Register 25\"),\n        (\"p15\", \"c14\", 0, \"c15\", 2): (\"PMEVTYPER26\", \"Performance Monitors Event Type Register 26\"),\n        (\"p15\", \"c14\", 0, \"c15\", 3): (\"PMEVTYPER27\", \"Performance Monitors Event Type Register 27\"),\n        (\"p15\", \"c14\", 0, \"c15\", 4): (\"PMEVTYPER28\", \"Performance Monitors Event Type Register 28\"),\n        (\"p15\", \"c14\", 0, \"c15\", 5): (\"PMEVTYPER29\", \"Performance Monitors Event Type Register 29\"),\n        (\"p15\", \"c14\", 0, \"c15\", 6): (\"PMEVTYPER30\", \"Performance Monitors Event Type Register 30\"),\n        (\"p15\", \"c14\", 0, \"c15\", 7): (\"PMCCFILTR\", \"Performance Monitors Cycle Count Filter Register\"),\n\n        # Activity Monitors\n        (\"p15\", \"c13\", 0, \"c2\", 1): (\"AMCFGR\", \"Activity Monitors Configuration Register\"),\n        (\"p15\", \"c13\", 0, \"c2\", 2): (\"AMCGCR\", \"Activity Monitors Counter Group Configuration Register\"),\n        (\"p15\", \"c13\", 0, \"c2\", 4): (\"AMCNTENCLR0\", \"Activity Monitors Count Enable Clear Register 0\"),\n        (\"p15\", \"c13\", 0, \"c3\", 0): (\"AMCNTENCLR1\", \"Activity Monitors Count Enable Clear Register 1\"),\n        (\"p15\", \"c13\", 0, \"c2\", 5): (\"AMCNTENSET0\", \"Activity Monitors Count Enable Set Register 0\"),\n        (\"p15\", \"c13\", 0, \"c3\", 1): (\"AMCNTENSET1\", \"Activity Monitors Count Enable Set Register 1\"),\n        (\"p15\", \"c13\", 0, \"c2\", 0): (\"AMCR\", \"Activity Monitors Control Register\"),\n        (\"p15\", \"c13\", 0, \"c6\", 0): (\"AMEVTYPER00\", \"Activity Monitors Event Type Registers 0\"),\n        (\"p15\", \"c13\", 0, \"c6\", 1): (\"AMEVTYPER01\", \"Activity Monitors Event Type Registers 0\"),\n        (\"p15\", \"c13\", 0, \"c6\", 2): (\"AMEVTYPER02\", \"Activity Monitors Event Type Registers 0\"),\n        (\"p15\", \"c13\", 0, \"c14\", 0): (\"AMEVTYPER10\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 1): (\"AMEVTYPER11\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 2): (\"AMEVTYPER12\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 3): (\"AMEVTYPER13\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 4): (\"AMEVTYPER14\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 5): (\"AMEVTYPER15\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 6): (\"AMEVTYPER16\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c14\", 7): (\"AMEVTYPER17\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 0): (\"AMEVTYPER18\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 1): (\"AMEVTYPER19\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 2): (\"AMEVTYPER110\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 3): (\"AMEVTYPER111\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 4): (\"AMEVTYPER112\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 5): (\"AMEVTYPER113\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c15\", 6): (\"AMEVTYPER114\", \"Activity Monitors Event Type Registers 1\"),\n        (\"p15\", \"c13\", 0, \"c2\", 3): (\"AMUSERENR\", \"Activity Monitors User Enable Register\"),\n\n        # Reliability\n        (\"p15\", \"c12\", 0, \"c1\", 1): (\"DISR\", \"Deferred Interrupt Status Register\"),\n        (\"p15\", \"c5\", 0, \"c3\", 0): (\"ERRIDR\", \"Error Record ID Register\"),\n        (\"p15\", \"c5\", 0, \"c3\", 1): (\"ERRSELR\", \"Error Record Select Register\"),\n        (\"p15\", \"c5\", 0, \"c4\", 3): (\"ERXADDR\", \"Selected Error Record Address Register\"),\n        (\"p15\", \"c5\", 0, \"c4\", 7): (\"ERXADDR2\", \"Selected Error Record Address Register 2\"),\n        (\"p15\", \"c5\", 0, \"c4\", 1): (\"ERXCTLR\", \"Selected Error Record Control Register\"),\n        (\"p15\", \"c5\", 0, \"c4\", 5): (\"ERXCTLR2\", \"Selected Error Record Control Register 2\"),\n        (\"p15\", \"c5\", 0, \"c4\", 0): (\"ERXFR\", \"Selected Error Record Feature Register\"),\n        (\"p15\", \"c5\", 0, \"c4\", 4): (\"ERXFR2\", \"Selected Error Record Feature Register 2\"),\n        (\"p15\", \"c5\", 0, \"c5\", 0): (\"ERXMISC0\", \"Selected Error Record Miscellaneous Register 0\"),\n        (\"p15\", \"c5\", 0, \"c5\", 1): (\"ERXMISC1\", \"Selected Error Record Miscellaneous Register 1\"),\n        (\"p15\", \"c5\", 0, \"c5\", 4): (\"ERXMISC2\", \"Selected Error Record Miscellaneous Register 2\"),\n        (\"p15\", \"c5\", 0, \"c5\", 5): (\"ERXMISC3\", \"Selected Error Record Miscellaneous Register 3\"),\n        (\"p15\", \"c5\", 0, \"c5\", 2): (\"ERXMISC4\", \"Selected Error Record Miscellaneous Register 4\"),\n        (\"p15\", \"c5\", 0, \"c5\", 3): (\"ERXMISC5\", \"Selected Error Record Miscellaneous Register 5\"),\n        (\"p15\", \"c5\", 0, \"c5\", 6): (\"ERXMISC6\", \"Selected Error Record Miscellaneous Register 6\"),\n        (\"p15\", \"c5\", 0, \"c5\", 7): (\"ERXMISC7\", \"Selected Error Record Miscellaneous Register 7\"),\n        (\"p15\", \"c5\", 0, \"c4\", 2): (\"ERXSTATUS\", \"Selected Error Record Primary Status Register\"),\n        (\"p15\", \"c5\", 4, \"c2\", 3): (\"VDFSR\", \"Virtual SError Exception Syndrome Register\"),\n        (\"p15\", \"c12\", 4, \"c1\", 1): (\"VDISR\", \"Virtual Deferred Interrupt Status Register\"),\n\n        # Memory attribute registers\n        (\"p15\", \"c10\", 0, \"c0\", 0): (\"N/A\", \"TLB Lockdown\"), # ARM11\n        (\"p15\", \"c10\", 0, \"c2\", 0): (\"MAIR0\", \"Memory Attribute Indirection Register 0\",\n                                     \"PRRR\", \"Primary Region Remap Register\"),\n        (\"p15\", \"c10\", 0, \"c2\", 1): (\"MAIR1\", \"Memory Attribute Indirection Register 1\",\n                                     \"NMRR\", \"Normal Memory Remap Register\"),\n        (\"p15\", \"c10\", 0, \"c3\", 0): (\"AMAIR0\", \"Auxiliary Memory Attribute Indirection Register 0\"),\n        (\"p15\", \"c10\", 0, \"c3\", 1): (\"AMAIR1\", \"Auxiliary Memory Attribute Indirection Register 1\"),\n        (\"p15\", \"c10\", 4, \"c2\", 0): (\"HMAIR0\", \"Hyp Memory Attribute Indirection Register 0\"),\n        (\"p15\", \"c10\", 4, \"c2\", 1): (\"HMAIR1\", \"Hyp Memory Attribute Indirection Register 1\"),\n        (\"p15\", \"c10\", 4, \"c3\", 0): (\"HAMAIR0\", \"Hyp Auxiliary Memory Attribute Indirection Register 0\"),\n        (\"p15\", \"c10\", 4, \"c3\", 1): (\"HAMAIR1\", \"Hyp Auxiliary Memory Attribute Indirection Register 1\"),\n\n        # DMA registers (ARM11)\n        # This definition conflicts with other coprocessor definitions.\n        # ARM v6 architecture (ARM11 core) is old and will be abandoned.\n        #(\"p15\", \"c11\", 0, \"c0\", 0): (\"N/A\", \"DMA Identification and Status (Present)\"),\n        #(\"p15\", \"c11\", 0, \"c0\", 1): (\"N/A\", \"DMA Identification and Status (Queued)\"),\n        #(\"p15\", \"c11\", 0, \"c0\", 2): (\"N/A\", \"DMA Identification and Status (Running)\"),\n        #(\"p15\", \"c11\", 0, \"c0\", 3): (\"N/A\", \"DMA Identification and Status (Interrupting)\"),\n        #(\"p15\", \"c11\", 0, \"c1\", 0): (\"N/A\", \"DMA User Accessibility\"),\n        #(\"p15\", \"c11\", 0, \"c2\", 0): (\"N/A\", \"DMA Channel Number\"),\n        #(\"p15\", \"c11\", 0, \"c3\", 0): (\"N/A\", \"DMA Enable (Stop)\"),\n        #(\"p15\", \"c11\", 0, \"c3\", 1): (\"N/A\", \"DMA Enable (Start)\"),\n        #(\"p15\", \"c11\", 0, \"c3\", 2): (\"N/A\", \"DMA Enable (Clear)\"),\n        #(\"p15\", \"c11\", 0, \"c4\", 0): (\"N/A\", \"DMA Control\"),\n        #(\"p15\", \"c11\", 0, \"c5\", 0): (\"N/A\", \"DMA Internal Start Address\"),\n        #(\"p15\", \"c11\", 0, \"c6\", 0): (\"N/A\", \"DMA External Start Address\"),\n        #(\"p15\", \"c11\", 0, \"c7\", 0): (\"N/A\", \"DMA Internal End Address\"),\n        #(\"p15\", \"c11\", 0, \"c8\", 0): (\"N/A\", \"DMA Channel Status\"),\n        #(\"p15\", \"c11\", 0, \"c15\", 0): (\"N/A\", \"DMA Context ID\"),\n\n        # Reset management registers.\n        (\"p15\", \"c12\", 0, \"c0\", 0): (\"VBAR\", \"Vector Base Address Register\"),\n        (\"p15\", \"c12\", 0, \"c0\", 1): (\"RVBAR\", \"Reset Vector Base Address Register\" ,\n                                     \"MVBAR\", \"Monitor Vector Base Address Register\"),\n        (\"p15\", \"c12\", 0, \"c0\", 2): (\"RMR\", \"Reset Management Register\"),\n        (\"p15\", \"c12\", 4, \"c0\", 2): (\"HRMR\", \"Hyp Reset Management Register\"),\n\n        (\"p15\", \"c12\", 0, \"c1\", 0): (\"ISR\", \"Interrupt Status Register\"),\n        (\"p15\", \"c12\", 4, \"c0\", 0): (\"HVBAR\", \"Hyp Vector Base Address Register\"),\n\n        (\"p15\", \"c13\", 0, \"c0\", 0): (\"FCSEIDR\", \"FCSE Process ID register\"),\n        (\"p15\", \"c13\", 0, \"c0\", 1): (\"CONTEXTIDR\", \"Context ID Register\"),\n        (\"p15\", \"c13\", 0, \"c0\", 2): (\"TPIDRURW\", \"PL0 Read/Write Software Thread ID Register\"),\n        (\"p15\", \"c13\", 0, \"c0\", 3): (\"TPIDRURO\", \"PL0 Read-Only Software Thread ID Register\"),\n        (\"p15\", \"c13\", 0, \"c0\", 4): (\"TPIDRPRW\", \"PL1 Software Thread ID Register\"),\n        (\"p15\", \"c13\", 4, \"c0\", 2): (\"HTPIDR\", \"Hyp Software Thread ID Register\"),\n\n        # Generic timer registers.\n        (\"p15\", \"c14\", 0, \"c0\", 0): (\"CNTFRQ\", \"Counter-timer Frequency register\"),\n        (\"p15\", \"c14\", 0, \"c1\", 0): (\"CNTKCTL\", \"Counter-timer Kernel Control register\"),\n        (\"p15\", \"c14\", 0, \"c2\", 0): (\"CNTP_TVAL\", \"Counter-timer Physical Timer TimerValue register\",\n                                     \"CNTHP_TVAL\", \"Counter-timer Hyp Physical Timer TimerValue register\",\n                                     \"CNTHPS_TVAL\", \"Counter-timer Secure Physical Timer TimerValue Register (EL2)\"),\n        (\"p15\", \"c14\", 0, \"c2\", 1): (\"CNTP_CTL\", \"Counter-timer Physical Timer Control register\",\n                                     \"CNTHP_CTL\", \"Counter-timer Hyp Physical Timer Control register\",\n                                     \"CNTHPS_CTL\", \"Counter-timer Secure Physical Timer Control Register (EL2)\"),\n        (\"p15\", \"c14\", 0, \"c3\", 0): (\"CNTV_TVAL\", \"Counter-timer Virtual Timer TimerValue register\",\n                                     \"CNTHV_TVAL\", \"Counter-timer Virtual Timer TimerValue register (EL2)\",\n                                     \"CNTHVS_TVAL\", \"Counter-timer Secure Virtual Timer TimerValue Register (EL2)\"),\n        (\"p15\", \"c14\", 0, \"c3\", 1): (\"CNTV_CTL\", \"Counter-timer Virtual Timer Control register\",\n                                     \"CNTHV_CTL\", \"Counter-timer Virtual Timer Control register (EL2)\",\n                                     \"CNTHVS_CTL\", \"Counter-timer Secure Virtual Timer Control Register (EL2)\"),\n        (\"p15\", \"c14\", 4, \"c1\", 0): (\"CNTHCTL\", \"Counter-timer Hyp Control register\"),\n        (\"p15\", \"c14\", 4, \"c2\", 0): (\"CNTHP_TVAL\", \"Counter-timer Hyp Physical Timer TimerValue register\"),\n        (\"p15\", \"c14\", 4, \"c2\", 1): (\"CNTHP_CTL\", \"Counter-timer Hyp Physical Timer Control register\"),\n\n        # Generic interrupt controller registers.\n        (\"p15\", \"c4\", 0, \"c6\", 0): (\"ICC_PMR\", \"Interrupt Controller Interrupt Priority Mask Register\",\n                                    \"ICV_PMR\", \"Interrupt Controller Virtual Interrupt Priority Mask Register\"),\n        (\"p15\", \"c12\", 0, \"c8\", 0): (\"ICC_IAR0\", \"Interrupt Controller Interrupt Acknowledge Register 0\",\n                                     \"ICV_IAR0\", \"Interrupt Controller Virtual Interrupt Acknowledge Register 0\"),\n        (\"p15\", \"c12\", 0, \"c8\", 1): (\"ICC_EOIR0\", \"Interrupt Controller End Of Interrupt Register 0\",\n                                     \"ICV_EOIR0\", \"Interrupt Controller Virtual End Of Interrupt Register 0\"),\n        (\"p15\", \"c12\", 0, \"c8\", 2): (\"ICC_HPPIR0\", \"Interrupt Controller Highest Priority Pending Interrupt Register 0\",\n                                     \"ICV_HPPIR0\", \"Interrupt Controller Virtual Highest Priority Pending Interrupt Register 0\"),\n        (\"p15\", \"c12\", 0, \"c8\", 3): (\"ICC_BPR0\", \"Interrupt Controller Binary Point Register 0\",\n                                     \"ICV_BPR0\", \"Interrupt Controller Virtual Binary Point Register 0\"),\n        (\"p15\", \"c12\", 0, \"c8\", 4): (\"ICC_AP0R0\", \"Interrupt Controller Active Priorities Group 0 Register 0\",\n                                     \"ICV_AP0R0\", \"Interrupt Controller Virtual Active Priorities Group 0 Register 0\"),\n        (\"p15\", \"c12\", 0, \"c8\", 5): (\"ICC_AP0R1\", \"Interrupt Controller Active Priorities Group 0 Register 1\",\n                                     \"ICV_AP0R1\", \"Interrupt Controller Virtual Active Priorities Group 0 Register 1\"),\n        (\"p15\", \"c12\", 0, \"c8\", 6): (\"ICC_AP0R2\", \"Interrupt Controller Active Priorities Group 0 Register 2\",\n                                     \"ICV_AP0R2\", \"Interrupt Controller Virtual Active Priorities Group 0 Register 2\"),\n        (\"p15\", \"c12\", 0, \"c8\", 7): (\"ICC_AP0R3\", \"Interrupt Controller Active Priorities Group 0 Register 3\",\n                                     \"ICV_AP0R3\", \"Interrupt Controller Virtual Active Priorities Group 0 Register 3\"),\n        (\"p15\", \"c12\", 0, \"c9\", 0): (\"ICC_AP1R0\", \"Interrupt Controller Active Priorities Group 1 Register 0\",\n                                     \"ICV_AP1R0\", \"Interrupt Controller Virtual Active Priorities Group 1 Register 0\"),\n        (\"p15\", \"c12\", 0, \"c9\", 1): (\"ICC_AP1R1\", \"Interrupt Controller Active Priorities Group 1 Register 1\",\n                                     \"ICV_AP1R1\", \"Interrupt Controller Virtual Active Priorities Group 1 Register 1\"),\n        (\"p15\", \"c12\", 0, \"c9\", 2): (\"ICC_AP1R2\", \"Interrupt Controller Active Priorities Group 1 Register 2\",\n                                     \"ICV_AP1R2\", \"Interrupt Controller Virtual Active Priorities Group 1 Register 2\"),\n        (\"p15\", \"c12\", 0, \"c9\", 3): (\"ICC_AP1R3\", \"Interrupt Controller Active Priorities Group 1 Register 3\",\n                                     \"ICV_AP1R3\", \"Interrupt Controller Virtual Active Priorities Group 1 Register 3\"),\n        (\"p15\", \"c12\", 0, \"c11\", 1): (\"ICC_DIR\", \"Interrupt Controller Deactivate Interrupt Register\",\n                                      \"ICV_DIR\", \"Interrupt Controller Deactivate Virtual Interrupt Register\"),\n        (\"p15\", \"c12\", 0, \"c11\", 3): (\"ICC_RPR\", \"Interrupt Controller Running Priority Register\",\n                                      \"ICV_RPR\", \"Interrupt Controller Virtual Running Priority Register\"),\n        (\"p15\", \"c12\", 0, \"c12\", 0): (\"ICC_IAR1\", \"Interrupt Controller Interrupt Acknowledge Register 1\",\n                                      \"ICV_IAR1\", \"Interrupt Controller Virtual Interrupt Acknowledge Register 1\"),\n        (\"p15\", \"c12\", 0, \"c12\", 1): (\"ICC_EOIR1\", \"Interrupt Controller End Of Interrupt Register 1\",\n                                      \"ICV_EOIR1\", \"Interrupt Controller Virtual End Of Interrupt Register 1\"),\n        (\"p15\", \"c12\", 0, \"c12\", 2): (\"ICC_HPPIR1\", \"Interrupt Controller Highest Priority Pending Interrupt Register 1\",\n                                      \"ICV_HPPIR1\", \"Interrupt Controller Virtual Highest Priority Pending Interrupt Register 1\"),\n        (\"p15\", \"c12\", 0, \"c12\", 3): (\"ICC_BPR1\", \"Interrupt Controller Binary Point Register 1\",\n                                      \"ICV_BPR1\", \"Interrupt Controller Virtual Binary Point Register 1\"),\n        (\"p15\", \"c12\", 0, \"c12\", 4): (\"ICC_CTLR\", \"Interrupt Controller Control Register\",\n                                      \"ICV_CTLR\", \"Interrupt Controller Virtual Control Register\"),\n        (\"p15\", \"c12\", 0, \"c12\", 5): (\"ICC_SRE\", \"Interrupt Controller System Register Enable register\"),\n        (\"p15\", \"c12\", 0, \"c12\", 6): (\"ICC_IGRPEN0\", \"Interrupt Controller Interrupt Group 0 Enable register\",\n                                      \"ICV_IGRPEN0\", \"Interrupt Controller Virtual Interrupt Group 0 Enable register\"),\n        (\"p15\", \"c12\", 0, \"c12\", 7): (\"ICC_IGRPEN1\", \"Interrupt Controller Interrupt Group 1 Enable register\",\n                                      \"ICV_IGRPEN1\", \"Interrupt Controller Virtual Interrupt Group 1 Enable register\"),\n        (\"p15\", \"c12\", 4, \"c8\", 0): (\"ICH_AP0R0\", \"Interrupt Controller Hyp Active Priorities Group 0 Register 0\"),\n        (\"p15\", \"c12\", 4, \"c8\", 1): (\"ICH_AP0R1\", \"Interrupt Controller Hyp Active Priorities Group 0 Register 1\"),\n        (\"p15\", \"c12\", 4, \"c8\", 2): (\"ICH_AP0R2\", \"Interrupt Controller Hyp Active Priorities Group 0 Register 2\"),\n        (\"p15\", \"c12\", 4, \"c8\", 3): (\"ICH_AP0R3\", \"Interrupt Controller Hyp Active Priorities Group 0 Register 3\"),\n        (\"p15\", \"c12\", 4, \"c9\", 0): (\"ICH_AP1R0\", \"Interrupt Controller Hyp Active Priorities Group 1 Register 0\"),\n        (\"p15\", \"c12\", 4, \"c9\", 1): (\"ICH_AP1R1\", \"Interrupt Controller Hyp Active Priorities Group 1 Register 1\"),\n        (\"p15\", \"c12\", 4, \"c9\", 2): (\"ICH_AP1R2\", \"Interrupt Controller Hyp Active Priorities Group 1 Register 2\"),\n        (\"p15\", \"c12\", 4, \"c9\", 3): (\"ICH_AP1R3\", \"Interrupt Controller Hyp Active Priorities Group 1 Register 3\"),\n        (\"p15\", \"c12\", 4, \"c9\", 5): (\"ICC_HSRE\", \"Interrupt Controller Hyp System Register Enable register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 0): (\"ICH_HCR\", \"Interrupt Controller Hyp Control Register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 1): (\"ICH_VTR\", \"Interrupt Controller VGIC Type Register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 2): (\"ICH_MISR\", \"Interrupt Controller Maintenance Interrupt State Register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 3): (\"ICH_EISR\", \"Interrupt Controller End of Interrupt Status Register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 5): (\"ICH_ELRSR\", \"Interrupt Controller Empty List Register Status Register\"),\n        (\"p15\", \"c12\", 4, \"c11\", 7): (\"ICH_VMCR\", \"Interrupt Controller Virtual Machine Control Register\"),\n        (\"p15\", \"c12\", 4, \"c12\", 0): (\"ICH_LR0\", \"Interrupt Controller List Register 0\"),\n        (\"p15\", \"c12\", 4, \"c12\", 1): (\"ICH_LR1\", \"Interrupt Controller List Register 1\"),\n        (\"p15\", \"c12\", 4, \"c12\", 2): (\"ICH_LR2\", \"Interrupt Controller List Register 2\"),\n        (\"p15\", \"c12\", 4, \"c12\", 3): (\"ICH_LR3\", \"Interrupt Controller List Register 3\"),\n        (\"p15\", \"c12\", 4, \"c12\", 4): (\"ICH_LR4\", \"Interrupt Controller List Register 4\"),\n        (\"p15\", \"c12\", 4, \"c12\", 5): (\"ICH_LR5\", \"Interrupt Controller List Register 5\"),\n        (\"p15\", \"c12\", 4, \"c12\", 6): (\"ICH_LR6\", \"Interrupt Controller List Register 6\"),\n        (\"p15\", \"c12\", 4, \"c12\", 7): (\"ICH_LR7\", \"Interrupt Controller List Register 7\"),\n        (\"p15\", \"c12\", 4, \"c13\", 0): (\"ICH_LR8\", \"Interrupt Controller List Register 8\"),\n        (\"p15\", \"c12\", 4, \"c13\", 1): (\"ICH_LR9\", \"Interrupt Controller List Register 9\"),\n        (\"p15\", \"c12\", 4, \"c13\", 2): (\"ICH_LR10\", \"Interrupt Controller List Register 10\"),\n        (\"p15\", \"c12\", 4, \"c13\", 3): (\"ICH_LR11\", \"Interrupt Controller List Register 11\"),\n        (\"p15\", \"c12\", 4, \"c13\", 4): (\"ICH_LR12\", \"Interrupt Controller List Register 12\"),\n        (\"p15\", \"c12\", 4, \"c13\", 5): (\"ICH_LR13\", \"Interrupt Controller List Register 13\"),\n        (\"p15\", \"c12\", 4, \"c13\", 6): (\"ICH_LR14\", \"Interrupt Controller List Register 14\"),\n        (\"p15\", \"c12\", 4, \"c13\", 7): (\"ICH_LR15\", \"Interrupt Controller List Register 15\"),\n        (\"p15\", \"c12\", 4, \"c14\", 0): (\"ICH_LRC0\", \"Interrupt Controller List Register 0\"),\n        (\"p15\", \"c12\", 4, \"c14\", 1): (\"ICH_LRC1\", \"Interrupt Controller List Register 1\"),\n        (\"p15\", \"c12\", 4, \"c14\", 2): (\"ICH_LRC2\", \"Interrupt Controller List Register 2\"),\n        (\"p15\", \"c12\", 4, \"c14\", 3): (\"ICH_LRC3\", \"Interrupt Controller List Register 3\"),\n        (\"p15\", \"c12\", 4, \"c14\", 4): (\"ICH_LRC4\", \"Interrupt Controller List Register 4\"),\n        (\"p15\", \"c12\", 4, \"c14\", 5): (\"ICH_LRC5\", \"Interrupt Controller List Register 5\"),\n        (\"p15\", \"c12\", 4, \"c14\", 6): (\"ICH_LRC6\", \"Interrupt Controller List Register 6\"),\n        (\"p15\", \"c12\", 4, \"c14\", 7): (\"ICH_LRC7\", \"Interrupt Controller List Register 7\"),\n        (\"p15\", \"c12\", 4, \"c15\", 0): (\"ICH_LRC8\", \"Interrupt Controller List Register 8\"),\n        (\"p15\", \"c12\", 4, \"c15\", 1): (\"ICH_LRC9\", \"Interrupt Controller List Register 9\"),\n        (\"p15\", \"c12\", 4, \"c15\", 2): (\"ICH_LRC10\", \"Interrupt Controller List Register 10\"),\n        (\"p15\", \"c12\", 4, \"c15\", 3): (\"ICH_LRC11\", \"Interrupt Controller List Register 11\"),\n        (\"p15\", \"c12\", 4, \"c15\", 4): (\"ICH_LRC12\", \"Interrupt Controller List Register 12\"),\n        (\"p15\", \"c12\", 4, \"c15\", 5): (\"ICH_LRC13\", \"Interrupt Controller List Register 13\"),\n        (\"p15\", \"c12\", 4, \"c15\", 6): (\"ICH_LRC14\", \"Interrupt Controller List Register 14\"),\n        (\"p15\", \"c12\", 4, \"c15\", 7): (\"ICH_LRC15\", \"Interrupt Controller List Register 15\"),\n        (\"p15\", \"c12\", 6, \"c12\", 4): (\"ICC_MCTLR\", \"Interrupt Controller Monitor Control Register\"),\n        (\"p15\", \"c12\", 6, \"c12\", 5): (\"ICC_MSRE\", \"Interrupt Controller Monitor System Register Enable register\"),\n        (\"p15\", \"c12\", 6, \"c12\", 7): (\"ICC_MGRPEN1\", \"Interrupt Controller Monitor Interrupt Group 1 Enable register\"),\n\n        (\"p15\", \"c15\", 0, \"c0\", 0): (\"IL1Data0\", \"Instruction L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c0\", 1): (\"IL1Data1\", \"Instruction L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c0\", 2): (\"IL1Data2\", \"Instruction L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c1\", 0): (\"DL1Data0\", \"Data L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c1\", 1): (\"DL1Data1\", \"Data L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c1\", 2): (\"DL1Data2\", \"Data L1 Data n Register\"),\n        (\"p15\", \"c15\", 0, \"c2\", 0): (\"N/A\", \"Data Memory Remap\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c2\", 1): (\"N/A\", \"Instruction Memory Remap\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c2\", 2): (\"N/A\", \"DMA Memory Remap\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c2\", 3): (\"N/A\", \"Peripheral Port Memory Remap\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c4\", 0): (\"RAMINDEX\", \"RAM Index Register\"),\n        (\"p15\", \"c15\", 0, \"c12\", 0): (\"N/A\", \"Performance Monitor Control\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c12\", 1): (\"CCNT\", \"Cycle Counter\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c12\", 2): (\"PMN0\", \"Count 0\"), # ARM11\n        (\"p15\", \"c15\", 0, \"c12\", 3): (\"PMN1\", \"Count 1\"), # ARM11\n        (\"p15\", \"c15\", 1, \"c0\", 0): (\"L2ACTLR\", \"L2 Auxiliary Control Register\"),\n        (\"p15\", \"c15\", 1, \"c0\", 3): (\"L2FPR\", \"L2 Prefetch Control Register\"),\n        (\"p15\", \"c15\", 3, \"c0\", 0): (\"N/A\", \"Data Debug Cache\"), # ARM11\n        (\"p15\", \"c15\", 3, \"c0\", 1): (\"N/A\", \"Instruction Debug Cache\"), # ARM11\n        (\"p15\", \"c15\", 3, \"c2\", 0): (\"N/A\", \"Data Tag RAM Read Operation\"), # ARM11\n        (\"p15\", \"c15\", 3, \"c2\", 1): (\"N/A\", \"Instruction Tag RAM Read Operation\"), # ARM11\n        (\"p15\", \"c15\", 4, \"c0\", 0): (\"CBAR\", \"Configuration Base Address Register\"),\n        (\"p15\", \"c15\", 5, \"c4\", 0): (\"N/A\", \"Data MicroTLB Index\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c4\", 1): (\"N/A\", \"Instruction MicroTLB Index\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c4\", 2): (\"N/A\", \"Read Main TLB Entry\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c4\", 4): (\"N/A\", \"Write Main TLB Entry\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c5\", 0): (\"N/A\", \"Data MicroTLB VA\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c5\", 1): (\"N/A\", \"Instruction MicroTLB VA\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c5\", 2): (\"N/A\", \"Main TLB VA\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c7\", 0): (\"N/A\", \"Data MicroTLB Attribute\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c7\", 1): (\"N/A\", \"Instruction MicroTLB Attribute\"), # ARM11\n        (\"p15\", \"c15\", 5, \"c7\", 2): (\"N/A\", \"Main TLB Attribute\"), # ARM11\n        (\"p15\", \"c15\", 7, \"c0\", 0): (\"N/A\", \"Cache Debug Control\"), # ARM11\n        (\"p15\", \"c15\", 7, \"c1\", 0): (\"N/A\", \"TLB Debug Control\"), # ARM11\n\n        # Preload Engine control registers\n        (\"p15\", \"c11\", 0, \"c0\", 0): (\"PLEIDR\", \"Preload Engine ID Register\"),\n        (\"p15\", \"c11\", 0, \"c0\", 2): (\"PLEASR\", \"Preload Engine Activity Status Register\"),\n        (\"p15\", \"c11\", 0, \"c0\", 4): (\"PLEFSR\", \"Preload Engine FIFO Status Register\"),\n        (\"p15\", \"c11\", 0, \"c1\", 0): (\"PLEUAR\", \"Preload Engine User Accessibility Register\"),\n        (\"p15\", \"c11\", 0, \"c1\", 1): (\"PLEPCR\", \"Preload Engine Parameters Control Register\"),\n\n        # Preload Engine operations\n        (\"p15\", \"c11\", 0, \"c2\", 1): (\"PLEFF\", \"Preload Engine FIFO flush operation\"),\n        (\"p15\", \"c11\", 0, \"c3\", 0): (\"PLEPC\", \"Preload Engine pause channel operation\"),\n        (\"p15\", \"c11\", 0, \"c3\", 1): (\"PLERC\", \"Preload Engine resume channel operation\"),\n        (\"p15\", \"c11\", 0, \"c3\", 2): (\"PLEKC\", \"Preload Engine kill channel operation\"),\n\n        # Jazelle registers\n        (\"p14\", \"c0\", 7, \"c0\", 0): (\"JIDR\", \"Jazelle ID Register\"),\n        (\"p14\", \"c1\", 7, \"c0\", 0): (\"JOSCR\", \"Jazelle OS Control Register\"),\n        (\"p14\", \"c2\", 7, \"c0\", 0): (\"JMCR\", \"Jazelle Main Configuration Register\"),\n\n        # Debug registers\n        (\"p15\", \"c4\", 3, \"c5\", 0): (\"DSPSR\", \"Debug Saved Program Status Register\"),\n        (\"p15\", \"c4\", 3, \"c5\", 1): (\"DLR\", \"Debug Link Register\"),\n        (\"p15\", \"c0\", 0, \"c3\", 5): (\"ID_DFR1\", \"Debug Feature Register 1\"),\n        (\"p14\", \"c0\", 0, \"c0\", 0): (\"DBGDIDR\", \"Debug ID Register\"),\n        (\"p14\", \"c0\", 0, \"c6\", 0): (\"DBGWFAR\", \"Debug Watchpoint Fault Address Register\"),\n        (\"p14\", \"c0\", 0, \"c6\", 2): (\"DBGOSECCR\", \"Debug OS Lock Exception Catch Control Register\"),\n        (\"p14\", \"c0\", 0, \"c7\", 0): (\"DBGVCR\", \"Debug Vector Catch Register\"),\n        (\"p14\", \"c0\", 0, \"c0\", 2): (\"DBGDTRRXext\", \"Debug OS Lock Data Transfer Register, Receive, External View\"),\n        (\"p14\", \"c0\", 0, \"c2\", 0): (\"DBGDCCINT\", \"DCC Interrupt Enable Register\"),\n        (\"p14\", \"c0\", 0, \"c2\", 2): (\"DBGDSCRext\", \"Debug Status and Control Register, External View\"),\n        (\"p14\", \"c0\", 0, \"c3\", 2): (\"DBGDTRTXext\", \"Debug OS Lock Data Transfer Register, Transmit\"),\n        (\"p14\", \"c0\", 0, \"c0\", 4): (\"DBGBVR0\", \"Debug Breakpoint Value Register 0\"),\n        (\"p14\", \"c0\", 0, \"c1\", 4): (\"DBGBVR1\", \"Debug Breakpoint Value Register 1\"),\n        (\"p14\", \"c0\", 0, \"c2\", 4): (\"DBGBVR2\", \"Debug Breakpoint Value Register 2\"),\n        (\"p14\", \"c0\", 0, \"c3\", 4): (\"DBGBVR3\", \"Debug Breakpoint Value Register 3\"),\n        (\"p14\", \"c0\", 0, \"c4\", 4): (\"DBGBVR4\", \"Debug Breakpoint Value Register 4\"),\n        (\"p14\", \"c0\", 0, \"c5\", 4): (\"DBGBVR5\", \"Debug Breakpoint Value Register 5\"),\n        (\"p14\", \"c0\", 0, \"c6\", 4): (\"DBGBVR6\", \"Debug Breakpoint Value Register 6\"),\n        (\"p14\", \"c0\", 0, \"c7\", 4): (\"DBGBVR7\", \"Debug Breakpoint Value Register 7\"),\n        (\"p14\", \"c0\", 0, \"c8\", 4): (\"DBGBVR8\", \"Debug Breakpoint Value Register 8\"),\n        (\"p14\", \"c0\", 0, \"c9\", 4): (\"DBGBVR9\", \"Debug Breakpoint Value Register 9\"),\n        (\"p14\", \"c0\", 0, \"c10\", 4): (\"DBGBVR10\", \"Debug Breakpoint Value Register 10\"),\n        (\"p14\", \"c0\", 0, \"c11\", 4): (\"DBGBVR11\", \"Debug Breakpoint Value Register 11\"),\n        (\"p14\", \"c0\", 0, \"c12\", 4): (\"DBGBVR12\", \"Debug Breakpoint Value Register 12\"),\n        (\"p14\", \"c0\", 0, \"c13\", 4): (\"DBGBVR13\", \"Debug Breakpoint Value Register 13\"),\n        (\"p14\", \"c0\", 0, \"c14\", 4): (\"DBGBVR14\", \"Debug Breakpoint Value Register 14\"),\n        (\"p14\", \"c0\", 0, \"c15\", 4): (\"DBGBVR15\", \"Debug Breakpoint Value Register 15\"),\n        (\"p14\", \"c0\", 0, \"c0\", 5): (\"DBGBCR0\", \"Debug Breakpoint Control Register 0\"),\n        (\"p14\", \"c0\", 0, \"c1\", 5): (\"DBGBCR1\", \"Debug Breakpoint Control Register 1\"),\n        (\"p14\", \"c0\", 0, \"c2\", 5): (\"DBGBCR2\", \"Debug Breakpoint Control Register 2\"),\n        (\"p14\", \"c0\", 0, \"c3\", 5): (\"DBGBCR3\", \"Debug Breakpoint Control Register 3\"),\n        (\"p14\", \"c0\", 0, \"c4\", 5): (\"DBGBCR4\", \"Debug Breakpoint Control Register 4\"),\n        (\"p14\", \"c0\", 0, \"c5\", 5): (\"DBGBCR5\", \"Debug Breakpoint Control Register 5\"),\n        (\"p14\", \"c0\", 0, \"c6\", 5): (\"DBGBCR6\", \"Debug Breakpoint Control Register 6\"),\n        (\"p14\", \"c0\", 0, \"c7\", 5): (\"DBGBCR7\", \"Debug Breakpoint Control Register 7\"),\n        (\"p14\", \"c0\", 0, \"c8\", 5): (\"DBGBCR8\", \"Debug Breakpoint Control Register 8\"),\n        (\"p14\", \"c0\", 0, \"c9\", 5): (\"DBGBCR9\", \"Debug Breakpoint Control Register 9\"),\n        (\"p14\", \"c0\", 0, \"c10\", 5): (\"DBGBCR10\", \"Debug Breakpoint Control Register 10\"),\n        (\"p14\", \"c0\", 0, \"c11\", 5): (\"DBGBCR11\", \"Debug Breakpoint Control Register 11\"),\n        (\"p14\", \"c0\", 0, \"c12\", 5): (\"DBGBCR12\", \"Debug Breakpoint Control Register 12\"),\n        (\"p14\", \"c0\", 0, \"c13\", 5): (\"DBGBCR13\", \"Debug Breakpoint Control Register 13\"),\n        (\"p14\", \"c0\", 0, \"c14\", 5): (\"DBGBCR14\", \"Debug Breakpoint Control Register 14\"),\n        (\"p14\", \"c0\", 0, \"c15\", 5): (\"DBGBCR15\", \"Debug Breakpoint Control Register 15\"),\n        (\"p14\", \"c0\", 0, \"c0\", 6): (\"DBGWVR0\", \"Debug Watchpoint Value Register 0\"),\n        (\"p14\", \"c0\", 0, \"c1\", 6): (\"DBGWVR1\", \"Debug Watchpoint Value Register 1\"),\n        (\"p14\", \"c0\", 0, \"c2\", 6): (\"DBGWVR2\", \"Debug Watchpoint Value Register 2\"),\n        (\"p14\", \"c0\", 0, \"c3\", 6): (\"DBGWVR3\", \"Debug Watchpoint Value Register 3\"),\n        (\"p14\", \"c0\", 0, \"c4\", 6): (\"DBGWVR4\", \"Debug Watchpoint Value Register 4\"),\n        (\"p14\", \"c0\", 0, \"c5\", 6): (\"DBGWVR5\", \"Debug Watchpoint Value Register 5\"),\n        (\"p14\", \"c0\", 0, \"c6\", 6): (\"DBGWVR6\", \"Debug Watchpoint Value Register 6\"),\n        (\"p14\", \"c0\", 0, \"c7\", 6): (\"DBGWVR7\", \"Debug Watchpoint Value Register 7\"),\n        (\"p14\", \"c0\", 0, \"c8\", 6): (\"DBGWVR8\", \"Debug Watchpoint Value Register 8\"),\n        (\"p14\", \"c0\", 0, \"c9\", 6): (\"DBGWVR9\", \"Debug Watchpoint Value Register 9\"),\n        (\"p14\", \"c0\", 0, \"c10\", 6): (\"DBGWVR10\", \"Debug Watchpoint Value Register 10\"),\n        (\"p14\", \"c0\", 0, \"c11\", 6): (\"DBGWVR11\", \"Debug Watchpoint Value Register 11\"),\n        (\"p14\", \"c0\", 0, \"c12\", 6): (\"DBGWVR12\", \"Debug Watchpoint Value Register 12\"),\n        (\"p14\", \"c0\", 0, \"c13\", 6): (\"DBGWVR13\", \"Debug Watchpoint Value Register 13\"),\n        (\"p14\", \"c0\", 0, \"c14\", 6): (\"DBGWVR14\", \"Debug Watchpoint Value Register 14\"),\n        (\"p14\", \"c0\", 0, \"c15\", 6): (\"DBGWVR15\", \"Debug Watchpoint Value Register 15\"),\n        (\"p14\", \"c0\", 0, \"c0\", 7): (\"DBGWCR0\", \"Debug Watchpoint Control Register 0\"),\n        (\"p14\", \"c0\", 0, \"c1\", 7): (\"DBGWCR1\", \"Debug Watchpoint Control Register 1\"),\n        (\"p14\", \"c0\", 0, \"c2\", 7): (\"DBGWCR2\", \"Debug Watchpoint Control Register 2\"),\n        (\"p14\", \"c0\", 0, \"c3\", 7): (\"DBGWCR3\", \"Debug Watchpoint Control Register 3\"),\n        (\"p14\", \"c0\", 0, \"c4\", 7): (\"DBGWCR4\", \"Debug Watchpoint Control Register 4\"),\n        (\"p14\", \"c0\", 0, \"c5\", 7): (\"DBGWCR5\", \"Debug Watchpoint Control Register 5\"),\n        (\"p14\", \"c0\", 0, \"c6\", 7): (\"DBGWCR6\", \"Debug Watchpoint Control Register 6\"),\n        (\"p14\", \"c0\", 0, \"c7\", 7): (\"DBGWCR7\", \"Debug Watchpoint Control Register 7\"),\n        (\"p14\", \"c0\", 0, \"c8\", 7): (\"DBGWCR8\", \"Debug Watchpoint Control Register 8\"),\n        (\"p14\", \"c0\", 0, \"c9\", 7): (\"DBGWCR9\", \"Debug Watchpoint Control Register 9\"),\n        (\"p14\", \"c0\", 0, \"c10\", 7): (\"DBGWCR10\", \"Debug Watchpoint Control Register 10\"),\n        (\"p14\", \"c0\", 0, \"c11\", 7): (\"DBGWCR11\", \"Debug Watchpoint Control Register 11\"),\n        (\"p14\", \"c0\", 0, \"c12\", 7): (\"DBGWCR12\", \"Debug Watchpoint Control Register 12\"),\n        (\"p14\", \"c0\", 0, \"c13\", 7): (\"DBGWCR13\", \"Debug Watchpoint Control Register 13\"),\n        (\"p14\", \"c0\", 0, \"c14\", 7): (\"DBGWCR14\", \"Debug Watchpoint Control Register 14\"),\n        (\"p14\", \"c0\", 0, \"c15\", 7): (\"DBGWCR15\", \"Debug Watchpoint Control Register 15\"),\n        (\"p14\", \"c1\", 0, \"c0\", 1): (\"DBGBXVR0\", \"Debug Breakpoint Extended Value Register 0\"),\n        (\"p14\", \"c1\", 0, \"c1\", 1): (\"DBGBXVR1\", \"Debug Breakpoint Extended Value Register 1\"),\n        (\"p14\", \"c1\", 0, \"c2\", 1): (\"DBGBXVR2\", \"Debug Breakpoint Extended Value Register 2\"),\n        (\"p14\", \"c1\", 0, \"c3\", 1): (\"DBGBXVR3\", \"Debug Breakpoint Extended Value Register 3\"),\n        (\"p14\", \"c1\", 0, \"c4\", 1): (\"DBGBXVR4\", \"Debug Breakpoint Extended Value Register 4\"),\n        (\"p14\", \"c1\", 0, \"c5\", 1): (\"DBGBXVR5\", \"Debug Breakpoint Extended Value Register 5\"),\n        (\"p14\", \"c1\", 0, \"c6\", 1): (\"DBGBXVR6\", \"Debug Breakpoint Extended Value Register 6\"),\n        (\"p14\", \"c1\", 0, \"c7\", 1): (\"DBGBXVR7\", \"Debug Breakpoint Extended Value Register 7\"),\n        (\"p14\", \"c1\", 0, \"c8\", 1): (\"DBGBXVR8\", \"Debug Breakpoint Extended Value Register 8\"),\n        (\"p14\", \"c1\", 0, \"c9\", 1): (\"DBGBXVR9\", \"Debug Breakpoint Extended Value Register 9\"),\n        (\"p14\", \"c1\", 0, \"c10\", 1): (\"DBGBXVR10\", \"Debug Breakpoint Extended Value Register 10\"),\n        (\"p14\", \"c1\", 0, \"c11\", 1): (\"DBGBXVR11\", \"Debug Breakpoint Extended Value Register 11\"),\n        (\"p14\", \"c1\", 0, \"c12\", 1): (\"DBGBXVR12\", \"Debug Breakpoint Extended Value Register 12\"),\n        (\"p14\", \"c1\", 0, \"c13\", 1): (\"DBGBXVR13\", \"Debug Breakpoint Extended Value Register 13\"),\n        (\"p14\", \"c1\", 0, \"c14\", 1): (\"DBGBXVR14\", \"Debug Breakpoint Extended Value Register 14\"),\n        (\"p14\", \"c1\", 0, \"c15\", 1): (\"DBGBXVR15\", \"Debug Breakpoint Extended Value Register 15\"),\n        (\"p14\", \"c1\", 0, \"c0\", 4): (\"DBGOSLAR\", \"Debug OS Lock Access Register\"),\n        (\"p14\", \"c1\", 0, \"c1\", 4): (\"DBGOSLSR\", \"Debug OS Lock Status Register\"),\n        (\"p14\", \"c1\", 0, \"c4\", 4): (\"DBGPRCR\", \"Debug Power Control Register\"),\n        (\"p14\", \"c7\", 0, \"c14\", 6): (\"DBGAUTHSTATUS\", \"Debug Authentication Status register\"),\n        (\"p14\", \"c7\", 0, \"c0\", 7): (\"DBGDEVID2\", \"Debug Device ID register 2\"),\n        (\"p14\", \"c7\", 0, \"c1\", 7): (\"DBGDEVID1\", \"Debug Device ID register 1\"),\n        (\"p14\", \"c7\", 0, \"c2\", 7): (\"DBGDEVID\", \"Debug Device ID register 0\"),\n        (\"p14\", \"c7\", 0, \"c8\", 6): (\"DBGCLAIMSET\", \"Debug Claim Tag Set register\"),\n        (\"p14\", \"c7\", 0, \"c9\", 6): (\"DBGCLAIMCLR\", \"Debug Claim Tag Clear register\"),\n        (\"p14\", \"c0\", 0, \"c1\", 0): (\"DBGDSCRint\", \"Debug Status and Control Register, Internal View\"),\n        (\"p14\", \"c0\", 0, \"c5\", 0): (\"DBGDTRRXint\", \"Debug Data Transfer Register, Receive\",\n                                    \"DBGDTRTXint\", \"Debug Data Transfer Register, Transmit\"),\n        (\"p14\", \"c1\", 0, \"c0\", 0): (\"DBGDRAR\", \"Debug ROM Address Register\"),\n        (\"p14\", \"c1\", 0, \"c3\", 4): (\"DBGOSDLR\", \"Debug OS Double Lock Register\"),\n        (\"p14\", \"c2\", 0, \"c0\", 0): (\"DBGDSAR\", \"Debug Self Address Register\"),\n        (\"p15\", \"c1\", 4, \"c2\", 1): (\"HTRFCR\", \"Hyp Trace Filter Control Register\"),\n        (\"p15\", \"c1\", 0, \"c2\", 1): (\"TRFCR\", \"Trace Filter Control Register\"),\n    }\n\n    def get_coproc_info(self, target_reg_name):\n        for k, v in self.AARCH32_COPROC_REGISTERS.items():\n            for reg_name, _desc in slicer(v, 2):\n                if target_reg_name == reg_name:\n                    return k\n        return None\n\n    def get_mrc_code(self, cp_info):\n        code = \"mrc {:s}, {:d}, r0, {:s}, {:s}, {:d}\".format(cp_info[0], cp_info[2], cp_info[1], cp_info[3], cp_info[4])\n        arch, mode = UnicornKeystoneCapstone.get_keystone_arch()\n        raw_insns = UnicornKeystoneCapstone.keystone_assemble(code, arch, mode, raw=True)\n        return raw_insns\n\n    def mrc_execute(self, reg_name):\n        cp_info = self.get_coproc_info(reg_name)\n        if cp_info is None:\n            return None\n        codes = [self.get_mrc_code(cp_info)]\n\n        before_pc = current_arch.pc\n        ret = ExecAsm(codes).exec_code()\n        after_pc = ret[\"reg\"][\"$pc\"]\n\n        # It jumps to the undefined exception vector when an access is made to a non-existent register.\n        # Even when execution is single-stepped, the PC register values can differ significantly.\n        if abs(after_pc - before_pc) > 0x10:\n            err(\"Undefined register, it probably crashes the kernel\")\n            return None\n        return ret[\"reg\"][current_arch.return_register]\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\",))\n    def do_invoke(self, args):\n        if current_arch is None:\n            err(\"current_arch is not set\")\n            return\n\n        reg_name = args.reg_name.upper()\n        if reg_name.startswith(\"$\"):\n            reg_name = reg_name[1:]\n\n        ret = self.mrc_execute(reg_name)\n        if ret is not None:\n            gef_print(\"{:s} = {:#x}\".format(reg_name, ret))\n        return\n\n\n@register_command\nclass UnicornEmulateCommand(GenericCommand):\n    \"\"\"Use Unicorn-Engine to emulate the behavior of the binary.\"\"\"\n\n    _cmdline_ = \"unicorn-emulate\"\n    _category_ = \"01-h. Debugging Support - Emulation\"\n    _aliases_ = [\"emulate\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--from-location\", type=AddressUtil.parse_address,\n                        help=\"specifies the start address of the emulated run. (default: current_arch.pc)\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-g\", \"--nb-gadget\", type=AddressUtil.parse_address,\n                        help=\"the number of gadgets to execute. (default mode, NB_GADGET: 10)\")\n    group.add_argument(\"-t\", \"--to-location\", type=AddressUtil.parse_address,\n                        help=\"the end address of the emulated run.\")\n    group.add_argument(\"-n\", \"--nb-insn\", type=AddressUtil.parse_address,\n                        help=\"the number of instructions from `FROM_LOCATION`.\")\n    parser.add_argument(\"-i\", \"--only-insns\", action=\"store_true\",\n                        help=\"show only instructions (no registers, memories, etc).\")\n    parser.add_argument(\"-s\", \"--skip-emulation\", \"--save\", action=\"store_true\",\n                        help=\"do not run, just save the script.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"displays the register values for each executed instruction.\")\n    parser.add_argument(\"-S\", \"--add-sse\", action=\"store_true\",\n                        help=\"initialization and display XMM registers (x64/x86 only).\")\n    parser.add_argument(\"-A\", \"--avoid-avx-neon-opt-func\", action=\"store_true\",\n                        help=\"patch GOT to replace (e.g., __XXX_avx2 with XXX), as Unicorn does not support them.\")\n    parser.add_argument(\"-E\", \"--emulate-mmap\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] used internally in gef, please don't use it.\")\n    parser.add_argument(\"-I\", \"--emulate-insn\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] used internally in gef, please don't use it.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -g 10               # from $pc to the point where 4 instructions are executed\",\n        \"{0:s} -n 5                # from $pc to 5 later instructions (assume it is no branch)\",\n        \"{0:s} -t 0x805678a4 -s    # from $pc to specified address with saving script\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"unicorn does not support emulating syscall.\",\n        \"unicorn does not support some instructions. (e.g., xsavec, xrstor, vpbroadcastb, vldr, etc.)\",\n        \"unicorn does not emulate ARM kernel-provided-user-helpers like $pc=0xffff0fe0, 0xffff0fc0, etc.\",\n        \"see: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def get_unicorn_end_addr(self, start_addr, nb):\n        dis = list(Disasm.gef_disassemble(start_addr, nb + 1))\n        last_insn = dis[-1]\n        return last_insn.address\n\n    def get_filename(self):\n        if is_remote_debug():\n            filepath = gdb.current_progspace().filename\n            if filepath.startswith(\"target:\"):\n                filepath = filepath[7:]\n            filename = os.path.basename(filepath)\n        else:\n            filename = Path.get_filename()\n        return filename\n\n    def make_script(self, kwargs):\n        arch, mode = UnicornKeystoneCapstone.get_unicorn_arch(to_string=True)\n        unicorn_registers = UnicornKeystoneCapstone.get_unicorn_registers(to_string=True, add_sse=kwargs[\"add_sse\"])\n        cs_arch, cs_mode = UnicornKeystoneCapstone.get_capstone_arch(to_string=True)\n        filename = self.get_filename()\n\n        Cache.reset_gef_caches(all=True)\n        vmmap = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True, allow_vsyscall=True)\n        if not vmmap:\n            warn(\"An error occurred when reading memory map\")\n            return\n\n        # header\n        content = \"#!{:s} -i\\n\".format(GefUtil.which(\"python3\"))\n        content += \"#\\n\"\n        content += \"# Emulation script for '{:s}'\".format(filename)\n        if kwargs[\"nb_gadget\"]:\n            content += \" from {:#x} to after {:#x} gadgets\\n\".format(kwargs[\"start_insn\"], kwargs[\"nb_gadget\"])\n        else:\n            content += \" from {:#x} to {:#x}\\n\".format(kwargs[\"start_insn\"], kwargs[\"end_insn\"])\n        content += \"#\\n\"\n        content += \"# Powered by gef, unicorn-engine, and capstone-engine\\n\"\n        content += \"#\\n\"\n        content += \"# Original: by @_hugsy_\\n\"\n        content += \"# Improvement: by @bata_24\\n\"\n        content += \"#\\n\"\n\n        # imports\n        content += \"import sys\\n\"\n        content += \"import re\\n\"\n        content += \"import traceback\\n\"\n        content += \"import collections\\n\"\n        content += \"import capstone\\n\"\n        content += \"import unicorn\\n\"\n        if is_ppc64() or is_ppc32():\n            content += \"import unicorn.ppc_const\\n\"\n        elif is_riscv32() or is_riscv64():\n            content += \"import unicorn.riscv_const\\n\"\n        elif is_s390x():\n            content += \"import unicorn.s390x_const\\n\"\n        content += \"\\n\"\n\n        # options, consts\n        content += \"uc = None\\n\"\n        content += \"verbose = {!s}\\n\".format(kwargs[\"verbose\"])\n        content += \"quiet = {!s}\\n\".format(kwargs[\"quiet\"])\n        content += \"only_insns = {!s}\\n\".format(kwargs[\"only_insns\"])\n        content += \"syscall_register = '{:s}'\\n\".format(current_arch.syscall_register)\n        content += \"count = 0\\n\"\n        content += \"changed_mem = {}\\n\"\n        content += \"\\n\"\n        content += \"registers = collections.OrderedDict({\\n\"\n        for r in unicorn_registers:\n            content += \"    '{:s}': {:s},\\n\".format(r.strip(), unicorn_registers[r])\n        content += \"})\\n\"\n        content += \"\\n\"\n\n        # capstone, disassembler\n        if is_arm32():\n            content += \"# hack: unicorn can handle if thumb or not, but capstone can't.\\n\"\n            content += \"# we have to handle it manually for capstone.\\n\"\n            cs_endian = cs_mode.split(\" + \")[-1]\n            content += \"cs_arm = capstone.Cs({:s}, {:s})\\n\".format(cs_arch, cs_endian)\n            content += \"cs_thumb = capstone.Cs({:s}, {:s})\\n\".format(cs_arch, \"capstone.CS_MODE_THUMB + \" + cs_endian)\n        else:\n            content += \"cs = capstone.Cs({:s}, {:s})\\n\".format(cs_arch, cs_mode)\n        content += \"\\n\"\n        content += \"def disassemble(emu, code, addr):\\n\"\n        if is_arm32():\n            content += \"    enable_thumb = emu.reg_read(registers['$cpsr']) & 0x20\\n\"\n            content += \"    cs = cs_thumb if enable_thumb else cs_arm\\n\"\n        content += \"    for insn in cs.disasm(code, addr):\\n\"\n        content += \"        return insn\\n\"\n        content += \"\\n\"\n\n        # hook functions\n        content += \"def code_hook(emu, address, size, user_data):\\n\"\n        content += \"    global count\\n\"\n        content += \"    if not quiet:\\n\"\n        content += \"        # unicorn passes 0xf1f1_f1f1 as size if opcode is unsupported.\\n\"\n        content += \"        # this causes memory read error, so we need to fix the size.\\n\"\n        content += \"        if size >= 0x40:\\n\"\n        content += \"            size = 0x10\\n\"\n        content += \"        # from unicorn 2.1.0, size as 4 if opcode is unsupported.\\n\"\n        content += \"        for i in range(10):\\n\"\n        content += \"            code = emu.mem_read(address, size + i)\\n\"\n        content += \"            insn = disassemble(emu, code, address)\\n\"\n        content += \"            if insn:\\n\"\n        content += \"                break\\n\"\n        content += \"        else:\\n\"\n        content += \"            raise\\n\"\n        content += \"        code_hex = code[:insn.size].hex()\\n\"\n        content += \"        if verbose:\\n\"\n        content += \"            print_regs(emu, registers)\\n\"\n        content += \"        fmt = '>>> {:d} {:#x}: {:24s} {:s} {:s}'\\n\"\n        content += \"        print(fmt.format(count, insn.address, code_hex, insn.mnemonic, insn.op_str))\\n\"\n        content += \"    count += 1\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n        content += \"def mem_invalid_hook(emu, access, address, size, value, user_data):\\n\"\n        content += \"    if access == unicorn.UC_MEM_WRITE_INVALID:\\n\"\n        content += \"        fmt = '  --> Invalid memory access; addr:{:#x}, size:{:#x}, value:{:#x}'\\n\"\n        content += \"        print(fmt.format(address, size, value))\\n\"\n        content += \"    elif access == unicorn.UC_MEM_READ_INVALID:\\n\"\n        content += \"        fmt = '  --> Invalid memory access; addr:{:#x}, size:{:#x}'\\n\"\n        content += \"        print(fmt.format(address, size))\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n        content += \"def mem_write_hook(emu, access, address, size, value, user_data):\\n\"\n        content += \"    if only_insns:\\n\"\n        content += \"        return\\n\"\n        content += \"    before = emu.mem_read(address, size)\\n\"\n        content += \"    for i in range(size):\\n\"\n        content += \"        accessed_address = address + i\\n\"\n        content += \"        if accessed_address not in changed_mem:\\n\"\n        content += \"            changed_mem[accessed_address] = {}\\n\"\n        content += \"            changed_mem[accessed_address]['before'] = before[i]\\n\"\n        content += \"        changed_mem[accessed_address]['after'] = (value >> (8 * i)) & 0xff\\n\"\n        content += \"        changed_mem[accessed_address]['type'] = 'modified'\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n        content += \"def intr_hook(emu, intno, user_data):\\n\"\n        if is_x86_32() or is_arm32() or is_arm64():\n            if is_x86_32():\n                intno = 0x80\n            elif is_arm32() or is_arm64():\n                intno = 0x2\n            content += \"    if intno == {:d}:\\n\".format(intno)\n            content += \"        syscall_hook(emu, user_data)\\n\"\n            content += \"        return\\n\"\n        if kwargs[\"emulate_insn\"] and is_arm64():\n            content += \"    if emulate_swpa_swpl(emu):\\n\"\n            content += \"        return\\n\"\n            content += \"    if emulate_casa_casl(emu):\\n\"\n            content += \"        return\\n\"\n        content += \"    print('  --> interrupt={:d}'.format(intno))\\n\"\n        content += \"    raise\\n\"\n        content += \"\\n\"\n        content += \"def syscall_hook(emu, user_data):\\n\"\n        content += \"    sysno = emu.reg_read(registers[syscall_register])\\n\"\n        if kwargs[\"emulate_mmap\"]:\n            content += \"    if emulate_mmap(emu, sysno):\\n\"\n            content += \"        return\\n\"\n            content += \"    if emulate_munmap(emu, sysno):\\n\"\n            content += \"        return\\n\"\n            content += \"    if emulate_brk(emu, sysno):\\n\"\n            content += \"        return\\n\"\n        content += \"    print('  --> syscall={:d} (not emulated)'.format(sysno))\\n\"\n        content += \"    raise\\n\"\n        content += \"\\n\"\n\n        # syscall emulation\n        if kwargs[\"emulate_mmap\"]:\n            name_table = get_syscall_table().name_table\n\n            if is_x86_32() or is_arm32():\n                mmap_entry = name_table[\"mmap2\"]\n            else:\n                mmap_entry = name_table[\"mmap\"]\n            content += \"def emulate_mmap(emu, sysno):\\n\"\n            content += \"    if sysno != {:d}:\\n\".format(mmap_entry.nr)\n            content += \"        return False\\n\"\n            content += \"\\n\"\n            content += \"    a1 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[0])\n            content += \"    if a1 != 0:\\n\"\n            content += \"        return False\\n\"\n            content += \"    a2 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[1])\n            content += \"    if a2 == 0 or (a2 & 0xfff) != 0:\\n\"\n            content += \"        return False\\n\"\n            content += \"    if a2 > 0x1000_0000: # heuristic value (0x800_0000 is used to create thread arena)\\n\"\n            content += \"        return False\\n\"\n            content += \"    a3 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[2])\n            content += \"    a3 &= 7\\n\"\n            content += \"    a4 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[3])\n            content += \"    if a4 != 0x22: # MAP_ANONYMOUS|MAP_PRIVATE\\n\"\n            content += \"        return False\\n\"\n            content += \"    a5 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[4])\n            content += \"    if a5 != 0xffff_ffff:\\n\"\n            content += \"        return False\\n\"\n            content += \"    a6 = emu.reg_read(registers['{:s}'])\\n\".format(mmap_entry.arg_regs[5])\n            content += \"\\n\"\n            content += \"    regions = [(None, 0, None)] + list(emu.mem_regions())\\n\"\n            content += \"    regions = regions[::-1]\\n\"\n            content += \"    for (mr1, mr2) in zip(regions[:-1], regions[1:]):\\n\"\n            if is_64bit():\n                content += \"        if mr1[0] >= 0x8000_0000_0000_0000: # avoid around [vsyscall]\\n\"\n                content += \"            continue\\n\"\n            content += \"        if mr1[0] - mr2[1] >= a2:\\n\"\n            content += \"            map_start = mr1[0] - a2\\n\"\n            content += \"            break\\n\"\n            content += \"    else:\\n\"\n            content += \"        return False # not found space\\n\"\n            content += \"    try:\\n\"\n            content += \"        emu.mem_map(map_start, a2, a3)\\n\"\n            content += \"        emu.reg_write(registers['{:s}'], map_start)\\n\".format(mmap_entry.ret_regs[0])\n            content += \"    except Exception:\\n\"\n            content += \"        return False\\n\"\n            content += \"    print('  --> syscall={:d} (emulated)'.format(sysno))\\n\"\n            content += \"    print(f'    --> {map_start:#x} = mmap({a1:#x}, {a2:#x}, {a3:#x}, {a4:#x}, {a5:#x}, {a6:#x})')\\n\"\n            content += \"    return True\\n\"\n            content += \"\\n\"\n\n            munmap_entry = name_table[\"munmap\"]\n            content += \"def emulate_munmap(emu, sysno):\\n\"\n            content += \"    if sysno != {:d}:\\n\".format(munmap_entry.nr)\n            content += \"        return False\\n\"\n            content += \"\\n\"\n            content += \"    a1 = emu.reg_read(registers['{:s}'])\\n\".format(munmap_entry.arg_regs[0])\n            content += \"    a2 = emu.reg_read(registers['{:s}'])\\n\".format(munmap_entry.arg_regs[1])\n            content += \"    if a2 == 0 or (a2 & 0xfff) != 0:\\n\"\n            content += \"        return False\\n\"\n            content += \"\\n\"\n            content += \"    try:\\n\"\n            content += \"        emu.mem_unmap(a1, a2)\\n\"\n            content += \"        emu.reg_write(registers['{:s}'], 0)\\n\".format(munmap_entry.ret_regs[0])\n            content += \"    except Exception:\\n\"\n            content += \"        return False\\n\"\n            content += \"    print('  --> syscall={:d} (emulated)'.format(sysno))\\n\"\n            content += \"    print(f'    --> munmap({a1:#x}, {a2:#x})')\\n\"\n            content += \"    return True\\n\"\n            content += \"\\n\"\n\n            brk_entry = name_table[\"brk\"]\n            current_brk = ExecSyscall(brk_entry.nr, [0x0]).exec_code()[\"reg\"][brk_entry.ret_regs[0]]\n            content += \"current_brk = {:#x}\\n\".format(current_brk)\n            content += \"\\n\"\n            content += \"# for main_arena expansion\\n\"\n            content += \"def emulate_brk(emu, sysno):\\n\"\n            content += \"    if sysno != {:d}:\\n\".format(brk_entry.nr)\n            content += \"        return False\\n\"\n            content += \"\\n\"\n            content += \"    global current_brk\\n\"\n            content += \"    a1 = emu.reg_read(registers['{:s}'])\\n\".format(brk_entry.arg_regs[0])\n            content += \"\\n\"\n            content += \"    if a1 == 0 or a1 == current_brk:\\n\"\n            content += \"        emu.reg_write(registers['{:s}'], current_brk)\\n\".format(brk_entry.ret_regs[0])\n            content += \"        return True\\n\"\n            content += \"\\n\"\n            content += \"    if a1 > current_brk:\\n\"\n            content += \"        for r in emu.mem_regions(): # get the permission of current brk region\\n\"\n            content += \"            if r[1] + 1 == current_brk:\\n\"\n            content += \"                map_perm = r[2]\\n\"\n            content += \"                break\\n\"\n            content += \"        else:\\n\"\n            content += \"            return False # something is wrong\\n\"\n            content += \"        try:\\n\"\n            content += \"            emu.mem_map(current_brk, a1 - current_brk, map_perm)\\n\"\n            content += \"        except Exception:\\n\"\n            content += \"            return False\\n\"\n            content += \"    else:\\n\"\n            content += \"        try:\\n\"\n            content += \"            emu.mem_unmap(a1, current_brk - a1)\\n\"\n            content += \"        except Exception:\\n\"\n            content += \"            return False\\n\"\n            content += \"\\n\"\n            content += \"    emu.reg_write(registers['{:s}'], a1)\\n\".format(brk_entry.ret_regs[0])\n            content += \"    print('  --> syscall={:d} (emulated)'.format(sysno))\\n\"\n            content += \"    print(f'    --> {a1:#x} = brk({a1:#x})')\\n\"\n            content += \"    current_brk = a1\\n\"\n            content += \"    return True\\n\"\n            content += \"\\n\"\n\n        # insn emulation\n        if kwargs[\"emulate_insn\"] and is_arm64():\n            content += \"def i2b(x, width={:d}):\\n\".format(current_arch.ptrsize)\n            content += \"    return x.to_bytes(width, byteorder='little')\\n\"\n            content += \"\\n\"\n            content += \"def b2i(x, width={:d}):\\n\".format(current_arch.ptrsize)\n            content += \"    i = int.from_bytes(x, byteorder='little')\\n\"\n            content += \"    if width == 4:\\n\"\n            content += \"        return i & 0xffff_ffff\\n\"\n            content += \"    return i\\n\"\n            content += \"\\n\"\n            content += \"def add_4_pc(emu):\\n\"\n            content += \"    address = emu.reg_read(registers['$pc'])\\n\"\n            content += \"    emu.reg_write(registers['$pc'], address + 4)\\n\"\n            content += \"    return\\n\"\n            content += \"\\n\"\n            content += \"def get_insn(emu):\\n\"\n            content += \"    address = emu.reg_read(registers['$pc'])\\n\"\n            content += \"    code = emu.mem_read(address, 4)\\n\"\n            content += \"    return disassemble(emu, code, address)\\n\"\n            content += \"\\n\"\n            content += \"def get_reg_and_width(m, i):\\n\"\n            content += \"    reg = registers['$x' + m.group(i)[1:]]\\n\"\n            content += \"    if m.group(i)[0] == 'x':\\n\"\n            content += \"        width = 8\\n\"\n            content += \"    elif m.group(i)[0] == 'w':\\n\"\n            content += \"        width = 4\\n\"\n            content += \"    return reg, width\\n\"\n            content += \"\\n\"\n            content += \"def reg_read(emu, reg, width):\\n\"\n            content += \"    val = emu.reg_read(reg)\\n\"\n            content += \"    val &= ((1 << (width * 8)) - 1)\\n\"\n            content += \"    return val\\n\"\n            content += \"\\n\"\n            content += \"def reg_write(emu, reg, width, val):\\n\"\n            content += \"    if isinstance(val, bytearray):\\n\"\n            content += \"        val = b2i(val, width)\\n\"\n            content += \"    else:\\n\"\n            content += \"        val &= (1 << (width * 8)) - 1\\n\"\n            content += \"    emu.reg_write(reg, val)\\n\"\n            content += \"    return\\n\"\n            content += \"\\n\"\n\n            content += \"def emulate_swpa_swpl(emu):\\n\"\n            content += \"    insn = get_insn(emu)\\n\"\n            content += \"    if insn.mnemonic not in ['swpa', 'swpl']:\\n\"\n            content += \"        return False\\n\"\n            content += \"    m = re.search(r'([xw]\\\\d+), ([xw]\\\\d+), \\\\[(x\\\\d+)\\\\]', insn.op_str)\\n\"\n            content += \"    if not m:\\n\"\n            content += \"        return False\\n\"\n            content += \"\"\n            content += \"    reg1, width1 = get_reg_and_width(m, 1)\\n\"\n            content += \"    reg2, width2 = get_reg_and_width(m, 2)\\n\"\n            content += \"    reg3, _ = get_reg_and_width(m, 3)\\n\"\n            content += \"\"\n            content += \"    mem_addr = emu.reg_read(reg3)\\n\"\n            content += \"    mem_val = emu.mem_read(mem_addr, 8)\\n\"\n            content += \"\"\n            content += \"    reg_write(emu, reg1, width1, mem_val)\\n\"\n            content += \"    reg2_val = reg_read(emu, reg2, width2)\\n\"\n            content += \"    emu.mem_write(mem_addr, i2b(reg2_val, width2))\\n\"\n            content += \"\"\n            content += \"    add_4_pc(emu)\\n\"\n            content += \"    return True\\n\"\n            content += \"\\n\"\n\n            content += \"def emulate_casa_casl(emu):\\n\"\n            content += \"    insn = get_insn(emu)\\n\"\n            content += \"    if insn.mnemonic not in ['casa', 'casl']:\\n\"\n            content += \"        return False\\n\"\n            content += \"    m = re.search(r'([xw]\\\\d+), ([xw]\\\\d+), \\\\[(x\\\\d+)\\\\]', insn.op_str)\\n\"\n            content += \"    if not m:\\n\"\n            content += \"        return False\\n\"\n            content += \"\"\n            content += \"    reg1, width1 = get_reg_and_width(m, 1)\\n\"\n            content += \"    reg2, width2 = get_reg_and_width(m, 2)\\n\"\n            content += \"    reg3, _ = get_reg_and_width(m, 3)\\n\"\n            content += \"\"\n            content += \"    mem_addr = emu.reg_read(reg3)\\n\"\n            content += \"    mem_val = emu.mem_read(mem_addr, 8)\\n\"\n            content += \"\"\n            content += \"    reg1_val = reg_read(emu, reg1, width1)\\n\"\n            content += \"    reg2_val = reg_read(emu, reg2, width2)\\n\"\n            content += \"    if reg1_val == b2i(mem_val, width1):\\n\"\n            content += \"        emu.mem_write(mem_addr, i2b(reg2_val, width2))\\n\"\n            content += \"    reg_write(emu, reg1, width1, mem_val)\\n\"\n            content += \"\"\n            content += \"    add_4_pc(emu)\\n\"\n            content += \"    return True\\n\"\n            content += \"\\n\"\n\n        # print function\n        content += \"def print_regs(emu, regs):\\n\"\n        content += \"    if only_insns:\\n\"\n        content += \"        return\\n\"\n        content += \"    for i, r in enumerate(regs):\\n\"\n        content += \"        if r.startswith('$xmm'):\\n\"\n        content += \"          fmt = '{{:7s}} = {{:#0{:d}x}}  '\\n\".format(32 + 2)\n        content += \"          print(fmt.format(r, emu.reg_read(regs[r])), end='')\\n\"\n        content += \"          if (i % 2 == 1) or (i == len(regs) - 1):\\n\"\n        content += \"              print('')\\n\"\n        content += \"        else:\\n\"\n        content += \"          fmt = '{{:7s}} = {{:#0{:d}x}}  '\\n\".format(current_arch.ptrsize * 2 + 2)\n        content += \"          print(fmt.format(r, emu.reg_read(regs[r])), end='')\\n\"\n        content += \"          if (i % 4 == 3) or (i == len(regs) - 1):\\n\"\n        content += \"              print('')\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n        content += \"def print_mems(emu):\\n\"\n        content += \"    if only_insns:\\n\"\n        content += \"        return\\n\"\n        content += \"    aligned_addrs = set([x & ~0xf for x in changed_mem.keys()])\\n\"\n        content += \"    for aligned_addr in aligned_addrs:\\n\"\n        content += \"        for pad_addr in range(aligned_addr, aligned_addr + 0x10):\\n\"\n        content += \"            if pad_addr in changed_mem:\\n\"\n        content += \"                pass\\n\"\n        content += \"            else:\\n\"\n        content += \"                changed_mem[pad_addr] = {}\\n\"\n        content += \"                changed_mem[pad_addr]['before'] = emu.mem_read(pad_addr, 1)[0]\\n\"\n        content += \"                changed_mem[pad_addr]['after'] = emu.mem_read(pad_addr, 1)[0]\\n\"\n        content += \"                changed_mem[pad_addr]['type'] = None\\n\"\n        content += \"    sorted_data = sorted(changed_mem.items())\\n\"\n        content += \"    sliced = [sorted_data[i:i + 16] for i in range(0, len(sorted_data), 16)]\\n\"\n        content += \"    prev_address = None\\n\"\n        content += \"    for chunk in sliced:\\n\"\n        content += \"        address = chunk[0][0]\\n\"\n        content += \"        prefix = '{{:#0{:d}x}}'.format(address)\\n\".format(current_arch.ptrsize * 2 + 2)\n        content += \"        before = ''\\n\"\n        content += \"        after = ''\\n\"\n        content += \"        for i in range({:d}):\\n\".format(16 // current_arch.ptrsize)\n        content += \"            atmp = []\\n\"\n        content += \"            btmp = []\\n\"\n        content += \"            for j in range({:d}):\\n\".format(current_arch.ptrsize)\n        content += \"                idx = i * {:d} + j\\n\".format(current_arch.ptrsize)\n        content += \"                a = chunk[idx][1]['after']\\n\"\n        content += \"                b = chunk[idx][1]['before']\\n\"\n        content += \"                if a == b:\\n\"\n        content += \"                    if chunk[idx][1]['type'] is None:\\n\"\n        content += \"                        btmp.append('{:02x}'.format(b))\\n\"\n        content += \"                        atmp.append('{:02x}'.format(a))\\n\"\n        content += \"                    else:\\n\"\n        content += \"                        btmp.append('\\\\033[2m{:02x}\\\\033[0m'.format(b))\\n\"\n        content += \"                        atmp.append('\\\\033[2m{:02x}\\\\033[0m'.format(a))\\n\"\n        content += \"                else:\\n\"\n        content += \"                    btmp.append('\\\\033[2m\\\\033[1m{:02x}\\\\033[0m'.format(b))\\n\"\n        content += \"                    atmp.append('\\\\033[2m\\\\033[1m{:02x}\\\\033[0m'.format(a))\\n\"\n        content += \"            before += '0x' + ''.join(btmp[::-1]) + ' '\\n\"\n        content += \"            after += '0x' + ''.join(atmp[::-1]) + ' '\\n\"\n        content += \"        line = '{:s} | {:s}| {:s}|'.format(prefix, before, after)\\n\"\n        content += \"        if prev_address is not None and prev_address + 0x10 != address:\\n\"\n        content += \"            print('*')\\n\"\n        content += \"        print(line)\\n\"\n        content += \"        prev_address = address\\n\"\n        content += \"    print('\\\\033[2m00\\\\033[0m: write accessed, ', end='')\\n\"\n        content += \"    print('\\\\033[2m\\\\033[1m00\\\\033[0m: value changes')\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n\n        # TLS\n        if is_x86():\n            content += \"# need to handle segmentation (and pagination) via MSR\\n\"\n            content += \"# from https://github.com/unicorn-engine/unicorn/blob/master/tests/regress/x86_64_msr.py\\n\"\n            content += \"SCRATCH_ADDR = 0xf000\\n\"\n            content += \"def set_msr(emu, msr, value, scratch=SCRATCH_ADDR):\\n\"\n            content += \"    buf = b'\\\\x0f\\\\x30' # x86: wrmsr\\n\"\n            content += \"    emu.mem_map(scratch, 0x1000)\\n\"\n            content += \"    emu.mem_write(scratch, buf)\\n\"\n            if is_x86_64():\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_RAX, value & 0xffff_ffff)\\n\"\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_RDX, (value >> 32) & 0xffff_ffff)\\n\"\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_RCX, msr & 0xffff_ffff)\\n\"\n            else:\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_EAX, value & 0xffff_ffff)\\n\"\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_EDX, (value >> 32) & 0xffff_ffff)\\n\"\n                content += \"    emu.reg_write(unicorn.x86_const.UC_X86_REG_ECX, msr & 0xffff_ffff)\\n\"\n            content += \"    emu.emu_start(scratch, scratch + len(buf), count=1)\\n\"\n            content += \"    emu.mem_unmap(scratch, 0x1000)\\n\"\n            content += \"    return\\n\"\n            content += \"\\n\"\n            content += \"def set_tls(emu, addr):\\n\"\n            if is_x86_64():\n                content += \"    FS_GS_MSR = 0xc0000100 # MSR_FS_BASE\\n\"\n            else:\n                content += \"    FS_GS_MSR = 0xc0000101 # MSR_GS_BASE\\n\"\n            content += \"    return set_msr(emu, FS_GS_MSR, addr)\\n\"\n            content += \"\\n\"\n\n        # setup registers\n        content += \"def reset_regs(emu):\\n\"\n        # special register (TLS)\n        if is_x86():\n            # If TLS is not initialized, the fixed address 0x2000 is used.\n            content += \"    set_tls(emu, {:#x})\\n\".format(current_arch.get_tls() or 0x2000)\n        if is_arm32() or is_arm64():\n            content += \"    # need first. because other register values may be broken when $cpsr is set.\\n\"\n            cpsr = get_register(\"$cpsr\")\n            content += \"    emu.reg_write({:s}, {:#x})\\n\".format(unicorn_registers[\"$cpsr\"], cpsr)\n        if is_arm64():\n            tpidr = get_register(\"$TPIDR_EL0\")\n            if tpidr is None:\n                tpidr = get_register(\"$tpidr\")\n            content += \"    emu.reg_write({:s}, {:#x})\\n\".format(unicorn_registers[\"$tpidr_el0\"], tpidr)\n        if is_arm32():\n            tls = current_arch.get_tls()\n            content += \"    emu.reg_write({:s}, {:#x})\\n\".format(unicorn_registers[\"$c13_c0_3\"], tls)\n        # special register (XMM)\n        if kwargs[\"add_sse\"]:\n            lines = Color.remove_color(gdb.execute(\"xmm\", to_string=True))\n            for reg in [\"$xmm{:d}\".format(i) for i in range(16)]:\n                r = re.findall(\"\\\\\" + reg + r\" +: (0x\\S+)\", lines)\n                if r:\n                    regvalue = int(r[0], 16)\n                    content += \"    emu.reg_write({:s}, {:#x})\\n\".format(unicorn_registers[reg], regvalue)\n        # general register\n        for reg in current_arch.all_registers:\n            if is_x86_64() and reg == \"$fs\":\n                continue\n            # On x86, writing to the segment register somehow fails, so skip it.\n            if is_x86_32() and reg in X86.special_registers:\n                continue\n            if (is_arm32() or is_arm64()) and reg == \"$cpsr\":\n                continue\n            regvalue = get_register(reg)\n            content += \"    emu.reg_write({:s}, {:#x})\\n\".format(unicorn_registers[reg], regvalue)\n        content += \"    return\\n\"\n        content += \"\\n\"\n\n        # memory dump\n        content += \"def reset_memories(emu):\\n\"\n        for sect in vmmap:\n            if sect.permission == Permission.NONE:\n                continue\n            content += \"    # Mapping {:s}: {:#x}-{:#x} [{!s}]\\n\".format(\n                sect.path, sect.page_start, sect.page_end, sect.permission,\n            )\n            content += \"    emu.mem_map({:#x}, {:#x}, {})\\n\".format(\n                sect.page_start, sect.size, oct(sect.permission.value),\n            )\n            if sect.permission & Permission.READ:\n                code = read_memory(sect.page_start, sect.size)\n                loc = os.path.join(kwargs[\"dloc\"], \"{:s}-{:#x}.raw\".format(filename, sect.page_start))\n                open(loc, \"wb\").write(bytes(code))\n                content += \"    emu.mem_write({:#x}, open('{:s}', 'rb').read())\\n\".format(sect.page_start, loc)\n\n        # memory patch to avoid avx/neon optimized function\n        if kwargs[\"patch_got\"] and (is_x86_64() or is_arm32()):\n            if is_x86_64():\n                RE_OPT = re.compile(r\"^(?:\\*ABS\\*|__str|__mem|str|mem).* \\| .+ \\| (0x\\S+) \\| (0x\\S+) <(__(\\w+)_avx2?.*)>\")\n            elif is_arm32():\n                RE_OPT = re.compile(r\"^(?:\\*ABS\\*|__str|__mem|str|mem).* \\| .+ \\| (0x\\S+) \\| (0x\\S+) <(__(\\w+)_neon.*)>\")\n\n            res = gdb.execute(\"got-all --no-pager\", to_string=True)\n            content += \"    # memory patch to avoid avx/neon optimized function\\n\"\n            for line in res.splitlines():\n                # search avx/neon optimized functions\n                line = Color.remove_color(line)\n                m = RE_OPT.search(line)\n                if not m:\n                    continue\n                try:\n                    got = int(m.group(1), 16)\n                    _current_func_addr = int(m.group(2), 16)\n                    current_func_name = m.group(3)\n                    base_func_name = m.group(4)\n                except ValueError:\n                    continue\n\n                # get original function (e.g., __memmove_avx_unaligned_erms -> __memmove)\n                try:\n                    base_func_addr = int(gdb.parse_and_eval(\"&{:s}\".format(base_func_name)))\n                except (gdb.error, ValueError):\n                    try:\n                        base_func_name = \"__\" + base_func_name # e.g., __memmove_chk\n                        base_func_addr = int(gdb.parse_and_eval(\"&{:s}\".format(base_func_name)))\n                    except (gdb.error, ValueError):\n                        continue\n\n                content += \"    emu.mem_write({:#x}, ({:#x}).to_bytes({:d}, byteorder='little')) # {:s} -> {:s}\\n\".format(\n                    got, base_func_addr, current_arch.ptrsize, current_func_name, base_func_name\n                )\n\n        content += \"    return\\n\"\n        content += \"\\n\"\n\n        # reset, emulate functions\n        content += \"def reset():\\n\"\n        content += \"    emu = unicorn.Uc({:s}, {:s})\\n\".format(arch, mode)\n        content += \"    reset_regs(emu)\\n\"\n        content += \"    reset_memories(emu)\\n\"\n        content += \"    # setup hook functions\\n\"\n        content += \"    emu.hook_add(unicorn.UC_HOOK_CODE, code_hook)\\n\"\n        content += \"    emu.hook_add(unicorn.UC_HOOK_INTR, intr_hook)\\n\"\n        if is_x86_64():\n            content += \"    emu.hook_add(unicorn.UC_HOOK_INSN, syscall_hook, None, 1, 0, unicorn.x86_const.UC_X86_INS_SYSCALL)\\n\"\n        content += \"    emu.hook_add(unicorn.UC_HOOK_MEM_READ_INVALID | unicorn.UC_HOOK_MEM_WRITE_INVALID, mem_invalid_hook)\\n\"\n        content += \"    emu.hook_add(unicorn.UC_HOOK_MEM_WRITE, mem_write_hook)\\n\"\n        content += \"    return emu\\n\"\n        content += \"\\n\"\n        content += \"def emulate(emu, start_addr, end_addr, count):\\n\"\n        content += \"    if not only_insns:\\n\"\n        content += \"        print('========================= Initial registers =========================')\\n\"\n        content += \"        print_regs(emu, registers)\\n\"\n        content += \"\\n\"\n        content += \"    if not only_insns:\\n\"\n        content += \"        print('========================= Starting emulation =========================')\\n\"\n        content += \"    try:\\n\"\n        content += \"        emu.emu_start(start_addr, end_addr, count=count)\\n\"\n        content += \"    except Exception:\\n\"\n        content += \"        emu.emu_stop()\\n\"\n        content += \"        print('========================= Emulation failed =========================')\\n\"\n        content += \"        traceback.print_exc(file=sys.stdout)\\n\"\n        content += \"\\n\"\n        content += \"    if not only_insns:\\n\"\n        content += \"        print('========================= Final registers =========================')\\n\"\n        content += \"        print_regs(emu, registers)\\n\"\n        content += \"        print('========================= Modified memories (before | after) =========================')\\n\"\n        content += \"        print_mems(emu)\\n\"\n        content += \"    return\\n\"\n        content += \"\\n\"\n        content += \"if __name__ == '__main__':\\n\"\n        content += \"    uc = reset()\\n\"\n        content += \"    emulate(uc, {:#x}, {:#x}, {:#x})\\n\".format(\n            kwargs[\"start_insn\"], kwargs[\"end_insn\"], kwargs[\"nb_gadget\"] or -1,\n        )\n        return content\n\n    def run_unicorn(self, content, kwargs):\n        tmp_fd, tmp_filename = GefUtil.mkstemp(prefix=\"unicorn-emulate\", suffix=\".py\", dt=kwargs[\"dt\"])\n        os.fdopen(tmp_fd, \"w\").write(content)\n        if kwargs[\"skip_emulation\"]:\n            info(\"Unicorn script generated as '{:s}'\".format(tmp_filename))\n            os.chmod(tmp_filename, 0o600)\n            return\n\n        if kwargs[\"nb_gadget\"] is None:\n            ok(\"Starting emulation: {:#x}  ->  {:#x}\".format(\n                kwargs[\"start_insn\"], kwargs[\"end_insn\"],\n            ))\n        else:\n            ok(\"Starting emulation: {:#x}  ->  after {:d} instructions are executed\".format(\n                kwargs[\"start_insn\"], kwargs[\"nb_gadget\"],\n            ))\n\n        try:\n            res = GefUtil.gef_execute_external([GefUtil.which(\"python3\"), tmp_filename], as_list=True)\n            gef_print(\"\\n\".join(res))\n        except subprocess.CalledProcessError as e:\n            gef_print(e.output.decode(\"utf-8\").rstrip())\n\n        os.unlink(tmp_filename)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @ModuleLoader.load_capstone\n    @ModuleLoader.load_unicorn\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.unicorn_support is False:\n            warn(\"This command is not supported on this architecture\")\n            return\n\n        # start_insn\n        start_insn = args.from_location\n        if start_insn is None:\n            start_insn = current_arch.pc\n\n        # ng_badget\n        if (args.to_location, args.nb_insn, args.nb_gadget) == (None, None, None):\n            nb_gadget = 10\n        else:\n            nb_gadget = args.nb_gadget\n\n        # end_insn\n        if nb_gadget is not None:\n            end_insn = 0\n        elif args.nb_insn is not None:\n            end_insn = self.get_unicorn_end_addr(start_insn, args.nb_insn)\n        else:\n            end_insn = args.to_location\n        if is_arm32() and end_insn:\n            end_insn &= ~1\n\n        # kwargs\n        dt = GefUtil.now_str()\n        kwargs = {\n            \"start_insn\": start_insn,\n            \"end_insn\": end_insn,\n            \"nb_gadget\": nb_gadget,\n            \"add_sse\": is_x86() and args.add_sse,\n            \"verbose\": args.verbose,\n            \"quiet\": args.quiet,\n            \"only_insns\": args.only_insns,\n            \"skip_emulation\": args.skip_emulation,\n            \"dt\": dt, # datetime\n            \"dloc\": os.path.join(GEF_TEMP_DIR, \"unicorn-emulate-\" + dt), # memory dump directory\n            \"patch_got\": args.avoid_avx_neon_opt_func,\n            \"emulate_mmap\": args.emulate_mmap,\n            \"emulate_insn\": args.emulate_insn,\n        }\n        os.mkdir(kwargs[\"dloc\"])\n\n        # thread locking\n        sched_lock = gdb.parameter(\"scheduler-locking\")\n        gdb.execute(\"set scheduler-locking on\", to_string=True)\n        # generate\n        script = self.make_script(kwargs)\n        # revert\n        gdb.execute(\"set scheduler-locking {:s}\".format(sched_lock), to_string=True)\n\n        # run\n        self.run_unicorn(script, kwargs)\n\n        # cleanup\n        if not kwargs[\"skip_emulation\"]:\n            GefUtil.rmdir(kwargs[\"dloc\"])\n        return\n\n\n@register_command\nclass AngrCommand(GenericCommand):\n    \"\"\"Use angr to find simple constraints.\"\"\"\n\n    _cmdline_ = \"angr\"\n    _category_ = \"01-h. Debugging Support - Emulation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--find\", action=\"append\", default=[],\n                        type=AddressUtil.parse_address, help=\"to find addresses.\")\n    parser.add_argument(\"-a\", \"--avoid\", action=\"append\", default=[],\n                        type=AddressUtil.parse_address, help=\"to avoid addresses.\")\n    parser.add_argument(\"-s\", \"--sym\", nargs=2, action=\"append\", metavar=(\"LOCATION\", \"SIZE\"), default=[],\n                        type=AddressUtil.parse_address, help=\"make memory symbolic.\")\n    parser.add_argument(\"-t\", \"--type\", action=\"append\", default=[],\n                        help=\"symbolic variable type. (A:A-Z, a:a-z, 0:0-9, s:0x20-0x7e, ?:0x00-0xff, z:0x00)\")\n    parser.add_argument(\"-S\", \"--skip-execution\", action=\"store_true\", help=\"do not execute.\")\n    parser.add_argument(\"-H\", \"--hook-stack-chk-fail-by-direct-return\", action=\"store_true\",\n                        help=\"hook `__stack_chk_fail@plt` by just `return`.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -f 0x400607 -a 0x400613 -s $rdi 30\",\n        \"{0:s} -f 0x400607 -a 0x400613 -s $rdi 30 -t Aa0                 # sym0:[A-Za-z0-9]+\",\n        \"{0:s} -f 0x400607 -a 0x400613 -s $rdi 30 -t ? -s $rdx 20 -t Az  # sym0:[0x00-0xff]+, sym1:[A-Z\\\\0]+\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"If there is a stack canary check, angr may fail to find the solution.\",\n        \"This occurs when execution begins inside a function but terminates outside of it.\",\n        \"To avoid it, you need to replace these instructions (e.g., `sub rdx, fs:28h; jnz loc_XXX`) with `nop`s.\",\n        \"Please patch memory or make other appropriate modifications before running the `angr` command.\",\n        \"\",\n        \"The -H option is designed to handle this issue automatically.\",\n        \"But it assumes that there is a `ret` after `call __stack_chk_fail@plt`.\",\n        \"Note that it will fail if there is a `ret` before `call __stack_chk_fail@plt`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_valid_plt(self):\n        \"\"\"Parse and return a dictionary of valid PLT entries from `got` command output.\"\"\"\n        res = gdb.execute(\"got --quiet --no-pager\", to_string=True)\n        res = Color.remove_color(res)\n        valid_plt = {}\n        for line in res.splitlines():\n            func_name, plt, *_ = line.split(\" | \")\n            if plt.startswith(\"Not found\"):\n                continue\n            valid_plt[func_name.strip()] = int(plt, 16)\n        return valid_plt\n\n    def save_memories(self, dt):\n        \"\"\"Dump all readable memory regions to files and yield their section info and file paths.\"\"\"\n        filename = Path.get_filename()\n        vmmap = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True, allow_vsyscall=True)\n        dloc = os.path.join(GEF_TEMP_DIR, \"angr-\" + dt)\n        os.mkdir(dloc)\n        for sect in vmmap:\n            if sect.permission & Permission.READ:\n                code = read_memory(sect.page_start, sect.size)\n                loc = os.path.join(dloc, \"{:s}-{:#x}.raw\".format(filename, sect.page_start))\n                open(loc, \"wb\").write(bytes(code))\n                yield sect, loc\n        return None\n\n    def make_angr_script(self, dt):\n        \"\"\"Generate an angr analysis script with memory, register, and symbolic constraints setup.\"\"\"\n        # initialize\n        content = \"#!{:s}\\n\".format(GefUtil.which(\"python3\"))\n        content += \"import angr\\n\"\n        content += \"import claripy\\n\"\n        content += \"import time\\n\"\n        content += \"\\n\"\n        content += \"start_time_real = time.perf_counter()\\n\"\n        content += \"start_time_proc = time.process_time()\\n\"\n        content += \"\\n\"\n        content += \"# initialize\\n\"\n        content += \"proj = angr.Project(\\n\"\n        content += \"    {!r},\\n\".format(Path.get_filepath())\n        content += \"    auto_load_libs=False,\\n\"\n        content += \")\\n\"\n        content += \"\\n\"\n        content += \"state = proj.factory.blank_state(\\n\"\n        content += \"    add_options={\\n\"\n        content += \"        angr.options.ZERO_FILL_UNCONSTRAINED_REGISTERS,\\n\"\n        content += \"        angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY,\\n\"\n        content += \"        #angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS,\\n\"\n        content += \"        #angr.options.SYMBOL_FILL_UNCONSTRAINED_MEMORY,\\n\"\n        content += \"        angr.options.CONSTRAINT_TRACKING_IN_SOLVER,\\n\"\n        content += \"    }\\n\"\n        content += \")\\n\"\n        content += \"\\n\"\n\n        # load memories\n        content += \"# load memories\\n\"\n        mems = self.save_memories(dt)\n        for sect, loc in mems:\n            content += \"# {!r} {!s}\\n\".format(sect.path or \"\", sect.permission)\n            content += \"state.memory.store({:#x}, open('{:s}', 'rb').read())\\n\".format(sect.page_start, loc)\n        content += \"\\n\"\n\n        # set registers\n        content += \"# set regs\\n\"\n        content += \"def set_register(reg, addr):\\n\"\n        content += \"    try:\\n\"\n        content += \"        setattr(state.regs, reg, addr)\\n\"\n        content += \"    except:\\n\"\n        content += \"        pass\\n\" # e.g., ARM32 cpsr\n        content += \"\\n\"\n        if hasattr(current_arch, \"general_registers\"):\n            target_registers = current_arch.general_registers\n        else:\n            target_registers = current_arch.all_registers\n        for reg in target_registers:\n            reg_value = get_register(reg)\n            if is_arm32():\n                if reg == \"$pc\":\n                    if current_arch.is_thumb():\n                        reg_value |= 1\n            content += \"set_register({!r}, {:#x})\\n\".format(reg.replace(\"$\", \"\"), reg_value)\n        content += \"\\n\"\n\n        # hook plt\n        content += \"# hook plt\\n\"\n        content += \"valid_plt = {\\n\"\n        valid_plt = self.get_valid_plt()\n        for func_name, plt in valid_plt.items():\n            content += '    \"{:s}\": {:#x},\\n'.format(func_name, plt)\n        content += \"}\\n\"\n        content += \"\\n\"\n        if self.args.hook_stack_chk_fail_by_direct_return:\n            content += \"class StackChkFail(angr.SimProcedure):\\n\"\n            content += \"    def run(self):\\n\"\n            content += \"        pass # do nothing\\n\"\n            content += \"\\n\"\n        content += \"for func_name, addr in valid_plt.items():\\n\"\n        if self.args.hook_stack_chk_fail_by_direct_return:\n            content += '    if func_name == \"__stack_chk_fail\":\\n'\n            content += \"        proj.hook(addr, StackChkFail())\\n\"\n            content += \"        continue\\n\"\n        content += '    if func_name in angr.SIM_PROCEDURES[\"libc\"]:\\n'\n        content += '        proj.hook(addr, angr.SIM_PROCEDURES[\"libc\"][func_name]())\\n'\n        content += \"\\n\"\n\n        # symboled memory\n        content += \"# symboled memories\\n\"\n        for i, (sym, sym_sz) in enumerate(self.args.sym):\n            content += \"sym_mem{:d} = claripy.BVS('sym_mem{:d}', {:d} * 8)\\n\".format(i, i, sym_sz)\n            if self.args.type:\n                args_type_i = sorted(set(self.args.type[i]))\n                if \"?\" in args_type_i:\n                    continue\n                content += \"for i in range({:d}):\\n\".format(sym_sz)\n                content += \"    byte = sym_mem{:d}.get_byte(i)\\n\".format(i)\n                content += \"    state.add_constraints(claripy.Or(\\n\"\n                if \"s\" in args_type_i:\n                    content += \"        claripy.And(0x20 <= byte, byte < 0x7f),\\n\"\n                if \"z\" in args_type_i:\n                    content += \"        byte == 0x00,\\n\"\n                if \"0\" in args_type_i:\n                    content += \"        claripy.And(ord('0') <= byte, byte <= ord('9')),\\n\"\n                if \"A\" in args_type_i:\n                    content += \"        claripy.And(ord('A') <= byte, byte <= ord('Z')),\\n\"\n                if \"a\" in args_type_i:\n                    content += \"        claripy.And(ord('a') <= byte, byte <= ord('z')),\\n\"\n                content += \"    ))\\n\"\n            content += \"state.memory.store({:#x}, sym_mem{:d})\\n\".format(sym, i)\n        content += \"\\n\"\n\n        # search\n        content += \"# search\\n\"\n        content += \"FIND_ADDR = [{:s}]\\n\".format(\",\".join([hex(x) for x in self.args.find]))\n        content += \"AVOID_ADDR = [{:s}]\\n\".format(\",\".join([hex(x) for x in self.args.avoid]))\n        content += \"simgr = proj.factory.simulation_manager(state)\\n\"\n        content += \"simgr.explore(find=FIND_ADDR, avoid=AVOID_ADDR)\\n\"\n        content += \"\\n\"\n        content += \"if simgr.found:\\n\"\n        content += \"    found_state = simgr.found[0]\\n\"\n        for i in range(len(self.args.sym)):\n            content += \"    solution = found_state.solver.eval(sym_mem{:d}, cast_to=bytes)\\n\".format(i)\n            content += '    print(\"\\\\033[1msym{:d}\\\\033[0m:\")\\n'.format(i)\n            content += '    print(\"  raw:\", repr(solution))\\n'\n            content += '    print(\"  hex:\", solution.hex())\\n'\n        content += \"else:\\n\"\n        content += '    print(\"No solution found\")\\n'\n        content += 'print(\"\")\\n'\n        content += \"\\n\"\n\n        # result perf\n        content += \"end_time_real = time.perf_counter()\\n\"\n        content += \"end_time_proc = time.process_time()\\n\"\n        content += \"\\n\"\n        content += \"real = int(end_time_real - start_time_real)\\n\"\n        content += \"cpu = int(end_time_proc - start_time_proc)\\n\"\n        content += 'print(\"Real: {:d}m{:d}s\".format(real // 60, real % 60))\\n'\n        content += 'print(\"CPU : {:d}m{:d}s\".format(cpu // 60, cpu % 60))\\n'\n\n        return content\n\n    def run_angr(self):\n        \"\"\"Generate, save, and optionally execute an angr analysis script, displaying the results.\"\"\"\n        # make script\n        dt = GefUtil.now_str()\n        content = self.make_angr_script(dt)\n\n        # write it\n        tmp_fd, tmp_filename = GefUtil.mkstemp(prefix=\"angr\", suffix=\".py\", dt=dt)\n        os.fdopen(tmp_fd, \"w\").write(content)\n        info(tmp_filename)\n\n        if self.args.skip_execution:\n            return\n\n        # run it\n        try:\n            res = GefUtil.gef_execute_external([GefUtil.which(\"python3\"), tmp_filename], as_list=True)\n            gef_print(\"\\n\".join(res))\n        except subprocess.CalledProcessError as e:\n            gef_print(e.output.decode(\"utf-8\").rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @ModuleLoader.load_angr\n    def do_invoke(self, args):\n        if not args.find or not args.sym:\n            self.usage()\n            return\n\n        if args.type:\n            if len(args.type) != len(args.sym):\n                err(\"The --type option must be specified for all symbols\")\n                return\n            for t in args.type:\n                for tc in t:\n                    if tc not in \"Aa0s?z\":\n                        err(\"Invalid symbolic type: {:s}\".format(tc))\n                        return\n\n        self.run_angr()\n        return\n\n\nclass StubBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to permanently disable a call (fork/alarm/signal/etc.).\"\"\"\n\n    def __init__(self, func, retval):\n        super().__init__(func, gdb.BP_BREAKPOINT, internal=False)\n        self.func = func\n        self.retval = retval\n\n        m = \"All calls to '{:s}' will be skipped\".format(self.func)\n        if self.retval is not None:\n            m += \" (with return value set to {:#x})\".format(self.retval)\n        info(m)\n        return\n\n    def stop(self):\n        m = \"Ignoring call to '{:s}' \".format(self.func)\n        m += \"(setting return value to {:#x})\".format(self.retval)\n        gdb.execute(\"return (unsigned int){:#x}\".format(self.retval))\n        ok(m)\n        return False\n\n\n@register_command\nclass StubCommand(GenericCommand):\n    \"\"\"Stub out the specified function to skip it. (e.g., fork)\"\"\"\n\n    _cmdline_ = \"stub\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"deactivate\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--retval\", type=int, default=0,\n                        help=\"the return value from stub. (default: %(default)s)\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"address/symbol to stub out.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -r 0 fork\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        loc = \"*{:#x}\".format(args.location)\n        StubBreakpoint(loc, args.retval)\n        return\n\n\n@register_command\nclass CapstoneDisassembleCommand(GenericCommand):\n    \"\"\"Use capstone disassembly framework to disassemble code.\"\"\"\n\n    _cmdline_ = \"capstone-disassemble\"\n    _category_ = \"01-e. Debugging Support - Assemble\"\n    _repeat_ = True\n    _aliases_ = [\"cs-dis\", \"pdisas\", \"nearpc\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address to disassemble. (default: current_arch.pc)\")\n    parser.add_argument(\"-l\", \"--length\", type=AddressUtil.parse_address,\n                        help=\"the length to disassemble. (default: context.nb_lines_code)\")\n    parser.add_argument(\"args\", metavar=\"ARGS\", nargs=\"*\", help=\"arguments for capstone. see following example.\")\n    _syntax_ = parser.format_help()\n\n    valid_arch_modes = {\n        \"ARM\" : [\"ARM\", \"THUMB\"],\n        \"ARM64\" : [\"ARM\"],\n        \"MIPS\" : [\"32\", \"64\"],\n        \"PPC\" : [\"32\", \"64\"],\n        \"SPARC\" : [\"32\", \"32PLUS\", \"64\"],\n        \"X86\" : [\"16\", \"32\", \"64\"],\n    }\n\n    _example_ = [\n        \"{0:s} -l 50 $pc                             # dump from $pc up to 50 lines later\",\n        \"{0:s} -l 50 $pc arch=ARM mode=ARM endian=1  # specify arch, mode and endian (1:big endian)\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Available architectures and modes:\"\n    ]\n    for arch in valid_arch_modes:\n        _note_.append(\" - {:8s} {}\".format(arch, \" / \".join(valid_arch_modes[arch])))\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        self.add_setting(\"nb_lines_code_default\", 50, \"Number of instruction if no length is specified.\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @ModuleLoader.load_capstone\n    @require_arch_set\n    def do_invoke(self, args):\n        kwargs = {}\n        for arg in args.args:\n            if \"=\" in arg:\n                key, value = arg.split(\"=\", 1)\n                kwargs[key] = value\n            else:\n                err(\"ARGS must be KEY=VALUE style\")\n                return\n\n        length = args.length or Config.get_gef_setting(\"capstone_disassemble.nb_lines_code_default\")\n        location = args.location or current_arch.pc\n\n        try:\n            skip = length * self.repeat_count\n            for insn in Disasm.capstone_disassemble(location, length, skip=skip, **kwargs):\n                if insn.address == current_arch.pc:\n                    msg = \" -> {:s}\".format(insn.colored_text(10, highlight=True))\n                else:\n                    msg = \"    {:s}\".format(insn.colored_text(10, highlight=False))\n                gef_print(msg)\n        except AttributeError:\n            err(\"Maybe unsupported architecture\")\n        except gdb.error:\n            pass\n        return\n\n\n@register_command\nclass GlibcHeapCommand(GenericCommand):\n    \"\"\"The base command to get information about the Glibc heap structure.\"\"\"\n\n    _cmdline_ = \"heap\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"arena\")\n    subparsers.add_parser(\"arenas\")\n    subparsers.add_parser(\"bins\")\n    subparsers.add_parser(\"bins-simple\")\n    subparsers.add_parser(\"chunk\")\n    subparsers.add_parser(\"chunks\")\n    subparsers.add_parser(\"top\")\n    subparsers.add_parser(\"try-free\")\n    subparsers.add_parser(\"try-malloc\")\n    subparsers.add_parser(\"try-realloc\")\n    subparsers.add_parser(\"try-calloc\")\n    subparsers.add_parser(\"tcache-index-helper\")\n    subparsers.add_parser(\"find-fake-fast\")\n    subparsers.add_parser(\"extract-heap-addr\")\n    subparsers.add_parser(\"calc-protected-fd\")\n    subparsers.add_parser(\"visual-heap\")\n    subparsers.add_parser(\"dump-image\")\n    subparsers.add_parser(\"tracer\")\n    subparsers.add_parser(\"parse\")\n    subparsers.add_parser(\"snapshot\")\n    subparsers.add_parser(\"snapshot-compare\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Supports up to glibc 2.43.\",\n        \"- 2.15+: GEF treats malloc_par.pagesize as absent (always None).\",\n        \"- 2.19+: malloc_state.next_free is handled.\",\n        \"- 2.23+: malloc_state.attached_threads is handled.\",\n        \"- 2.24+: GEF treats malloc_par.max_total_mem as absent (always None).\",\n        \"- 2.26: tcache is introduced.\",\n        \"- 2.26+: MALLOC_ALIGNMENT changes for x86_32/riscv32/ppc32 affect NFASTBINS and bin-size tables.\",\n        \"- 2.27+: malloc_state layout handling changes (have_fastchunks/fastbins offsets).\",\n        \"- 2.30: tcache_perthread_struct.counts element size changes 1->2 bytes.\",\n        \"- 2.32: Safe-Linking (pointer mangling) for tcache/fastbins fd is supported.\",\n        \"- 2.34+: GEF no longer uses the __malloc_hook-based strategy to locate main_arena.\",\n        \"- 2.35: heap_info.pagesize is handled.\",\n        \"- 2.35: malloc_par.{thp_pagesize,hp_pagesize,hp_flags} are handled.\",\n        \"- 2.42: TCACHE_MAX_BINS 64->76 (+12 large bins, arch-dependent size ranges).\",\n        \"- 2.42: tcache_perthread_struct.counts changes to num_slots.\",\n        \"- 2.43: fastbins are removed.\",\n        \"- 2.43: TCACHE_FILL_COUNT 7->16.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        self.add_setting(\"tcache_max_count\", -1, \"Max chunks per tcache bin (if configured by GLIBC_TUNABLES)\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass GlibcHeapTopCommand(GenericCommand):\n    \"\"\"Display heap top chunk.\"\"\"\n\n    _cmdline_ = \"heap top\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"top-chunk\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        # get top\n        if args.arena_addr:\n            res = gdb.execute(\"heap arena --no-pager --arena-addr {:#x}\".format(args.arena_addr), to_string=True)\n        else:\n            res = gdb.execute(\"heap arena --no-pager\", to_string=True)\n\n        m = re.search(r\"top = (0x\\S+),\", Color.remove_color(res))\n        if not m:\n            err(\"Could not find top address\")\n            return\n\n        top = int(m.group(1), 16)\n        info(\"arena.top: {:#x}\".format(top))\n        top += current_arch.ptrsize * 2\n        gef_print(GlibcHeap.GlibcChunk(arena, top).psprint())\n        return\n\n\n@register_command\nclass GlibcHeapArenasCommand(GenericCommand):\n    \"\"\"List heap arenas.\"\"\"\n\n    _cmdline_ = \"heap arenas\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"arenas\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # main_arena\n        arena = GlibcHeap.get_main_arena()\n\n        if arena is None:\n            err(\"Could not find glibc main arena\")\n            return\n\n        gef_print(titlify(\"main_arena\"))\n        gef_print(\"{}\".format(arena))\n\n        # thread arena\n        gef_print(titlify(\"thread_arena\"))\n        arena = arena.get_next()\n        if arena is None:\n            gef_print(\"Not found\")\n        while arena:\n            gef_print(\"{}\".format(arena))\n            arena = arena.get_next()\n        return\n\n\n@register_command\nclass GlibcHeapArenaCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display information on a heap arena.\"\"\"\n\n    _cmdline_ = \"heap arena\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"arena\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def parse_arena(self, arena):\n        \"\"\"Parse and append a formatted representation of the given arena's structure\n        to the output list.\"\"\"\n        try:\n            cmd = \"p ((struct malloc_state*) {:#x})[0]\".format(arena.addr)\n            title = titlify(\"[arena - parsed via debuginfo] --- {:s}\".format(cmd))\n            result = gdb.execute(cmd, to_string=True)\n            self.out.append(title)\n            self.out.extend(result.splitlines())\n        except gdb.error:\n            title = titlify(\"[arena - parsed heuristically] --- {:#x}\".format(arena.addr))\n            self.out.append(title)\n            self.out.append(\"$1 = {\")\n            self.out.append(\"  mutex = {:#x},\".format(int(arena.mutex)))\n            self.out.append(\"  flags = {:#x},\".format(int(arena.flags)))\n            if get_libc_version() >= (2, 27) and get_libc_version() < (2, 43):\n                self.out.append(\"  have_fastchunks = {:#x},\".format(int(arena.have_fastchunks)))\n            if get_libc_version() < (2, 43):\n                self.out.append(\"  fastbinsY = {\")\n                for i in range(int(arena.num_fastbins)):\n                    self.out.append(\"    [{:#x}] = {:#x},\".format(i, int(arena.fastbinsY[i])))\n                self.out.append(\"  },\")\n            self.out.append(\"  top = {:#x},\".format(int(arena.top)))\n            self.out.append(\"  last_remainder = {:#x},\".format(int(arena.last_remainder)))\n            self.out.append(\"  bins = {\")\n            for i in range(int(arena.num_bins)):\n                self.out.append(\"    [{:#x}] = {:#x},\".format(i, int(arena.bins[i])))\n            self.out.append(\"  },\")\n            self.out.append(\"  binmap = {\")\n            for i in range(int(arena.num_binmap)):\n                self.out.append(\"    [{:#x}] = {:#x},\".format(i, int(arena.binmap[i])))\n            self.out.append(\"  },\")\n            self.out.append(\"  next = {:#x},\".format(int(arena.next)))\n            self.out.append(\"  next_free = {:#x},\".format(int(arena.next_free)))\n            self.out.append(\"  attached_threads = {:#x},\".format(int(arena.attached_threads)))\n            self.out.append(\"  system_mem = {:#x},\".format(int(arena.system_mem)))\n            self.out.append(\"  max_system_mem = {:#x},\".format(int(arena.max_system_mem)))\n            self.out.append(\"}\")\n        return\n\n    def parse_mp(self):\n        \"\"\"Parse and append a formatted representation of the malloc_par (mp_) structure\n        to the output list.\"\"\"\n        try:\n            mp = AddressUtil.parse_address(\"&mp_\")\n        except gdb.error:\n            mp = GlibcHeap.search_for_mp_()\n            if mp is None:\n                self.out.append(titlify(\"[mp_]\"))\n                self.out.append(\"Could not find &mp_\")\n                return\n\n        try:\n            cmd = \"p ((struct malloc_par*) {:#x})[0]\".format(mp)\n            title = titlify(\"[mp_ - parsed via debuginfo] --- {:s}\".format(cmd))\n            result = gdb.execute(cmd, to_string=True)\n            self.out.append(title)\n            self.out.extend(result.splitlines())\n        except gdb.error:\n            mp = GlibcHeap.MallocPar(mp)\n            self.out.append(titlify(\"[mp_ - parsed heuristically] --- {:#x}\".format(mp.addr)))\n            self.out.append(\"$1 = {\")\n            self.out.append(\"  trim_threshold = {:#x},\".format(int(mp.trim_threshold)))\n            self.out.append(\"  top_pad = {:#x},\".format(int(mp.top_pad)))\n            self.out.append(\"  mmap_threshold = {:#x},\".format(int(mp.mmap_threshold)))\n            self.out.append(\"  arena_test = {:#x},\".format(int(mp.arena_test)))\n            self.out.append(\"  arena_max = {:#x},\".format(int(mp.arena_max)))\n            if get_libc_version() >= (2, 35):\n                self.out.append(\"  thp_pagesize = {:#x},\".format(int(mp.thp_pagesize)))\n                self.out.append(\"  hp_pagesize = {:#x},\".format(int(mp.hp_pagesize)))\n                self.out.append(\"  hp_flags = {:#x},\".format(int(mp.hp_flags)))\n            self.out.append(\"  n_mmaps = {:#x},\".format(int(mp.n_mmaps)))\n            self.out.append(\"  n_mmaps_max = {:#x},\".format(int(mp.n_mmaps_max)))\n            self.out.append(\"  max_n_mmaps = {:#x},\".format(int(mp.max_n_mmaps)))\n            self.out.append(\"  no_dyn_threshold = {:#x},\".format(int(mp.no_dyn_threshold)))\n            if get_libc_version() < (2, 15):\n                self.out.append(\"  pagesize = {:#x},\".format(int(mp.pagesize)))\n            self.out.append(\"  mmapped_mem = {:#x},\".format(int(mp.mmapped_mem)))\n            self.out.append(\"  max_mmapped_mem = {:#x},\".format(int(mp.max_mmapped_mem)))\n            if get_libc_version() < (2, 24):\n                self.out.append(\"  max_total_mem = {:#x},\".format(int(mp.max_total_mem)))\n            self.out.append(\"  sbrk_base = {:#x},\".format(int(mp.sbrk_base)))\n            if get_libc_version() >= (2, 26):\n                if get_libc_version() < (2, 42):\n                    self.out.append(\"  tcache_bins = {:#x},\".format(int(mp.tcache_bins)))\n                else:\n                    self.out.append(\"  tcache_small_bins = {:#x},\".format(int(mp.tcache_bins)))\n                self.out.append(\"  tcache_max_bytes = {:#x},\".format(int(mp.tcache_max_bytes)))\n                self.out.append(\"  tcache_unsorted_limit = {:#x},\".format(int(mp.tcache_unsorted_limit)))\n            self.out.append(\"}\")\n        return\n\n    def parse_heap_info(self, arena):\n        \"\"\"Parse and append a formatted representation of the _heap_info structure\n        for the given arena to the output list.\"\"\"\n        if arena.is_main_arena:\n            self.out.append(titlify(\"[heap_info]\"))\n            self.out.append(\"Not thread arena\")\n            return\n\n        heap_info = arena.addr & get_pagesize_mask_high()\n\n        try:\n            cmd = \"p ((struct _heap_info*) {:#x})[0]\".format(heap_info)\n            title = titlify(\"[heap_info - parsed via debuginfo] --- {:s}\".format(cmd))\n            result = gdb.execute(cmd, to_string=True)\n            self.out.append(title)\n            self.out.extend(result.splitlines())\n        except gdb.error:\n            heap_info = GlibcHeap.HeapInfo(heap_info)\n            self.out.append(titlify(\"[heap_info - parsed heuristically] --- {:#x}\".format(heap_info.addr)))\n            self.out.append(\"$1 = {\")\n            self.out.append(\"  ar_ptr = {:#x},\".format(int(heap_info.ar_ptr)))\n            self.out.append(\"  prev = {:#x},\".format(int(heap_info.prev)))\n            self.out.append(\"  size = {:#x},\".format(int(heap_info.size)))\n            self.out.append(\"  mprotect_size = {:#x},\".format(int(heap_info.mprotect_size)))\n            if get_libc_version() >= (2, 35):\n                self.out.append(\"  pagesize = {:#x},\".format(int(heap_info.pagesize)))\n            self.out.append(\"  pad = {},\".format(heap_info.pad))\n            self.out.append(\"}\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        # dump\n        self.out = []\n        self.parse_arena(arena)\n        self.parse_mp()\n        self.parse_heap_info(arena)\n\n        # colorize\n        if not Color.disable_color():\n            for i in range(len(self.out)):\n                self.out[i] = re.sub(\"  ([a-zA-Z_]+) =\", \"  \\033[36m\\\\1\\033[0m =\", self.out[i])\n                self.out[i] = re.sub(\" = (0x[0-9a-f]+)\", \" = \\033[34m\\\\1\\033[0m\", self.out[i])\n\n        self.print_output()\n        return\n\n\n@register_command\nclass GlibcHeapChunkCommand(GenericCommand):\n    \"\"\"Display information on a heap chunk.\"\"\"\n\n    _cmdline_ = \"heap chunk\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"chunk\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to interpret as a chunk.\")\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-b\", \"--as-base\", action=\"store_true\",\n                        help=\"use LOCATION as chunk base address (chunk_base_address = chunk_address - ptrsize * 2).\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        # get chunk\n        if args.as_base:\n            chunk = GlibcHeap.GlibcChunk(arena, args.location, from_base=True)\n        else:\n            chunk = GlibcHeap.GlibcChunk(arena, args.location)\n\n        # dump\n        try:\n            gef_print(chunk.psprint())\n        except gdb.MemoryError:\n            err(\"Invalid address\")\n            return\n\n        # extra information\n        info = []\n        info.extend(arena.get_bins_info(chunk, skip_top=True))\n        if chunk.chunk_base_address == arena.top:\n            info.append(\"top\")\n\n        if info:\n            freelist_hint_color = Config.get_gef_setting(\"theme.heap_freelist_hint\")\n            gef_print(\"  Found freelist/top: {:s}\".format(Color.colorify(\", \".join(info), freelist_hint_color)))\n        else:\n            gef_print(\"  Found freelist/top: None\")\n        return\n\n\n@register_command\nclass GlibcHeapChunksCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display information on all heap chunks.\"\"\"\n\n    _cmdline_ = \"heap chunks\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"chunks\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as the beginning of a contiguous chunk. (default: arena.heap_base)\")\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-b\", \"--nb-byte\", type=AddressUtil.parse_address,\n                        help=\"temporarily override `heap_chunks.peek_nb_byte`.\")\n    parser.add_argument(\"-o\", \"--peek-offset\", type=AddressUtil.parse_address, default=0,\n                        help=\"temporarily override `heap_chunks.peek_offset`.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} -a 0x7ffff0000020\",\n        \"{0:s} -a 1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"about the annotation:\",\n        '  - \"tcache[idx=7,sz=0x90][1/2]\"',\n        \"    - idx: 0-origin index.\",\n        \"    - sz : the size of the chunk including metadata.\",\n        \"    - 1/ : a position in the free-list.\",\n        \"    -  /2: parsed free-list length including corrupted chunks.\",\n        \"           NOT the value of tcache_perthread_struct.count[idx], be careful!\",\n        '  - \"largebins[idx=98,sz=0x1000-0x1200][8/8]\"',\n        \"    - idx: 0-origin index that `i-th idx` means `bins[i*2 : (i+1)*2]`.\",\n        \"    - sz : the size range of the chunk including metadata.\",\n        \"    - 8/ : a position in the free-list. largebins are FIFO, so the last chunk will be used first.\",\n        \"    -  /8: parsed free-list length including corrupted chunks.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        self.add_setting(\"peek_nb_byte\", 0, \"Hexdump N first byte(s) inside the chunk data (0 to disable)\")\n        self.add_setting(\"peek_offset\", 0, \"the offset to start dumping from when using peek_nb_byte\")\n        return\n\n    def print_heap_chunks(self, arena, dump_start, peek_nb, peek_offset):\n        \"\"\"Iterate and display heap chunks in the given arena, with corruption checks and optional memory peeking.\"\"\"\n        # Do not show if top is broken, as it affects exit conditions.\n        if is_32bit() and arena.top % 0x08:\n            self.err_add_out(\"arena.top is corrupted\")\n            return\n        elif is_64bit() and arena.top % 0x10:\n            self.err_add_out(\"arena.top is corrupted\")\n            return\n\n        # It continues even if last_remainder is broken because it doesn't affect the exit condition.\n        if is_32bit() and arena.last_remainder % 0x08:\n            self.warn_add_out(\"arena.last_remainder is corrupted\")\n        elif is_64bit() and arena.last_remainder % 0x10:\n            self.warn_add_out(\"arena.last_remainder is corrupted\")\n\n        freelist_hint_color = Config.get_gef_setting(\"theme.heap_freelist_hint\")\n        current_chunk = GlibcHeap.GlibcChunk(arena, dump_start, from_base=True)\n\n        while True:\n            if current_chunk.chunk_base_address == arena.top:\n                top_str = Color.colorify(\" <-  top\", freelist_hint_color)\n                self.out.append(\"{!s} {:s}\".format(current_chunk, top_str))\n                break\n            if current_chunk.chunk_base_address > arena.top:\n                self.err_add_out(\"Corrupted: chunk > top\")\n                break\n            if current_chunk.size == 0:\n                # EOF\n                break\n\n            line = str(current_chunk)\n\n            # in or not in free-list\n            info = arena.get_bins_info(current_chunk)\n            if info:\n                freelist_hint = Color.colorify(\"  <-  {:s}\".format(\", \".join(info)), freelist_hint_color)\n                line += freelist_hint\n\n            self.out.append(line)\n\n            # peek nbyte\n            if peek_nb:\n                peek_addr = current_chunk.chunk_base_address + peek_offset\n                peeked_data = read_memory(peek_addr, peek_nb)\n                h = hexdump(peeked_data, 0x10, base=peek_addr)\n                self.out.append(h)\n\n            # goto next\n            next_chunk = current_chunk.get_next_chunk()\n            if next_chunk is None:\n                break\n            if not is_valid_addr(next_chunk.address):\n                self.err_add_out(\"Corrupted: next_chunk_address is invalid\")\n                break\n            current_chunk = next_chunk\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.location is None:\n            dump_start = arena.heap_base\n            # specific pattern\n            if arena.is_main_arena:\n                if (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                    dump_start += 8\n        else:\n            dump_start = args.location\n\n        if args.nb_byte is not None:\n            peek_nb = args.nb_byte\n        else:\n            peek_nb = Config.get_gef_setting(\"heap_chunks.peek_nb_byte\")\n\n        if args.peek_offset is not None:\n            peek_offset = args.peek_offset\n        else:\n            peek_offset = Config.get_gef_setting(\"heap_chunks.peek_offset\")\n\n        self.out = []\n        self.print_heap_chunks(arena, dump_start, peek_nb, peek_offset)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapParseCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display information on all heap chunks as Pwngdb style.\"\"\"\n\n    _cmdline_ = \"heap parse\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"parseheap\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} -a 0x7ffff0000020\",\n        \"{0:s} -a 1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = GlibcHeapChunksCommand._note_\n\n    def make_line(self, arena, chunk):\n        width = 14 if is_64bit() else 10\n        prev_width = 20 if is_64bit() else 12\n\n        info = arena.get_bins_info(chunk)\n        hint = \", \".join(info)\n\n        if arena.is_chunk_in_freelists(chunk):\n            chunk_freed_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n            chunk_base_addr_str = Color.colorify(\"{:<#{:d}x}\".format(chunk.chunk_base_address, width), chunk_freed_color)\n            used_str = Color.colorify(\"{:{:d}s}\".format(\"Freed\", width), chunk_freed_color)\n            if arena.is_chunk_in_tcache(chunk) or arena.is_chunk_in_fastbins(chunk):\n                fd_str = \"{:<#{:d}x}\".format(chunk.get_fwd_ptr(True), width)\n                bk_str = \"{:<{:d}s}\".format(\"-\", width)\n            else:\n                fd_str = \"{:<#{:d}x}\".format(chunk.fd, width)\n                bk_str = \"{:<#{:d}x}\".format(chunk.bk, width)\n        else:\n            chunk_used_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n            chunk_base_addr_str = Color.colorify(\"{:<#{:d}x}\".format(chunk.chunk_base_address, width), chunk_used_color)\n            used_str = Color.colorify(\"{:{:d}s}\".format(\"Used\", width), chunk_used_color)\n            fd_str = \"{:<{:d}s}\".format(\"-\", width)\n            bk_str = \"{:<{:d}s}\".format(\"-\", width)\n\n        if chunk.has_p_bit():\n            prev_size_str = \"({:#x})\".format(chunk.get_prev_chunk_size())\n        else:\n            prev_size_str = \"{:#x}\".format(chunk.get_prev_chunk_size())\n\n        return \"{:s}  {:<{:d}s}  {:<#{:d}x}  {:s}  {:s}  {:s}  {:s}\".format(\n            chunk_base_addr_str,\n            prev_size_str,\n            prev_width,\n            chunk.size,\n            width,\n            used_str,\n            fd_str,\n            bk_str,\n            hint,\n        )\n\n    def parse_heap(self, arena, dump_start):\n        # Do not show if top is broken, as it affects exit conditions.\n        if is_32bit() and arena.top % 0x08:\n            self.err_add_out(\"arena.top is corrupted\")\n            return\n        elif is_64bit() and arena.top % 0x10:\n            self.err_add_out(\"arena.top is corrupted\")\n            return\n\n        # It continues even if last_remainder is broken because it doesn't affect the exit condition.\n        if is_32bit() and arena.last_remainder % 0x08:\n            self.warn_add_out(\"arena.last_remainder is corrupted\")\n        elif is_64bit() and arena.last_remainder % 0x10:\n            self.warn_add_out(\"arena.last_remainder is corrupted\")\n\n        width = 14 if is_64bit() else 10\n        prev_width = 20 if is_64bit() else 12\n        fmt = \"{:{:d}s}  {:{:d}s}  {:{:d}s}  {:{:d}s}  {:{:d}s}  {:{:d}s}  {:s}\"\n        legend = [\"addr\", width, \"prev_size\", prev_width, \"size\", width, \"status\", width, \"fd\", width, \"bk\", width, \"hint\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        current_chunk = GlibcHeap.GlibcChunk(arena, dump_start, from_base=True)\n        while True:\n            if current_chunk.chunk_base_address == arena.top:\n                self.out.append(self.make_line(arena, current_chunk))\n                break\n            if current_chunk.chunk_base_address > arena.top:\n                self.err_add_out(\"Corrupted: chunk > top\")\n                break\n            if current_chunk.size == 0:\n                # EOF\n                break\n\n            line = self.make_line(arena, current_chunk)\n            self.out.append(line)\n\n            # goto next\n            next_chunk = current_chunk.get_next_chunk()\n            if next_chunk is None:\n                break\n            if not is_valid_addr(next_chunk.address):\n                self.err_add_out(\"Corrupted: next_chunk_address is invalid\")\n                break\n            current_chunk = next_chunk\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        dump_start = arena.heap_base\n        # specific pattern\n        if arena.is_main_arena:\n            if (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                dump_start += 8\n\n        self.out = []\n        self.parse_heap(arena, dump_start)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapBinsSimpleCommand(GenericCommand):\n    \"\"\"Simply display information on the bins of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins-simple\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"bs\", \"heapinfo\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-s\", \"--skip-size\", action=\"store_true\", help=\"skip size information.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} -a 0x7ffff0000020 -v\",\n        \"{0:s} -a 1 -v\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"The meaning of the tcache expression:\",\n        \"  e.g.; 0x80 [6] (1): 0x55555557e480\",\n        \"    0x80: size; [6]: tcache index; (1): tcache_perthread_struct.count[i]\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def bins_simple(self, arenas):\n\n        def get_size(arena, c, from_base=True):\n            if self.args.skip_size:\n                return \"\"\n            try:\n                sz = GlibcHeap.GlibcChunk(arena, c, from_base=from_base).size\n                return \" (sz:{:#x})\".format(sz)\n            except gdb.MemoryError:\n                return \"\"\n\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        libc_version = get_libc_version()\n\n        # iterate arena ------------------------------------------------------------------------------------------------------\n        for arena in arenas:\n            gef_print(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n\n            # tcache ---------------------------------------------------------------------------------------------------------\n            TCACHE_SMALL_BINS = arena.TCACHE_SMALL_BINS()\n            TCACHE_FILL_COUNT = arena.TCACHE_FILL_COUNT()\n\n            gef_print(titlify(\"tcache\"))\n            if libc_version < (2, 26):\n                info(\"No tcache in this version of libc\")\n            else:\n                for i, chunks in arena.get_tcache_list().items():\n                    m = []\n                    for c in chunks:\n                        if isinstance(c, str):\n                            m.append(Color.colorify(c, corrupted_msg_color))\n                        elif libc_version < (2, 42) or i < TCACHE_SMALL_BINS:\n                            m.append(\"{!s}{:s}\".format(\n                                ProcessMap.lookup_address(c), Symbol.get_symbol_string(c),\n                            ))\n                        else:\n                            m.append(\"{!s}{:s}{:s}\".format(\n                                ProcessMap.lookup_address(c), Symbol.get_symbol_string(c), get_size(arena, c, from_base=False),\n                            ))\n                    if m or self.args.verbose:\n                        count = arena.tcachebins_i_count(i)\n                        if \"size\" in GlibcHeap.get_binsize_table()[\"tcache\"][i]:\n                            size = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size\"]\n                            gef_print(\"{:#x} [{:d}] ({:d}/{:d}): {:s}\".format(\n                                size, i, count, TCACHE_FILL_COUNT, \" -> \".join(m),\n                            ).rstrip())\n                        else:\n                            size_min = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size_min\"]\n                            size_max = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size_max\"]\n                            gef_print(\"{:#x}-{:#x} [{:d}] ({:d}/{:d}): {:s}\".format(\n                                size_min, size_max, i, count, TCACHE_FILL_COUNT, \" -> \".join(m),\n                            ).rstrip())\n\n            # fastbins -------------------------------------------------------------------------------------------------------\n            gef_print(titlify(\"fastbins\"))\n            if libc_version < (2, 43):\n                for i, chunks in arena.get_fastbins_list().items():\n                    m = []\n                    for c in chunks:\n                        if isinstance(c, str):\n                            m.append(Color.colorify(c, corrupted_msg_color))\n                        else:\n                            m.append(\"{!s}{:s}\".format(\n                                ProcessMap.lookup_address(c), Symbol.get_symbol_string(c),\n                            ))\n                    if m or self.args.verbose:\n                        size = GlibcHeap.get_binsize_table()[\"fastbins\"][i][\"size\"]\n                        gef_print(\"{:#x} [{:d}]: {:s}\".format(size, i, \" -> \".join(m)).rstrip())\n            else:\n                info(\"No fastbins in this version of libc\")\n\n            # unsorted bin ---------------------------------------------------------------------------------------------------\n            gef_print(titlify(\"unsorted bin\"))\n            for _, chunks in arena.get_unsortedbin_list().items():\n                m = []\n                for c in chunks:\n                    if isinstance(c, str):\n                        m.append(Color.colorify(c, corrupted_msg_color))\n                    else:\n                        m.append(\"{!s}{:s}{:s}\".format(\n                            ProcessMap.lookup_address(c), Symbol.get_symbol_string(c), get_size(arena, c),\n                        ))\n                if m or self.args.verbose:\n                    gef_print(\"any [0]: {:s}\".format(\" <-> \".join(m)).rstrip())\n\n            # small bins -----------------------------------------------------------------------------------------------------\n            gef_print(titlify(\"small bins\"))\n            for i, chunks in arena.get_smallbins_list().items():\n                m = []\n                for c in chunks:\n                    if isinstance(c, str):\n                        m.append(Color.colorify(c, corrupted_msg_color))\n                    else:\n                        m.append(\"{!s}{:s}\".format(\n                            ProcessMap.lookup_address(c), Symbol.get_symbol_string(c),\n                        ))\n                if m or self.args.verbose:\n                    size = GlibcHeap.get_binsize_table()[\"small_bins\"][i][\"size\"]\n                    gef_print(\"{:#x} [{:d}]: {:s}\".format(size, i, \" <-> \".join(m)).rstrip())\n\n            # large bins -----------------------------------------------------------------------------------------------------\n            gef_print(titlify(\"large bins\"))\n            for i, chunks in arena.get_largebins_list().items():\n                m = []\n                for c in chunks:\n                    if isinstance(c, str):\n                        m.append(Color.colorify(c, corrupted_msg_color))\n                    else:\n                        m.append(\"{!s}{:s}{:s}\".format(\n                            ProcessMap.lookup_address(c), Symbol.get_symbol_string(c), get_size(arena, c),\n                        ))\n                if m or self.args.verbose:\n                    size_min = GlibcHeap.get_binsize_table()[\"large_bins\"][i][\"size_min\"]\n                    size_max = GlibcHeap.get_binsize_table()[\"large_bins\"][i][\"size_max\"]\n                    gef_print(\"{:#x}-{:#x} [{:d}]: {:s}\".format(size_min, size_max, i, \" <-> \".join(m)).rstrip())\n\n            gef_print(titlify(\"arena\"))\n            # top ------------------------------------------------------------------------------------------------------------\n            top = arena.top\n            gef_print(\"top: {!s}{:s}{:s}\".format(\n                ProcessMap.lookup_address(top), Symbol.get_symbol_string(top), get_size(arena, top),\n            ))\n\n            # last_remainder -------------------------------------------------------------------------------------------------\n            lm = arena.last_remainder\n            gef_print(\"last_remainder: {!s}{:s}{:s}\".format(\n                ProcessMap.lookup_address(lm), Symbol.get_symbol_string(lm), get_size(arena, lm),\n            ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        self.bins_simple(arenas)\n        return\n\n\nclass GlibcHeapBinsDump:\n    \"\"\"Manage glibc heap bins dumper.\"\"\"\n\n    def print_tcache(self, arena, verbose=False, index_filter=None):\n        \"\"\"Pretty-print tcache bins for the given arena, detecting loops and chunk corruption.\"\"\"\n        if get_libc_version() < (2, 26):\n            return\n\n        self.out.append(titlify(\"tcache (&tcache_perthread_struct: {:#x})\".format(\n            arena.tcache_perthread_struct,\n        )))\n\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        nb_chunk = 0\n        for i in range(arena.TCACHE_MAX_BINS()):\n            # index filter\n            if index_filter is not None:\n                if i != index_filter:\n                    continue\n\n            chunk = arena.get_tcachebins_i(i)\n            chunks = []\n            m = []\n\n            # Only print the entry if there are valid chunks. Don't trust count\n            while True:\n                if chunk is None:\n                    break\n                try:\n                    m.append(\" -> {!s}\".format(chunk))\n                    if chunk.address in chunks:\n                        m.append(Color.colorify(\n                            \" -> {:#x} [Loop detected]\".format(chunk.address),\n                            corrupted_msg_color,\n                        ))\n                        break\n\n                    chunks.append(chunk.address)\n                    nb_chunk += 1\n\n                    next_chunk = chunk.get_fwd_ptr(True)\n                    if next_chunk == 0 or next_chunk is None:\n                        break\n\n                    chunk = GlibcHeap.GlibcChunk(arena, next_chunk)\n                except gdb.MemoryError:\n                    m.append(Color.colorify(\n                        \" -> {:#x} [Corrupted chunk]\".format(chunk.address),\n                        corrupted_msg_color,\n                    ))\n                    break\n\n            if m or verbose:\n                count = arena.tcachebins_i_count(i)\n                bins_addr = ProcessMap.lookup_address(arena.addrof_tcachebins_i(i))\n                fd = ProcessMap.lookup_address(read_int_from_memory(bins_addr.value))\n                if \"size\" in GlibcHeap.get_binsize_table()[\"tcache\"][i]:\n                    size = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size\"]\n                    self.out.append(\"tcachebins[idx={:d}, size={:#x}, @{!s}]: fd={!s} count={:d}\".format(\n                        i, size, bins_addr, fd, count,\n                    ))\n                else:\n                    size_min = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size_min\"]\n                    size_max = GlibcHeap.get_binsize_table()[\"tcache\"][i][\"size_max\"]\n                    self.out.append(\"tcachebins[idx={:d}, size={:#x}-{:#x}, @{!s}]: fd={!s} count={:d}\".format(\n                        i, size_min, size_max, bins_addr, fd, count,\n                    ))\n                if m:\n                    self.out.extend(m)\n\n        self.info_add_out(\"Found {:d} valid chunks in tcache\".format(nb_chunk))\n        return\n\n    def print_fastbin(self, arena, verbose=False, index_filter=None):\n        \"\"\"Pretty-print fastbin lists for the given arena, checking for loops and incorrect indices.\"\"\"\n        if get_libc_version() >= (2, 43):\n            return\n\n        def fastbin_index(sz):\n            return (sz >> 4) - 2 if SIZE_SZ == 8 else (sz >> 3) - 2\n\n        SIZE_SZ = current_arch.ptrsize\n        MAX_FAST_SIZE = 80 * SIZE_SZ // 4\n        NFASTBINS = fastbin_index(MAX_FAST_SIZE) - 1\n\n        self.out.append(titlify(\"fastbins\"))\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        nb_chunk = 0\n        for i in range(NFASTBINS):\n            # index filter\n            if index_filter is not None:\n                if i != index_filter:\n                    continue\n\n            chunk = arena.get_fastbins_i(i)\n            chunks = []\n            m = []\n\n            while True:\n                if chunk is None:\n                    break\n\n                try:\n                    m.append(\" -> {!s}\".format(chunk))\n                    if chunk.address in chunks:\n                        m.append(Color.colorify(\n                            \" -> {:#x} [Loop detected]\".format(chunk.chunk_base_address),\n                            corrupted_msg_color,\n                        ))\n                        break\n\n                    if fastbin_index(chunk.get_chunk_size()) != i:\n                        m.append(Color.colorify(\"[Incorrect fastbin_index]\", corrupted_msg_color))\n\n                    chunks.append(chunk.address)\n                    nb_chunk += 1\n\n                    next_chunk = chunk.get_fwd_ptr(True)\n                    if next_chunk == 0 or next_chunk is None:\n                        break\n\n                    chunk = GlibcHeap.GlibcChunk(arena, next_chunk, from_base=True)\n                except gdb.MemoryError:\n                    m.append(Color.colorify(\n                        \" -> {:#x} [Corrupted chunk]\".format(chunk.chunk_base_address),\n                        corrupted_msg_color,\n                    ))\n                    break\n\n            if m or verbose:\n                bin_table = GlibcHeap.get_binsize_table()[\"fastbins\"]\n                if i in bin_table:\n                    size = bin_table[i][\"size\"]\n                    bins_addr = ProcessMap.lookup_address(arena.addrof_fastbins_i(i))\n                    fd = ProcessMap.lookup_address(read_int_from_memory(bins_addr.value))\n                    self.out.append(\"fastbins[idx={:d}, size={:#x}, @{!s}]: fd={!s}\".format(\n                        i, size, bins_addr, fd,\n                    ))\n                    if m:\n                        self.out.extend(m)\n\n        self.info_add_out(\"Found {:d} valid chunks in fastbins\".format(nb_chunk))\n        return\n\n    def pprint_bin(self, arena, index, bin_name, verbose=False):\n        \"\"\"Pretty-print the contents of a heap bin, following forward and backward links\n        and checking for corruption.\"\"\"\n        fw, bk = arena.get_bins_i(index)\n\n        if bk == 0 and fw == 0:\n            warn(\"Invalid backward and forward bin pointers(fd==bk==NULL)\")\n            return -1\n\n        bins_addr = arena.addrof_bins_i(index)\n        head = bins_addr - current_arch.ptrsize * 2\n        if fw == head and not verbose:\n            return 0\n\n        bin_table = GlibcHeap.get_binsize_table()[bin_name]\n        if index not in bin_table:\n            return 0\n\n        bin_info = bin_table[index]\n        if \"size\" in bin_info:\n            size_str = \"{:#x}\".format(bin_info[\"size\"])\n        elif \"size_min\" in bin_info and \"size_max\" in bin_info:\n            size_str = \"{:#x}-{:#x}\".format(bin_info[\"size_min\"], bin_info[\"size_max\"])\n        else:\n            size_str = \"any\"\n\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        corrupted = False\n\n        # follow the link backward\n        mb = []\n        seen_bk = []\n        nb_chunk = 0\n        while bk != head:\n            chunk = GlibcHeap.GlibcChunk(arena, bk, from_base=True)\n            if chunk.address in seen_bk:\n                mb.append(Color.colorify(\n                    \" -> {:#x} [Loop detected]\".format(chunk.chunk_base_address),\n                    corrupted_msg_color,\n                ))\n                corrupted = True\n                break\n            seen_bk.append(chunk.address)\n            try:\n                mb.append(\" -> {!s}\".format(chunk))\n            except gdb.MemoryError:\n                mb.append(Color.colorify(\n                    \" -> {:#x} [Corrupted chunk]\".format(chunk.chunk_base_address),\n                    corrupted_msg_color,\n                ))\n                corrupted = True\n                break\n            bk = chunk.bck\n            nb_chunk += 1\n\n        if corrupted:\n            # follow the link forward\n            mf = []\n            seen_fw = []\n            while fw != head:\n                chunk = GlibcHeap.GlibcChunk(arena, fw, from_base=True)\n                if chunk.address in seen_bk:\n                    break\n                if chunk.address in seen_fw:\n                    mf.append(Color.colorify(\n                        \" -> {:#x} [Loop detected]\".format(chunk.chunk_base_address),\n                        corrupted_msg_color,\n                    ))\n                    break\n                seen_fw.append(chunk.address)\n                try:\n                    mf.append(\" -> {!s}\".format(chunk))\n                except gdb.MemoryError:\n                    mf.append(Color.colorify(\n                        \" -> {:#x} [Corrupted chunk]\".format(chunk.chunk_base_address),\n                        corrupted_msg_color,\n                    ))\n                    break\n                fw = chunk.fwd\n\n        # concat\n        m = []\n        m.append(\"{:s}[idx={:d}, size={:s}, @{!s}]: fd={!s}, bk={!s}\".format(\n            bin_name, index, size_str,\n            ProcessMap.lookup_address(bins_addr),\n            ProcessMap.lookup_address(fw),\n            ProcessMap.lookup_address(bk),\n        ))\n        if corrupted and mf:\n            m += mf\n        m += mb[::-1]\n\n        self.out.extend(m)\n        return nb_chunk\n\n\n@register_command\nclass GlibcHeapBinsCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the bins of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"bins\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} -a 0x7ffff0000020 -v\",\n        \"{0:s} -a 1 -v\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n\n            # tcache\n            self.print_tcache(arena, args.verbose)\n\n            # fastbins\n            self.print_fastbin(arena, args.verbose)\n\n            # unsorted bin\n            self.out.append(titlify(\"unsorted bin\"))\n            nb_chunk = self.pprint_bin(arena, 0, \"unsorted_bin\", args.verbose)\n            self.info_add_out(\"Found {:d} valid chunks in unsorted bin (when traced from `bk`)\".format(nb_chunk))\n\n            # small bins\n            self.out.append(titlify(\"small bins\"))\n            bins = {}\n            for i in range(1, 63):\n                nb_chunk = self.pprint_bin(arena, i, \"small_bins\", args.verbose)\n                if nb_chunk < 0:\n                    break\n                if nb_chunk > 0:\n                    bins[i] = nb_chunk\n            self.info_add_out(\"Found {:d} valid chunks in {:d} small bins (when traced from `bk`)\".format(\n                sum(bins.values()), len(bins),\n            ))\n\n            # large bins\n            self.out.append(titlify(\"large bins\"))\n            bins = {}\n            for i in range(63, 126):\n                nb_chunk = self.pprint_bin(arena, i, \"large_bins\", args.verbose)\n                if nb_chunk < 0:\n                    break\n                if nb_chunk > 0:\n                    bins[i] = nb_chunk\n            self.info_add_out(\"Found {:d} valid chunks in {:d} large bins (when traced from `bk`)\".format(\n                sum(bins.values()), len(bins),\n            ))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapTcachebinsCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the Tcache of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins tcache\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"tcachebins\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-i\", \"--index-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by tcache index.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # Determine if we are using libc with tcache built in (2.26+)\n        if get_libc_version() < (2, 26):\n            info(\"No tcache in this version of libc\")\n            return\n\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n            self.print_tcache(arena, args.verbose, args.index_filter)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapFastbinsYCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the fastbinsY of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins fast\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"fastbins\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-i\", \"--index-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by fastbins index.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n            self.print_fastbin(arena, args.verbose, args.index_filter)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapUnsortedBinsCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the Unsorted Bins of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins unsorted\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"unsortedbin\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n            self.out.append(titlify(\"unsorted bin\"))\n            nb_chunk = self.pprint_bin(arena, 0, \"unsorted_bin\", args.verbose)\n            self.info_add_out(\"Found {:d} valid chunks in unsorted bin (when traced from `bk`)\".format(nb_chunk))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapSmallBinsCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the Small Bins of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins small\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"smallbins\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-i\", \"--index-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by smallbins index.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n            self.out.append(titlify(\"small bins\"))\n            bins = {}\n            for i in range(1, 63):\n                # index filter\n                if args.index_filter is not None:\n                    if i != args.index_filter:\n                        continue\n\n                # print\n                nb_chunk = self.pprint_bin(arena, i, \"small_bins\", args.verbose)\n                if nb_chunk < 0:\n                    break\n                if nb_chunk > 0:\n                    bins[i] = nb_chunk\n            self.info_add_out(\"Found {:d} valid chunks in {:d} small bins (when traced from `bk`)\".format(\n                sum(bins.values()), len(bins),\n            ))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapLargeBinsCommand(GenericCommand, GlibcHeapBinsDump, BufferingOutput):\n    \"\"\"Display information about the Large Bins of an arena.\"\"\"\n\n    _cmdline_ = \"heap bins large\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"largebins\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-i\", \"--index-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by largebins index.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display empty bins.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        self.out = []\n        for arena in arenas:\n            self.out.append(titlify(\"arena: {:#x}{:s}\".format(\n                arena.addr, Symbol.get_symbol_string(arena.addr)), color=\"bold\", msg_color=\"bold\"),\n            )\n            self.out.append(titlify(\"large bins\"))\n            bins = {}\n            for i in range(63, 126):\n                # index filter\n                if args.index_filter is not None:\n                    if i != args.index_filter:\n                        continue\n\n                # print\n                nb_chunk = self.pprint_bin(arena, i, \"large_bins\", args.verbose)\n                if nb_chunk < 0:\n                    break\n                if nb_chunk > 0:\n                    bins[i] = nb_chunk\n            self.info_add_out(\"Found {:d} valid chunks in {:d} large bins (when traced from `bk`)\".format(\n                sum(bins.values()), len(bins),\n            ))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapTryFreeCommand(GenericCommand):\n    \"\"\"Emulate with unicorn to check errors when freeing a chunk.\"\"\"\n\n    _cmdline_ = \"heap try-free\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"try-free\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the memory address to be freed.\")\n    parser.add_argument(\"-a\", \"--free-addr\", dest=\"caller_address\", type=AddressUtil.parse_address,\n                        help=\"the memory address of free().\")\n    parser.add_argument(\"-s\", \"--skip-emulation\", \"--save\", action=\"store_true\",\n                        help=\"do not run, just save the script.\")\n    parser.add_argument(\"-c\", \"--command\", action=\"append\", default=[],\n                        help=\"command to be executed after emulation succeeds, with the memory state temporarily reflected.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show internal state.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x555555579930\",\n        \"{0:s} -a 0x7ffff7cadd30 0x555555579930    # need free address when no symbol\",\n        '{0:s} -c \"visual-heap\" 0x555555579930     # execute visual-heap',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"It may work even if NOT Glibc (untested).\",\n        \"It may be detected as a failure even though it actually succeeded.\",\n        \"  - Any system call was called\",\n        \"  - Any interrupt was raised\",\n        \"  - An instruction that unicorn does not support was executed\",\n        \"They are emulated to the best extent possible, but the emulation may be incomplete.\",\n        \"  - The address returned by mmap can differ from the actual one; this is an emulation limitation.\",\n        \"The failure message may not be detected because it is searched for heuristically.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def get_caller_address(self, name):\n        \"\"\"Resolve and return the caller address for a given symbol name,\n        considering user input, PLT, and real addresses.\"\"\"\n        # user specified address\n        if self.args.caller_address is not None:\n            return self.args.caller_address\n\n        # searching through symbols\n        caller_address = None\n\n        # PLT pattern (e.g., &'malloc@plt')\n        try:\n            caller_address = int(gdb.parse_and_eval(\"&'{:s}@plt'\".format(name)))\n        except gdb.error:\n            pass\n        if caller_address is not None:\n            # If you use PLT, only userland binary's PLT is valid (libc PLT is invalid)\n            x = ProcessMap.lookup_address(caller_address)\n            if x and x.section and x.section.path == Path.get_filepath(append_proc_root_prefix=False):\n                return caller_address\n\n        # real address (not PLT)\n        try:\n            caller_address = int(gdb.parse_and_eval(\"&{:s}\".format(name)))\n        except gdb.error:\n            pass\n        return caller_address\n\n    def make_patch_info(self, caller_address, arg1, arg2):\n        \"\"\"Prior to running unicorn-emulate, generate a patch to be applied.\"\"\"\n        patches = {}\n        if is_x86_64():\n            regs_new = {\"$rdi\": arg1, \"$rsi\": arg2, \"$rax\": caller_address}\n            patches[current_arch.pc] = bytes.fromhex(\"ffd0\") # call rax\n            stop_address = current_arch.pc + 2\n\n        elif is_x86_32():\n            regs_new = {\"$edi\": arg1, \"$esi\": arg2, \"$eax\": caller_address}\n            patches[current_arch.pc] = bytes.fromhex(\"5657ffd0\") # push esi; push edi; call eax\n            stop_address = current_arch.pc + 4\n\n        elif is_arm32():\n            # Check if caller_address is thumb2\n            # The reason for checking only 3 instructions is that xxx@plt is 3 instructions.\n            res = gdb.execute(\"x/3i {:#x}\".format(caller_address), to_string=True)\n            # pattern 1 (thumb2)\n            #   0x4085fdb0 <realloc@plt>:                    @ <UNDEFINED> instruction: 0xe7fd4778\n            #   0x4085fdb4 <realloc@plt+4>:  add     r12, pc, #0, 12\n            #   0x4085fdb8 <realloc@plt+8>:  add     r12, r12, #240, 20      @ 0xf0000\n            # in fact:\n            #   0x4085fdb1 <realloc@plt>:    bx      pc\n            if \"UNDEFINED\" in res.splitlines()[0]:\n                caller_address += 1\n            else:\n                # pattern 2 (thumb2)\n                #   0x408abb60 <__GI___libc_malloc>:     push    {r3, r4, r5, r6, r7, lr}\n                #   0x408abb62 <__GI___libc_malloc+2>:   mov     r6, r0\n                #   0x408abb64 <__GI___libc_malloc+4>:   ldr     r3, [pc, #548]\n                addrs = [int(x.strip().split()[0], 16) for x in res.splitlines()]\n                if any(a % 4 == 2 for a in addrs):\n                    caller_address += 1\n                else:\n                    # pattern 3 (ARM)\n                    #   0x4085fdc0 <calloc@plt>:     add     r12, pc, #0, 12\n                    #   0x4085fdc4 <calloc@plt+4>:   add     r12, r12, #240, 20      @ 0xf0000\n                    #   0x4085fdc8 <calloc@plt+8>:   ldr     pc, [r12, #152]!        @ 0x98\n                    pass\n            # Check current $pc is thumb2\n            if current_arch.is_thumb():\n                regs_new = {\"$r0\": arg1, \"$r1\": arg2, \"$r2\": caller_address}\n                patches[current_arch.pc & ~1] = bytes.fromhex(\"9047\") # blx r2\n                stop_address = (current_arch.pc & ~1) + 2\n            else:\n                regs_new = {\"$r0\": arg1, \"$r1\": arg2, \"$r2\": caller_address}\n                patches[current_arch.pc] = bytes.fromhex(\"32ff2fe1\") # blx r2\n                stop_address = current_arch.pc + 4\n\n        elif is_arm64():\n            regs_new = {\"$x0\": arg1, \"$x1\": arg2, \"$x2\": caller_address}\n            patches[current_arch.pc] = bytes.fromhex(\"40003fd6\") # blr x2\n            stop_address = current_arch.pc + 4\n\n        # create namedtuple\n        dic = {}\n        dic[\"regs_new\"] = {r: v for r, v in regs_new.items() if v is not None}\n        dic[\"regs_old\"] = {r: get_register(r) for r, v in regs_new.items() if v is not None}\n        dic[\"patches\"] = patches\n        dic[\"stop_address\"] = stop_address\n        Info = collections.namedtuple(\"Info\", dic.keys())\n        return Info(*dic.values())\n\n    def get_reason(self, res):\n        \"\"\"From the results of unicorn-emulate, get the reason why the run failed.\"\"\"\n        if \"UC_ERR_READ_UNMAPPED\" in res:\n            return \"Memory read error\"\n\n        if \"UC_ERR_WRITE_UNMAPPED\" in res:\n            return \"Memory write error\"\n\n        # heuristic search\n        if \"Modified memories (before | after)\" in res:\n            # In cases where emulation fails, an interrupt or system call has occurred.\n            # When execution stops, any memory that has been modified up to this point\n            # will likely contain a pointer to the error message.\n            # e.g.,\n            # ========================= Modified memories (before | after) =========================\n            # 0x00007fffffffd6f0 | 0x00007fffffffd724 0x00007fff00000038 | 0x00007fffffffd724 0x00007ffff7c9094e |\n            # 0x00007fffffffd700 | 0x00007fff015c0adc 0x00007ffff7fc5860 | 0x00007fffffffd730 0x0000000000000000 |\n            # 0x00007fffffffd710 | 0x000000005702b738 0x00007ffff7fc5bac | 0x000000005702b738 0x00007fff00000010 |\n            # 0x00007fffffffd720 | 0x00000000f7fbd160 0x0000000000000000 | 0x00007fffffffd820 0x00007fffffffd7b0 |\n            modified_memories = res[res.find(\"Modified memories (before | after)\"):]\n            modified_memories = Color.remove_color(modified_memories)\n            message_strings = set()\n            for line in modified_memories.splitlines():\n                # search pointer of `after`\n                if line.count(\"|\") != 3:\n                    continue\n                after_memories = line.split(\"|\")[-2]\n                for x in after_memories.strip().split():\n                    addr = int(x, 16)\n                    s = read_cstring_from_memory(addr)\n                    if not s:\n                        continue\n                    if len(s) <= current_arch.ptrsize: # too short\n                        continue\n                    if \" \" not in s or \"(\" not in s or \")\" not in s: # wrong message\n                        continue\n                    message_strings.add(s)\n            if message_strings:\n                if len(message_strings) == 1:\n                    return list(message_strings)[0]\n                return str(list(message_strings))\n\n        if \"UC_ERR_INSN_INVALID\" in res:\n            return \"Maybe try to execute unicorn unsupported instruction\"\n        return \"???\"\n\n    def get_syscall(self, res):\n        \"\"\"From the results of unicorn-emulate, get information about the system calls that were called.\"\"\"\n        # syscall=N is detected and displayed by unicorn-emulate.\n        m = re.search(r\"syscall=(\\d+)\", res)\n        if not m:\n            return None\n\n        # match against syscall_table\n        syscall_num = int(m.group(1))\n        syscall_table = get_syscall_table()\n        syscall_entry = syscall_table.nr_table.get(syscall_num, None)\n        if syscall_entry:\n            syscall_name = syscall_entry.name\n        else:\n            syscall_name = \"???\"\n        return syscall_num, syscall_name\n\n    def get_allocated_address(self, res):\n        \"\"\"From the results of unicorn-emulate, get the allocated address.\"\"\"\n        final_registers = res[res.find(\"Final registers\"):]\n        if is_x86_64():\n            m = re.search(r\"\\$rax\\s+=\\s+(0x\\S+)\", final_registers)\n        elif is_x86_32():\n            m = re.search(r\"\\$eax\\s+=\\s+(0x\\S+)\", final_registers)\n        elif is_arm32():\n            m = re.search(r\"\\$r0\\s+=\\s+(0x\\S+)\", final_registers)\n        elif is_arm64():\n            m = re.search(r\"\\$x0\\s+=\\s+(0x\\S+)\", final_registers)\n        allocated_address = int(m.group(1), 16)\n        return allocated_address\n\n    def print_result(self, name, res):\n        \"\"\"Print the result of an emulation run, displaying errors or success messages based on system call outcomes.\"\"\"\n        if \"Emulation failed\" in res:\n            # fail\n            success = False\n\n            # The system call that could not be emulated\n            syscall = self.get_syscall(res)\n            if syscall:\n                err(\"Trace failed: system call emulation error: {:d} (={:s})\".format(syscall[0], syscall[1]))\n\n            # If write* system call was called, it is assumed that an abort was called.\n            # By investigating the changed memory address, the reason may be found.\n            if not syscall or \"write\" in syscall[1]:\n                reason = self.get_reason(res)\n                err(\"{:s} failed: {:s}\".format(name, Color.boldify(reason)))\n        else:\n            # success\n            success = True\n\n            # The system call that could be emulated\n            syscall = self.get_syscall(res)\n            if syscall:\n                info(\"System call emulated: {:d} (={:s})\".format(syscall[0], syscall[1]))\n\n            if name == \"free\":\n                ok(\"{:s} succeeded\".format(name))\n            else:\n                allocated_address = self.get_allocated_address(res)\n                ok(\"{:s} succeeded: {:s}\".format(name, Color.colorify_hex(allocated_address, \"bold\")))\n        return success\n\n    def make_patch_info_from_emulation_result(self, res):\n        \"\"\"Parse emulation output and create a dictionary of memory patches from modified memory regions.\"\"\"\n        patches = {}\n        if \"Modified memories (before | after)\" in res:\n            modified_memories = res[res.find(\"Modified memories (before | after)\"):]\n            modified_memories = Color.remove_color(modified_memories)\n            for line in modified_memories.splitlines():\n                # search pointer of `after`\n                if line.count(\"|\") != 3:\n                    continue\n                addr = int(line.split(\"|\")[0], 16)\n                after_memories = line.split(\"|\")[-2]\n                values = [int(x, 16) for x in after_memories.strip().split()]\n                values = [x.to_bytes(current_arch.ptrsize, \"little\") for x in values]\n                patches[addr] = b\"\".join(values)\n        return patches\n\n    def doit(self, name, arg1, arg2):\n        \"\"\"For each of free, malloc, realloc, and calloc, generate a patch to memory,\n        emulate the execution, collect and interpret the output, and then undoe the patch.\"\"\"\n        caller_address = self.get_caller_address(name)\n        if caller_address is None:\n            err(\"Could not find `{:s}`\".format(name))\n            return\n\n        # make patch info\n        # The arguments of free, malloc, realloc, and calloc are at most 2\n        patch_info = self.make_patch_info(caller_address, arg1, arg2)\n\n        # modify (registers, memories)\n        for regname, regvalue in patch_info.regs_new.items():\n            if self.args.verbose:\n                info(\"set {:s}={:#x}\".format(regname, regvalue))\n            gdb.execute(\"set {:s}={:#x}\".format(regname, regvalue))\n        tag = PatchCommand.PatchInfo.get_unique_tag()\n        for patch_addr, patch_code in patch_info.patches.items():\n            if self.args.verbose:\n                info(\"patch hex {:#x} {:s}\".format(patch_addr, patch_code.hex()))\n            PatchCommand.PatchInfo(patch_addr, patch_code, tag=tag).patch(silent=not self.args.verbose)\n\n        # execute\n        option = [\"-t\", hex(patch_info.stop_address), \"-A\", \"-E\", \"-I\"]\n        if self.args.skip_emulation:\n            option.append(\"-s\")\n        res = \"\"\n        try:\n            if self.args.verbose:\n                info(\"unicorn-emulate {:s}\".format(\" \".join(option)))\n            res = gdb.execute(\"unicorn-emulate {:s}\".format(\" \".join(option)), to_string=True)\n            if self.args.verbose or self.args.skip_emulation:\n                gef_print(res.rstrip())\n        except Exception:\n            pass\n\n        # print\n        if res and not self.args.skip_emulation:\n            success = self.print_result(name, res)\n\n            # temporarily execute command\n            if success and self.args.command:\n                # temporarily reflects changes in memory\n                patches = self.make_patch_info_from_emulation_result(res)\n                for addr, value in patches.items():\n                    PatchCommand.PatchInfo(addr, value, tag=tag).patch(silent=not self.args.verbose)\n                # do command\n                for cmd in self.args.command:\n                    try:\n                        gef_print(titlify(cmd, color=\"bold\", msg_color=\"bold\"))\n                        gdb.execute(cmd)\n                    except Exception:\n                        exc_type, exc_value, exc_traceback = sys.exc_info()\n                        gef_print(exc_value)\n\n        # revert (registers, memories, thread locking)\n        for regname, regvalue in patch_info.regs_old.items():\n            if self.args.verbose:\n                info(\"set {:s}={:#x}\".format(regname, regvalue))\n            gdb.execute(\"set {:s}={:#x}\".format(regname, regvalue))\n        PatchCommand.PatchInfo.revert_to_tag(tag, silent=not self.args.verbose)\n        if self.args.verbose:\n            info(\"patch revert ok\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.doit(\"free\", args.address, None)\n        return\n\n\n@register_command\nclass GlibcHeapTryMallocCommand(GlibcHeapTryFreeCommand):\n    \"\"\"Emulate with unicorn to check errors when allocating a chunk.\"\"\"\n\n    _cmdline_ = \"heap try-malloc\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"try-malloc\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size to be allocated.\")\n    parser.add_argument(\"-a\", \"--malloc-addr\", dest=\"caller_address\", type=AddressUtil.parse_address,\n                        help=\"the memory address of malloc().\")\n    parser.add_argument(\"-s\", \"--skip-emulation\", \"--save\", action=\"store_true\",\n                        help=\"do not run, just save the script.\")\n    parser.add_argument(\"-c\", \"--command\", action=\"append\", default=[],\n                        help=\"command to be executed after emulation succeeds, with the memory state temporarily reflected.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show internal state.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x120\",\n        \"{0:s} -a 0x7ffff7cad650 0x120    # need malloc address when no symbol\",\n        '{0:s} -c \"visual-heap\" 0x120     # execute visual-heap',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.doit(\"malloc\", args.size, None)\n        return\n\n\n@register_command\nclass GlibcHeapTryReallocCommand(GlibcHeapTryFreeCommand):\n    \"\"\"Emulate with unicorn to check errors when re-allocating a chunk.\"\"\"\n\n    _cmdline_ = \"heap try-realloc\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"try-realloc\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the memory address to be re-allocated.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size to be re-allocated.\")\n    parser.add_argument(\"-a\", \"--realloc-addr\", dest=\"caller_address\", type=AddressUtil.parse_address,\n                        help=\"the memory address of realloc().\")\n    parser.add_argument(\"-s\", \"--skip-emulation\", \"--save\", action=\"store_true\",\n                        help=\"do not run, just save the script.\")\n    parser.add_argument(\"-c\", \"--command\", action=\"append\", default=[],\n                        help=\"command to be executed after emulation succeeds, with the memory state temporarily reflected.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show internal state.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x555555579930 0x120\",\n        \"{0:s} -a 0x7ffff7cae0a0 0x555555579930 0x120    # need realloc address when no symbol\",\n        '{0:s} -c \"visual-heap\" 0x555555579930 0x120     # execute visual-heap',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.doit(\"realloc\", args.address, args.size)\n        return\n\n\n@register_command\nclass GlibcHeapTryCallocCommand(GlibcHeapTryFreeCommand):\n    \"\"\"Emulate with unicorn to check errors when allocating a zero-initialized chunk.\"\"\"\n\n    _cmdline_ = \"heap try-calloc\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"try-calloc\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size to be allocated.\")\n    parser.add_argument(\"nmemb\", metavar=\"NMEMB\", type=AddressUtil.parse_address,\n                        help=\"the number of blocks.\")\n    parser.add_argument(\"-a\", \"--calloc-addr\", dest=\"caller_address\", type=AddressUtil.parse_address,\n                        help=\"the memory address of calloc().\")\n    parser.add_argument(\"-s\", \"--skip-emulation\", \"--save\", action=\"store_true\",\n                        help=\"do not run, just save the script.\")\n    parser.add_argument(\"-c\", \"--command\", action=\"append\", default=[],\n                        help=\"command to be executed after emulation succeeds, with the memory state temporarily reflected.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show internal state.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x10 1\",\n        \"{0:s} -a 0x7ffff7cae7a0 0x10 1    # need calloc address when no symbol\",\n        '{0:s} -c \"visual-heap\" 0x10 1     # execute visual-heap',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.doit(\"calloc\", args.size, args.nmemb)\n        return\n\n\n@register_command\nclass GlibcHeapTcacheIndexHelperCommand(GenericCommand):\n    \"\"\"Helper for calculating tcache index etc.\"\"\"\n    _cmdline_ = \"heap tcache-index-helper\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-i\", \"--index\", type=AddressUtil.parse_address,\n                        help=\"the index of tcache entry (0 ~ 63 (~glibc 2.41) or 75 (glibc 2.42~)).\")\n    parser.add_argument(\"-c\", \"--count-addr\", type=AddressUtil.parse_address,\n                        help=\"the address of &tcache.counts[i].\")\n    parser.add_argument(\"-e\", \"--entry-addr\", type=AddressUtil.parse_address,\n                        help=\"the address of &tcache.entries[i].\")\n    _syntax_ = parser.format_help()\n\n    def print_tcache_info(self, arena, index):\n        \"\"\"Print addresses of tcache count and entry for the specified bin index in the given arena.\"\"\"\n        if index < 0:\n            err(\"Invalid index (< 0)\")\n            return\n        if index >= arena.TCACHE_MAX_BINS():\n            err(\"Invalid index (>= TCACHE_MAX_BINS)\")\n            return\n\n        # counts / num_slots\n        if get_libc_version() < (2, 42):\n            count_addr = arena.addrof_tcachebins_i_count(index)\n            info(\"&tcache.counts[{:d}] = {!s}\".format(index, ProcessMap.lookup_address(count_addr)))\n        else:\n            num_slots_addr = arena.addrof_tcachebins_i_count(index)\n            info(\"&tcache.num_slots[{:d}] = {!s}\".format(index, ProcessMap.lookup_address(num_slots_addr)))\n\n        # entries\n        entry_addr = arena.addrof_tcachebins_i(index)\n        info(\"&tcache.entries[{:d}] = {!s}\".format(index, ProcessMap.lookup_address(entry_addr)))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        # Determine if we are using libc with tcache built in (2.26+)\n        if get_libc_version() < (2, 26):\n            err(\"No tcache in this version of libc\")\n            return\n\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        # doit\n        info(\"heap_base: {!s}\".format(ProcessMap.lookup_address(arena.heap_base)))\n        info(\"tcache: {!s} (tcache_perthread_struct)\".format(ProcessMap.lookup_address(arena.tcache_perthread_struct)))\n\n        if (args.index, args.count_addr, args.entry_addr) == (None, None, None):\n            self.print_tcache_info(arena, 0)\n            return\n\n        if args.index is not None:\n            self.print_tcache_info(arena, args.index)\n\n        if args.count_addr is not None:\n            if get_libc_version() < (2, 30):\n                index = args.count_addr - arena.addrof_tcachebins_i_count(0)\n            else:\n                if args.count_addr % 2 == 1:\n                    err(\"Invalid address (count_addr % 2 == 1)\")\n                    return\n                index = (args.count_addr - arena.addrof_tcachebins_i_count(0)) // 2\n            self.print_tcache_info(arena, index)\n\n        if args.entry_addr is not None:\n            index = (args.entry_addr - arena.addrof_tcachebins_i(0)) // current_arch.ptrsize\n            self.print_tcache_info(arena, index)\n        return\n\n\n@register_command\nclass GlibcHeapFindFakeFastCommand(GenericCommand, BufferingOutput):\n    \"\"\"Find candidate fake fast chunks from RW memory.\"\"\"\n\n    _cmdline_ = \"heap find-fake-fast\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--include-heap\", action=\"store_true\", help=\"heap is also included in the search target.\")\n    parser.add_argument(\"--aligned\", action=\"store_true\", help=\"search only aligned chunks.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"search target size.\")\n    parser.add_argument(\"--region-size-threshold\", type=AddressUtil.parse_address, default=0x0200_0000,\n                        help=\"threshold for region size to skip search. (default: %(default)#x)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"It is not possible to find candidates that straddle the two regions.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def print_result(self, m, pos, size_candidate):\n        \"\"\"Display the result of a memory search, including address, flags, and a memory dump with colored highlights.\"\"\"\n        path = \"unknown\" if m.path == \"\" else m.path\n        address = ProcessMap.lookup_address(m.page_start + pos)\n        self.info_add_out(\"Found at {!s} in {!r} [{!s}]\".format(address, path, m.permission))\n\n        # flag with coloring\n        flag = []\n\n        color = \"\"\n        if size_candidate & 0b100:\n            color = Config.get_gef_setting(\"theme.heap_chunk_flag_non_main_arena\")\n        flag += [Color.colorify(\"NON_MAIN_ARENA\", color)]\n\n        color = \"\"\n        if size_candidate & 0b10:\n            color = Config.get_gef_setting(\"theme.heap_chunk_flag_is_mmapped\")\n        flag += [Color.colorify(\"IS_MMAPED\", color)]\n\n        color = \"\"\n        if size_candidate & 0b1:\n            color = Config.get_gef_setting(\"theme.heap_chunk_flag_prev_inuse\")\n        flag += [Color.colorify(\"PREV_INUSE\", color)]\n\n        self.out.append(\"    [{:s}]\".format(\" \".join(flag)))\n\n        # dump\n        try:\n            if is_64bit():\n                res = gdb.execute(\"x/6xg {:#x}\".format(address.value), to_string=True)\n            else:\n                res = gdb.execute(\"x/6xw {:#x}\".format(address.value), to_string=True)\n            truncated_flag = False\n        except Exception:\n            if is_64bit():\n                res = gdb.execute(\"x/2xg {:#x}\".format(address.value), to_string=True)\n            else:\n                res = gdb.execute(\"x/2xw {:#x}\".format(address.value), to_string=True)\n            truncated_flag = True\n\n        for line in res.splitlines():\n            self.out.append(\"    {:s}\".format(line))\n\n        if truncated_flag:\n            self.warn_add_out(\"Areas from {!s} are inaccessible and display truncated.\".format(address))\n        return\n\n    def find_fake_fast(self, target_size):\n        \"\"\"Scan memory regions for fake fastbin chunks matching the target size and display findings.\"\"\"\n        if is_64bit():\n            mask = ~0xf\n            unpack = u64\n        else:\n            mask = ~0x7\n            unpack = u32\n\n        if self.args.aligned:\n            unit = 0x10\n        else:\n            unit = 0x1\n\n        ZERO_PAGE = b\"\\0\" * get_pagesize()\n        target_size &= mask\n        vmmap = ProcessMap.get_process_maps_exclude_special_regions()\n\n        for m in vmmap:\n            # RW permission required\n            if not (m.permission & Permission.READ):\n                continue\n            if not (m.permission & Permission.WRITE):\n                continue\n\n            # ignore \"[heap]\" or not\n            if m.path.startswith(\"[heap]\"):\n                if not self.args.include_heap:\n                    continue\n\n            # skip if too large region\n            if m.size >= self.args.region_size_threshold:\n                path = \"unknown\" if m.path == \"\" else m.path\n                self.info_add_out(\"{!r} is skipped since too large ({:#x} >= {:#x})\".format(\n                    path, m.size, self.args.region_size_threshold,\n                ))\n                continue\n\n            data = read_memory(m.page_start, m.size)\n            # Scanning page-by-page\n            pos = 0\n            while pos < m.size:\n                if (pos & get_pagesize_mask_low()) == 0:\n                    # fast check for all zero, because there may be huge mmap-ed memory\n                    if data[pos:pos + get_pagesize()] == ZERO_PAGE:\n                        pos += get_pagesize()\n                        continue\n\n                pos_of_size_start = pos + current_arch.ptrsize\n                pos_of_size_end = pos + current_arch.ptrsize * 2\n                size_candidate = data[pos_of_size_start:pos_of_size_end]\n\n                # even if it is found near the end of region, it cannot be used.\n                if len(size_candidate) != current_arch.ptrsize:\n                    break\n\n                # check if it's the size you want\n                size_candidate = unpack(size_candidate)\n                if (size_candidate & mask) != target_size:\n                    pos += unit\n                    continue\n\n                # found\n                self.print_result(m, pos, size_candidate)\n                pos += unit\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        MIN_SIZE = GlibcHeap.HeapInfo.MIN_SIZE()\n        if args.size < MIN_SIZE:\n            err(\"Wrong size\")\n            return\n\n        self.out = []\n        self.find_fake_fast(args.size)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GlibcHeapExtractHeapAddrCommand(GenericCommand):\n    \"\"\"Extract heap address from protected `fd` pointer of single linked-list (glibc 2.32~).\"\"\"\n\n    _cmdline_ = \"heap extract-heap-addr\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"value\", metavar=\"VALUE\", nargs=\"?\", type=AddressUtil.parse_address,\n                       help=\"the value to extract.\")\n    group.add_argument(\"--source\", action=\"store_true\",\n                       help=\"shows the source instead of displaying extracted value.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x000055500000C7F9\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def reveal(self, fd):\n        # https://smallkirby.hatenablog.com/entry/safeunlinking\n        L = fd >> 36\n        for i in range(3):\n            temp = (fd >> (36 - (i + 1) * 8)) & 0xff\n            element = ((L >> 4) ^ temp) & 0xff\n            L = (L << 8) + element\n        return L << 12\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.source:\n            s = GefUtil.get_source(GlibcHeapExtractHeapAddrCommand.reveal)\n            gef_print(s)\n            return\n\n        extracted_ptr = self.reveal(args.value)\n        extracted_ptr = ProcessMap.lookup_address(extracted_ptr)\n        gef_print(\"Protected fd pointer: {:#x}\".format(args.value))\n        gef_print(\" -> Extracted heap address: {!s} (=fd & ~0xfff)\".format(extracted_ptr))\n        return\n\n\n@register_command\nclass GlibcHeapCalcProtectedFdCommand(GenericCommand):\n    \"\"\"Calculate a valid value as protected `fd` pointer of single linked-list (glibc 2.32~).\"\"\"\n\n    _cmdline_ = \"heap calc-protected-fd\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"fd\", type=AddressUtil.parse_address, help=\"the fd value.\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to interpret as a chunk.\")\n    parser.add_argument(\"-b\", \"--as-base\", action=\"store_true\",\n                        help=\"use LOCATION as chunk base address (chunk_base_address = chunk_address - ptrsize * 2).\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0 0x5555555594e0\",\n        \"{0:s} 0 0x5555555594e0 -b\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        loc = args.location\n        if args.as_base:\n            loc -= current_arch.ptrsize * 2\n        ptr = (loc >> 12) ^ args.fd\n        gef_print(\"Protected fd pointer: {:#x}\".format(ptr))\n        return\n\n\n@register_command\nclass GlibcHeapVisualHeapCommand(GenericCommand, BufferingOutput):\n    \"\"\"Visualize chunks on a heap.\"\"\"\n\n    _cmdline_ = \"heap visual-heap\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"visual-heap\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as the beginning of a contiguous chunk. (default: arena.heap_base)\")\n    parser.add_argument(\"-a\", dest=\"arena_addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-c\", dest=\"max_count\", type=AddressUtil.parse_address,\n                        help=\"maximum number of chunks to parse; use when the number of chunks is very large.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\",\n                        help=\"display the same line without omitting.\")\n    parser.add_argument(\"-d\", \"--dark-color\", action=\"store_true\",\n                        help=\"use the dark color if chunk is allocated.\")\n    parser.add_argument(\"-s\", \"--safe-linking-decode\", action=\"store_true\",\n                        help=\"decode safe-linking encoded pointer if tcache or fastbins.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    normal_colors = [\n        Color.redify,\n        Color.greenify,\n        Color.blueify,\n        Color.yellowify,\n    ]\n    dark_colors = [\n        lambda x: Color.colorify(x, \"bright_black\"),\n        lambda x: Color.colorify(x, \"graphite\"),\n    ]\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def generate_visual_chunk(self, chunk, idx):\n        \"\"\"Generate a visual, colorized representation of a heap chunk's contents,\n        grouping repeated rows and annotating bin info.\"\"\"\n        unpack = u32 if current_arch.ptrsize == 4 else u64\n        data = slicer(chunk.data, current_arch.ptrsize * 2)\n        group_line_threshold = 8\n\n        arena = chunk.arena\n        addr = chunk.chunk_base_address\n        width = current_arch.ptrsize * 2 + 2\n        exceed_top = False\n        has_bins_info = False\n\n        out_tmp = []\n        # Group rows to display rows with the same value together.\n        for blk, blks in itertools.groupby(data):\n            repeat_count = len(list(blks))\n            d1, d2 = unpack(blk[:current_arch.ptrsize]), unpack(blk[current_arch.ptrsize:])\n            dascii = \"\".join([chr(x) if 0x20 <= x < 0x7f else \".\" for x in blk])\n\n            if self.args.full or repeat_count < group_line_threshold:\n                # non-collapsed line\n                for _ in range(repeat_count):\n                    bins_info = arena.get_bins_info(addr)\n                    if bins_info:\n                        bins_info = \" <-  {:s}\".format(\", \".join(bins_info))\n                        has_bins_info = True\n                    else:\n                        bins_info = \"\"\n\n                    if self.args.safe_linking_decode:\n                        if chunk.address == addr and (\"tcache\" in bins_info or \"fastbins\" in bins_info):\n                            d1 = chunk.get_fwd_ptr(True)\n\n                    offset1 = addr - chunk.chunk_base_address\n                    offset2 = addr - arena.heap_base\n                    out_tmp.append(\"{:#x}|{:+#08x}|{:+#08x}: {:#0{:d}x} {:#0{:d}x} | {:s} | {:s}\".format(\n                        addr, offset1, offset2, d1, width, d2, width, dascii, bins_info,\n                    ).rstrip())\n                    addr += current_arch.ptrsize * 2\n\n                    if addr > arena.top + current_arch.ptrsize * 4:\n                        exceed_top = True\n                        break\n            else:\n                # collapsed line\n                bins_info = arena.get_bins_info(addr)\n                if bins_info:\n                    bins_info = \" <-  {:s}\".format(\", \".join(bins_info))\n                    has_bins_info = True\n                else:\n                    bins_info = \"\"\n\n                offset1 = addr - chunk.chunk_base_address\n                offset2 = addr - arena.heap_base\n                out_tmp.append(\"{:#x}|{:+#08x}|{:+#08x}: {:#0{:d}x} {:#0{:d}x} | {:s} | {:s}\".format(\n                    addr, offset1, offset2, d1, width, d2, width, dascii, bins_info,\n                ).rstrip())\n                addr += current_arch.ptrsize * 2 * repeat_count\n                out_tmp.append(\"* {:#d} lines, {:#x} bytes\".format(\n                    repeat_count - 1, (repeat_count - 1) * current_arch.ptrsize * 2,\n                ))\n\n            if exceed_top:\n                break\n\n        # coloring\n        if self.args.dark_color and not has_bins_info:\n            color_func = self.dark_colors[idx % len(self.dark_colors)]\n        else:\n            color_func = self.normal_colors[idx % len(self.normal_colors)]\n        self.out.append(\"\\n\".join(map(color_func, out_tmp)))\n\n        # corrupted case\n        if exceed_top:\n            self.out.append(Color.boldify(\"...\"))\n        return\n\n    def generate_visual_heap(self, arena, dump_start, max_count):\n        \"\"\"Generate a visual representation of the heap by iterating over chunks,\n        handling corruption and optional progress display.\"\"\"\n        sect = ProcessMap.process_lookup_address(dump_start)\n        if sect:\n            end = sect.page_end\n        else:\n            # If qemu-user 8.1 or higher, the `process_lookup_address` to obtain the section list\n            # uses `info proc mappings` internally.\n            # This is fast, but does not return an accurate list in some cases.\n            # For example, sparc64 may not include the heap area.\n            # So it detects the end of the page from arena.top.\n            end = arena.top + GlibcHeap.GlibcChunk(arena, arena.top, from_base=True).size\n\n        try:\n            from tqdm import tqdm\n        except ImportError:\n            tqdm = None\n        if tqdm:\n            pbar = tqdm(total=end - dump_start, leave=False)\n\n        addr = dump_start\n        i = 0\n        while addr < end:\n            chunk = GlibcHeap.GlibcChunk(arena, addr + current_arch.ptrsize * 2)\n            # corrupt check\n            if chunk.size == 0:\n                msg = \"{} Corrupted (chunk.size == 0)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                self.generate_visual_chunk(chunk, i)\n                break\n            elif addr != arena.top and addr + chunk.size > arena.top:\n                msg = \"{} Corrupted (addr + chunk.size > arena.top)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                self.generate_visual_chunk(chunk, i)\n                break\n            elif addr + chunk.size > end:\n                msg = \"{} Corrupted (addr + chunk.size > sect.page_end)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                self.generate_visual_chunk(chunk, i)\n                break\n            # maybe not corrupted\n            try:\n                chunk.data = read_memory(addr, chunk.size)\n            except gdb.MemoryError:\n                break\n            self.generate_visual_chunk(chunk, i)\n            addr += chunk.size\n            i += 1\n\n            if tqdm:\n                pbar.update(chunk.size)\n\n            if max_count and max_count <= i:\n                break\n\n        if tqdm:\n            pbar.close()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.location is None:\n            dump_start = arena.heap_base\n            # specific pattern\n            if arena.is_main_arena:\n                if (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                    dump_start += 8\n        else:\n            dump_start = args.location\n\n        self.out = []\n        self.generate_visual_heap(arena, dump_start, args.max_count)\n        self.print_output()\n        return\n\n\n@register_command\nclass GlibcHeapDumpImageCommand(GenericCommand):\n    \"\"\"Visualize chunks on a heap as composition image.\"\"\"\n\n    _cmdline_ = \"heap dump-image\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"dump-image\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as the beginning of a contiguous chunk. (default: arena.heap_base)\")\n    parser.add_argument(\"-a\", dest=\"arena_addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"-c\", dest=\"max_count\", type=AddressUtil.parse_address,\n                        help=\"maximum number of chunks to parse; use when the number of chunks is very large.\")\n    parser.add_argument(\"-t\", \"--include-top\", action=\"store_true\", help=\"include top chunk.\")\n    parser.add_argument(\"-s\", \"--save-as-png\", action=\"store_true\", help=\"save as png.\")\n    parser.add_argument(\"-S\", \"--scale\", type=float, default=1.0, help=\"magnification to enlarge or reduce the image.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        Color.colorify(\"In-use chunks\", \"underline\") + \" are displayed alternately in \" + \\\n        Color.colorify(\"dark gray\", \"gray\") + \" and \" + Color.colorify(\"light gray\", \"cloud\") + \".\",\n        Color.colorify(\"Freed chunks\", \"underline\") + \" are displayed alternately in \" + \\\n        Color.colorify(\"muted red\", \"orange\") + \" and \" + Color.colorify(\"muted yellow\", \"lemon_yellow\") + \".\",\n        \"In both cases, the color is determined by whether the chunk's position from the beginning\",\n        \"is odd-numbered or even-numbered.\",\n        \"\",\n        \"The `convert` command limits height to 32000px; output may shrink based on heap size.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def collect_chunks(self, arena, dump_start, max_count):\n        sect = ProcessMap.process_lookup_address(dump_start)\n        if sect:\n            end = sect.page_end\n        else:\n            # If qemu-user 8.1 or higher, the `process_lookup_address` to obtain the section list\n            # uses `info proc mappings` internally.\n            # This is fast, but does not return an accurate list in some cases.\n            # For example, sparc64 may not include the heap area.\n            # So it detects the end of the page from arena.top.\n            end = arena.top + GlibcHeap.GlibcChunk(arena, arena.top, from_base=True).size\n\n        try:\n            from tqdm import tqdm\n        except ImportError:\n            tqdm = None\n        if tqdm:\n            pbar = tqdm(total=end - dump_start, leave=False)\n\n        chunks = []\n        err_msg = None\n        addr = dump_start\n        i = 0\n        while addr < end:\n            chunk = GlibcHeap.GlibcChunk(arena, addr + current_arch.ptrsize * 2)\n            # corrupt check\n            if chunk.size == 0:\n                err_msg = \"{} Corrupted (chunk.size == 0)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                chunks.append(chunk)\n                break\n            elif addr != arena.top and addr + chunk.size > arena.top:\n                err_msg = \"{} Corrupted (addr + chunk.size > arena.top)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                chunks.append(chunk)\n                break\n            elif addr + chunk.size > end:\n                err_msg = \"{} Corrupted (addr + chunk.size > sect.page_end)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                chunk.data = read_memory(addr, max(arena.top - addr + 0x10, 0))\n                chunks.append(chunk)\n                break\n            # maybe not corrupted\n            try:\n                chunk.data = read_memory(addr, chunk.size)\n            except gdb.MemoryError:\n                break\n\n            if chunk.is_top():\n                if not self.args.include_top:\n                    break\n            chunks.append(chunk)\n            addr += chunk.size\n            i += 1\n\n            if tqdm:\n                pbar.update(chunk.size)\n\n            if max_count and max_count <= i:\n                break\n\n        if tqdm:\n            pbar.close()\n        return chunks, err_msg\n\n    def generate_image(self, chunks):\n        MIN_SIZE = GlibcHeap.HeapInfo.MIN_SIZE()\n        MALLOC_ALIGNMENT = GlibcHeap.HeapInfo.MALLOC_ALIGNMENT()\n\n        def chunk_size_to_line_number(chunk):\n            line_num = ((chunk.size - MIN_SIZE) // MALLOC_ALIGNMENT) + 1\n            return max(line_num, 1)\n\n        line_nums = [chunk_size_to_line_number(c) for c in chunks]\n        used_or_freed = [c.is_real_used() for c in chunks]\n\n        total = sum(line_nums)\n        if total <= 0:\n            return None\n\n        used_cols = [\n            b\"\\xb3\\xb3\\xb3\",  # 70% gray (179)\n            b\"\\x4d\\x4d\\x4d\",  # 30% gray (77)\n        ]\n\n        freed_cols = [\n            b\"\\xc6\\x6b\\x5b\",  # muted red\n            b\"\\xd8\\xb4\\x5a\",  # muted yellow\n        ]\n\n        target_h = 30000 # limit of convert command\n        target_w = 1\n\n        # assign to target_h by ratio (rounding error is absorbed by accumulator)\n        data_parts = []\n        acc = 0 # error accumulation (molecule side)\n        for i, (h, u) in enumerate(zip(line_nums, used_or_freed)):\n            if u:\n                color = used_cols[i & 1]\n            else:\n                color = freed_cols[i & 1]\n\n            acc += h * target_h\n            px = acc // total\n            acc = acc % total\n\n            px = int(px)\n            if px <= 0:\n                continue\n\n            data_parts.append(color * (px * target_w))\n\n        data = b\"\".join(data_parts)\n\n        tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"heap-dump-image\", suffix=\".raw\")\n        os.fdopen(tmp_fd, \"wb\").write(data)\n        return tmp_path\n\n    def make_command_line(self, image_path):\n        img_height = os.path.getsize(image_path) // 3 # RGB\n        img_width = 1\n\n        command_options = [\n            \"-size {:d}x{:d}\".format(img_width, img_height),\n            \"-depth 8\",\n        ]\n\n        # terminal size (number of characters)\n        term_height, term_width = GefUtil.get_terminal_size()\n        # it's too tight, so make it slightly smaller.\n        term_width *= 0.95\n        term_height *= 0.95\n        # number of pixels per character\n        font_width_px = 6\n        font_height_px = 12\n        # pixel dimensions of the terminal\n        term_width_px = int(term_width * font_width_px * self.args.scale)\n        term_height_px = int(term_height * font_height_px * self.args.scale)\n        # convert option\n        command_options.extend([\n            \"-filter Box\",\n            \"-resize {:d}x{:d}!\".format(term_width_px, term_height_px),\n        ])\n\n        if self.args.save_as_png:\n            cmd = \"{!r} {:s} rgb:{!r} PNG:{!r}\".format(\n                GefUtil.which(\"convert\"),\n                \" \".join(command_options),\n                image_path, image_path[:-4] + \".png\"\n            )\n        else:\n            cmd = \"{!r} {:s} rgb:{!r} sixel:-\".format(\n                GefUtil.which(\"convert\"),\n                \" \".join(command_options),\n                image_path,\n            )\n        return cmd\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        try:\n            GefUtil.which(\"convert\") # imagemagick\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.location is None:\n            dump_start = arena.heap_base\n            # specific pattern\n            if arena.is_main_arena:\n                if (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                    dump_start += 8\n        else:\n            dump_start = args.location\n\n        # parse chunks\n        chunks, err_msg = self.collect_chunks(arena, dump_start, args.max_count)\n\n        # make image\n        image_path = self.generate_image(chunks)\n        if not image_path:\n            return\n\n        # show\n        cmd = self.make_command_line(image_path)\n        os.system(cmd)\n        os.unlink(image_path)\n\n        if args.save_as_png:\n            info(\"Saved as {!r}\".format(image_path[:-4] + \".png\"))\n        return\n\n\n@register_command\nclass GlibcHeapSnapshotCommand(GenericCommand):\n    \"\"\"Take a snapshot of heap.\"\"\"\n\n    _cmdline_ = \"heap snapshot\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"dump all arenas.\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def dump_heap(arena):\n        # data\n        try:\n            section = ProcessMap.lookup_address(arena.heap_base).section\n            page_start = section.page_start\n            region_size = section.size\n        except Exception:\n            err(\"Failed to get memory range\")\n            return None\n\n        try:\n            raw = read_memory(page_start, region_size)\n        except gdb.MemoryError:\n            err(\"Failed to dump memory\")\n            return None\n\n        # info\n        try:\n            heap_base = arena.heap_base\n            dump_start = heap_base\n            if arena.is_main_arena:\n                if (is_x86_32() or is_riscv32() or is_ppc32()) and get_libc_version() >= (2, 26):\n                    dump_start += 8\n\n            info = {\n                \"heap_base\": arena.heap_base,\n                \"dump_start\": dump_start,\n                \"top\": arena.top,\n            }\n\n            chunks = []\n            current_chunk = GlibcHeap.GlibcChunk(arena, dump_start, from_base=True)\n            while True:\n                \"\"\"\n                0x555555fa9500|+0x00000: 0x0000000000000020 0x0000000000000041  <- start_offset\n                0x555555fa9510|+0x00010: 0x726f7272652d736c 0x2d746f6e6e61632d\n                0x555555fa9520|+0x00020: 0x7269642d6e65706f 0x622d79726f746365\n                0x555555fa9530|+0x00030: 0x72637365642d6461 0x696c2f726f747069  <- end_offset\n                \"\"\"\n                start_offset = current_chunk.chunk_base_address - heap_base\n                chunks.append({\n                    \"start_offset\": start_offset,\n                    \"size\": current_chunk.size,\n                    \"end_offset\": start_offset + current_chunk.size - (current_arch.ptrsize * 2),\n                    \"used\": current_chunk.is_real_used(),\n                    \"extra\": \"\",\n                })\n                if current_chunk.chunk_base_address > arena.top:\n                    break\n                if current_chunk.size == 0:\n                    break\n                chunks[-1][\"extra\"] = \",\".join(arena.get_bins_info(current_chunk))\n                if current_chunk.chunk_base_address == arena.top:\n                    break\n\n                next_chunk = current_chunk.get_next_chunk()\n                if next_chunk is None:\n                    break\n                if not is_valid_addr(next_chunk.address):\n                    break\n                current_chunk = next_chunk\n\n            info[\"chunks\"] = chunks\n        except Exception:\n            return None\n\n        return raw, info\n\n    @staticmethod\n    def take_snapshot(arena, arena_index):\n        ret = GlibcHeapSnapshotCommand.dump_heap(arena)\n        if ret is None:\n            return None\n        raw, info = ret\n\n        raw_fd, raw_filepath = GefUtil.mkstemp(\n            prefix=\"heap-ss-arena{:d}\".format(arena_index),\n            dt=datetime.datetime.now().strftime(\"%H%M%S\"),\n            suffix=\".raw\",\n        )\n        os.fdopen(raw_fd, \"wb\").write(raw)\n\n        base, _ = os.path.splitext(raw_filepath)\n        json.dump(info, open(base + \".json\", \"w\"))\n\n        GlibcHeapSnapshotCommand.last_dumped_filepath = raw_filepath\n        return raw_filepath\n\n    @staticmethod\n    def read_snapshot(filepath):\n        if os.path.basename(filepath) == filepath:\n            filepath = os.path.join(GEF_TEMP_DIR, filepath)\n\n        base, _ = os.path.splitext(filepath)\n        raw_path = base + \".raw\"\n        json_path = base + \".json\"\n\n        if not os.path.exists(raw_path) or os.path.getsize(raw_path) == 0:\n            err(\"Invalid file path (.raw)\")\n            return None\n        if not os.path.exists(json_path) or os.path.getsize(json_path) == 0:\n            err(\"Invalid file path (.json)\")\n            return None\n\n        try:\n            raw = open(raw_path, \"rb\").read()\n        except gdb.MemoryError:\n            return None\n        try:\n            info = json.loads(open(json_path).read())\n        except Exception:\n            return None\n        return raw, info\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        # parse arena\n        arena = GlibcHeap.get_arena(args.arena_addr)\n\n        if arena is None:\n            err(\"No valid arena\")\n            return\n\n        if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n            err(\"Heap is not initialized\")\n            return\n\n        if args.all:\n            arenas = GlibcHeap.get_all_arenas()\n        else:\n            arenas = [arena]\n\n        # doit\n        for i, arena in enumerate(arenas):\n            path = self.take_snapshot(arena, i)\n            if path:\n                info(\"Snapshot successful: {:s}\".format(path))\n        return\n\n\n@register_command\nclass GlibcHeapSnapshotCompareCommand(GenericCommand, BufferingOutput):\n    \"\"\"Compare current heap with a previously saved heap-snapshot.\"\"\"\n\n    _cmdline_ = \"heap snapshot-compare\"\n    _category_ = \"05-a. Heap - Glibc\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--arena-addr\", type=AddressUtil.parse_address,\n                        help=\"the address or number to interpret as an arena. (default: main_arena)\")\n    parser.add_argument(\"file_path\", metavar=\"FILE_PATH\", nargs=\"?\",\n                        help=\"the filepath to compare (default: last dumped file).\")\n    parser.add_argument(\"file_path2\", metavar=\"FILE_PATH2\", nargs=\"?\", help=\"the filepath to compare.\")\n    parser.add_argument(\"-e\", \"--extra\", action=\"store_true\", help=\"display extra chunk info.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\", help=\"display after `top` chunk.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} /path/to/snapshot1                     # compare the current memory and file1\",\n        \"{0:s} /path/to/snapshot1 /path/to/snapshot2  # compare file1 and file2\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Please specify the file obtained by the `heap snapshot` command.\",\n        \"Usually, it is saved in /tmp/gef/heap-snashot-arenaN-...\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    class LightRangeDict:\n        def __init__(self):\n            self.starts = []\n            self.items = []\n            return\n\n        def add(self, start, stop, value):\n            import bisect\n            if not (start < stop):\n                raise ValueError(\"start must be < stop\")\n\n            i = bisect.bisect_left(self.starts, start)\n\n            if 0 < i and start < self.items[i - 1][1]:\n                raise ValueError(\"overlapping range\")\n\n            if i < len(self.items) and self.items[i][0] < stop:\n                raise ValueError(\"overlapping range\")\n\n            self.starts.insert(i, start)\n            self.items.insert(i, (start, stop, value))\n            return None\n\n        def __getitem__(self, key):\n            import bisect\n            i = bisect.bisect_right(self.starts, key) - 1\n            if 0 <= i:\n                start, stop, value = self.items[i]\n                if key < stop:\n                    return value\n            if hasattr(self, \"default\"):\n                return self.default\n            raise KeyError(key)\n\n        def setdefault(self, default):\n            self.default = default\n            return\n\n    def compare(self, raw1, info1, raw2, info2):\n        ptrsize = current_arch.ptrsize\n        assert len(raw1) % ptrsize == 0\n        assert len(raw2) % ptrsize == 0\n\n        double_ptrsize = ptrsize * 2\n        hex_width = double_ptrsize + 2\n\n        if self.args.full:\n            max_size = max(len(raw1), len(raw2))\n        else:\n            max_size = max(\n                info1[\"top\"] + double_ptrsize - info1[\"heap_base\"],\n                info2[\"top\"] + double_ptrsize - info2[\"heap_base\"],\n            )\n\n        color_dict = {\n            # same, is_size, is_underline, is_used\n            (True, True, True, True): \"underline magenta\",\n            (True, True, True, False): \"underline magenta\",\n            (True, True, False, True): \"magenta\",\n            (True, True, False, False): \"magenta\",\n            (True, False, True, True): \"underline graphite\",\n            (True, False, True, False): \"underline\",\n            (True, False, False, True): \"graphite\",\n            (True, False, False, False): \"\",\n            (False, True, True, True): \"bold underline magenta\",\n            (False, True, True, False): \"bold underline magenta\",\n            (False, True, False, True): \"bold magenta\",\n            (False, True, False, False): \"bold magenta\",\n            (False, False, True, True): \"bold underline graphite\",\n            (False, False, True, False): \"bold underline\",\n            (False, False, False, True): \"bold graphite\",\n            (False, False, False, False): \"bold\",\n        }\n\n        start_offset_list1 = {c[\"start_offset\"] for c in info1[\"chunks\"]}\n        start_offset_list2 = {c[\"start_offset\"] for c in info2[\"chunks\"]}\n        end_offset_list1 = {c[\"end_offset\"] for c in info1[\"chunks\"]}\n        end_offset_list2 = {c[\"end_offset\"] for c in info2[\"chunks\"]}\n        if self.args.extra:\n            prefix_blank = \" \" * (AddressUtil.get_format_address_width() + 18)\n            fwidth = (double_ptrsize + 2) * 2 + 7 + double_ptrsize\n            extra_dict1 = {c[\"start_offset\"]: c[\"extra\"] for c in info1[\"chunks\"]}\n            extra_dict2 = {c[\"start_offset\"]: c[\"extra\"] for c in info2[\"chunks\"]}\n\n        used_dict1 = self.LightRangeDict()\n        used_dict1.setdefault(False)\n        for ch in info1[\"chunks\"]:\n            used_dict1.add(ch[\"start_offset\"], ch[\"start_offset\"] + ch[\"size\"], ch[\"used\"])\n        used_dict2 = self.LightRangeDict()\n        used_dict2.setdefault(False)\n        for ch in info2[\"chunks\"]:\n            used_dict2.add(ch[\"start_offset\"], ch[\"start_offset\"] + ch[\"size\"], ch[\"used\"])\n\n        def to_ascii(v):\n            s = \"\"\n            for i in range(ptrsize):\n                c = (v >> (8 * i)) & 0xff\n                s += chr(c) if 0x20 <= c < 0x7f else \".\"\n            return s\n\n        # process block\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for pos in tqdm(range(0, max_size, double_ptrsize), leave=False):\n            # skip or not\n            raw16_1 = raw1[pos : pos + double_ptrsize]\n            raw16_2 = raw2[pos : pos + double_ptrsize]\n\n            # coloring\n            hex_1 = []\n            hex_2 = []\n            ascii_1 = []\n            ascii_2 = []\n            is_line_same = True\n\n            # unpack\n            values1 = slice_unpack(raw16_1, ptrsize)\n            values2 = slice_unpack(raw16_2, ptrsize)\n\n            # check size, underline, used\n            is_size1 = pos in start_offset_list1\n            is_size2 = pos in start_offset_list2\n            is_underline1 = pos in end_offset_list1\n            is_underline2 = pos in end_offset_list2\n            is_used1 = used_dict1[pos]\n            is_used2 = used_dict2[pos]\n\n            # cmp\n            for i in range(2):\n                try:\n                    v1 = values1[i]\n                    h1 = \"{:#0{:d}x}\".format(v1, hex_width)\n                    a1 = to_ascii(v1)\n                except IndexError:\n                    v1 = None\n                    h1 = \" \" * hex_width\n                    a1 = \" \" * ptrsize\n                try:\n                    v2 = values2[i]\n                    h2 = \"{:#0{:d}x}\".format(v2, hex_width)\n                    a2 = to_ascii(v2)\n                except IndexError:\n                    v2 = None\n                    h2 = \" \" * hex_width\n                    a2 = \" \" * ptrsize\n\n                # element coloring\n                is_same = (v1 is None) or (v2 is None) or v1 == v2\n                is_line_same &= is_same\n                is_size1_e = is_size1 & (i == 1)\n                is_size2_e = is_size2 & (i == 1)\n                hex_1.append(Color.colorify(h1, color_dict[is_same, is_size1_e, is_underline1, is_used1]))\n                ascii_1.append(Color.colorify(a1, color_dict[is_same, is_size1_e, is_underline1, is_used1]))\n                hex_2.append(Color.colorify(h2, color_dict[is_same, is_size2_e, is_underline2, is_used2]))\n                ascii_2.append(Color.colorify(a2, color_dict[is_same, is_size2_e, is_underline2, is_used2]))\n\n            # blank coloring\n            sep1 = Color.colorify(\" \", \" \".join(color_dict[True, False, is_underline1, is_used1]))\n            sep2 = Color.colorify(\" \", \" \".join(color_dict[True, False, is_underline2, is_used2]))\n            hex_1_joined = sep1.join(hex_1)\n            hex_2_joined = sep2.join(hex_2)\n            ascii_1_joined = sep1.join(ascii_1)\n            ascii_2_joined = sep2.join(ascii_2)\n\n            if self.args.extra:\n                # make extra line\n                extra1 = extra_dict1.get(pos, \"\")\n                extra2 = extra_dict2.get(pos, \"\")\n                if extra1 or extra2:\n                    line = \"{:s} {:{:d}s} {:{:d}s}\".format(prefix_blank, extra1, fwidth, extra2, fwidth)\n                    self.out.append(line.rstrip())\n\n            # make line\n            addr = ProcessMap.lookup_address(info1[\"dump_start\"] + pos)\n            line = \"{:s}{!s}|{:+#08x}|{:+06d}: {:s} | {:s} | {:s} | {:s} |\".format(\n                \" \" if is_line_same else \"+\",\n                addr, pos, pos // double_ptrsize,\n                hex_1_joined, ascii_1_joined,\n                hex_2_joined, ascii_2_joined,\n            )\n            self.out.append(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.file_path is not None and args.file_path2 is not None:\n            ret1 = GlibcHeapSnapshotCommand.read_snapshot(self.args.file_path)\n            ret2 = GlibcHeapSnapshotCommand.read_snapshot(self.args.file_path2)\n            file_path1 = os.path.basename(self.args.file_path)\n            file_path2 = os.path.basename(self.args.file_path2)\n        else:\n            # parse arena\n            arena = GlibcHeap.get_arena(args.arena_addr)\n\n            if arena is None:\n                err(\"No valid arena\")\n                return\n\n            if arena.heap_base is None or not is_valid_addr(arena.heap_base):\n                err(\"Heap is not initialized\")\n                return\n\n            ret1 = GlibcHeapSnapshotCommand.dump_heap(arena)\n            file_path1 = \"Current memory\"\n\n            if args.file_path is None:\n                if not hasattr(GlibcHeapSnapshotCommand, \"last_dumped_filepath\"):\n                    err(\"Invalid filepath\")\n                    return\n                ret2 = GlibcHeapSnapshotCommand.read_snapshot(GlibcHeapSnapshotCommand.last_dumped_filepath)\n                file_path2 = os.path.basename(GlibcHeapSnapshotCommand.last_dumped_filepath)\n            else:\n                ret2 = GlibcHeapSnapshotCommand.read_snapshot(self.args.file_path)\n                file_path2 = os.path.basename(self.args.file_path)\n\n        if ret1 is None or ret2 is None:\n            return\n        raw1, info1 = ret1\n        raw2, info2 = ret2\n\n        # legend\n        self.out = []\n        fwidth = (current_arch.ptrsize * 2 + 2) * 2 + 7 + (current_arch.ptrsize * 2)\n        fmt = \" {:{:d}s} {:8s} {:6s}  {:{:d}s} {:{:d}s}\"\n        legend = [\n            \"Address\", AddressUtil.get_format_address_width(), \"Offset\", \"Line\",\n            file_path1, fwidth, file_path2, fwidth,\n        ]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # doit\n        self.compare(memoryview(raw1), info1, memoryview(raw2), info2)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass RegistersCommand(GenericCommand):\n    \"\"\"Display many or all register values from current architecture.\"\"\"\n\n    _cmdline_ = \"registers\"\n    _category_ = \"01-a. Debugging Support - Context\"\n    _aliases_ = [\"regs\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"registers\", metavar=\"REGISTERS\", nargs=\"*\",\n                        type=lambda x: x if x.startswith(\"$\") else \"$\" + x,\n                        help=\"An array of registers. (default: current_arch.all_registers)\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"skip dereference.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} $eax $eip $esp\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def get_all_registers(self):\n        if is_x86():\n            all_registers = current_arch.all_registers + current_arch.virtual_registers\n        else:\n            all_registers = current_arch.all_registers\n        return all_registers\n\n    def check_unavailable_regs(self):\n        \"\"\"Detect and record unavailable registers for later display handling.\"\"\"\n        if hasattr(self, \"regs_to_check_unavailable\"):\n            return\n\n        self.regs_to_check_unavailable = []\n        for regname in self.get_all_registers():\n            try:\n                reg = gdb.parse_and_eval(regname)\n            except gdb.error:\n                # older qemu cannot resolve `fs_base` etc.\n                continue\n            if reg.type.code == gdb.TYPE_CODE_VOID:\n                continue\n            if str(reg) == \"<unavailable>\":\n                self.regs_to_check_unavailable.append(regname)\n        return\n\n    def get_regname_color(self, regname, regvalue):\n        \"\"\"Return the appropriate color for a register name based on whether its value has changed.\"\"\"\n        unchanged_color = Config.get_gef_setting(\"theme.registers_register_name\")\n        changed_color = Config.get_gef_setting(\"theme.registers_value_changed\")\n\n        old_value = ContextRegistersCommand.old_registers.get(regname, 0)\n\n        if regvalue == old_value:\n            color = unchanged_color\n        else:\n            color = changed_color\n        return color\n\n    def dump_seg_reg_x86_16(self):\n        \"\"\"Format and return x86 16-bit segment register values with color and dereferencing.\"\"\"\n        lines = []\n        for regname, (seg, reg) in current_arch.seg_extended_registers.items():\n            segval = get_register(seg) & 0xffff\n            regval = get_register(reg) & 0xffff\n            value = current_arch.real2phys(segval, regval)\n\n            # colorling\n            color = self.get_regname_color(regname, value)\n\n            # reg name\n            line = \"{}:\".format(Color.colorify(regname, color))\n\n            # dereference values\n            value_s = AddressUtil.format_address(value, memalign_size=2.5)\n            line += \" {:04x}:{:04x}: {:s}  ->  \".format(segval, regval, value_s)\n            line += AddressUtil.recursive_dereference_to_string(value, skip_idx=1)\n\n            lines.append(line)\n        return lines\n\n    def dump_regs(self, target_regs):\n        \"\"\"Format and return register values for display, with color, alignment, and optional dereferencing.\"\"\"\n        aliased_registers = current_arch.get_aliased_registers()\n        widest = current_arch.get_aliased_registers_name_max()\n        special_line = \"\"\n        flag_line = \"\"\n\n        lines = []\n        for regname in target_regs:\n            try:\n                reg = gdb.parse_and_eval(regname)\n            except gdb.error:\n                # invalid register\n                continue\n\n            if reg.type.code == gdb.TYPE_CODE_VOID:\n                continue\n\n            # str(reg) is slow, so skip if unneeded\n            if regname in self.regs_to_check_unavailable:\n                # for qiling framework, fs_base/gs_base (x86), cpsr/fpsr/fpcr (Aarch64) are unavailable\n                if str(reg) == \"<unavailable>\":\n                    padreg = aliased_registers.get(regname, regname).ljust(widest, \" \")\n                    line = \"{:s}: {:s}\".format(\n                        Color.colorify(padreg, Config.get_gef_setting(\"theme.registers_register_name\")),\n                        Color.colorify(\"<unavailable>\", \"yellow underline\"),\n                    )\n                    lines.append(line)\n                    continue\n\n            # value\n            try:\n                if hasattr(reg, \"bytes\"):\n                    reg_len = len(reg.bytes)\n                else:\n                    reg_len = current_arch.ptrsize\n            except gdb.error:\n                # In the qiling framework, it may fail just by doing hasattr (e.g., bndstatus)\n                continue\n            value = AddressUtil.align_address(int(reg), memalign_size=reg_len)\n\n            # colorling\n            color = self.get_regname_color(regname, value)\n\n            # special (e.g., segment) registers go on their own line\n            if current_arch.special_registers and regname in current_arch.special_registers:\n                special_line += \"{:s}: {:#06x} \".format(\n                    Color.colorify(regname, color), get_register(regname),\n                )\n                continue\n\n            # reg name\n            padreg = aliased_registers.get(regname, regname).ljust(widest, \" \")\n\n            # flag register\n            if current_arch.flag_register and regname == current_arch.flag_register:\n                flag_line += \"{:s}: {:s}\".format(\n                    Color.colorify(padreg, color), current_arch.flag_register_to_human(),\n                )\n                continue\n\n            # make one line\n            line = \"{:s}: \".format(Color.colorify(padreg, color))\n            if self.args.simple:\n                # not dereference\n                line += \"{:s} \".format(ProcessMap.lookup_address(value).long_fmt())\n            else:\n                # dereference values\n                if is_x86_16():\n                    line += AddressUtil.format_address(value, memalign_size=4)\n                    derefs = AddressUtil.recursive_dereference_to_string(value, skip_idx=1)\n                    if derefs:\n                        line += \"  ->  {:s}\".format(derefs)\n                elif is_mipsn32():\n                    line += AddressUtil.format_address(value, memalign_size=8, long_fmt=True)\n                    derefs = AddressUtil.recursive_dereference_to_string(value, skip_idx=1)\n                    if derefs:\n                        line += \"  ->  {:s}\".format(derefs)\n                else:\n                    line += AddressUtil.recursive_dereference_to_string(value)\n\n            lines.append(line)\n\n        if self.args.simple:\n            one_width = widest + 5 + current_arch.ptrsize * 2\n            nb = GefUtil.get_terminal_size()[1] // one_width\n            lines = [\"\".join(r) for r in slicer(lines, nb)]\n\n        if flag_line:\n            lines.append(flag_line)\n\n        if special_line:\n            lines.append(special_line.rstrip())\n\n        if not self.args.simple:\n            if is_x86_16():\n                lines += self.dump_seg_reg_x86_16()\n        return lines\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.check_unavailable_regs()\n\n        if args.registers:\n            target_regs = args.registers\n        else:\n            target_regs = self.get_all_registers()\n\n        out = self.dump_regs(target_regs)\n        if out:\n            gef_print(\"\\n\".join(out))\n        return\n\n\n@register_command\nclass RopperCommand(GenericCommand):\n    \"\"\"Invoke ropper to search rop gadgets.\"\"\"\n\n    _cmdline_ = \"ropper\"\n    _category_ = \"01-i. Debugging Support - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"args\", metavar=\"ROPPER_OPTIONS\", nargs=\"*\",\n                        help=\"An array of arguments to pass as is to the ropper command. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} -h                  # show detail of options\",\n        '{0:s} --jmp \"rax,rcx\"     # filter by jmp registers',\n        '{0:s} --search \"pop r?x\"  # filter by pop registers',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _help_ = None\n    _help_examples_ = None\n\n    def print_help(self):\n        self.usage()\n\n        ropper_bin = GefUtil.which(\"ropper\")\n        if self._help_ is None:\n            self._help_ = subprocess.check_output([ropper_bin, \"--help\"]).decode(\"utf-8\")\n        if self._help_examples_ is None:\n            self._help_examples_ = subprocess.check_output([ropper_bin, \"--help-examples\"]).decode(\"utf-8\")\n\n        help_text = titlify(\"gef --help\")\n        help_text += self._help_\n        help_text += titlify(\"gef --help-examples\")\n        help_text += self._help_examples_\n        gef_print(help_text, less=True)\n        return\n\n    # Need not @parse_args because argparse can't stop interpreting options for ropper.\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @ModuleLoader.load_ropper\n    @require_arch_set\n    def do_invoke(self, argv):\n        if \"-h\" in argv or \"--help\" in argv:\n            self.print_help()\n            return\n\n        if \"--file\" not in argv:\n            filepath = Path.get_filepath()\n            if filepath is None:\n                err(\"Missing info about file. Please set: `file /path/to/target_binary`\")\n                return\n            argv.extend([\"--file\", filepath])\n        else:\n            try:\n                filepath = argv[argv.index(\"--file\") + 1]\n            except IndexError:\n                self.print_help()\n                return\n\n        if not os.path.isfile(filepath):\n            err(\"Invalid filepath\")\n            return\n\n        # ropper set up own autocompleter after which gdb/gef autocomplete don't work\n        # due to fork/waitpid, child will be broken but parent will not change\n        gef_print(titlify(filepath))\n        pid = os.fork()\n        if pid == 0:\n            # Reorder GdbRemoveReadlineFinder in child processes so readline can be loaded.\n            finder = None\n            for x in list(sys.meta_path):\n                if type(x).__name__ == \"GdbRemoveReadlineFinder\":\n                    finder = x\n                    sys.meta_path.remove(x)\n                    break\n            if finder is not None:\n                sys.meta_path.append(finder)\n            # doit\n            try:\n                ropper = sys.modules[\"ropper\"]\n                ropper.start(argv)\n            except (Exception, SystemExit):\n                pass\n            os._exit(0)\n        else:\n            os.waitpid(pid, 0)\n        return\n\n\n@register_command\nclass RpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Invoke rp++ (v2) command to search rop gadgets (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"rp\"\n    _category_ = \"01-i. Debugging Support - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"--bin\", action=\"store_true\", help=\"apply rp++ to binary itself.\")\n    group.add_argument(\"--libc\", action=\"store_true\", help=\"apply rp++ to libc.so searched from vmmap.\")\n    group.add_argument(\"--file\", help=\"apply rp++ to specified file.\")\n    group.add_argument(\"--kernel\", action=\"store_true\", help=\"dump kernel, then apply vmlinux-to-elf and rp++.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[], help=\"REGEXP filter.\")\n    parser.add_argument(\"-r\", \"--rop\", dest=\"rop_N\", type=int, default=3,\n                        help=\"the max length of rop gadget. (default: %(default)s)\")\n    parser.add_argument(\"-a\", \"--allow-branches\", action=\"store_true\", help=\"enable --allow-branches.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"--no-print\", action=\"store_true\",\n                        help=\"run rp, create a temporary file, but don't display it.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} --bin -f \"pop r[abcd]x\"',\n        '{0:s} --libc -f \"(xchg|mov) [re]sp, \\\\\\\\w+\" -f \"ret\"',\n        \"{0:s} --bin -a                                      # show more gadgets\",\n        \"{0:s} --kernel                                      # only under qemu-system\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def exec_rp(self, rp, ropN, allow_branches, path):\n        \"\"\"Run rp++ to search for ROP gadgets, saving output to a file and returning its path.\"\"\"\n        astr = \"ab\" if allow_branches else \"\"\n        output_file = \"rp{:d}{:s}_{:s}.txt\".format(ropN, astr, os.path.basename(path))\n        output_path = os.path.join(GEF_TEMP_DIR, output_file)\n        aops = \"--allow-branches \" if allow_branches else \"\"\n        cmd = \"{!r} --file={!r} --rop={:d} {:s}--unique > {!r}\".format(rp, path, ropN, aops, output_path)\n        gef_print(titlify(cmd))\n        if not os.path.exists(output_path):\n            os.system(cmd)\n        return output_path\n\n    def apply_filter(self, rp_output_path, base_address):\n        \"\"\"Apply regex filters to rp++ output, adjust gadget addresses, and store matching lines.\"\"\"\n        if not os.path.exists(rp_output_path):\n            err(\"Could not find {!r}\".format(rp_output_path))\n            return\n        lines = open(rp_output_path, \"r\").read()\n\n        for line in lines.splitlines():\n            line = Color.remove_color(line)\n\n            match = True\n            for re_pattern in self.args.filter:\n                if not re_pattern.search(line):\n                    match = False\n                    break\n\n            if match:\n                if line.startswith(\"0x\"):\n                    x = line.split(\":\")\n                    addr, gadget = int(x[0], 16), \":\".join(x[1:])\n                    addr -= base_address # fix address\n                    x = Color.redify(\"{:#08x}\".format(addr)) + \":\" + gadget # repaint color\n                else:\n                    x = line\n                self.out.append(x)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        try:\n            rp = GefUtil.which(\"rp-lin\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        if args.kernel:\n            try:\n                nm = GefUtil.which(Config.get_gef_setting(\"gef.nm_command\"))\n                grep = GefUtil.which(\"grep\")\n            except FileNotFoundError as e:\n                err(\"{}\".format(e))\n                return\n\n        base_address = 0\n        if args.libc:\n            libc_targets = (\"libc-2.\", \"libc.so.6\", \"libuClibc-\")\n            libc = ProcessMap.process_lookup_path(libc_targets)\n            if libc is None:\n                err(\"Could not find the libc\")\n                return\n            path = libc.path\n        elif args.bin:\n            binary = Path.get_filepath()\n            if binary is None:\n                err(\"Could not find the binary\")\n                return\n            path = binary\n        elif args.file:\n            if not os.path.exists(args.file):\n                err(\"Could not find {}\".format(args.file))\n                return\n            path = args.file\n        elif args.kernel:\n            if not is_qemu_system():\n                err(\"--kernel are supported under qemu-system only\")\n                return\n\n            info(\"Wait for memory scan\")\n            # dump kernel then apply vmlinux-to-elf\n            symboled_vmlinux_file = VmlinuxToElfApplyCommand.dump_kernel_elf()\n            if symboled_vmlinux_file is None:\n                err(\"Failed to create kernel ELF\")\n                return\n            path = symboled_vmlinux_file\n\n            cmd = \"{!r} {!r} | {!r} ' _stext$'\".format(nm, symboled_vmlinux_file, grep)\n            out = GefUtil.gef_execute_external(cmd, as_list=True, shell=True)\n            if len(out) != 1:\n                err(\"Failed to resolve _stext\")\n                return\n            base_address = int(out[0].split()[0], 16)\n\n        # invoke rp++\n        rp_output_path = self.exec_rp(rp, args.rop_N, args.allow_branches, path)\n\n        if args.no_print:\n           return\n\n        # filtering\n        self.out = []\n        self.apply_filter(rp_output_path, base_address)\n\n        # print\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass AssembleCommand(GenericCommand):\n    \"\"\"Assemble inline code using Keystone.\"\"\"\n\n    _cmdline_ = \"asm\"\n    _category_ = \"01-e. Debugging Support - Assemble\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", dest=\"arch\", help=\"specify the architecture. (default: current_arch.arch)\")\n    parser.add_argument(\"-m\", dest=\"mode\", help=\"specify the mode. (default: current_arch.mode)\")\n    parser.add_argument(\"-e\", dest=\"big_endian\", action=\"store_true\", help=\"use big-endian.\")\n    parser.add_argument(\"-s\", dest=\"as_shellcode\", action=\"store_true\", help=\"output like shellcode style.\")\n    parser.add_argument(\"-l\", dest=\"overwrite_location\", metavar=\"LOCATION\",\n                        type=AddressUtil.parse_address, help=\"write to memory address.\")\n    parser.add_argument(\"-H\", \"--hex\", action=\"store_true\", help=\"show in hex style.\")\n    parser.add_argument(\"instruction\", metavar=\"INSTRUCTION\", nargs=\"+\", help=\"the code to assemble.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} -a X86 -m 64 \"mov rax, qword ptr [rax] ; inc rax ;\"',\n        '{0:s} -a X86 -m 32 \"mov eax, dword ptr [eax] ; inc eax ;\"',\n        '{0:s} -a X86 -m 16 \"mov ax, word ptr [ax] ; inc ax\"',\n        '{0:s} -a ARM -m ARM      \"sub r1, r2, r3\"',\n        '{0:s} -a ARM -m ARM -e   \"sub r1, r2, r3\"',\n        '{0:s} -a ARM -m THUMB    \"movs r4, #0xf0\"',\n        '{0:s} -a ARM -m THUMB -e \"movs r4, #0xf0\"',\n        '{0:s} -a ARM64 -m ARM    \"ldr w1, [sp, #0x8]\"',\n        '{0:s} -a MIPS -m 32    \"and $9, $6, $7\"',\n        '{0:s} -a MIPS -m 32 -e \"and $9, $6, $7\"',\n        '{0:s} -a MIPS -m 64    \"and $9, $6, $7\"',\n        '{0:s} -a MIPS -m 64 -e \"and $9, $6, $7\"',\n        '{0:s} -a PPC -m 32 -e \"add 1, 2, 3\"',\n        '{0:s} -a PPC -m 64    \"add 1, 2, 3\"',\n        '{0:s} -a PPC -m 64 -e \"add 1, 2, 3\"',\n        '{0:s} -a SPARC -m 32 -e \"add %g1, %g2, %g3\"',\n        '{0:s} -a SPARC -m 32PLUS -e \"add %g1, %g2, %g3\"',\n        '{0:s} -a SPARC -m 64 -e \"add %g1, %g2, %g3\"',\n        '{0:s} -a S390X -m 64 -e \"a %r0, 4095(%r15,%r1)\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @ModuleLoader.load_keystone\n    def do_invoke(self, args):\n        if (args.arch, args.mode) == (None, None):\n            if is_alive() and current_arch:\n                arch, mode = UnicornKeystoneCapstone.get_keystone_arch(\n                    arch=current_arch.arch, mode=current_arch.mode, endian=Endian.is_big_endian(),\n                )\n                arch_mode_s = \":\".join([current_arch.arch, current_arch.mode])\n                endian_s = \"big\" if Endian.is_big_endian() else \"little\"\n            else:\n                # if not alive, defaults to x86-64\n                arch, mode = UnicornKeystoneCapstone.get_keystone_arch(arch=\"X86\", mode=\"64\", endian=False)\n                arch_mode_s = \"X86:64\"\n                endian_s = \"little\"\n        elif not args.arch:\n            err(\"An architecture (-a) must be provided\")\n            return\n        elif not args.mode:\n            # keystone gives no error so check here\n            err(\"A mode (-m) must be provided\")\n            return\n        elif args.arch in [\"SPARC\", \"S390X\"] and args.big_endian is False:\n            # keystone gives no error so check here\n            err(\"A big endian flag (-e) must be provided\")\n            return\n        else:\n            try:\n                arch, mode = UnicornKeystoneCapstone.get_keystone_arch(\n                    arch=args.arch, mode=args.mode, endian=args.big_endian,\n                )\n                arch_mode_s = \":\".join([args.arch, args.mode])\n                endian_s = \"big\" if args.big_endian else \"little\"\n            except AttributeError:\n                self.usage()\n                return\n\n        insns = \" \".join(args.instruction)\n        insns = [x.strip() for x in insns.split(\";\") if x is not None and x.strip() != \"\"]\n\n        info(\"Assembling {:d} instruction{:s} for {:s} ({:s} endian)\".format(\n            len(insns), \"s\" if len(insns) > 1 else \"\", arch_mode_s, endian_s,\n        ))\n\n        if args.as_shellcode:\n            gef_print('sc = \"\"')\n\n        raw = b\"\"\n        for insn in insns:\n            res = UnicornKeystoneCapstone.keystone_assemble(insn, arch, mode, raw=True)\n            if not res:\n                gef_print(\"(Invalid)\")\n                continue\n\n            if args.overwrite_location is not None:\n                raw += res\n                continue\n\n            s = binascii.hexlify(res)\n            if args.hex:\n                res = String.bytes2str(s)\n            else:\n                res = b\"\\\\x\" + b\"\\\\x\".join([s[i:i + 2] for i in range(0, len(s), 2)])\n                res = res.decode(\"utf-8\")\n\n            if args.as_shellcode:\n                res = 'sc += \"{:s}\"'.format(res)\n\n            gef_print(\"{:60s} # {:s}\".format(res, insn))\n\n        if args.overwrite_location is not None:\n            hex_code = binascii.hexlify(raw).decode()\n            gdb.execute(\"patch hex {:#x} {:s}\".format(args.overwrite_location, hex_code))\n        return\n\n\n@register_command\nclass DisassembleCommand(GenericCommand):\n    \"\"\"Disassemble inline code using Capstone.\"\"\"\n\n    _cmdline_ = \"dasm\"\n    _category_ = \"01-e. Debugging Support - Assemble\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", dest=\"arch\", help=\"specify the architecture. (default: current_arch.arch)\")\n    parser.add_argument(\"-m\", dest=\"mode\", help=\"specify the mode. (default: current_arch.mode)\")\n    parser.add_argument(\"-e\", dest=\"big_endian\", action=\"store_true\", help=\"use big-endian.\")\n    parser.add_argument(\"hex_code\", metavar=\"HEX_CODE\", nargs=\"+\", help=\"the hex code to disassemble.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} -a X86 -m 64 \"488b00 48ffc0\"',\n        '{0:s} -a X86 -m 32 \"8b00 40\"',\n        '{0:s} -a X86 -m 16 \"8b00 40\"',\n        '{0:s} -a ARM -m ARM      \"031042e0\"',\n        '{0:s} -a ARM -m ARM -e   \"e0421003\"',\n        '{0:s} -a ARM -m THUMB    \"f024\"',\n        '{0:s} -a ARM -m THUMB -e \"24f0\"',\n        '{0:s} -a ARM64 -m ARM    \"e10b40b9\"',\n        '{0:s} -a MIPS -m 32    \"2448c700\"',\n        '{0:s} -a MIPS -m 32 -e \"00c74824\"',\n        '{0:s} -a MIPS -m 64    \"2448c700\"',\n        '{0:s} -a MIPS -m 64 -e \"00c74824\"',\n        '{0:s} -a PPC -m 32 -e \"7c221a14\"',\n        '{0:s} -a PPC -m 64    \"141a227c\"',\n        '{0:s} -a PPC -m 64 -e \"7c221a14\"',\n        '{0:s} -a SPARC -m 32 -e \"86004002\"',\n        '{0:s} -a SPARC -m 32PLUS -e \"86004002\"',\n        '{0:s} -a SPARC -m 64 -e \"86004002\"',\n        '{0:s} -a RISCV -m 32 \"97c10600\"',\n        '{0:s} -a RISCV -m 64 \"97c10600\"',\n        '{0:s} -a S390X -m 64 -e \"5a0f1fff\"',\n        '{0:s} -a M68K -m 32 -e \"9dce\"',\n        '{0:s} -a LOONGARCH -m 64 \"89001500\" # capstone v6.x~',\n        '{0:s} -a LOONGARCH -m 32 \"89001500\" # capstone v6.x~',\n        '{0:s} -a ALPHA -m 64    \"0b00bd27\" # capstone v6.x~',\n        '{0:s} -a ALPHA -m 64 -e \"27bd000b\" # capstone v6.x~',\n        '{0:s} -a HPPA -m 32 -e \"0fc01299\" # capstone v6.x~',\n        '{0:s} -a HPPA -m 64 -e \"0fc01299\" # capstone v6.x~',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @ModuleLoader.load_capstone\n    def do_invoke(self, args):\n        if (args.arch, args.mode) == (None, None):\n            if is_alive() and current_arch:\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n                    arch=current_arch.arch, mode=current_arch.mode, endian=Endian.is_big_endian(),\n                )\n                arch_mode_s = \":\".join([current_arch.arch, current_arch.mode])\n                endian_s = \"big\" if Endian.is_big_endian() else \"little\"\n            else:\n                # if not alive, defaults to x86-64\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n                    arch=\"X86\", mode=\"64\", endian=False,\n                )\n                arch_mode_s = \"X86:64\"\n                endian_s = \"little\"\n        elif not args.arch:\n            err(\"An architecture (-a) must be provided\")\n            return\n        elif not args.mode:\n            err(\"A mode (-m) must be provided\")\n            return\n        elif args.arch in [\"SPARC\", \"S390X\", \"M68K\", \"HPPA\"] and args.big_endian is False:\n            # capstone gives no error so check here\n            err(\"A big endian flag (-e) must be provided\")\n            return\n        else:\n            try:\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n                    arch=args.arch, mode=args.mode, endian=args.big_endian,\n                )\n                arch_mode_s = \":\".join([args.arch, args.mode])\n                endian_s = \"big\" if args.big_endian else \"little\"\n            except AttributeError:\n                self.usage()\n                return\n\n        insns = \" \".join(args.hex_code)\n        insns = insns.replace(\" \", \"\").replace(\"\\t\", \"\")\n        try:\n            insns = binascii.unhexlify(insns)\n        except binascii.Error:\n            err(\"Invalid format\")\n            return\n\n        info(\"Disassembling {:d} bytes for {:s} ({:s} endian)\".format(\n            len(insns), arch_mode_s, endian_s,\n        ))\n\n        capstone = sys.modules[\"capstone\"]\n        try:\n            cs = capstone.Cs(arch, mode)\n        except capstone.CsError:\n            err(\"CsError\")\n            return\n        cs.detail = True # noqa\n\n        for insn in cs.disasm(insns, 0x0):\n            b = binascii.hexlify(insn.bytes).decode(\"utf-8\")\n            gef_print(\"{:>#6x}:\\t{:<10s}\\t{:s}\\t{:s}\".format(insn.address, b, insn.mnemonic, insn.op_str))\n        return\n\n\n@register_command\nclass AsmListCommand(GenericCommand):\n    \"\"\"List general instructions by capstone (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"asm-list\"\n    _category_ = \"01-e. Debugging Support - Assemble\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", dest=\"arch\", help=\"specify the architecture. (default: current_arch.arch)\")\n    parser.add_argument(\"-m\", dest=\"mode\", help=\"specify the mode. (default: current_arch.mode)\")\n    parser.add_argument(\"-e\", dest=\"big_endian\", action=\"store_true\", help=\"use big-endian.\")\n    parser.add_argument(\"-b\", dest=\"nbyte\", type=int, help=\"filter by the length of asm byte.\")\n    parser.add_argument(\"-f\", dest=\"include\", action=\"append\", help=\"filter by specified string.\")\n    parser.add_argument(\"-v\", dest=\"exclude\", action=\"append\", help=\"filter by specified string.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -a X86 -m 64\",\n        \"{0:s} -a X86 -m 32\",\n        \"{0:s} -a X86 -m 16\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"- F0 (LOCK prefix) is ignored\",\n        \"- F2/F3 (REPNE/REP prefix) are ignored\",\n        \"- 2E/36/3E/26/64/65 (CS/SS/DS/ES/FS/GS override prefix) are ignored\",\n        \"- 2E/3E (branch hint prefix) are ignored\",\n        \"- 66 (operand size prefix) is included\",\n        \"- 67 (address size prefix) is ignored\",\n        \"- 40-4F (REX prefix) are ignored\",\n        \"- C4/C5 (VEX prefix) are ignored\",\n        \"- 8F (XOP prefix) is ignored\",\n        \"- 62 (EVEX prefix) is ignored\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    cache = None\n\n    def listup_x86(self, arch, mode):\n        if self.cache:\n            return self.cache\n\n        DISP64 = \"1122334455667788\"\n        DISP32 = \"11223344\"\n        DISP16 = \"1122\"\n        DISP8 = \"11\"\n\n        @Cache.cache_this_session\n        def get_typical_bytecodes_modrm(reg_value):\n            mod_list = range(4)\n            assert 0 <= reg_value <= 7\n            reg_list = [reg_value]\n            rm_list = [0, 0b100] # The correct value is range(8), but it is reduced for speed.\n            sib_list = [0, 0b01001001] # The correct value is range(256), but it is reduced for speed.\n\n            bytecodes = []\n            for mod, reg, rm in itertools.product(mod_list, reg_list, rm_list):\n                modrm = \"{:02X}\".format((mod << 6) | (reg << 3) | rm)\n                if mod == 0b00:\n                    if rm == 0b101: # special case; [REG + disp32]\n                        bytecode = modrm + DISP32\n                    elif rm == 0b100: # use sib; [INDEX * SCALE + BASE]\n                        for sib in sib_list:\n                            bytecode = modrm + \"{:02X}\".format(sib)\n                    else: # [REG]\n                        bytecode = modrm\n                elif mod == 0b01:\n                    if rm == 0b100: # use sib; [INDEX * SCALE + BASE + disp8]\n                        bytecode = []\n                        for sib in sib_list:\n                            b = modrm + \"{:02X}\".format(sib) + DISP8\n                            bytecode.append(b)\n                    else: # [REG + disp8]\n                        bytecode = modrm + DISP8\n                elif mod == 0b10:\n                    if rm == 0b100: # use sib; [INDEX * SCALE + BASE + disp32]\n                        bytecode = []\n                        for sib in sib_list:\n                            b = modrm + \"{:02X}\".format(sib) + DISP32\n                            bytecode.append(b)\n                    else: # [REG + disp32]\n                        bytecode = modrm + DISP32\n                elif mod == 0b11: # REG\n                    bytecode = modrm\n                if isinstance(bytecode, list):\n                    bytecodes.extend(bytecode)\n                else:\n                    bytecodes.append(bytecode)\n            return bytecodes\n\n        def get_typical_bytecodes(opcodes):\n            bytecodes = []\n            for operand in opcodes.split():\n                if operand in [\"ib\", \"cb\"]:\n                    bytecode = [DISP8]\n                elif operand in [\"iw\", \"cw\"]:\n                    bytecode = [DISP16]\n                elif operand in [\"id\", \"cd\"]:\n                    bytecode = [DISP32]\n                elif operand in [\"iq\"]:\n                    bytecode = [DISP64]\n                elif operand in [\"/0\", \"/1\", \"/2\", \"/3\", \"/4\", \"/5\", \"/6\", \"/7\"]:\n                    bytecode = get_typical_bytecodes_modrm(int(operand[1]))\n                elif operand == \"/r\":\n                    bytecode = get_typical_bytecodes_modrm(0)\n                elif operand.endswith((\"+r\", \"+i\")):\n                    b = int(operand.split(\"+\")[0], 16)\n                    bytecode = [\"{:02X}\".format(b + x) for x in range(8)]\n                else:\n                    bytecode = [operand]\n                bytecodes.append(bytecode)\n            return [\"\".join(b) for b in itertools.product(*bytecodes)]\n\n        def load_x86_json():\n            x86data_js = os.path.join(GEF_TEMP_DIR, \"x86data.js\")\n            if os.path.exists(x86data_js) and os.path.getsize(x86data_js) > 0:\n                x86 = open(x86data_js, \"rb\").read()\n            else:\n                url = \"https://raw.githubusercontent.com/bata24/gef/dev/asmdb/x86data.js\"\n                x86 = http_get(url)\n                if x86 is None:\n                    err(\"Connection timed out: {:s}\".format(url))\n                    return None\n                open(x86data_js, \"wb\").write(x86)\n\n            x86 = x86.split(b\"// ${JSON:BEGIN}\")[1].split(b\"// ${JSON:END}\")[0]\n            return json.loads(x86)\n\n        # load capstone\n        capstone = sys.modules[\"capstone\"]\n        try:\n            cs = capstone.Cs(arch, mode)\n        except capstone.CsError:\n            err(\"CsError\")\n            return None\n\n        # default instruction set\n        x86 = load_x86_json()\n        # manually added\n        x86_insns = x86[\"instructions\"]\n        # [opcode_str, unused, unused, opcodes, attr]\n        x86_insns.append([\"icebp\", \"\", \"\", \"F1\", \"Undocumented\"])\n        x86_insns.append([\"salc\", \"\", \"\", \"D6\", \"Undocumented\"])\n        #x86_insns.append([\"umov\", \"\", \"\", \"0F 10 /r\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"umov\", \"\", \"\", \"0F 11 /r\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"umov\", \"\", \"\", \"0F 12 /r\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"umov\", \"\", \"\", \"0F 13 /r\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"loadall\", \"\", \"\", \"0F 05\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"loadall\", \"\", \"\", \"0F 07\", \"Undocumented\"]) # used by another opcode\n        #x86_insns.append([\"xbts\", \"\", \"\", \"0F A6\", \"Undocumented\"]) # removed now\n        #x86_insns.append([\"ibts\", \"\", \"\", \"0F A7\", \"Undocumented\"]) # removed now\n\n        # parse it\n        valid_patterns = []\n        seen_patterns = []\n        for insn in x86_insns:\n            opcodes = insn[3]\n            attr = insn[4].split()\n\n            # filter ignore prefix pattern\n            if \"REX.W\" in opcodes.split():\n                continue\n            if \"VEX\" in opcodes.split()[0].split(\".\"):\n                continue\n            if \"EVEX\" in opcodes.split()[0].split(\".\"):\n                continue\n            if \"XOP\" in opcodes.split()[0].split(\".\"):\n                continue\n\n            # e.g., \"FF /2\" -> [\"FF10\", \"FF5011\", ...]\n            bytecodes = get_typical_bytecodes(opcodes)\n\n            # check it is valid or not\n            for hex_code in bytecodes:\n                # dup check\n                if hex_code in seen_patterns:\n                    continue\n                # disasm\n                code = bytes.fromhex(hex_code)\n                try:\n                    asm = cs.disasm(code, 0).__next__()\n                except StopIteration:\n                    continue\n                opstr = asm.mnemonic + \" \" + asm.op_str\n                # add\n                valid_patterns.append([hex_code, opstr, opcodes, attr])\n                seen_patterns.append(hex_code)\n\n        self.cache = valid_patterns\n        return valid_patterns\n\n    @parse_args\n    @ModuleLoader.load_capstone\n    @require_arch_set\n    def do_invoke(self, args):\n        if (args.arch, args.mode) == (None, None):\n            if is_alive():\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n                    arch=current_arch.arch, mode=current_arch.mode, endian=Endian.is_big_endian(),\n                )\n                arch_mode_s = \":\".join([current_arch.arch, current_arch.mode])\n                endian_s = \"big\" if Endian.is_big_endian() else \"little\"\n            else:\n                # if not alive, defaults to x86-64\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(arch=\"X86\", mode=\"64\", endian=False)\n                arch_mode_s = \"X86:64\"\n                endian_s = \"little\"\n        elif not args.arch:\n            err(\"An architecture (-a) must be provided\")\n            return\n        elif not args.mode:\n            err(\"A mode (-m) must be provided\")\n            return\n        elif args.arch in [\"SPARC\", \"S390X\", \"M68K\"] and args.big_endian is False:\n            # capstone gives no error so check here\n            err(\"A big endian flag (-e) must be provided\")\n            return\n        else:\n            try:\n                arch, mode = UnicornKeystoneCapstone.get_capstone_arch(\n                    arch=args.arch, mode=args.mode, endian=args.big_endian,\n                )\n                arch_mode_s = \":\".join([args.arch, args.mode])\n                endian_s = \"big\" if args.big_endian else \"little\"\n            except AttributeError:\n                self.usage()\n                return\n\n        # list bytecode pattern\n        if arch_mode_s.startswith(\"X86:\"):\n            if endian_s == \"big\":\n                err(\"X86 is not big endian\")\n                return\n            patterns = self.listup_x86(arch, mode)\n        else:\n            err(\"Unsupported other than x86/x64\")\n            return\n\n        if patterns is None:\n            err(\"Failed to list entries\")\n            return\n\n        # filter and print\n        self.out = []\n        fmt = \"{:22s} {:70s} {:22s} {!s}\"\n        legend = [\"Hex code\", \"Assembly code\", \"Opcode\", \"Attributes\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for hex_code, opstr, opcodes, attr in patterns:\n            # byte length filter\n            if args.nbyte is not None and args.nbyte * 2 != len(hex_code):\n                continue\n\n            # keyword filter\n            line = \"{:22s} {:70s} {:22s} {!s}\".format(hex_code, opstr, opcodes, \",\".join(attr))\n            if args.include and any(f not in line for f in args.include):\n                continue\n            if args.exclude and any(f in line for f in args.exclude):\n                continue\n\n            # not filtered\n            self.out.append(line)\n\n        gef_print(\"\\n\".join(self.out), less=not args.no_pager)\n        return\n\n\n@register_command\nclass ProcessSearchCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display a smart list of processes.\"\"\"\n\n    _cmdline_ = \"ps\"\n    _category_ = \"02-a. Process Information - General\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"pattern\", metavar=\"REGEX_PATTERN\", nargs=\"?\", help=\"filter by regex.\")\n    parser.add_argument(\"-a\", \"--attach\", type=int, help=\"attach it.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"include kernel thread, socat, grep, gdb, sshd, bash, systemd, etc.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} ./a.out\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def get_processes(self):\n        output = GefUtil.gef_execute_external([GefUtil.which(\"ps\"), \"auxww\"], as_list=True)\n        names = [x.lower().replace(\"%\", \"\") for x in output[0].split()]\n\n        for line in output[1:]:\n            fields = line.split()\n            t = {}\n\n            for i, name in enumerate(names):\n                if i == len(names) - 1:\n                    t[name] = \" \".join(fields[i:])\n                else:\n                    t[name] = fields[i]\n            yield t\n        return\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.pattern:\n            pattern = re.compile(args.pattern)\n        else:\n            pattern = re.compile(\"^.*$\")\n\n        self.out = []\n        for process in self.get_processes():\n            pid = int(process[\"pid\"])\n            command = process[\"command\"]\n            process[\"user\"] = process[\"user\"].ljust(8)\n\n            if not re.search(pattern, command):\n                continue\n\n            if not args.verbose:\n                if command.startswith(\"[\") and command.endswith(\"]\"): # kernel thread\n                    continue\n\n                skip_list = [\n                    # common\n                    \"socat \",\n                    \"grep \",\n                    \"gdb \",\n                    \"gdb-multiarch\",\n                    \"-bash\",\n                    \"sshd:\",\n                    \"ssh-agent \",\n                    # VMware tools\n                    \"vmhgfs-fuse\",\n                    \"vmware-vmblock-fuse\",\n                    \"fusermount3\",\n                    # system service\n                    \"avahi-daemon:\",\n                    \"@dbus-daemon\",\n                    \"(sd-pam)\",\n                    \"gjs \",\n                    \"gdm-session-worker\",\n                    \"cupsd \",\n                    \"cups-browsed \",\n                    # common path\n                    (\"/bin/\", \"/usr/bin/\"),\n                    (\"/sbin/\", \"/usr/sbin/\"),\n                    (\"/lib/\", \"/usr/lib/\"),\n                    \"/usr/libexec/\",\n                    \"/snap/\",\n                    \"/var/lib/pcp/pmdas\",\n                ]\n                if any(command.startswith(x) for x in skip_list):\n                    continue\n\n            if args.attach:\n                if args.attach == pid:\n                    ok(\"Attaching to process='{:s}' pid={:d}\".format(process[\"command\"], pid))\n                    gdb.execute(\"attach {:d}\".format(pid))\n                    return\n\n            line = [process[i] for i in (\"pid\", \"user\", \"cpu\", \"mem\", \"tty\", \"command\")]\n            self.out.append(\"\\t\".join(line))\n\n        self.print_output()\n        return\n\n\n@register_command\nclass ElfInfoCommand(GenericCommand):\n    \"\"\"Display a limited subset of ELF header information.\"\"\"\n\n    _cmdline_ = \"elf-info\"\n    _category_ = \"02-a. Process Information - General\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-e\", \"--use-readelf\", action=\"store_true\", help=\"use readelf.\")\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-f\", \"--file\", help=\"the file path to parse.\")\n    parser.add_argument(\"-a\", \"--address\", type=AddressUtil.parse_address,\n                        help=\"the memory address to parse.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"dump the content of each section.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                    # parse binary itself\",\n        \"{0:s} -f /bin/ls         # parse binary\",\n        \"{0:s} -f /bin/ls -r      # parse remote binary\",\n        \"{0:s} -a 0x555555554000  # parse memory\",\n        \"{0:s} -e -f /bin/ls      # show `readelf -a FILE | less`\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    classes = {\n        Elf.ELF_CLASS_NONE : \"Unknown\",\n        Elf.ELF_32_BITS    : \"32-bit\",\n        Elf.ELF_64_BITS    : \"64-bit\",\n    }\n\n    endianness = {\n        Elf.ELF_DATA_NONE : \"Unknown\",\n        Elf.LITTLE_ENDIAN : \"Little-Endian\",\n        Elf.BIG_ENDIAN    : \"Big-Endian\",\n    }\n\n    osabis = {\n        Elf.OSABI_SYSTEMV    : \"UNIX System V ABI\",\n        Elf.OSABI_HPUX       : \"Hewlett-Packard HP-UX\",\n        Elf.OSABI_NETBSD     : \"NetBSD\",\n        Elf.OSABI_LINUX      : \"GNU Linux\",\n        Elf.OSABI_HURD       : \"GNU Hurd\",\n        Elf.OSABI_86OPEN     : \"86Open Common IA32 ABI\",\n        Elf.OSABI_SOLARIS    : \"Sun Solaris\",\n        Elf.OSABI_AIX        : \"IBM AIX\",\n        Elf.OSABI_IRIX       : \"SGI IRIX\",\n        Elf.OSABI_FREEBSD    : \"FreeBSD\",\n        Elf.OSABI_TRU64      : \"Compaq TRU64 UNIX\",\n        Elf.OSABI_MODESTO    : \"Novell Modesto\",\n        Elf.OSABI_OPENBSD    : \"OpenBSD\",\n        Elf.OSABI_OPENVMS    : \"OpenVMS\",\n        Elf.OSABI_NSK        : \"Hewlett-Packard Non-Stop Kernel\",\n        Elf.OSABI_AROS       : \"Amiga Research OS\",\n        Elf.OSABI_FENIXOS    : \"The FenixOS highly scalable multi-core OS\",\n        Elf.OSABI_CLOUDABI   : \"Nuxi CloudABI\",\n        Elf.OSABI_OPENVOS    : \"Stratus Technologies OpenVOS\",\n        Elf.OSABI_ARM_AEABI  : \"ARM EABI\",\n        Elf.OSABI_ARM        : \"ARM\",\n        Elf.OSABI_STANDALONE : \"Standalone (embedded) application\",\n    }\n\n    types = {\n        Elf.ET_NONE : \"No file type\",\n        Elf.ET_REL  : \"Relocatable\",\n        Elf.ET_EXEC : \"Executable\",\n        Elf.ET_DYN  : \"Shared\",\n        Elf.ET_CORE : \"Core\",\n    }\n\n    machines = {\n        Elf.EM_NONE                  : \"No machine\",\n        Elf.EM_M32                   : \"AT&T WE 32100\",\n        Elf.EM_SPARC                 : \"SUN SPARC\",\n        Elf.EM_386                   : \"Intel 80386\",\n        Elf.EM_68K                   : \"Motorola m68k family\",\n        Elf.EM_88K                   : \"Motorola m88k family\",\n        Elf.EM_IAMCU                 : \"Intel MCU\",\n        Elf.EM_860                   : \"Intel 80860\",\n        Elf.EM_MIPS                  : \"MIPS R3000 big-endian\",\n        Elf.EM_S370                  : \"IBM System/370 Processor\",\n        Elf.EM_MIPS_RS3_LE           : \"MIPS RS3000 Little-endian\",\n        Elf.EM_PARISC                : \"Hewlett-Packard PA-RISC\",\n        Elf.EM_VPP500                : \"Fujitsu VPP500\",\n        Elf.EM_SPARC32PLUS           : \"Enhanced instruction set SPARC\",\n        Elf.EM_960                   : \"Intel 80960\",\n        Elf.EM_PPC                   : \"PowerPC\",\n        Elf.EM_PPC64                 : \"64-bit PowerPC\",\n        Elf.EM_S390                  : \"IBM System/390 Processor\",\n        Elf.EM_SPU                   : \"IBM SPU/SPC\",\n        Elf.EM_V800                  : \"NEC V800\",\n        Elf.EM_FR20                  : \"Fujitsu FR20\",\n        Elf.EM_RH32                  : \"TRW RH-32\",\n        Elf.EM_RCE                   : \"Motorola RCE\",\n        Elf.EM_ARM                   : \"ARM 32-bit architecture (AARCH32)\",\n        Elf.EM_ALPHA                 : \"Digital Alpha\",\n        Elf.EM_SH                    : \"Hitachi SH\",\n        Elf.EM_SPARCV9               : \"SPARC Version 9\",\n        Elf.EM_TRICORE               : \"Siemens TriCore embedded processor\",\n        Elf.EM_ARC                   : \"Argonaut RISC Core, Argonaut Technologies Inc.\",\n        Elf.EM_H8_300                : \"Hitachi H8/300\",\n        Elf.EM_H8_300H               : \"Hitachi H8/300H\",\n        Elf.EM_H8S                   : \"Hitachi H8S\",\n        Elf.EM_H8_500                : \"Hitachi H8/500\",\n        Elf.EM_IA_64                 : \"Intel IA-64 processor architecture\",\n        Elf.EM_MIPS_X                : \"Stanford MIPS-X\",\n        Elf.EM_COLDFIRE              : \"Motorola ColdFire\",\n        Elf.EM_68HC12                : \"Motorola M68HC12\",\n        Elf.EM_MMA                   : \"Fujitsu MMA Multimedia Accelerator\",\n        Elf.EM_PCP                   : \"Siemens PCP\",\n        Elf.EM_NCPU                  : \"Sony nCPU embedded RISC processor\",\n        Elf.EM_NDR1                  : \"Denso NDR1 microprocessor\",\n        Elf.EM_STARCORE              : \"Motorola Star*Core processor\",\n        Elf.EM_ME16                  : \"Toyota ME16 processor\",\n        Elf.EM_ST100                 : \"STMicroelectronics ST100 processor\",\n        Elf.EM_TINYJ                 : \"Advanced Logic Corp. TinyJ embedded processor family\",\n        Elf.EM_X86_64                : \"AMD x86-64 architecture\",\n        Elf.EM_PDSP                  : \"Sony DSP Processor\",\n        Elf.EM_PDP10                 : \"Digital Equipment Corp. PDP-10\",\n        Elf.EM_PDP11                 : \"Digital Equipment Corp. PDP-11\",\n        Elf.EM_FX66                  : \"Siemens FX66 microcontroller\",\n        Elf.EM_ST9PLUS               : \"STMicroelectronics ST9+ 8/16 bit microcontroller\",\n        Elf.EM_ST7                   : \"STMicroelectronics ST7 8-bit microcontroller\",\n        Elf.EM_68HC16                : \"Motorola MC68HC16 Microcontroller\",\n        Elf.EM_68HC11                : \"Motorola MC68HC11 Microcontroller\",\n        Elf.EM_68HC08                : \"Motorola MC68HC08 Microcontroller\",\n        Elf.EM_68HC05                : \"Motorola MC68HC05 Microcontroller\",\n        Elf.EM_SVX                   : \"Silicon Graphics SVx\",\n        Elf.EM_ST19                  : \"STMicroelectronics ST19 8-bit microcontroller\",\n        Elf.EM_VAX                   : \"Digital VAX\",\n        Elf.EM_CRIS                  : \"Axis Communications 32-bit embedded processor\",\n        Elf.EM_JAVELIN               : \"Infineon Technologies 32-bit embedded processor\",\n        Elf.EM_FIREPATH              : \"Element 14 64-bit DSP Processor\",\n        Elf.EM_ZSP                   : \"LSI Logic 16-bit DSP Processor\",\n        Elf.EM_MMIX                  : \"Donald Knuth's educational 64-bit processor\",\n        Elf.EM_HUANY                 : \"Harvard University machine-independent object files\",\n        Elf.EM_PRISM                 : \"SiTera Prism\",\n        Elf.EM_AVR                   : \"Atmel AVR 8-bit microcontroller\",\n        Elf.EM_FR30                  : \"Fujitsu FR30\",\n        Elf.EM_D10V                  : \"Mitsubishi D10V\",\n        Elf.EM_D30V                  : \"Mitsubishi D30V\",\n        Elf.EM_V850                  : \"NEC v850\",\n        Elf.EM_M32R                  : \"Mitsubishi M32R\",\n        Elf.EM_MN10300               : \"Matsushita MN10300\",\n        Elf.EM_MN10200               : \"Matsushita MN10200\",\n        Elf.EM_PJ                    : \"picoJava\",\n        Elf.EM_OPENRISC              : \"OpenRISC 32-bit embedded processor\",\n        Elf.EM_ARC_COMPACT           : \"ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)\",\n        Elf.EM_XTENSA                : \"Tensilica Xtensa Architecture\",\n        Elf.EM_VIDEOCORE             : \"Alphamosaic VideoCore processor\",\n        Elf.EM_TMM_GPP               : \"Thompson Multimedia General Purpose Processor\",\n        Elf.EM_NS32K                 : \"National Semiconductor 32000 series\",\n        Elf.EM_TPC                   : \"Tenor Network TPC processor\",\n        Elf.EM_SNP1K                 : \"Trebia SNP 1000 processor\",\n        Elf.EM_ST200                 : \"STMicroelectronics ST200 microcontroller\",\n        Elf.EM_IP2K                  : \"Ubicom IP2xxx microcontroller family\",\n        Elf.EM_MAX                   : \"MAX Processor\",\n        Elf.EM_CR                    : \"National Semiconductor CompactRISC microprocessor\",\n        Elf.EM_F2MC16                : \"Fujitsu F2MC16\",\n        Elf.EM_MSP430                : \"Texas Instruments embedded microcontroller msp430\",\n        Elf.EM_BLACKFIN              : \"Analog Devices Blackfin (DSP) processor\",\n        Elf.EM_SE_C33                : \"S1C33 Family of Seiko Epson processors\",\n        Elf.EM_SEP                   : \"Sharp embedded microprocessor\",\n        Elf.EM_ARCA                  : \"Arca RISC Microprocessor\",\n        Elf.EM_UNICORE               : \"Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University\",\n        Elf.EM_EXCESS                : \"eXcess: 16/32/64-bit configurable embedded CPU\",\n        Elf.EM_DXP                   : \"Icera Semiconductor Inc. Deep Execution Processor\",\n        Elf.EM_ALTERA_NIOS2          : \"Altera Nios II soft-core processor\",\n        Elf.EM_CRX                   : \"National Semiconductor CompactRISC CRX microprocessor\",\n        Elf.EM_XGATE                 : \"Motorola XGATE embedded processor\",\n        Elf.EM_C166                  : \"Infineon C16x/XC16x processor\",\n        Elf.EM_M16C                  : \"Renesas M16C series microprocessors\",\n        Elf.EM_DSPIC30F              : \"Microchip Technology dsPIC30F Digital Signal Controller\",\n        Elf.EM_CE                    : \"Freescale Communication Engine RISC core\",\n        Elf.EM_M32C                  : \"Renesas M32C series microprocessors\",\n        Elf.EM_TSK3000               : \"Altium TSK3000 core\",\n        Elf.EM_RS08                  : \"Freescale RS08 embedded processor\",\n        Elf.EM_SHARC                 : \"Analog Devices SHARC family of 32-bit DSP processors\",\n        Elf.EM_ECOG2                 : \"Cyan Technology eCOG2 microprocessor\",\n        Elf.EM_SCORE7                : \"Sunplus S+core7 RISC processor\",\n        Elf.EM_DSP24                 : \"New Japan Radio (NJR) 24-bit DSP Processor\",\n        Elf.EM_VIDEOCORE3            : \"Broadcom VideoCore III processor\",\n        Elf.EM_LATTICEMICO32         : \"RISC processor for Lattice FPGA architecture\",\n        Elf.EM_SE_C17                : \"Seiko Epson C17 family\",\n        Elf.EM_TI_C6000              : \"The Texas Instruments TMS320C6000 DSP family\",\n        Elf.EM_TI_C2000              : \"The Texas Instruments TMS320C2000 DSP family\",\n        Elf.EM_TI_C5500              : \"The Texas Instruments TMS320C55x DSP family\",\n        Elf.EM_TI_ARP32              : \"Texas Instruments Application Specific RISC Processor, 32bit fetch\",\n        Elf.EM_TI_PRU                : \"Texas Instruments Programmable Realtime Unit\",\n        Elf.EM_MMDSP_PLUS            : \"STMicroelectronics 64bit VLIW Data Signal Processor\",\n        Elf.EM_CYPRESS_M8C           : \"Cypress M8C microprocessor\",\n        Elf.EM_R32C                  : \"Renesas R32C series microprocessors\",\n        Elf.EM_TRIMEDIA              : \"NXP Semiconductors TriMedia architecture family\",\n        Elf.EM_QDSP6                 : \"QUALCOMM DSP6 Processor\",\n        Elf.EM_8051                  : \"Intel 8051 and variants\",\n        Elf.EM_STXP7X                : \"STMicroelectronics STxP7x family of configurable and extensible RISC processors\",\n        Elf.EM_NDS32                 : \"Andes Technology compact code size embedded RISC processor family\",\n        Elf.EM_ECOG1                 : \"Cyan Technology eCOG1X family\",\n        Elf.EM_ECOG1X                : \"Cyan Technology eCOG1X family\",\n        Elf.EM_MAXQ30                : \"Dallas Semiconductor MAXQ30 Core Micro-controllers\",\n        Elf.EM_XIMO16                : \"New Japan Radio (NJR) 16-bit DSP Processor\",\n        Elf.EM_MANIK                 : \"M2000 Reconfigurable RISC Microprocessor\",\n        Elf.EM_CRAYNV2               : \"Cray Inc. NV2 vector architecture\",\n        Elf.EM_RX                    : \"Renesas RX family\",\n        Elf.EM_METAG                 : \"Imagination Technologies META processor architecture\",\n        Elf.EM_MCST_ELBRUS           : \"MCST Elbrus general purpose hardware architecture\",\n        Elf.EM_ECOG16                : \"Cyan Technology eCOG16 family\",\n        Elf.EM_CR16                  : \"National Semiconductor CompactRISC CR16 16-bit microprocessor\",\n        Elf.EM_ETPU                  : \"Freescale Extended Time Processing Unit\",\n        Elf.EM_SLE9X                 : \"Infineon Technologies SLE9X core\",\n        Elf.EM_L10M                  : \"Intel L10M\",\n        Elf.EM_K10M                  : \"Intel K10M\",\n        182                          : \"Reserved for future Intel use\",\n        Elf.EM_AARCH64               : \"ARM 64-bit architecture (AARCH64)\",\n        184                          : \"Reserved for future ARM use\",\n        Elf.EM_AVR32                 : \"Atmel Corporation 32-bit microprocessor family\",\n        Elf.EM_STM8                  : \"STMicroeletronics STM8 8-bit microcontroller\",\n        Elf.EM_TILE64                : \"Tilera TILE64 multicore architecture family\",\n        Elf.EM_TILEPRO               : \"Tilera TILEPro multicore architecture family\",\n        Elf.EM_MICROBLAZE            : \"Xilinx MicroBlaze 32-bit RISC soft processor core\",\n        Elf.EM_CUDA                  : \"NVIDIA CUDA architecture\",\n        Elf.EM_TILEGX                : \"Tilera TILE-Gx multicore architecture family\",\n        Elf.EM_CLOUDSHIELD           : \"CloudShield architecture family\",\n        Elf.EM_COREA_1ST             : \"KIPO-KAIST Core-A 1st generation processor family\",\n        Elf.EM_COREA_2ND             : \"KIPO-KAIST Core-A 2nd generation processor family\",\n        Elf.EM_ARCV2                 : \"Synopsys ARCompact V2\", # codespell:ignore\n        Elf.EM_OPEN8                 : \"Open8 8-bit RISC soft processor core\",\n        Elf.EM_RL78                  : \"Renesas RL78 family\",\n        Elf.EM_VIDEOCORE5            : \"Broadcom VideoCore V processor\",\n        Elf.EM_78KOR                 : \"Renesas 78KOR family\",\n        Elf.EM_56800EX               : \"Freescale 56800EX Digital Signal Controller (DSC)\",\n        Elf.EM_BA1                   : \"Beyond BA1 CPU architecture\",\n        Elf.EM_BA2                   : \"Beyond BA2 CPU architecture\",\n        Elf.EM_XCORE                 : \"XMOS xCORE processor family\",\n        Elf.EM_MCHP_PIC              : \"Microchip 8-bit PIC(r) family\",\n        Elf.EM_INTELGT               : \"Intel Graphics Technology\",\n        Elf.EM_INTEL206              : \"Reserved by Intel\",\n        Elf.EM_INTEL207              : \"Reserved by Intel\",\n        Elf.EM_INTEL208              : \"Reserved by Intel\",\n        Elf.EM_INTEL209              : \"Reserved by Intel\",\n        Elf.EM_KM32                  : \"KM211 KM32 32-bit processor\",\n        Elf.EM_KMX32                 : \"KM211 KMX32 32-bit processor\",\n        Elf.EM_KMX16                 : \"KM211 KMX16 16-bit processor\",\n        Elf.EM_KMX8                  : \"KM211 KMX8 8-bit processor\",\n        Elf.EM_KVARC                 : \"KM211 KVARC processor\",\n        Elf.EM_CDP                   : \"Paneve CDP architecture family\",\n        Elf.EM_COGE                  : \"Cognitive Smart Memory Processor\",\n        Elf.EM_COOL                  : \"Bluechip Systems CoolEngine\",\n        Elf.EM_NORC                  : \"Nanoradio Optimized RISC\",\n        Elf.EM_CSR_KALIMBA           : \"CSR Kalimba architecture family\",\n        Elf.EM_Z80                   : \"Zilog Z80\",\n        Elf.EM_VISIUM                : \"Controls and Data Services VISIUMcore processor\",\n        Elf.EM_FT32                  : \"FTDI Chip FT32 high performance 32-bit RISC architecture\",\n        Elf.EM_MOXIE                 : \"Moxie processor family\",\n        Elf.EM_AMDGPU                : \"AMD GPU architecture\",\n        Elf.EM_RISCV                 : \"RISC-V\",\n        Elf.EM_LANAI                 : \"Lanai 32-bit processor\",\n        Elf.EM_CEVA                  : \"CEVA Processor Architecture Family\",\n        Elf.EM_CEVA_X2               : \"CEVA X2 Processor Family\",\n        Elf.EM_BPF                   : \"Linux BPF - in-kernel virtual machine\",\n        Elf.EM_GRAPHCORE_IPU         : \"Graphcore Intelligent Processing Unit\",\n        Elf.EM_IMG1                  : \"Imagination Technologies\",\n        Elf.EM_NFP                   : \"Netronome Flow Processor\",\n        Elf.EM_VE                    : \"NEC Vector Engine\",\n        Elf.EM_CSKY                  : \"C-SKY processor family\",\n        Elf.EM_ARC_COMPACT3_64       : \"Synopsys ARCv2.3 64-bit\", # codespell:ignore\n        Elf.EM_MCS6502               : \"MOS Technology MCS 6502 processor\",\n        Elf.EM_ARC_COMPACT3          : \"Synopsys ARCv2.3 32-bit\", # codespell:ignore\n        Elf.EM_KVX                   : \"Kalray VLIW core of the MPPA processor family\",\n        Elf.EM_65816                 : \"WDC 65816/65C816\",\n        Elf.EM_LOONGARCH             : \"LoongArch\",\n        Elf.EM_KF32                  : \"ChipON KungFu32\",\n        Elf.EM_U16_U8CORE            : \"LAPIS nX-U16/U8\",\n        Elf.EM_TACHYUM               : \"Tachyum\",\n        Elf.EM_56800EF               : \"NXP 56800EF Digital Signal Controller (DSC)\",\n\n        Elf.EM_AVR_UNOFFICIAL        : \"AVR (unofficial)\",\n        Elf.EM_MSP430_UNOFFICIAL     : \"MSP430 (unofficial)\",\n        Elf.EM_EPIPHANY_UNOFFICIAL   : \"Adapteva Epiphany (unofficial)\",\n        Elf.EM_AVR32_UNOFFICIAL      : \"Atmel AVR32 (unofficial)\",\n        Elf.EM_MT_UNOFFICIAL         : \"Morpho MT (unofficial)\",\n        Elf.EM_FR30_UNOFFICIAL       : \"FR30 (unofficial)\",\n        Elf.EM_OPENRISC_OLD          : \"OpenRISC (obsolete)\",\n        Elf.EM_WEBASSEMBLY           : \"Web Assembly binaries (unofficial)\",\n        Elf.EM_C166_UNOFFICIAL       : \"Infineon C166 (unofficial)\",\n        Elf.EM_S12Z                  : \"Freescale S12Z\",\n        Elf.EM_FRV_UNOFFICIAL        : \"Cygnus FR-V (unofficial)\",\n        Elf.EM_DLX_UNOFFICIAL        : \"DLX (unofficial)\",\n        Elf.EM_D10V_UNOFFICIAL       : \"Cygnus D10V (unofficial)\",\n        Elf.EM_D30V_UNOFFICIAL       : \"Cygnus D30V (unofficial)\",\n        Elf.EM_IP2K_UNOFFICIAL       : \"Ubicom IP2xxx (unofficial)\",\n        Elf.EM_OPENRISC_OLD2         : \"OpenRISC (obsolete)\",\n        Elf.EM_PPC_UNOFFICIAL        : \"Cygnus PowerPC (unofficial)\",\n        Elf.EM_ALPHA_UNOFFICIAL      : \"Digital Alpha (unofficial)\",\n        Elf.EM_M32R_UNOFFICIAL       : \"Cygnus M32R (unofficial)\",\n        Elf.EM_V850_UNOFFICIAL       : \"Cygnus V859 (unofficial)\",\n        Elf.EM_S390_OLD              : \"IBM S/390 (obsolete)\",\n        Elf.EM_XTENSA_UNOFFICIAL     : \"Old Xtensa (unofficial)\",\n        Elf.EM_XSTORMY_UNOFFICIAL    : \"xstormy16 (unofficial)\",\n        Elf.EM_MICROBLAZE_UNOFFICIAL : \"Old MicroBlaze (unofficial)\",\n        Elf.EM_MN10300_UNOFFICIAL    : \"Cygnus MN10300 (unofficial)\",\n        Elf.EM_MN10200_UNOFFICIAL    : \"Cygnus MN10200 (unofficial)\",\n        Elf.EM_MEP_UNOFFICIAL        : \"Toshiba MeP (unofficial)\",\n        Elf.EM_M32C_UNOFFICIAL       : \"Renesas M32C (unofficial)\",\n        Elf.EM_IQ2000_UNOFFICIAL     : \"Vitesse IQ2000 (unofficial)\",\n        Elf.EM_NIOS_UNOFFICIAL       : \"NIOS (unofficial)\",\n        Elf.EM_MOXIE_UNOFFICIAL      : \"Moxie (unofficial)\",\n    }\n\n    versions = {\n        Elf.EV_NONE    : \"Invalid version\",\n        Elf.EV_CURRENT : \"Current version\",\n    }\n\n    ptype = {\n        Elf.Phdr.PT_NULL          : \"NULL\",\n        Elf.Phdr.PT_LOAD          : \"LOAD\",\n        Elf.Phdr.PT_DYNAMIC       : \"DYNAMIC\",\n        Elf.Phdr.PT_INTERP        : \"INTERP\",\n        Elf.Phdr.PT_NOTE          : \"NOTE\",\n        Elf.Phdr.PT_SHLIB         : \"SHLIB\",\n        Elf.Phdr.PT_PHDR          : \"PHDR\",\n        Elf.Phdr.PT_TLS           : \"TLS\",\n        Elf.Phdr.PT_GNU_EH_FRAME  : \"GNU_EH_FLAME\",\n        Elf.Phdr.PT_GNU_STACK     : \"GNU_STACK\",\n        Elf.Phdr.PT_GNU_RELRO     : \"GNU_RELRO\",\n        Elf.Phdr.PT_GNU_PROPERTY  : \"GNU_PROPERTY\",\n        Elf.Phdr.PT_GNU_SFRAME    : \"SFRAME\",\n        Elf.Phdr.PT_SUNWBSS       : \"SUNWBSS\",\n        Elf.Phdr.PT_SUNWSTACK     : \"SUNWSTACK\",\n    }\n\n    pflags = {\n        0                                             : \"---\",\n        Elf.Phdr.PF_X                                 : \"--X\",\n        Elf.Phdr.PF_W                                 : \"-W-\",\n        Elf.Phdr.PF_R                                 : \"R--\",\n        Elf.Phdr.PF_W | Elf.Phdr.PF_X                 : \"-WX\",\n        Elf.Phdr.PF_R | Elf.Phdr.PF_X                 : \"R-X\",\n        Elf.Phdr.PF_R | Elf.Phdr.PF_W                 : \"RW-\",\n        Elf.Phdr.PF_R | Elf.Phdr.PF_W | Elf.Phdr.PF_X : \"RWX\",\n    }\n\n    stype = {\n        Elf.Shdr.SHT_NULL                     : \"NULL\",\n        Elf.Shdr.SHT_PROGBITS                 : \"PROGBITS\",\n        Elf.Shdr.SHT_SYMTAB                   : \"SYMTAB\",\n        Elf.Shdr.SHT_STRTAB                   : \"STRTAB\",\n        Elf.Shdr.SHT_RELA                     : \"RELA\",\n        Elf.Shdr.SHT_HASH                     : \"HASH\",\n        Elf.Shdr.SHT_DYNAMIC                  : \"DYNAMIC\",\n        Elf.Shdr.SHT_NOTE                     : \"NOTE\",\n        Elf.Shdr.SHT_NOBITS                   : \"NOBITS\",\n        Elf.Shdr.SHT_REL                      : \"REL\",\n        Elf.Shdr.SHT_SHLIB                    : \"SHLIB\",\n        Elf.Shdr.SHT_DYNSYM                   : \"DYNSYM\",\n        Elf.Shdr.SHT_INIT_ARRAY               : \"INIT_ARRAY\",\n        Elf.Shdr.SHT_FINI_ARRAY               : \"FINI_ARRAY\",\n        Elf.Shdr.SHT_PREINIT_ARRAY            : \"PREINIT_ARRAY\",\n        Elf.Shdr.SHT_GROUP                    : \"GROUP\",\n        Elf.Shdr.SHT_SYMTAB_SHNDX             : \"SYMTAB_SHNDX\",\n        Elf.Shdr.SHT_RELR                     : \"RELR\",\n        Elf.Shdr.SHT_ANDROID_REL              : \"ANDROID_REL\",\n        Elf.Shdr.SHT_ANDROID_RELA             : \"ANDROID_RELA\",\n        Elf.Shdr.SHT_GNU_INCREMENTAL_INPUTS   : \"GNU_INCREMENTAL_INPUTS\",\n        Elf.Shdr.SHT_LLVM_ODRTAB              : \"LLVM_ODRTAB\",\n        Elf.Shdr.SHT_LLVM_LINKER_OPTIONS      : \"LLVM_LINKER_OPTIONS\",\n        Elf.Shdr.SHT_LLVM_CALL_GRAPH_PROFILE  : \"LLVM_CALL_GRAPH_PROFILE\",\n        Elf.Shdr.SHT_LLVM_ADDRSIG             : \"LLVM_ADDRSIG\",\n        Elf.Shdr.SHT_LLVM_DEPENDENT_LIBRARIES : \"LLVM_DEPENDENT_LIBRARIES\",\n        Elf.Shdr.SHT_LLVM_SYMPART             : \"LLVM_SYMPART\",\n        Elf.Shdr.SHT_LLVM_PART_EHDR           : \"LLVM_PART_EHDR\",\n        Elf.Shdr.SHT_LLVM_PART_PHDR           : \"LLVM_PART_PHDR\",\n        Elf.Shdr.SHT_LLVM_BB_ADDR_MAP_V0      : \"LLVM_BB_ADDR_MAP_V0\",\n        Elf.Shdr.SHT_LLVM_CALL_GRAPH_PROFILE  : \"LLVM_CALL_GRAPH_PROFILE\",\n        Elf.Shdr.SHT_LLVM_BB_ADDR_MAP         : \"LLVM_BB_ADDR_MAP\",\n        Elf.Shdr.SHT_LLVM_OFFLOADING          : \"LLVM_OFFLOADING\",\n        Elf.Shdr.SHT_LLVM_LTO                 : \"LLVM_LTO\",\n        Elf.Shdr.SHT_ANDROID_RELR             : \"ANDROID_RELR\",\n        Elf.Shdr.SHT_GNU_ATTRIBUTES           : \"GNU_ATTRIBUTES\",\n        Elf.Shdr.SHT_GNU_HASH                 : \"GNU_HASH\",\n        Elf.Shdr.SHT_GNU_LIBLIST              : \"GNU_LIBLIST\",\n        Elf.Shdr.SHT_CHECKSUM                 : \"CHECKSUM\",\n        Elf.Shdr.SHT_SUNW_move                : \"SUNW_move\",\n        Elf.Shdr.SHT_SUNW_COMDAT              : \"SUNW_COMDAT\",\n        Elf.Shdr.SHT_SUNW_syminfo             : \"SUNW_syminfo\",\n        Elf.Shdr.SHT_GNU_verdef               : \"GNU_verdef\",\n        Elf.Shdr.SHT_GNU_verneed              : \"GNU_verneed\",\n        Elf.Shdr.SHT_GNU_versym               : \"GNU_versym\",\n    }\n\n    def elf_info(self, elf, orig_filepath=None):\n        if elf.filename:\n            if orig_filepath:\n                filename = \"{:s} (remote: {:s})\".format(elf.filename, orig_filepath)\n            else:\n                filename = elf.filename\n        elif elf.addr is not None:\n            filename = \"{:#x}\".format(elf.addr)\n\n        magic_hex = \" \".join(slicer(struct.pack(\">I\", elf.e_magic).hex(), 2))\n        if Endian.is_big_endian():\n            magic_str = repr(p32(elf.e_magic).decode())\n        else:\n            magic_str = repr(p32(elf.e_magic).decode()[::-1])\n        data = [\n            (\"Magic\", \"{:s} ({:s})\".format(magic_hex, magic_str)),\n            (\"Class\", \"{:#x} - {:s}\".format(elf.e_class, self.classes[elf.e_class])),\n            (\"Endianness\", \"{:#x} - {:s}\".format(elf.e_endianness, self.endianness[elf.e_endianness])),\n            (\"ELF Version\", \"{:#x} - {:s}\".format(elf.e_eiversion, self.versions[elf.e_eiversion])),\n            (\"OS ABI\", \"{:#x} - {:s}\".format(elf.e_osabi, self.osabis[elf.e_osabi])),\n            (\"ABI Version\", \"{:#x}\".format(elf.e_abiversion)),\n            (\"Type\", \"{:#x} - {:s}\".format(elf.e_type, self.types[elf.e_type])),\n            (\"Machine\", \"{:#x} - {:s}\".format(elf.e_machine, self.machines.get(elf.e_machine, \"Unknown\"))),\n            (\"Version\", \"{:#x} - {:s}\".format(elf.e_version, self.versions[elf.e_version])),\n            (\"Entry point\", \"{:s}\".format(AddressUtil.format_address(elf.e_entry))),\n            (\"Program Header Table\", \"{:s}\".format(AddressUtil.format_address(elf.e_phoff))),\n            (\"Program Header Entry Size\", \"{0:d} ({0:#x})\".format(elf.e_phentsize)),\n            (\"Number of Program Headers\", \"{:d}\".format(elf.e_phnum)),\n            (\"Section Header Table\", \"{:s}\".format(AddressUtil.format_address(elf.e_shoff))),\n            (\"Section Header Entry Size\", \"{0:d} ({0:#x})\".format(elf.e_shentsize)),\n            (\"Number of Section Headers\", \"{:d}\".format(elf.e_shnum)),\n            (\"ELF Header Size\", \"{0:d} ({0:#x})\".format(elf.e_ehsize)),\n            (\"Section Header String Table Index\", \"{0:d} ({0:#x})\".format(elf.e_shstrndx)),\n            (\"Processor Specific Flags\", \"{:#x}\".format(elf.e_flags)),\n        ]\n\n        self.out.append(titlify(\"ELF Header - {:s}\".format(filename)))\n        for title, content in data:\n            self.out.append(\"{:<34s}: {}\".format(title, content))\n\n        self.out.append(titlify(\"Program Header - {:s}\".format(filename)))\n        self.phdr_info(elf)\n\n        self.out.append(titlify(\"Section Header - {:s}\".format(filename)))\n        self.shdr_info(elf)\n        return\n\n    def phdr_info(self, elf):\n        name_width = max([len(self.ptype.get(p.p_type, \"UNKNOWN\")) for p in elf.phdrs])\n\n        fmt = \"[{:>2s}] {:{:d}s} {:>12s} {:>12s} {:>12s} {:>12s} {:>12s} {:5s} {:>8s}\"\n        legend = [\n            \"#\", \"Type\", name_width, \"Offset\", \"Virtaddr\",\n            \"Physaddr\", \"FileSiz\", \"MemSiz\", \"Flags\", \"Align\",\n        ]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for i, p in enumerate(elf.phdrs):\n            p_type = self.ptype.get(p.p_type, \"UNKNOWN\")\n            p_flags = self.pflags.get(p.p_flags, \"???\")\n            fmt = \"[{:2d}] {:{:d}s} {:#12x} {:#12x} {:#12x} {:#12x} {:#12x} {:5s} {:#8x}\"\n            args = [\n                i, p_type, name_width, p.p_offset, p.p_vaddr,\n                p.p_paddr, p.p_filesz, p.p_memsz, p_flags, p.p_align,\n            ]\n            self.out.append(fmt.format(*args))\n        return\n\n    def shdr_info(self, elf):\n        if not elf.shdrs:\n            self.out.append(\"Not loaded\")\n            return\n\n        name_width = max([len(s.sh_name) for s in elf.shdrs])\n\n        fmt = \"[{:>2s}] {:{:d}s} {:>15s} {:>12s} {:>12s} {:>12s} {:>12s} {:>5s} {:>5s} {:>5s} {:>8s}\"\n        legend = [\"#\", \"Name\", name_width, \"Type\", \"Address\", \"Offset\", \"Size\", \"EntSiz\", \"Flags\", \"Link\", \"Info\", \"Align\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for i, s in enumerate(elf.shdrs):\n            sh_type = self.stype.get(s.sh_type, \"UNKNOWN\")\n            sh_flags = \"\"\n            if s.sh_flags & Elf.Shdr.SHF_WRITE:\n                sh_flags += \"W\"\n            if s.sh_flags & Elf.Shdr.SHF_ALLOC:\n                sh_flags += \"A\"\n            if s.sh_flags & Elf.Shdr.SHF_EXECINSTR:\n                sh_flags += \"X\"\n            if s.sh_flags & Elf.Shdr.SHF_MERGE:\n                sh_flags += \"M\"\n            if s.sh_flags & Elf.Shdr.SHF_STRINGS:\n                sh_flags += \"S\"\n            if s.sh_flags & Elf.Shdr.SHF_INFO_LINK:\n                sh_flags += \"I\"\n            if s.sh_flags & Elf.Shdr.SHF_LINK_ORDER:\n                sh_flags += \"L\"\n            if s.sh_flags & Elf.Shdr.SHF_OS_NONCONFORMING:\n                sh_flags += \"O\"\n            if s.sh_flags & Elf.Shdr.SHF_GROUP:\n                sh_flags += \"G\"\n            if s.sh_flags & Elf.Shdr.SHF_TLS:\n                sh_flags += \"T\"\n            if s.sh_flags & Elf.Shdr.SHF_EXCLUDE:\n                sh_flags += \"E\"\n            if s.sh_flags & Elf.Shdr.SHF_COMPRESSED:\n                sh_flags += \"C\"\n\n            fmt = \"[{:2d}] {:{:d}s} {:>15s} {:#12x} {:#12x} {:#12x} {:#12x} {:5s} {:#5x} {:#5x} {:#8x}\"\n            args = [\n                i, s.sh_name, name_width, sh_type, s.sh_addr, s.sh_offset, s.sh_size,\n                s.sh_entsize, sh_flags, s.sh_link, s.sh_info, s.sh_addralign,\n            ]\n            self.out.append(fmt.format(*args))\n\n            if self.args.verbose:\n                if s.sh_size > 0x1000: # heuristic value\n                    self.out.append(\"Skip because too large ({:#x} > 0x1000)\".format(s.sh_size))\n                else:\n                    fd = open(elf.filename, \"rb\")\n                    fd.seek(s.sh_offset, 0)\n                    section_data = fd.read(s.sh_size)\n                    self.out.append(hexdump(section_data, show_symbol=False, base=s.sh_offset))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        local_filepath = None\n        remote_filepath = None\n        tmp_filepath = None\n        self.out = []\n\n        # memory parse pattern\n        if args.address is not None:\n            try:\n                elf = Elf.get_elf(args.address)\n            except gdb.MemoryError:\n                err(\"Memory read error\")\n                return\n\n            if elf is None or not elf.is_valid():\n                err(\"Failed to parse ELF\")\n            else:\n                self.elf_info(elf)\n                gef_print(\"\\n\".join(self.out), less=not args.no_pager)\n            return\n\n        # file parse pattern\n        if args.remote:\n            if not is_remote_debug():\n                err(\"-r option is allowed only remote debug\")\n                return\n            if is_qemu_system():\n                err(\"-r option is unsupported under qemu-system\")\n                return\n\n            if args.file:\n                remote_filepath = args.file # if specified, assume it is remote\n            elif gdb.current_progspace().filename:\n                f = gdb.current_progspace().filename\n                if f.startswith(\"target:\"): # gdbserver\n                    f = f[7:]\n                remote_filepath = f\n            elif Pid.get_pid(remote=True):\n                remote_filepath = \"/proc/{:d}/exe\".format(Pid.get_pid(remote=True))\n            else:\n                err(\"File name could not be determined\")\n                return\n\n            data = Path.read_remote_file(remote_filepath, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                err(\"Failed to read remote filepath\")\n                return\n            tmp_fd, tmp_filepath = GefUtil.mkstemp(prefix=\"elf-info\", suffix=\".elf\")\n            os.fdopen(tmp_fd, \"wb\").write(data)\n            local_filepath = tmp_filepath\n            del data\n\n        elif args.file:\n            local_filepath = args.file\n\n        elif args.file is None:\n            if is_qemu_system():\n                err(\"Argument-less calls are unsupported under qemu-system\")\n                return\n            local_filepath = Path.get_filepath()\n\n        if local_filepath is None:\n            err(\"File name could not be determined\")\n            return\n\n        # readelf pattern\n        if args.use_readelf:\n            try:\n                readelf = GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n            except FileNotFoundError:\n                err(\"Could not find readelf\")\n                return\n            try:\n                less = GefUtil.which(\"less\")\n            except FileNotFoundError:\n                less = False\n            if args.no_pager or not less:\n                os.system(\"LANG=C {!r} -a --wide {!r}\".format(readelf, local_filepath))\n            else:\n                os.system(\"LANG=C {!r} -a --wide {!r} | {!r}\".format(readelf, local_filepath, less))\n            if tmp_filepath and os.path.exists(tmp_filepath):\n                os.unlink(tmp_filepath)\n            return\n\n        # self parse pattern\n        elf = Elf.get_elf(local_filepath)\n        if elf is None or not elf.is_valid():\n            err(\"Failed to parse ELF\")\n        else:\n            data = open(local_filepath, \"rb\").read()\n            self.out.append(\"size: {:d} bytes, sha1: {:s}\".format(len(data), hashlib.sha1(data).hexdigest()))\n            self.elf_info(elf, remote_filepath)\n            gef_print(\"\\n\".join(self.out), less=not args.no_pager)\n\n        if tmp_filepath and os.path.exists(tmp_filepath):\n            os.unlink(tmp_filepath)\n        return\n\n\n@register_command\nclass ChecksecCommand(GenericCommand):\n    \"\"\"Check the security properties of the current executable or passed as argument.\"\"\"\n\n    _cmdline_ = \"checksec\"\n    _category_ = \"02-f. Process Information - Security\"\n    _aliases_ = [\"cs\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-f\", \"--file\", help=\"the file path to parse.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -f /bin/ls\",\n        \"{0:s} -r\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def check_CET_SHSTK(self, sec):\n        # Intel CET SHSTK flags via Ehdr\n        if \"CET SHSTK flag\" not in sec:\n            # ELF is not x86_64\n            return\n        if sec[\"CET SHSTK flag\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK feature flag (via Ehdr)\", Color.colorify(\"Found\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK feature flag (via Ehdr)\", Color.colorify(\"Not found\", \"bold red\")))\n\n        # gdb mode check\n        if not is_x86():\n            return\n        if not is_alive():\n            return\n        if is_rr():\n            return\n\n        # Intel CET SHSTK status via arch_prctl\n        if is_pin():\n            # Intel SDE implements userspace CET SHSTK but old interface\n            r = Checksec.get_cet_status_old_interface()\n            if r is None:\n                msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel does not support; Intel SDE has no `-cet` option)\"\n                gef_print(\"{:<40s}: {:s}\".format(\"CET IBT status (via old arch_prctl IF)\", msg))\n            else:\n                if r & 0b10:\n                    msg = Color.colorify(\"Enabled\", \"bold green\") + \" (kernel supports; Intel SDE has `-cet` option)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via old arch_prctl IF)\", msg))\n                else:\n                    msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports but disabled; Intel SDE has `-cet` option)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via old arch_prctl IF)\", msg))\n        else:\n            # kernel 6.6 or after supports userspace CET SHSTK\n            r = Checksec.get_cet_status_new_interface()\n            if r is None:\n                msg = Color.colorify(\"Unimplemented\", \"bold red\") + \" (kernel does not support; kernel supports it from 6.6)\"\n                gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via new arch_prctl IF)\", msg))\n            else:\n                if r & 0b01:\n                    msg = Color.colorify(\"Enabled\", \"bold green\") + \" (kernel supports and enabled)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via new arch_prctl IF)\", msg))\n                else:\n                    msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports but disabled)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via new arch_prctl IF)\", msg))\n\n        # Intel CET SHSTK status via procfs\n        r = Checksec.get_cet_status_via_procfs()\n        if r is None:\n            msg = Color.grayify(\"Unknown\") + \" (failed to open /proc/PID/status)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via procfs)\", msg))\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK Lock status (via procfs)\", msg))\n        elif r is False:\n            msg = Color.colorify(\"Unimplemented\", \"bold red\") + \" (kernel does not support; kernel supports it from 6.6)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via procfs)\", msg))\n            gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK Lock status (via procfs)\", msg))\n        else:\n            if r[\"shstk\"]:\n                gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via procfs)\", Color.colorify(\"Enabled\", \"bold green\")))\n            else:\n                msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports but disabled)\"\n                gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK status (via procfs)\", msg))\n            if r[\"shstk lock\"]:\n                gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK Lock status (via procfs)\", Color.colorify(\"Enabled\", \"bold green\")))\n            else:\n                msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports but no locked)\"\n                gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK Lock status (via procfs)\", msg))\n        return\n\n    def check_CET_IBT(self, sec):\n        # Intel CET IBT flags via Ehdr\n        if \"CET IBT flag\" not in sec:\n            # ELF is not x86_64\n            return\n        if sec[\"CET IBT flag\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET IBT feature flag (via Ehdr)\", Color.colorify(\"Found\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET IBT feature flag (via Ehdr)\", Color.colorify(\"Not found\", \"bold red\")))\n\n        # gdb mode check\n        if not is_x86():\n            return\n        if not is_alive():\n            return\n        if is_rr():\n            return\n\n        # Intel CET IBT status via arch_prctl\n        if is_pin():\n            # Intel SDE implements userspace CET IBT but old interface\n            r = Checksec.get_cet_status_old_interface()\n            if r is None:\n                msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel does not support; Intel SDE has no `-cet` option)\"\n                gef_print(\"{:<40s}: {:s}\".format(\"CET IBT status (via old arch_prctl IF)\", msg))\n            else:\n                if r & 0b01:\n                    msg = Color.colorify(\"Enabled\", \"bold green\") + \" (kernel supports; Intel SDE has `-cet` option)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET IBT status (via old arch_prctl IF)\", msg))\n                else:\n                    msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports but disabled; Intel SDE has `-cet` option)\"\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET IBT status (via old arch_prctl IF)\", msg))\n        else:\n            # kernel does not support userspace CET IBT yet, only supports kernel space CET IBT.\n            # https://lwn.net/Articles/889475/ (2022/3/31)\n            msg = Color.colorify(\"Unimplemented\", \"bold red\") + \" (at least kernel 6.6 does not support userspace IBT)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"CET IBT status\", msg))\n        return\n\n    def check_PAC(self, sec):\n        # PAC opcode\n        if \"PAC\" not in sec:\n            # ELF is not ARM64\n            return\n        if sec[\"PAC\"] is None:\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC opcode\", Color.grayify(\"Unknown\")))\n        elif sec[\"PAC\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC opcode\", Color.colorify(\"Found\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC opcode\", Color.colorify(\"Not found\", \"bold red\")))\n\n        # gdb mode check\n        if not is_arm64():\n            return\n        if not is_alive():\n            return\n        if is_rr():\n            return\n\n        # PAC status\n        r = Checksec.get_pac_status()\n        if r is None:\n            msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel does not support PAC)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC\", msg))\n        elif r < 0:\n            msg = Color.grayify(\"Unknown\") + \" (kernel supports PAC but does not support PR_PAC_GET_ENABLED_KEYS prctl option)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC\", msg))\n        elif r == 0:\n            msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports PAC but no keys are enabled)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC\", msg))\n        elif r > 0:\n            keys = []\n            if r & 0b00001:\n                keys.append(\"APIAKEY\")\n            if r & 0b00010:\n                keys.append(\"APIBKEY\")\n            if r & 0b00100:\n                keys.append(\"APDAKEY\")\n            if r & 0b01000:\n                keys.append(\"APDBKEY\")\n            if r & 0b10000:\n                keys.append(\"APGAKEY\")\n            keys = \", \".join(keys)\n            msg = Color.colorify(\"Enabled\", \"bold green\") + \" (enabled keys: {:s})\".format(keys)\n            gef_print(\"{:<40s}: {:s}\".format(\"PAC\", msg))\n        return\n\n    def check_MTE(self, sec):\n        # gdb mode check\n        if not is_arm64():\n            return\n        if not is_alive():\n            return\n        if is_rr():\n            return\n\n        # MTE status\n        r = Checksec.get_mte_status()\n        if r is None:\n            msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel does not support MTE)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"MTE\", msg))\n        elif r < 0:\n            msg = Color.grayify(\"Unknown\") + \" (kernel supports MTE but does not support PR_SET_TAGGED_ADDR_CTRL)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"MTE\", msg))\n        elif (r & 0b1) == 0:\n            msg = Color.colorify(\"Disabled\", \"bold red\") + \" (kernel supports MTE but disabled)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"MTE\", msg))\n        elif (r & 0b1) == 1 and (r & 0b110) == 0:\n            msg = Color.colorify(\"Disabled\", \"bold red\") + \" (MTE is enabled, but fault is ignored)\"\n            gef_print(\"{:<40s}: {:s}\".format(\"MTE\", msg))\n        else:\n            keys = []\n            if r & 0b010:\n                keys.append(\"PR_MTE_TCF_SYNC\")\n            if r & 0b100:\n                keys.append(\"PR_MTE_TCF_ASYNC\")\n            keys = \", \".join(keys)\n            msg = Color.colorify(\"Enabled\", \"bold green\") + \" (MTE is enabled as: {:s})\".format(keys)\n            gef_print(\"{:<40s}: {:s}\".format(\"MTE\", msg))\n        return\n\n    def check_system_ASLR(self):\n        if is_remote_debug():\n            msg = Color.grayify(\"Unknown\")\n            gef_print(\"{:<40s}: {:s} (remote process)\".format(\"System-ASLR\", msg))\n        else:\n            try:\n                system_aslr = int(open(\"/proc/sys/kernel/randomize_va_space\").read())\n                if system_aslr == 0:\n                    msg = Color.colorify(\"Disabled\", \"bold red\")\n                    gef_print(\"{:<40s}: {:s} (randomize_va_space: 0)\".format(\"System ASLR\", msg))\n                elif system_aslr == 1:\n                    msg = Color.colorify(\"Partially Enabled\", \"bold yellow\")\n                    gef_print(\"{:<40s}: {:s} (randomize_va_space: 1)\".format(\"System ASLR\", msg))\n                elif system_aslr == 2:\n                    msg = Color.colorify(\"Enabled\", \"bold green\")\n                    gef_print(\"{:<40s}: {:s} (randomize_va_space: 2)\".format(\"System ASLR\", msg))\n            except (FileNotFoundError, OSError):\n                msg = Color.grayify(\"Unknown\")\n                gef_print(\"{:<40s}: {:s} (randomize_va_space: error)\".format(\"System-ASLR\", msg))\n        return\n\n    def check_gdb_ASLR(self):\n        if is_attach() or is_remote_debug():\n            msg = Color.grayify(\"Ignored\")\n            gef_print(\"{:<40s}: {:s} (attached or remote process)\".format(\"GDB ASLR setting\", msg))\n        else:\n            ret = gdb.parameter(\"disable-randomization\")\n            if ret is True:\n                msg = Color.colorify(\"Disabled\", \"bold red\")\n                gef_print(\"{:<40s}: {:s} (disable-randomization: on)\".format(\"GDB ASLR setting\", msg))\n            elif ret is False:\n                msg = Color.colorify(\"Enabled\", \"bold green\")\n                gef_print(\"{:<40s}: {:s} (disable-randomization: off)\".format(\"GDB ASLR setting\", msg))\n            else:\n                msg = Color.grayify(\"Unknown\")\n                gef_print(\"{:<40s}: {:s}\".format(\"GDB ASLR setting\", msg))\n        return\n\n    def get_colored_msg(self, val):\n        if val is True:\n            msg = Color.greenify(Color.boldify(\"Enabled\"))\n        elif val is False:\n            msg = Color.redify(Color.boldify(\"Disabled\"))\n        elif val is None:\n            msg = Color.grayify(\"Unknown\")\n        return msg\n\n    def print_security_properties(self, filename):\n        elf = Elf.get_elf(filename)\n        if elf is None or not elf.is_valid():\n            err(\"checksec is failed\")\n            return\n\n        sec = elf.checksec()\n        if sec is False:\n            err(\"checksec is failed\")\n            return\n\n        gef_print(titlify(\"Basic information\"))\n\n        # Canary\n        msg = self.get_colored_msg(sec[\"Canary\"])\n        if sec[\"Canary\"] is True and is_alive():\n            res = CanaryCommand.gef_read_canary()\n            if not res:\n                msg += \" (Could not get the canary value)\"\n            else:\n                msg += \" (value: {:#x})\".format(res[0])\n        gef_print(\"{:<40s}: {:s}\".format(\"Canary\", msg))\n\n        # NX\n        gef_print(\"{:<40s}: {:s}\".format(\"NX\", self.get_colored_msg(sec[\"NX\"])))\n\n        # PIE\n        if sec[\"PIE\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"PIE\", self.get_colored_msg(sec[\"PIE\"])))\n        else:\n            vaddr = min([p.p_vaddr for p in elf.phdrs if p.p_type == Elf.Phdr.PT_LOAD])\n            gef_print(\"{:<40s}: {:s} ({:#x})\".format(\"PIE\", self.get_colored_msg(sec[\"PIE\"]), vaddr))\n\n        # RELRO\n        if sec[\"Full RELRO\"]:\n            # -Wl,-z,relro -Wl,-z,now\n            gef_print(\"{:<40s}: {:s}\".format(\"RELRO\", Color.colorify(\"Full RELRO\", \"bold green\")))\n        elif sec[\"Partial RELRO\"]:\n            # -Wl,-z,relro -Wl,-z,lazy\n            gef_print(\"{:<40s}: {:s}\".format(\"RELRO\", Color.colorify(\"Partial RELRO\", \"bold yellow\")))\n        else:\n            # -Wl,-z,norelro\n            gef_print(\"{:<40s}: {:s}\".format(\"RELRO\", Color.colorify(\"No RELRO\", \"bold red\")))\n\n        # Fortify\n        if sec[\"Fortify\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"Fortify\", Color.colorify(\"Found\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Fortify\", Color.colorify(\"Not found\", \"bold red\")))\n\n        gef_print(titlify(\"Additional information\"))\n\n        # Static\n        if sec[\"Static\"]:\n            if sec[\"PIE\"]:\n                gef_print(\"{:<40s}: {:s}\".format(\"Static/Dynamic\", \"Static-PIE\"))\n            else:\n                gef_print(\"{:<40s}: {:s}\".format(\"Static/Dynamic\", \"Static\"))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Static/Dynamic\", \"Dynamic\"))\n\n        # Symbol\n        if sec[\"Symbol\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"Symbol\", Color.colorify(\"Found\", \"bold red\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Symbol\", Color.colorify(\"Stripped\", \"bold green\")))\n\n        # Debug information\n        if sec[\"Debuginfo\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"Debuginfo\", Color.colorify(\"Found\", \"bold red\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Debuginfo\", Color.colorify(\"Stripped\", \"bold green\")))\n\n        # Intel CET\n        self.check_CET_SHSTK(sec)\n        self.check_CET_IBT(sec)\n\n        # ARM64 PAC/MTE\n        self.check_PAC(sec)\n        self.check_MTE(sec)\n\n        # RPATH\n        if sec[\"RPATH\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"RPATH\", Color.colorify(\"Found\", \"bold red\")))\n\n        # RUNPATH\n        if sec[\"RUNPATH\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"RUNPATH\", Color.colorify(\"Found\", \"bold red\")))\n\n        # Clang CFI\n        if sec[\"Clang CFI\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"Clang CFI\", self.get_colored_msg(sec[\"Clang CFI\"])))\n\n        # Clang SafeStack\n        if sec[\"Clang SafeStack\"]:\n            gef_print(\"{:<40s}: {:s}\".format(\"Clang SafeStack\", self.get_colored_msg(sec[\"Clang SafeStack\"])))\n\n        # ASLR\n        self.check_system_ASLR()\n        self.check_gdb_ASLR()\n        return\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\", \"kgdb\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if is_qemu_system() or is_vmware():\n            info(\"Redirect to kchecksec\")\n            gdb.execute(\"kchecksec\")\n            return\n\n        local_filepath = None\n        remote_filepath = None\n        tmp_filepath = None\n\n        if args.remote:\n            if not is_remote_debug():\n                err(\"-r option is allowed only remote debug\")\n                return\n\n            if args.file:\n                remote_filepath = args.file # if specified, assume it is remote\n            elif gdb.current_progspace().filename:\n                f = gdb.current_progspace().filename\n                if f.startswith(\"target:\"): # gdbserver\n                    f = f[7:]\n                remote_filepath = f\n            elif Pid.get_pid(remote=True):\n                remote_filepath = \"/proc/{:d}/exe\".format(Pid.get_pid(remote=True))\n            else:\n                err(\"File name could not be determined\")\n                return\n\n            data = Path.read_remote_file(remote_filepath, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                err(\"Failed to read remote filepath\")\n                return\n            tmp_fd, tmp_filepath = GefUtil.mkstemp(prefix=\"checksec\", suffix=\".elf\")\n            os.fdopen(tmp_fd, \"wb\").write(data)\n            local_filepath = tmp_filepath\n            del data\n\n        elif args.file:\n            local_filepath = args.file\n\n        elif args.file is None:\n            if is_qemu_system():\n                err(\"Argument-less calls are unsupported under qemu-system\")\n                return\n            local_filepath = Path.get_filepath()\n\n        if local_filepath is None:\n            err(\"File name could not be determined\")\n            return\n\n        self.print_security_properties(local_filepath)\n\n        if tmp_filepath and os.path.exists(tmp_filepath):\n            os.unlink(tmp_filepath)\n        return\n\n\n@register_command\nclass KernelChecksecCommand(GenericCommand):\n    \"\"\"Check the security properties of the current kernel.\"\"\"\n\n    _cmdline_ = \"kchecksec\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def check_basic_information(self):\n        kcmdline = Kernel.kernel_cmdline()\n        if kcmdline is None or kcmdline.cmdline is None:\n            gef_print(\"{:<40s}: {:s}\".format(\"Kernel cmdline\", \"Not found\"))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Kernel cmdline\", kcmdline.cmdline.strip()))\n\n        text_base = Kernel.get_kernel_base()\n        if text_base is None:\n            gef_print(\"{:<40s}: {:s}\".format(\"Kernel base (heuristic)\", \"Not found\"))\n        else:\n            gef_print(\"{:<40s}: {:#x}\".format(\"Kernel base (heuristic)\", text_base))\n\n        stext = Symbol.get_ksymaddr(\"_stext\")\n        if stext is None:\n            gef_print(\"{:<40s}: {:s}\".format(\"Kernel base (_stext from kallsyms)\", \"Not found\"))\n        else:\n            gef_print(\"{:<40s}: {:#x}\".format(\"Kernel base (_stext from kallsyms)\", stext))\n        return\n\n    def x86_specific(self):\n        if not is_x86():\n            return\n\n        cr0 = get_register(\"cr0\", use_monitor=True)\n        cr4 = get_register(\"cr4\", use_monitor=True)\n\n        # WP\n        if (cr0 >> 16) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"Write Protection (CR0 bit 16)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Write Protection (CR0 bit 16)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # PAE\n        if (cr4 >> 5) & 1:\n            gef_print(\"{:<40s}: {:s} (NX is supported)\".format(\"PAE (CR4 bit 5)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s} (NX is unsupported)\".format(\"PAE (CR4 bit 5)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # SMEP\n        if (cr4 >> 20) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"SMEP (CR4 bit 20)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"SMEP (CR4 bit 20)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # SMAP\n        if (cr4 >> 21) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"SMAP (CR4 bit 21)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"SMAP (CR4 bit 21)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # CET\n        if (cr4 >> 23) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET (CR4 bit 23)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"CET (CR4 bit 23)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # CET MSR\n        if (cr4 >> 23) & 1:\n            if is_kvm_enabled():\n                additional = \"for more precisely, use `msr MSR_IA32_S_CET` without --enable-kvm\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(\"CET SHSTK (MSR_IA32_S_CET bit 0)\", Color.grayify(\"Unknown\"), additional))\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(\"CET IBT (MSR_IA32_S_CET bit 2)\", Color.grayify(\"Unknown\"), additional))\n            else:\n                ret = gdb.execute(\"msr --quiet MSR_IA32_S_CET\", to_string=True)\n                MSR_IA32_S_CET = int(ret, 16)\n                if MSR_IA32_S_CET & 1:\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK (MSR_IA32_S_CET bit 0)\", Color.colorify(\"Enabled\", \"bold green\")))\n                else:\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET SHSTK (MSR_IA32_S_CET bit 0)\", Color.colorify(\"Disabled\", \"bold red\")))\n                if (MSR_IA32_S_CET >> 2) & 1:\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET IBT (MSR_IA32_S_CET bit 2)\", Color.colorify(\"Enabled\", \"bold green\")))\n                else:\n                    gef_print(\"{:<40s}: {:s}\".format(\"CET IBT (MSR_IA32_S_CET bit 2)\", Color.colorify(\"Disabled\", \"bold red\")))\n        return\n\n    def arm32_specific(self):\n        if not is_arm32():\n            return\n\n        # PXN\n        ID_MMFR0 = get_register(\"$ID_MMFR0\")\n        ID_MMFR0_S = get_register(\"$ID_MMFR0_S\")\n        if ID_MMFR0 is not None and (ID_MMFR0 >> 2) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"PXN (ID_MMFR0 bit 2)\", Color.colorify(\"Enabled\", \"bold green\")))\n        elif ID_MMFR0_S is not None and (ID_MMFR0_S >> 2) & 1:\n            gef_print(\"{:<40s}: {:s}\".format(\"PXN (ID_MMFR0 bit 2)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"PXN (ID_MMFR0 bit 2)\", Color.colorify(\"Disabled\", \"bold red\")))\n\n        # PAN\n        gef_print(\"{:<40s}: {:s} (all ARMv7 is unsupported)\".format(\"PAN\", Color.colorify(\"Disabled\", \"bold red\")))\n        return\n\n    def arm64_specific(self):\n        if not is_arm64():\n            return\n\n        # PXN\n        gef_print(\"{:<40s}: {:s} (all ARMv8~ is supported)\".format(\"PXN\", Color.colorify(\"Enabled\", \"bold green\")))\n\n        # PAN\n        ID_AA64MMFR1_EL1 = get_register(\"$ID_AA64MMFR1_EL1\", use_mbed_exec=True)\n        if ID_AA64MMFR1_EL1 is not None and ((ID_AA64MMFR1_EL1 >> 20) & 0b1111) != 0b0000:\n            gef_print(\"{:<40s}: {:s}\".format(\"PAN (ID_AA64MMFR1_EL1 bit 23-20)\", Color.colorify(\"Enabled\", \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"PAN (ID_AA64MMFR1_EL1 bit 23-20)\", Color.colorify(\"Disabled\", \"bold red\")))\n        return\n\n    def check_kaslr(self):\n        cfg = \"CONFIG_RANDOMIZE_BASE (KASLR)\"\n        kcmdline = Kernel.kernel_cmdline()\n        ksym_ret = gdb.execute(\"ksymaddr-remote --quiet --no-pager kaslr_\", to_string=True)\n\n        if not ksym_ret:\n            additional = \"`kaslr_*`: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        if kcmdline and \"nokaslr\" in kcmdline.cmdline:\n            additional = \"nokaslr is in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            additional = \"`kaslr_*`: Found, nokaslr is not in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_fgkaslr(self):\n        if not is_x86_64():\n            return\n\n        # https://github.com/alobakin/linux/pull/3\n        cfg = \"CONFIG_FG_KASLR (FGKASLR)\"\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.5\":\n            # https://lore.kernel.org/kernel-hardening/20200205223950.1212394-1-kristen@linux.intel.com/\n            additional = \"FGKASLR was first proposed in 5.5.0-rc7\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            cfg = \"CONFIG_MODULE_FG_KASLR (FGKASLR)\"\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\")))\n            return\n\n        if \"6.14\" <= kversion:\n            # As of 6.14, the following detection logic is no longer available.\n            # It has not yet been incorporated into the mainline, and no samples are available.\n            # Therefore, this check is disabled.\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n            cfg = \"CONFIG_MODULE_FG_KASLR (FGKASLR)\"\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n            return\n\n        swapgs_restore_regs_and_return_to_usermode = Symbol.get_ksymaddr(\"swapgs_restore_regs_and_return_to_usermode\")\n        commit_creds = Symbol.get_ksymaddr(\"commit_creds\")\n\n        # something is wrong\n        if not swapgs_restore_regs_and_return_to_usermode or not commit_creds:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n            cfg = \"CONFIG_MODULE_FG_KASLR (FGKASLR)\"\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n            return\n\n        # swapgs_restore_regs_and_return_to_usermode is in a fixed location.\n        # commit_creds are placed dynamically.\n        if swapgs_restore_regs_and_return_to_usermode < commit_creds: # For some reason this works fine\n            kcmdline = Kernel.kernel_cmdline()\n            if kcmdline and \"nokaslr\" in kcmdline.cmdline:\n                additional = \"nokaslr is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"nofgkaslr\" in kcmdline.cmdline:\n                additional = \"nofgkaslr is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"fgkaslr=off\" in kcmdline.cmdline:\n                additional = \"fgkaslr=off is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            else:\n                additional = \"swapgs_restore_regs_and_return_to_usermode < commit_creds\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            # Could not build detection logic for CONFIG_MODULE_FG_KASLR.\n            # But there is no way to disable it except at build time.\n            # It's included in the patch that introduces FGKASLR, so it is assumed to be always enabled.\n            cfg = \"CONFIG_MODULE_FG_KASLR (FGKASLR)\"\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Enabled (maybe)\", \"bold green\")))\n        else:\n            additional = \"swapgs_restore_regs_and_return_to_usermode > commit_creds\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            cfg = \"CONFIG_MODULE_FG_KASLR (FGKASLR)\"\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\")))\n        return\n\n    def check_kpti(self):\n        kversion = Kernel.kernel_version()\n        if \"6.9\" <= kversion:\n            cfg = \"CONFIG_MITIGATION_PAGE_TABLE_ISOLATION (KPTI)\"\n        else:\n            cfg = \"CONFIG_PAGE_TABLE_ISOLATION (KPTI)\"\n        kcmdline = Kernel.kernel_cmdline()\n\n        if is_x86():\n            pti_init = Symbol.get_ksymaddr(\"pti_init\")\n            if pti_init is None:\n                additional = \"pti_init: Not found\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            elif kcmdline and \"nopti\" in kcmdline.cmdline:\n                additional = \"nopti is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"pti=off\" in kcmdline.cmdline:\n                additional = \"pti=off is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"mitigations=off\" in kcmdline.cmdline:\n                additional = \"mitigations=off is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"pti=on\" in kcmdline.cmdline:\n                additional = \"pti=on is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            elif is_in_kernel():\n                lines = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --simple --disable-color\").splitlines()\n                for line in lines:\n                    if \"USER\" in line and \"R-X\" in line:\n                        # If the qemu startup option does not include `-cpu kvm64`,\n                        # isolation will not occur even if KPTI is enabled.\n                        additional = \"USER memory has R-X permission in kernel context\"\n                        gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n                        return\n                else:\n                    additional = \"USER memory has no R-X permission in kernel context\"\n                    gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled (maybe)\", \"bold green\"), additional))\n            else:\n                gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n\n        if is_arm32():\n            gef_print(\"{:<40s}: {:s} (ARMv7 is unsupported)\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\")))\n\n        if is_arm64():\n            pti_init = Symbol.get_ksymaddr(\"pti_init\")\n            if pti_init is None:\n                additional = \"pti_init: Not found\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            elif kcmdline and \"kpti=0\" in kcmdline.cmdline:\n                additional = \"kpti=0 is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"mitigations=off\" in kcmdline.cmdline and \"nokaslr\" in kcmdline.cmdline:\n                additional = \"mitigations=off and nokaslr are in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif kcmdline and \"mitigations=off\" in kcmdline.cmdline and \"nokaslr\" not in kcmdline.cmdline:\n                additional = \"mitigations=off is in cmdline, nokaslr is not in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            elif kcmdline and \"kpti=1\" in kcmdline.cmdline:\n                additional = \"kpti=1 is in cmdline\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            else:\n                gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Enabled (maybe)\", \"bold green\")))\n        return\n\n    def check_rwx_page(self):\n        cfg = \"RWX kernel page\"\n        kinfo = Kernel.get_kernel_layout()\n        for m in kinfo.maps:\n            if m[2] == \"RWX\":\n                gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Found\", \"bold red\")))\n                return\n\n        gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Not found\", \"bold green\")))\n        return\n\n    def check_secure_world(self):\n        if not is_arm32() and not is_arm64():\n            return\n\n        mtree_ret = gdb.execute(\"monitor info mtree -f\", to_string=True)\n        if \".secure-ram\" in mtree_ret:\n            gef_print(\"{:<40s}: {:s}\".format(\"Secure world\", \"Found\"))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(\"Secure world\", \"Not found\"))\n        return\n\n    def check_CONFIG_SLAB_FREELIST_HARDENED(self):\n        cfg = \"CONFIG_SLAB_FREELIST_HARDENED\"\n        slab_cache_names = \" \".join(\"kmalloc-{:d}\".format(n) for n in [8, 16, 32, 64, 96, 128, 192, 256, 512])\n        slub_dump_ret = gdb.execute(\"slub-dump --quiet --no-pager {:s}\".format(slab_cache_names), to_string=True)\n        if slub_dump_ret.count(\"Corrupted\") >= 2: # Destruction of up to one SLUB freelist is allowed.\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.grayify(\"Unknown\")))\n            return\n\n        slub_dump_ret = gdb.execute(\"slub-dump --meta\", to_string=True)\n        r = re.search(r\"offsetof\\(kmem_cache, random\\): (0x\\S+)\", slub_dump_ret)\n        if r:\n            additional = \"offsetof(kmem_cache, random): {:s}\".format(r.group(1))\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Disabled\", \"bold red\")))\n        return\n\n    def check_CONFIG_SLAB_VIRTUAL(self):\n        cfg = \"CONFIG_SLAB_VIRTUAL\"\n        # https://patchwork.kernel.org/project/linux-mm/patch/20230915105933.495735-12-matteorizzo@google.com/#25548022\n        stw = \"slub_tlbflush_worker\"\n        if not Symbol.get_ksymaddr(stw):\n            additional = \"{:s}: {:s}\".format(stw, \"Not found\")\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"6.6\":\n            additional = \"{:s}: Found (kernel version < 6.6)\".format(stw)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            # If version is >= 6.6, vmlinux can switch `slab_virtual` status with boot-parameter\n            kcmdline = Kernel.kernel_cmdline()\n            r = re.search(r\"slab_virtual=(\\d+)\", kcmdline.cmdline)\n            if r:\n                additional = \"{:s}: Found, {:s} is in cmdline\".format(stw, r.group(0))\n                if r.group(1) == \"0\":\n                    gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n                else:\n                    gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            else:\n                additional = \"{:s}: Found, slab_virtual is NOT in cmdline\".format(stw)\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_selinux(self):\n        cfg = \"SELinux\"\n        # SELinux does not support being built as a kernel module.\n        # Therefore, only symbols in the kernel can be used to determine whether SELinux is supported or not.\n        selinux_init = Symbol.get_ksymaddr(\"selinux_init\")\n        if selinux_init is None:\n            additional = \"selinux_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.17\":\n            selinux_enabled_addr = Symbol.get_ksymaddr(\"selinux_enabled\")\n            selinux_enforcing_addr = Symbol.get_ksymaddr(\"selinux_enforcing\")\n            if selinux_enabled_addr is None:\n                additional = \"selinux_init: Found, selinux_enabled: Not detected\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n                return\n\n            if selinux_enforcing_addr is None:\n                additional = \"selinux_init: Found, seliux_enforcing: Not detected\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n                return\n\n            selinux_enabled = read_int32_from_memory(selinux_enabled_addr)\n            selinux_enforcing = read_int32_from_memory(selinux_enforcing_addr)\n            additional = \"selinux_init: Found, selinux_enabled: {:d}, selinux_enforcing: {:d}\".format(\n                selinux_enabled, selinux_enforcing,\n            )\n            if selinux_enabled == 0:\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            elif selinux_enforcing == 0:\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Permissive\", \"bold red\"), additional))\n            else:\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enforcing\", \"bold green\"), additional))\n            return\n\n        # 4.17 <= kernel\n        \"\"\"\n        struct selinux_state {\n        #ifdef CONFIG_SECURITY_SELINUX_DISABLE\n            abool disabled;\n        #endif\n        #ifdef CONFIG_SECURITY_SELINUX_DEVELOP\n            abool enforcing;\n        #endif\n            abool checkreqprot;\n            abool initialized;\n            abool policycap[__POLICYDB_CAP_MAX]; # __POLICYDB_CAP_MAX:6 ~ 8 bytes\n            astruct page *status_page;\n            astruct mutex status_lock;\n            astruct selinux_avc *avc;\n            astruct selinux_policy __rcu *policy;\n            astruct mutex policy_mutex;\n        } __randomize_layout;\n\n        x64 sample\n        gef> x/16xg 0xffffffff8ba20740\n        0xffffffff8ba20740:     0x0100010101010001      0x0000000000000001\n        0xffffffff8ba20750:     0xffffe3bc00215140      0x0000000000000000\n        0xffffffff8ba20760:     0x0000000000000000      0xffffffff8ba20768\n        0xffffffff8ba20770:     0xffffffff8ba20768      0xffffffff8ba1ef20\n        0xffffffff8ba20780:     0xffff8ecc7fe62800      0x0000000000000000\n        \"\"\"\n\n        selinux_state = KernelAddressHeuristicFinder.get_selinux_state()\n\n        if selinux_state is None:\n            additional = \"selinux_init: Found, selinux_state: Not detected\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        if read_int64_from_memory(selinux_state) == 0:\n            additional = \"selinux_init: Found, selinux_state: Not initialized\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            return\n\n        selinux_disable = Symbol.get_ksymaddr(\"selinux_disable\")\n        CONFIG_SECURITY_SELINUX_DISABLE = selinux_disable is not None\n        enforcing_setup = Symbol.get_ksymaddr(\"enforcing_setup\")\n        CONFIG_SECURITY_SELINUX_DEVELOP = enforcing_setup is not None\n\n        # selinux_state.disabled\n        if CONFIG_SECURITY_SELINUX_DISABLE:\n            selinux_disabled = read_int8_from_memory(selinux_state)\n            additional = \"selinux_init: Found, selinux_state.disable: {:d}\".format(selinux_disabled)\n        else:\n            selinux_disabled = None\n            additional = \"selinux_init: Found, selinux_state.disable: Not found\"\n\n        # selinux_state.enforcing\n        if CONFIG_SECURITY_SELINUX_DEVELOP and CONFIG_SECURITY_SELINUX_DISABLE:\n            selinux_enforcing = read_int8_from_memory(selinux_state + 1)\n            additional += \", selinux_state.enforcing: {:d}\".format(selinux_enforcing)\n        elif CONFIG_SECURITY_SELINUX_DEVELOP and not CONFIG_SECURITY_SELINUX_DISABLE:\n            selinux_enforcing = read_int8_from_memory(selinux_state)\n            additional += \", selinux_state.enforcing: {:d}\".format(selinux_enforcing)\n        else:\n            selinux_enforcing = True\n            additional += \", selinux_state.enforcing: Not found\"\n\n        if selinux_disabled:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        elif not selinux_enforcing:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Permissive\", \"bold red\"), additional))\n        elif selinux_enforcing:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enforcing\", \"bold green\"), additional))\n        return\n\n    def check_smack(self):\n        cfg = \"SMACK\"\n        smack_init = Symbol.get_ksymaddr(\"smack_init\")\n        if smack_init is None:\n            additional = \"smack_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        kfilesystems_ret = gdb.execute(\"kfilesystems --quiet --no-pager --skip-mount-path\", to_string=True)\n        if not kfilesystems_ret:\n            additional = \"smack_init: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        if \"smackfs\" in kfilesystems_ret:\n            additional = \"smack_init: Found, smackfs: Mounted\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            additional = \"smack_init: Found, smackfs: Not mounted\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_apparmor(self):\n        cfg = \"AppArmor\"\n        apparmor_init = Symbol.get_ksymaddr(\"apparmor_init\")\n        if apparmor_init is None:\n            additional = \"apparmor_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        apparmor_enabled_addr = KernelAddressHeuristicFinder.get_apparmor_enabled()\n        apparmor_initialized_addr = KernelAddressHeuristicFinder.get_apparmor_initialized()\n        if apparmor_enabled_addr is None:\n            additional = \"apparmor_init: Found, apparmor_enabled: Not detected\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        if apparmor_initialized_addr is None:\n            additional = \"apparmor_init: Found, apparmor_initialized: Not detected\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.1\":\n            apparmor_enabled = read_int8_from_memory(apparmor_enabled_addr) # bool\n        else:\n            apparmor_enabled = read_int32_from_memory(apparmor_enabled_addr) # int\n        apparmor_initialized = read_int32_from_memory(apparmor_initialized_addr)\n\n        if apparmor_enabled not in [0, 1]:\n            additional = \"apparmor_init: Found, apparmor_enabled: {:#x}\".format(apparmor_enabled)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        if apparmor_initialized not in [0, 1]:\n            additional = \"apparmor_init: Found, apparmor_initialized: {:#x}\".format(apparmor_initialized)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        additional = \"apparmor_init: Found\"\n        additional += \", apparmor_initialized: {:d}\".format(apparmor_initialized)\n        additional += \", apparmor_enabled: {:d}\".format(apparmor_enabled)\n        if apparmor_enabled == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        elif apparmor_initialized == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_tomoyo(self):\n        cfg = \"TOMOYO\"\n        tomoyo_init = Symbol.get_ksymaddr(\"tomoyo_init\")\n        if tomoyo_init is None:\n            additional = \"tomoyo_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        tomoyo_enabled_addr = KernelAddressHeuristicFinder.get_tomoyo_enabled()\n        if tomoyo_enabled_addr is None:\n            additional = \"tomoyo_init: Found, tomoyo_enabled: Not detected\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        tomoyo_enabled = read_int32_from_memory(tomoyo_enabled_addr)\n        additional = \"tomoyo_init: Found, tomoyo_enabled: {:d}\".format(tomoyo_enabled)\n        if tomoyo_enabled == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_yama(self):\n        cfg = \"Yama (ptrace_scope)\"\n        yama_init = Symbol.get_ksymaddr(\"yama_init\")\n        if yama_init is None:\n            additional = \"yama_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        ptrace_scope_addr = KernelAddressHeuristicFinder.get_ptrace_scope()\n        if ptrace_scope_addr is None:\n            additional = \"yama_init: Found, kernel.yama.ptrace_scope: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        ptrace_scope = read_int32_from_memory(ptrace_scope_addr)\n        additional = \"yama_init: Found, kernel.yama.ptrace_scope: {:d}\".format(ptrace_scope)\n        if ptrace_scope == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_integrity(self):\n        cfg = \"Integrity (IMA/EVM)\"\n        integrity_iintcache_init = Symbol.get_ksymaddr(\"integrity_iintcache_init\")\n        if integrity_iintcache_init is None:\n            additional = \"integrity_iintcache_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        kcmdline = Kernel.kernel_cmdline()\n        if kcmdline and \"ima_appraise=enforce\" in kcmdline.cmdline:\n            additional = \"integrity_iintcache_init: Found, ima_appraise=enforce is in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        elif kcmdline and \"ima_appraise=off\" in kcmdline.cmdline:\n            additional = \"integrity_iintcache_init: Found, ima_appraise=off is in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        elif kcmdline and \"ima_appraise=log\" in kcmdline.cmdline:\n            additional = \"integrity_iintcache_init: Found, ima_appraise=log is in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Permissive\", \"bold red\"), additional))\n        elif kcmdline and \"ima_appraise=fix\" in kcmdline.cmdline:\n            additional = \"integrity_iintcache_init: Found, ima_appraise=fix is in cmdline\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Permissive\", \"bold red\"), additional))\n        else:\n            additional = \"integrity_iintcache_init: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n        return\n\n    def check_loadpin(self):\n        cfg = \"LoadPin\"\n        loadpin_init = Symbol.get_ksymaddr(\"loadpin_init\")\n        if loadpin_init is None:\n            additional = \"loadpin_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.20\":\n            loadpin_cfg_name = \"kernel.loadpin.enabled\"\n            loadpin_cfg_addr = KernelAddressHeuristicFinder.get_loadpin_enabled()\n        else:\n            loadpin_cfg_name = \"kernel.loadpin.enforce\"\n            loadpin_cfg_addr = KernelAddressHeuristicFinder.get_loadpin_enforce()\n\n        if loadpin_cfg_addr is None:\n            additional = \"loadpin_init: Found, {:s}: Not found\".format(loadpin_cfg_name)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        loadpin_status = read_int32_from_memory(loadpin_cfg_addr)\n        additional = \"loadpin_init: Found, {:s}: {:d}\".format(loadpin_cfg_name, loadpin_status)\n        if loadpin_status == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_safe_setid(self):\n        cfg = \"SafeSetID\"\n        safesetid_security_init = Symbol.get_ksymaddr(\"safesetid_security_init\")\n        if safesetid_security_init is None:\n            additional = \"safesetid_security_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        additional = \"safesetid_security_init: Found\"\n        gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n        return\n\n    def check_lockdown(self):\n        cfg = \"Lockdown\"\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.4\":\n            additional = \"{:s}: implemented from linux 5.4\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold red\"), additional))\n            return\n\n        lockdown_lsm_init = Symbol.get_ksymaddr(\"lockdown_lsm_init\")\n        if lockdown_lsm_init is None:\n            additional = \"lockdown_lsm_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        kernel_locked_down = KernelAddressHeuristicFinder.get_kernel_locked_down()\n        if kernel_locked_down is None:\n            additional = \"lockdown_lsm_init: Found, kernel_locked_down: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        try:\n            val = read_int32_from_memory(kernel_locked_down)\n        except gdb.MemoryError:\n            additional = \"lockdown_lsm_init: Found, kernel_locked_down: Memory read error\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n            return\n\n        if val == 0:\n            additional = \"lockdown_lsm_init: Found, kernel_locked_down: 0 (none)\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            if val == 1:\n                additional = \"lockdown_lsm_init: Found, kernel_locked_down: 1 (integrity)\"\n            elif val == 2:\n                additional = \"lockdown_lsm_init: Found, kernel_locked_down: 2 (confidentiality)\"\n            else:\n                additional = \"lockdown_lsm_init: Found, kernel_locked_down: {:d}\".format(val)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_bpf(self):\n        cfg = \"BPF\"\n        bpf_lsm_init = Symbol.get_ksymaddr(\"bpf_lsm_init\")\n        if bpf_lsm_init is None:\n            additional = \"bpf_lsm_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        additional = \"bpf_lsm_init: Found\"\n        gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n        return\n\n    def check_landlock(self):\n        cfg = \"Landlock\"\n        landlock_init = Symbol.get_ksymaddr(\"landlock_init\")\n        if landlock_init is None:\n            additional = \"landlock_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unsupported\", \"bold red\"), additional))\n            return\n\n        additional = \"landlock_init: Found\"\n        gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, \"Supported\", additional))\n        return\n\n    def check_lkrg(self):\n        cfg = \"Linux Kernel Runtime Guard (LKRG)\"\n        kmod_ret = gdb.execute(\"kmod --quiet --no-pager\", to_string=True)\n        if \"Not found\" in kmod_ret:\n            additional = \"kmod is failed\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        if \": lkrg \" in kmod_ret:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), \"Loaded\"))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), \"Not loaded\"))\n        return\n\n    def check_unprivileged_userfaultfd(self):\n        cfg = \"vm.unprivileged_userfaultfd\"\n\n        stv_uff_ret = gdb.execute(\"syscall-table-view -f userfaultfd --quiet --no-pager\", to_string=True)\n        if \"userfaultfd\" not in stv_uff_ret:\n            additional = \"userfaultfd syscall: Unimplemented\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Syscall unsupported\", \"bold green\"), additional))\n            return\n\n        if \"invalid userfaultfd\" in stv_uff_ret:\n            additional = \"userfaultfd syscall: Disabled\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Syscall unsupported\", \"bold green\"), additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.2\":\n            additional = \"userfaultfd syscall: Enabled, but without {:s} restriction! (implemented from linux 5.2)\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold red\"), additional))\n            return\n\n        sysctl_unprivileged_userfaultfd = KernelAddressHeuristicFinder.get_sysctl_unprivileged_userfaultfd()\n        if sysctl_unprivileged_userfaultfd is None:\n            additional = \"{:s}: Not found\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        v = read_int32_from_memory(sysctl_unprivileged_userfaultfd)\n        additional = \"{:s}: {:d}\".format(cfg, v)\n        if v == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        return\n\n    def check_unprivileged_bpf_disabled(self):\n        cfg = \"kernel.unprivileged_bpf_disabled\"\n\n        stv_bpf_ret = gdb.execute(\"syscall-table-view -f bpf --quiet --no-pager\", to_string=True)\n        if \"bpf\" not in stv_bpf_ret:\n            additional = \"bpf syscall: Unimplemented\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Syscall unsupported\", \"bold green\"), additional))\n            return\n\n        if \"invalid bpf\" in stv_bpf_ret:\n            additional = \"bpf syscall: Disabled\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Syscall unsupported\", \"bold green\"), additional))\n            return\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.4\":\n            additional = \"bpf syscall: Enabled, without {:s}, but it needs CAP_SYS_ADMIN (implemented from linux 4.4)\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold green\"), additional))\n            return\n\n        sysctl_unprivileged_bpf_disabled = KernelAddressHeuristicFinder.get_sysctl_unprivileged_bpf_disabled()\n        if sysctl_unprivileged_bpf_disabled is None:\n            additional = \"{:s}: Not found\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        v = read_int32_from_memory(sysctl_unprivileged_bpf_disabled)\n        additional = \"{:s}: {:d}\".format(cfg, v)\n        if v == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_kexec_load_disabled(self):\n        cfg = \"kernel.kexec_load_disabled\"\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.14\":\n            additional = \"{:s}: implemented from linux 3.14\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold red\"), additional))\n            return\n\n        r1 = gdb.execute(\"syscall-table-view -f kexec_load --quiet --no-pager\", to_string=True)\n        r2 = gdb.execute(\"syscall-table-view -f kexec_file_load --quiet --no-pager\", to_string=True)\n        if (\"kexec_load\" not in r1 or \"invalid kexec_load\" in r1) and \\\n           (\"kexec_file_load\" not in r2 or \"invalid kexec_file_load\" in r2):\n            additional = \"\"\n            if \"kexec_load\" not in r1:\n                additional = \"kexec_load syscall: Unimplemented\"\n            elif \"invalid kexec_load\" in r1:\n                additional = \"kexec_load syscall: Disabled\"\n            if \"kexec_file_load\" not in r2:\n                additional += \", \" + \"kexec_file_load syscall: Unimplemented\"\n            elif \"invalid kexec_file_load\" in r2:\n                additional += \", \" + \"kexec_file_load syscall: Disabled\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Syscall unsupported\", \"bold green\"), additional))\n            return\n\n        kexec_load_disabled = KernelAddressHeuristicFinder.get_kexec_load_disabled()\n        if kexec_load_disabled is None:\n            additional = \"{:s}: Not found\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        v1 = read_int32_from_memory(kexec_load_disabled)\n        additional = \"{:s}: {:d}\".format(cfg, v1)\n        if v1 == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_namespaces(self):\n        kversion = Kernel.kernel_version()\n        ksysctl_ret = Kernel.get_ksysctl(\"kernel.version\")\n        cfgs = [\n            [\"4.9\", \"user.max_user_namespaces\"],\n            [\"4.9\", \"user.max_pid_namespaces\"],\n            [\"4.9\", \"user.max_uts_namespaces\"],\n            [\"4.9\", \"user.max_ipc_namespaces\"],\n            [\"4.9\", \"user.max_net_namespaces\"],\n            [\"4.9\", \"user.max_mnt_namespaces\"],\n            [\"4.9\", \"user.max_cgroup_namespaces\"],\n            [\"5.6\", \"user.max_time_namespaces\"],\n        ]\n        prev_fail = False\n        for kv, cfg in cfgs:\n            if kversion < kv:\n                additional = \"{:s}: implemented from linux {:s}\".format(cfg, kv)\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold red\"), additional))\n                continue\n\n            if not ksysctl_ret: # maybe CONFIG_RANDSTRUCT=y\n                additional = \"{:s}: Not found\".format(cfg)\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n                continue\n\n            if prev_fail: # Kernel.get_ksysctl is very slow, so skip if previous Kernel.get_ksysctl() was failed\n                additional = \"{:s}: Not found\".format(cfg)\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n                continue\n\n            addr = Kernel.get_ksysctl(cfg) # very slow\n            if addr is None:\n                additional = \"{:s}: Not found\".format(cfg)\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n                prev_fail = True\n                continue\n\n            val = read_int32_from_memory(addr)\n            if val:\n                gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"{:d}\".format(val), \"bold red\")))\n            else:\n                gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"{:d}\".format(val), \"bold green\")))\n        return\n\n    def check_unprivileged_userns_clone(self):\n        cfg = \"kernel.unprivileged_userns_clone\"\n        addr = Kernel.get_ksysctl(cfg)\n        if addr is None:\n            additional = \"{:s}: Not found, Only present in debian-based environments\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        val = read_int32_from_memory(addr)\n        additional = \"{:s}: {:d}, Only present in debian-based environments\".format(cfg, val)\n        if val:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        return\n\n    def check_userns_restrict(self):\n        cfg = \"kernel.userns_restrict\"\n        addr = Kernel.get_ksysctl(cfg)\n        if addr is None:\n            additional = \"{:s}: Not found, Only present in ALT-linux-based environments\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        val = read_int32_from_memory(addr)\n        additional = \"{:s}: {:d}, Only present in ALT-linux-based environments\".format(cfg, val)\n        if val:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_CONFIG_KALLSYMS_ALL(self):\n        cfg = \"CONFIG_KALLSYMS_ALL\"\n        modprobe_path = Symbol.get_ksymaddr(\"modprobe_path\")\n        if modprobe_path:\n            additional = \"modprobe_path: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        else:\n            additional = \"modprobe_path: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        return\n\n    def check_CONFIG_IKCONFIG(self):\n        cfg = \"CONFIG_IKCONFIG\"\n        ikconfig_init = Symbol.get_ksymaddr(\"ikconfig_init\")\n        if ikconfig_init:\n            additional = \"ikconfig_init: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        else:\n            additional = \"ikconfig_init: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        return\n\n    def check_CONFIG_DEBUG_INFO_BTF(self):\n        cfg = \"CONFIG_DEBUG_INFO_BTF\"\n        __start_BTF = Symbol.get_ksymaddr(\"__start_BTF\")\n        if __start_BTF:\n            additional = \"__start_BTF: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        else:\n            additional = \"__start_BTF: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        return\n\n    def check_CONFIG_RANDSTRUCT(self):\n        cfg = \"CONFIG_RANDSTRUCT\"\n        # In cases where kallsyms could be resolved, but ksysctl could not be resolved correctly,\n        # it is assumed that the structure is strange.\n        # Each structure parsed by ksysctl has no difference among kernel versions, except for `struct ctl_dir.inodes`.\n        # Additionally, the first member of struct ctl_table is a *char procname, which will almost certainly\n        # readable something. If this fails, it can be determined that the randstruct is used.\n        ksysctl_ret = Kernel.get_ksysctl(\"kernel.version\")\n        if not ksysctl_ret:\n            additional = \"ksysctl was failed\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            warn(Color.boldify(\"With `CONFIG_RANDSTRUCT=y`, identifying structure members may be unreliable.\"))\n            warn(Color.boldify(\"As a result, many GEF commands will not work correctly.\"))\n        else:\n            additional = \"ksysctl was successful\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_CONFIG_STATIC_USERMODEHELPER(self):\n\n        def get_permission(addr):\n            maps = Kernel.get_maps()\n            if not maps:\n                return None\n            for vaddr, size, perm in maps:\n                if vaddr <= addr < vaddr + size:\n                    return perm\n            return None\n\n        cfg = \"CONFIG_STATIC_USERMODEHELPER\"\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.11\":\n            additional = \"{:s}: implemented from linux 4.11\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Unimplemented\", \"bold red\"), additional))\n            return\n\n        call_usermodehelper_setup = Symbol.get_ksymaddr(\"call_usermodehelper_setup\")\n        if call_usermodehelper_setup is None:\n            additional = \"call_usermodehelper_setup: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        res = gdb.execute(\"x/50i {:#x}\".format(call_usermodehelper_setup), to_string=True)\n        use_static = False\n        if is_x86_64():\n            g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res)\n        elif is_x86_32():\n            g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res)\n        elif is_arm64():\n            g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n        elif is_arm32():\n            g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n        for x in g:\n            if not is_valid_addr(x):\n                continue\n            # default value of CONFIG_STATIC_USERMODEHELPER_PATH is \"/sbin/usermode-helper\".\n            if read_memory(x, 5) == b\"/sbin\":\n                use_static = True\n                break\n            # sometimes CONFIG_STATIC_USERMODEHELPER_PATH is set to \"\".\n            # If CONFIG_STATIC_USERMODEHELPER_PATH is \"\", one NUL should be stored.\n            # In many cases, another string seems to start being stored at the next address of NUL.\n            # It is rare for two consecutive NULs to occur, and we use this in the detection logic.\n            if read_memory(x, 1) == b\"\\x00\" and read_memory(x + 1, 1) != b\"\\x00\":\n                # check if the address is read-only or not\n                if get_permission(x) == \"R--\":\n                    use_static = True\n                    break\n        if use_static:\n            additional = \"call_usermodehelper_setup uses static path\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            additional = \"call_usermodehelper_setup uses dynamic path\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_CONFIG_STACKPROTECTOR(self):\n        cfg = \"CONFIG_STACKPROTECTOR\"\n        ktask_ret = gdb.execute(\"ktask --meta\", to_string=True)\n        r = re.search(r\"offsetof\\(task_struct, stack_canary\\): (0x\\S+)\", ktask_ret)\n        if r:\n            additional = \"offsetof(task_struct, stack_canary): {:s}\".format(r.group(1))\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            return\n\n        if \"stack_canary\" in ktask_ret:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify(\"Disabled\", \"bold red\")))\n        else:\n            additional = \"ktask was failed\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n        return\n\n    def check_CONFIG_SHADOW_CALL_STACK(self):\n        if not is_arm64():\n            return\n\n        cfg = \"CONFIG_SHADOW_CALL_STACK (Clang ARM64)\"\n        scs_alloc = Symbol.get_ksymaddr(\"scs_alloc\")\n        if scs_alloc:\n            additional = \"scs_alloc: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            additional = \"scs_alloc: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_CONFIG_HARDENED_USERCOPY(self):\n        cfg = \"CONFIG_HARDENED_USERCOPY\"\n        __check_heap_object = Symbol.get_ksymaddr(\"__check_heap_object\")\n        if __check_heap_object:\n            additional = \"__check_heap_object: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        else:\n            additional = \"__check_heap_object: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        return\n\n    def check_CONFIG_FUSE_FS(self):\n        cfg = \"CONFIG_FUSE_FS\"\n        fuse_do_open = Symbol.get_ksymaddr(\"fuse_do_open\")\n        if fuse_do_open:\n            additional = \"fuse_do_open: Found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n        else:\n            ret = gdb.execute(\"kmod --filter fuse --quiet\", to_string=True)\n            if ret:\n                additional = \"fuse module: Found\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold red\"), additional))\n            else:\n                additional = \"fuse module: Not found\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold green\"), additional))\n        return\n\n    def check_kadr_kallsyms(self):\n        cfg = \"KADR (kallsyms)\"\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.15\":\n            kptr_restrict = KernelAddressHeuristicFinder.get_kptr_restrict()\n            if kptr_restrict is None:\n                additional = \"kernel.kptr_restrict: Not found\"\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n                return\n\n            v1 = read_int32_from_memory(kptr_restrict)\n            additional = \"kernel.kptr_restrict: {:d}\".format(v1)\n            if v1 == 0:\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n            else:\n                gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n            return\n\n        kptr_restrict = KernelAddressHeuristicFinder.get_kptr_restrict()\n        sysctl_perf_event_paranoid = KernelAddressHeuristicFinder.get_sysctl_perf_event_paranoid()\n        if kptr_restrict is None:\n            additional = \"kernel.kptr_restrict: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        if sysctl_perf_event_paranoid is None:\n            additional = \"kernel.perf_event_paranoid: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        v1 = read_int32_from_memory(kptr_restrict)\n        v2 = u32(read_memory(sysctl_perf_event_paranoid, 4), s=True)\n        additional = \"kernel.kptr_restrict: {:d}, kernel.perf_event_paranoid: {:d}\".format(v1, v2)\n        if v1 == 0 and v2 <= 1:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_kadr_dmesg(self):\n        dmesg_restrict = KernelAddressHeuristicFinder.get_dmesg_restrict()\n        cfg = \"KADR (dmesg)\"\n        if dmesg_restrict is None:\n            additional = \"kernel.dmesg_restrict: Not found\"\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        v1 = read_int32_from_memory(dmesg_restrict)\n        additional = \"kernel.dmesg_restrict: {:d}\".format(v1)\n        if v1 == 0:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Disabled\", \"bold red\"), additional))\n        else:\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.colorify(\"Enabled\", \"bold green\"), additional))\n        return\n\n    def check_mmap_min_addr(self):\n        cfg = \"vm.mmap_min_addr\"\n        mmap_min_addr = KernelAddressHeuristicFinder.get_mmap_min_addr()\n        if mmap_min_addr is None:\n            additional = \"{:s}: Not found\".format(cfg)\n            gef_print(\"{:<40s}: {:s} ({:s})\".format(cfg, Color.grayify(\"Unknown\"), additional))\n            return\n\n        val = read_int_from_memory(mmap_min_addr)\n        if val:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify_hex(val, \"bold green\")))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, Color.colorify_hex(val, \"bold red\")))\n        return\n\n    def check_supported_syscall(self):\n        cfg = \"Supported system call\"\n        supported_syscall = []\n        if is_x86_32():\n            if KernelAddressHeuristicFinder.get_sys_call_table_x86():\n                supported_syscall.append(\"x86(native)\")\n        elif is_x86_64():\n            if KernelAddressHeuristicFinder.get_sys_call_table_x64():\n                supported_syscall.append(\"x64\")\n            if KernelAddressHeuristicFinder.get_sys_call_table_x86():\n                supported_syscall.append(\"x86(compat)\")\n            elif Symbol.get_ksymaddr(\"ia32_sys_call\"): # 6.6.26~\n                supported_syscall.append(\"x86(compat)\")\n            if KernelAddressHeuristicFinder.get_sys_call_table_x32():\n                supported_syscall.append(\"x32\")\n            elif Symbol.get_ksymaddr(\"x32_sys_call\"): # 6.6.26~\n                supported_syscall.append(\"x32\")\n        elif is_arm32():\n            if KernelAddressHeuristicFinder.get_sys_call_table_arm32():\n                supported_syscall.append(\"arm32(native)\")\n        elif is_arm64():\n            if KernelAddressHeuristicFinder.get_sys_call_table_arm64():\n                supported_syscall.append(\"arm64\")\n            if KernelAddressHeuristicFinder.get_sys_call_table_arm64_compat():\n                supported_syscall.append(\"arm32(compat)\")\n\n        if supported_syscall:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, \", \".join(supported_syscall)))\n        else:\n            gef_print(\"{:<40s}: {:s}\".format(cfg, \"???\"))\n        return\n\n    def print_security_properties_qemu_system(self):\n        gef_print(titlify(\"Kernel information\"))\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        gef_print(\"{:<40s}: {:d}.{:d}.{:d}\".format(\"Kernel version\", *kversion.version_tuple))\n        self.check_basic_information()\n\n        gef_print(titlify(\"Register settings\"))\n        self.x86_specific()\n        self.arm32_specific()\n        self.arm64_specific()\n\n        if Symbol.get_ksymaddr(\"_stext\") is None:\n            err(\"ksymaddr-remote is failed\")\n            return\n\n        gef_print(titlify(\"Memory settings\"))\n        self.check_kaslr()\n        self.check_fgkaslr()\n        self.check_kpti()\n        self.check_rwx_page()\n        self.check_secure_world()\n\n        gef_print(titlify(\"Allocator\"))\n        allocator = Kernel.get_slab_type()\n        gef_print(\"{:<40s}: {:s}\".format(\"Allocator\", allocator))\n        if allocator == \"SLUB\":\n            self.check_CONFIG_SLAB_FREELIST_HARDENED()\n            self.check_CONFIG_SLAB_VIRTUAL()\n\n        gef_print(titlify(\"Security Module\"))\n        self.check_selinux()\n        self.check_smack()\n        self.check_apparmor()\n        self.check_tomoyo()\n        self.check_yama()\n        self.check_integrity()\n        self.check_loadpin()\n        self.check_safe_setid()\n        self.check_lockdown()\n        self.check_bpf()\n        self.check_landlock()\n        self.check_lkrg()\n\n        gef_print(titlify(\"Dangerous system call\"))\n        self.check_unprivileged_userfaultfd()\n        self.check_unprivileged_bpf_disabled()\n        self.check_kexec_load_disabled()\n\n        gef_print(titlify(\"namespaces\"))\n        self.check_namespaces()\n        self.check_unprivileged_userns_clone()\n        self.check_userns_restrict()\n\n        gef_print(titlify(\"Other\"))\n        self.check_CONFIG_KALLSYMS_ALL()\n        self.check_CONFIG_IKCONFIG()\n        self.check_CONFIG_DEBUG_INFO_BTF()\n        self.check_CONFIG_RANDSTRUCT()\n        self.check_CONFIG_STATIC_USERMODEHELPER()\n        self.check_CONFIG_STACKPROTECTOR()\n        self.check_CONFIG_SHADOW_CALL_STACK()\n        self.check_CONFIG_HARDENED_USERCOPY()\n        self.check_CONFIG_FUSE_FS()\n        self.check_kadr_kallsyms()\n        self.check_kadr_dmesg()\n        self.check_mmap_min_addr()\n        self.check_supported_syscall()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.print_security_properties_qemu_system()\n        return\n\n\n@register_command\nclass DwarfExceptionHandlerInfoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the DWARF exception handler information with the byte code itself.\"\"\"\n\n    _cmdline_ = \"dwarf-exception-handler\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-f\", \"--file\", help=\"the file path to parse.\")\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-x\", \"--hexdump\", action=\"store_true\", help=\"with hexdump.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                  # parse loaded binary\",\n        \"{0:s} -r               # parse remote binary\",\n        \"{0:s} -f /usr/bin/apt  # parse specified binary\",\n        \"{0:s} -x               # with hexdump\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified DWARF exception structure:\",\n        \"\",\n        \"[OLD IMPLEMENTATION]\",\n        \" libgcc_s.so bss area               ELF Program Header (for .eh_frame_hdr)\",\n        \"+-----------------------+      +-->+----------------+\",\n        \"| ...                   |      |   | p_type         |\",\n        \"| frame_hdr_cache_head  |---+  |   | p_flags        |\",\n        \"+-frame_hdr_cache_entry-+<--+  |   | p_offset       |\",\n        \"| pc_low                |      |   | p_vaddr        |----+\",\n        \"| pc_high               |      |   | p_paddr        |    |\",\n        \"| load_base             |      |   | p_filesz       |    |\",\n        \"| p_eh_frame_hdr        |------+   | p_memsz        |    |\",\n        \"| p_dynamic             |          | p_align        |    |         [NEW IMPLEMENTATION]\",\n        \"| link                  |---+      +----------------+    |          _dlfo_main@ld.so rodata area\",\n        \"+-frame_hdr_cache_entry-+<--+                            |          _dlfo_nodelete_mappings@ld.so rodata area\",\n        \"| pc_low                |                                |         +-------------+\",\n        \"| pc_high               |                                |         | map_start   |\",\n        \"| load_base             |                                |         | map_end     |\",\n        \"| p_eh_frame_hdr        |                                |         | map         |\",\n        \"| p_dynamic             |                                |<--------| eh_frame    |\",\n        \"| link                  |                                |         | (eh_dbase)  |\",\n        \"+-----------------------+                                |         | (eh_count)  |\",\n        \"The frame_hdr_cache_head and frame_hdr_cache_entry are   |         +-------------+\",\n        \"initialized the first time they are called.              |\",\n        \"                                                         |\",\n        \"                           +-----------------------------+\",\n        \"                           |\",\n        \".eh_frame_hdr              |      .eh_frame                                           .gcc_except_table\",\n        \"+----------------------+<--+  +-->+-CIE-------------------+<--+                   +-->+-LSDA-----------------+\",\n        \"| version              |      |   | length                |   |                   |   | lpstart_enc          |\",\n        \"| eh_frame_ptr_enc     |      |   | cie_id (=0)           |   |                   |   | ttype_enc            |\",\n        \"| fde_count_enc        |      |   | version               |   |                   |   | ttype_off            |\",\n        \"| table_enc            |      |   | augmentation_string   |   |                   |   | call_site_encoding   |\",\n        \"| eh_frame_ptr         |------+   | code_alignment_factor |   |                   |   | call_site_table_len  |\",\n        \"| fde_count            |          | data_alignment_factor |   |                   |   |+-CallSite-----------+|\",\n        \"| Table[0] initial_loc |          | retaddr_register      |   |                   |   || call_site_start    || try_start\",\n        \"| Table[0] fde         |---+      | augmentation_len      |   |                   |   || call_site_length   || try_end\",\n        \"| Table[1] initial_loc |   |      | augmentation_data[0]  |   |                   |   || landing_pad        || catch_start\",\n        \"| Table[1] fde         |   |      | ...                   |-(augmentation=='P')-+ |   || action             ||---+\",\n        \"| ...                  |   |      | ...                   |   |                 | |   |+-CallSite-----------+|   |\",\n        \"| Table[N] initial_loc |   |      | augmentation_data[N]  |   |                 | |   || ...                ||   |\",\n        \"| Table[N] fde         |   |      | program               |   |                 | |   |+-ActionTable--------+|<--+\",\n        \"+----------------------+   +----->+-FDE-------------------+   |                 | |   || ar_filter          ||---+\",\n        \"                                  | length                |   |                 | |   || ar_disp            ||   |\",\n        \"                                  | cie_pointer (!=0)     |---+                 | |   |+-ActionTable--------+|   |\",\n        \"                                  | pc_begin              | try_catch_base      | |   || ...                ||   |\",\n        \"                                  | pc_range              |                     | |   |+-TTypeTable---------+|   |\",\n        \"                                  | augmentation_len      |                     | |   || ...(stored upward) ||   |\",\n        \"                                  | augmentation_data[0]  |                     | |   |+-TTypeTable---------+|<--+\",\n        \"                                  | ...                   |-(augmentation=='L')-|-+   || ttype              ||---> type_info\",\n        \"                                  | augmentation_data[N]  |                     |     |+--------------------+|\",\n        \"                                  | program               |                     |     +-LSDA-----------------+\",\n        \"                                  +-CIE-------------------+   +-----------------+     | ...                  |\",\n        \"                                  | ...                   |   |                       +----------------------+\",\n        \"                                  +-FDE-------------------+   |\",\n        \"                                  | ...                   |   |\",\n        \"                                  +-----------------------+   |\",\n        \"                                                              +----> personality_routine(=__gxx_personality_v0@libstdc++.so)\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    class ErrorEntry:\n        def __init__(self, *args):\n            self.tag = \"error\"\n            assert len(args) == 2\n            self.msg1 = args[0]\n            self.msg2 = args[1]\n            return\n\n        def __str__(self):\n            msg = \"[!] {:s}\\n{:s}\".format(self.msg1, self.msg2)\n            return msg\n\n    class SeparatorEntry:\n        def __init__(self, *args):\n            self.tag = \"separator\"\n            assert 2 <= len(args) <= 3\n            self.pos = args[0]\n            self.name = args[1]\n            if len(args) == 3 and args[2] is not None:\n                self.extra = args[2]\n            else:\n                self.extra = \"\"\n            return\n\n        def __str__(self):\n            if self.extra:\n                extra_s = \"  |  {:s}\".format(self.extra)\n            else:\n                extra_s = \"\"\n            msg = \"[{:#06x}] {:4s}{:s}\".format(self.pos, self.name, extra_s)\n            msg = titlify(msg, color=\"red\", msg_color=\"red\")\n            return msg\n\n    class DataEntry:\n        def __init__(self, *args):\n            self.tag = \"data\"\n            assert 3 <= len(args) <= 5\n            self.pos = args[0]\n            self.raw_data = args[1]\n            self.name = args[2]\n            if len(args) >= 4 and args[3] is not None:\n                self.value = args[3]\n            else:\n                self.value = \"\"\n            if len(args) == 5 and args[4] is not None:\n                self.extra = args[4]\n            else:\n                self.extra = \"\"\n            return\n\n        def __str__(self):\n            pos_s = \"[{:#08x}|+{:#06x}]\".format(self.sec.offset + self.pos, self.pos)\n\n            if self.raw_data is None:\n                raw_data_s = \"\"\n            elif isinstance(self.raw_data, int):\n                raw_data_s = \"{:02x}\".format(self.raw_data)\n            elif isinstance(self.raw_data, bytes):\n                raw_data_s = \" \".join([\"{:02x}\".format(x) for x in self.raw_data])\n            else:\n                raise\n\n            if isinstance(self.value, str):\n                value_s = self.value\n            elif isinstance(self.value, int):\n                value_s = \"{:#018x}\".format(self.value)\n            elif isinstance(self.value, list):\n                value_s = \" \".join([\"{:#018x}\".format(x) for x in self.value])\n            else:\n                raise\n\n            if self.extra:\n                extra_s = \"  |  {:s}\".format(self.extra)\n            else:\n                extra_s = \"\"\n\n            if self.value is not None:\n                msg = \"{:s} {:<23s} {:<30s}: {:<18s}{:s}\".format(\n                    pos_s, raw_data_s, self.name, value_s, extra_s,\n                )\n            else:\n                msg = \"{:s} {:<23s} {:<50s}{:s}\".format(\n                    pos_s, raw_data_s, self.name, extra_s,\n                )\n            return msg\n\n        def add_sec(self, sec):\n            self.sec = sec\n            return\n\n    def format_entry(self, sec, entries):\n        out = []\n        out.append(titlify(sec.name))\n\n        # hexdump\n        if self.args.hexdump:\n            out.append(hexdump(sec.data, show_symbol=False, base=sec.offset))\n\n        # print details\n        fmt = \"[{:<8}|+{:<6}] {:<23s} {:<30s}: {:<18s}  |  {:s}\"\n        legend = [\"FileOff\", \"Offset\", \"Raw bytes\", \"Name\", \"Value\", \"Extra Information\"]\n        out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # print each entries\n        for entry in entries:\n            if entry.tag == \"data\":\n                entry.add_sec(sec)\n            out.append(str(entry))\n        return out\n\n    def get_uleb128(self, data, pos):\n        acc = 0\n        i = 0\n        while True:\n            if i == 10:\n                return pos, 0xffff_ffff_ffff_ffff\n            pos, b = self.read_1ubyte(data, pos)\n            acc |= (b & 0x7f) << (i * 7)\n            if (b & 0x80) == 0:\n                return pos, acc\n            i += 1\n\n    def get_sleb128(self, data, pos):\n        orig_pos = pos\n        pos, acc = self.get_uleb128(data, pos)\n        length = pos - orig_pos\n        sleb_sign_mask = 1 << (length * 7 - 1)\n        if (acc & sleb_sign_mask) == 0:\n            return pos, acc\n        else:\n            sleb_value_mask = sleb_sign_mask - 1\n            sleb_value = acc & sleb_value_mask\n            bit_len = len(\"{:b}\".format(sleb_value))\n            real_sign_mask = 1 << bit_len\n            real_value_mask = real_sign_mask - 1\n            return pos, -1 * (((~sleb_value) & real_value_mask) + 1)\n\n    def read_1ubyte(self, data, pos):\n        acc = data[pos]\n        return pos + 1, acc\n\n    def read_1sbyte(self, data, pos):\n        pB = lambda a: struct.pack(\"<B\", a & 0xff)\n        ub = lambda a: struct.unpack(\"<b\", a)[0]\n        u2i = lambda a: ub(pB(a))\n        acc = data[pos]\n        return pos + 1, u2i(acc)\n\n    def read_2ubyte(self, data, pos):\n        acc = (data[pos + 1] << 8) | data[pos]\n        return pos + 2, acc\n\n    def read_2sbyte(self, data, pos):\n        pH = lambda a: struct.pack(\"<H\", a & 0xffff)\n        uh = lambda a: struct.unpack(\"<h\", a)[0]\n        u2i = lambda a: uh(pH(a))\n        acc = (data[pos + 1] << 8) | data[pos]\n        return pos + 2, u2i(acc)\n\n    def read_4ubyte(self, data, pos):\n        acc = (data[pos + 3] << 24) | (data[pos + 2] << 16)\n        acc |= (data[pos + 1] << 8) | data[pos]\n        return pos + 4, acc\n\n    def read_4sbyte(self, data, pos):\n        pI = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        u2i = lambda a: ui(pI(a))\n        acc = (data[pos + 3] << 24) | (data[pos + 2] << 16)\n        acc |= (data[pos + 1] << 8) | data[pos]\n        return pos + 4, u2i(acc)\n\n    def read_8ubyte(self, data, pos):\n        acc = (data[pos + 7] << 56) | (data[pos + 6] << 48)\n        acc |= (data[pos + 5] << 40) | (data[pos + 4] << 32)\n        acc |= (data[pos + 3] << 24) | (data[pos + 2] << 16)\n        acc |= (data[pos + 1] << 8) | data[pos]\n        return pos + 8, acc\n\n    def read_8sbyte(self, data, pos):\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        u2i = lambda a: uq(pQ(a))\n        acc = (data[pos + 7] << 56) | (data[pos + 6] << 48)\n        acc |= (data[pos + 5] << 40) | (data[pos + 4] << 32)\n        acc |= (data[pos + 3] << 24) | (data[pos + 2] << 16)\n        acc |= (data[pos + 1] << 8) | data[pos]\n        return pos + 8, u2i(acc)\n\n    # FDE data encoding\n    DW_EH_PE_ptr      = 0x00\n    DW_EH_PE_uleb128  = 0x01\n    DW_EH_PE_udata2   = 0x02\n    DW_EH_PE_udata4   = 0x03\n    DW_EH_PE_udata8   = 0x04\n    DW_EH_PE_signed   = 0x08 # noqa: F841\n    DW_EH_PE_sleb128  = 0x09\n    DW_EH_PE_sdata2   = 0x0a\n    DW_EH_PE_sdata4   = 0x0b\n    DW_EH_PE_sdata8   = 0x0c\n    # FDE flags\n    DW_EH_PE_absptr   = 0x00\n    DW_EH_PE_pcrel    = 0x10\n    DW_EH_PE_textrel  = 0x20\n    DW_EH_PE_datarel  = 0x30\n    DW_EH_PE_funcrel  = 0x40\n    DW_EH_PE_aligned  = 0x50\n    DW_EH_PE_indirect = 0x80\n    DW_EH_PE_omit     = 0xff\n\n    def read_encoded(self, encoding, data, pos):\n        if (encoding & 0xf) == self.DW_EH_PE_ptr:\n            if self.elf.e_class == Elf.ELF_32_BITS:\n                pos, res = self.read_4ubyte(data, pos)\n            else:\n                pos, res = self.read_8ubyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_uleb128:\n            pos, res = self.get_uleb128(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_sleb128:\n            pos, res = self.get_sleb128(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_udata2:\n            pos, res = self.read_2ubyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_udata4:\n            pos, res = self.read_4ubyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_udata8:\n            pos, res = self.read_8ubyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_sdata2:\n            pos, res = self.read_2sbyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_sdata4:\n            pos, res = self.read_4sbyte(data, pos)\n        elif (encoding & 0xf) == self.DW_EH_PE_sdata8:\n            pos, res = self.read_8sbyte(data, pos)\n        else:\n            raise\n        return pos, res\n\n    def get_encoding_str(self, fde_encoding):\n        if fde_encoding == self.DW_EH_PE_omit:\n            return \"omit\"\n        s = []\n        if (fde_encoding & 0xf) == self.DW_EH_PE_ptr:\n            s.append(\"ptr\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_uleb128:\n            s.append(\"uleb128\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_sleb128:\n            s.append(\"sleb128\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_udata2:\n            s.append(\"udata2\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_sdata2:\n            s.append(\"sdata2\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_udata4:\n            s.append(\"udata4\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_sdata4:\n            s.append(\"sdata4\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_udata8:\n            s.append(\"udata8\")\n        elif (fde_encoding & 0xf) == self.DW_EH_PE_sdata8:\n            s.append(\"sdata8\")\n        if (fde_encoding & 0x70) == self.DW_EH_PE_absptr:\n            s.append(\"absptr\")\n        elif (fde_encoding & 0x70) == self.DW_EH_PE_pcrel:\n            s.append(\"pcrel\")\n        elif (fde_encoding & 0x70) == self.DW_EH_PE_textrel:\n            s.append(\"textrel\")\n        elif (fde_encoding & 0x70) == self.DW_EH_PE_datarel:\n            s.append(\"datarel\")\n        elif (fde_encoding & 0x70) == self.DW_EH_PE_funcrel:\n            s.append(\"funcrel\")\n        elif (fde_encoding & 0x70) == self.DW_EH_PE_aligned:\n            s.append(\"aligned\")\n        if (fde_encoding & 0x80) == self.DW_EH_PE_indirect:\n            s.append(\"indirect\")\n        return \",\".join(s)\n\n    def encoded_ptr_size(self, encoding, ptr_size):\n        if (encoding & 0xf) == self.DW_EH_PE_ptr:\n            return ptr_size\n        elif (encoding & 0xf) in [self.DW_EH_PE_udata2, self.DW_EH_PE_sdata2]:\n            return 2\n        elif (encoding & 0xf) in [self.DW_EH_PE_udata4, self.DW_EH_PE_sdata4]:\n            return 4\n        elif (encoding & 0xf) in [self.DW_EH_PE_udata8, self.DW_EH_PE_sdata8]:\n            return 8\n        elif encoding == self.DW_EH_PE_omit:\n            return 0\n        err(\"Unsupported pointer encoding: {:#x}, assuming pointer size of {:d}\".format(\n            encoding, ptr_size,\n        ))\n        return 0\n\n    def parse_eh_frame_hdr(self, eh_frame_hdr):\n        data = eh_frame_hdr.data\n        shdr = self.elf.get_shdr(\".eh_frame_hdr\")\n        load_base = self.elf.get_phdr(Elf.Phdr.PT_LOAD).p_vaddr\n\n        entries = []\n        pos = 0\n\n        try:\n            new_pos, version = self.read_1ubyte(data, pos)\n            entries.append(self.DataEntry(pos, data[pos:new_pos], \"version\", version))\n            pos = new_pos\n\n            new_pos, eh_frame_ptr_enc = self.read_1ubyte(data, pos)\n            encoding_str = self.get_encoding_str(eh_frame_ptr_enc)\n            entries.append(self.DataEntry(\n                pos, data[pos:new_pos], \"eh_frame_ptr_enc\", eh_frame_ptr_enc,\n                \"encoding: {:s}\".format(encoding_str),\n            ))\n            pos = new_pos\n\n            new_pos, fde_count_enc = self.read_1ubyte(data, pos)\n            encoding_str = self.get_encoding_str(fde_count_enc)\n            entries.append(self.DataEntry(\n                pos, data[pos:new_pos], \"fde_count_enc\", fde_count_enc,\n                \"encoding: {:s}\".format(encoding_str),\n            ))\n            pos = new_pos\n\n            new_pos, table_enc = self.read_1ubyte(data, pos)\n            encoding_str = self.get_encoding_str(table_enc)\n            entries.append(self.DataEntry(\n                pos, data[pos:new_pos], \"table_enc\", table_enc,\n                \"encoding: {:s}\".format(encoding_str),\n            ))\n            pos = new_pos\n\n            eh_frame_ptr = 0\n            if eh_frame_ptr_enc != self.DW_EH_PE_omit:\n                new_pos, eh_frame_ptr = self.read_encoded(eh_frame_ptr_enc, data, pos)\n                if (eh_frame_ptr_enc & 0x70) == self.DW_EH_PE_pcrel:\n                    elf_offset = shdr.sh_offset + 4 + eh_frame_ptr\n                    if self.elf.is_pie():\n                        extra_s = \"vma: $codebase+{:#x}\".format(load_base + elf_offset)\n                    else:\n                        extra_s = \"vma: {:#x}\".format(load_base + elf_offset)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"eh_frame_ptr\", elf_offset, extra_s,\n                    ))\n                else:\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"eh_frame_ptr\", eh_frame_ptr,\n                    ))\n                pos = new_pos\n\n            fde_count = 0\n            if fde_count_enc != self.DW_EH_PE_omit:\n                new_pos, fde_count = self.read_encoded(fde_count_enc, data, pos)\n                entries.append(self.DataEntry(pos, data[pos:new_pos], \"fde_count\", fde_count))\n                pos = new_pos\n\n            table_cnt = 0\n            if table_enc == (self.DW_EH_PE_datarel | self.DW_EH_PE_sdata4):\n                while fde_count and data[pos:]:\n                    entries.append(self.SeparatorEntry(pos, \"Table[{:4d}]\".format(table_cnt)))\n\n                    new_pos, initial_loc = self.read_4sbyte(data, pos)\n                    initial_offset = shdr.sh_offset + initial_loc\n                    if self.elf.is_pie():\n                        extra_s = \"vma: $codebase+{:#x}\".format(load_base + initial_offset)\n                    else:\n                        extra_s = \"vma: {:#x}\".format(load_base + initial_offset)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"initial_loc\", initial_offset, extra_s,\n                    ))\n                    pos = new_pos\n\n                    new_pos, fde_offset = self.read_4sbyte(data, pos)\n                    fde_offset_adjusted = fde_offset - (eh_frame_ptr + 4)\n                    if self.elf.is_pie():\n                        extra_s = \"vma: $codebase+{:#x}\".format(load_base + shdr.sh_offset + fde_offset)\n                    else:\n                        extra_s = \"vma: {:#x}\".format(load_base + shdr.sh_offset + fde_offset)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"fde\", fde_offset_adjusted, extra_s,\n                    ))\n                    pos = new_pos\n\n                    table_cnt += 1\n        except (IndexError, ValueError):\n            _exc_type, exc_value, _exc_traceback = sys.exc_info()\n            entries.append(self.ErrorEntry(\"Parse Error\", exc_value))\n        return entries\n\n    def parse_eh_frame(self, eh_frame):\n        data = eh_frame.data\n        shdr = self.elf.get_shdr(\".eh_frame\")\n        load_base = self.elf.get_phdr(Elf.Phdr.PT_LOAD).p_vaddr\n\n        cies = []\n        entries = []\n        pos = 0\n\n        try:\n            while data[pos:]:\n                offset = pos\n                tmp_entries = []\n\n                # parse length\n                new_pos, unit_length = self.read_4ubyte(data, pos)\n                length = 4 # default\n                tmp_entries.append(self.DataEntry(\n                    pos, data[pos:new_pos], \"length\", unit_length,\n                ))\n                pos = new_pos\n                if unit_length == 0xffff_ffff:\n                    new_pos, unit_length = self.read_8ubyte(data, pos)\n                    length = 8\n                    tmp_entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"extended_length\", unit_length,\n                    ))\n                    pos = new_pos\n                if unit_length == 0:\n                    entries.append(self.SeparatorEntry(offset, \"Zero terminator\"))\n                    entries += tmp_entries\n                    tmp_entries = []\n                    continue\n\n                ptr_size = 4 if self.elf.e_class == Elf.ELF_32_BITS else 8\n                start = pos # use later\n                cie_end = pos + unit_length\n\n                # parse cie_id / cie_pointer\n                if length == 4:\n                    new_pos, cie_id = self.read_4ubyte(data, pos)\n                else:\n                    new_pos, cie_id = self.read_8ubyte(data, pos)\n                if cie_id == 0:\n                    tmp_entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"cie_id\", cie_id, \"type: CIE\",\n                    ))\n                else:\n                    extra_s = \"type: FDE, Associated_CIE: {:#x}(={:#x}-{:#x})\".format(\n                        start - cie_id, start, cie_id,\n                    )\n                    tmp_entries.append(\n                        self.DataEntry(pos, data[pos:new_pos], \"cie_pointer\", cie_id, extra_s,\n                    ))\n                pos = new_pos\n\n                version = 2\n                fde_encoding = 0\n                lsda_encoding = 0\n                initial_location = 0\n                vma_base = 0\n\n                if cie_id == 0:  # CIE parsing\n                    entries.append(self.SeparatorEntry(offset, \"CIE\"))\n                    entries += tmp_entries\n                    tmp_entries = []\n\n                    # parse version\n                    new_pos, version = self.read_1ubyte(data, pos)\n                    entries.append(self.DataEntry(pos, data[pos:new_pos], \"version\", version))\n                    pos = new_pos\n\n                    # parse augmentation string\n                    orig_pos = pos\n                    augmentation = \"\"\n                    while data[pos]:\n                        augmentation += chr(data[pos])\n                        pos += 1\n                    pos += 1 # skip NUL\n                    entries.append(self.DataEntry(\n                        orig_pos, data[orig_pos:pos],\n                        \"augmentation_string\", '\"{:s}\"'.format(augmentation),\n                    ))\n\n                    # parse ptr_size, segment_size\n                    segment_size = 0\n                    if version >= 4:\n                        new_pos, ptr_size = self.read_1ubyte(data, pos)\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], \"ptr_size\", ptr_size))\n                        pos = new_pos\n                        new_pos, segment_size = self.read_1ubyte(data, pos)\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], \"segment_size\", segment_size))\n                        pos = new_pos\n\n                    # parse code/data alignment factor\n                    new_pos, code_alignment_factor = self.get_uleb128(data, pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"code_alignment_factor\", code_alignment_factor,\n                    ))\n                    pos = new_pos\n                    new_pos, data_alignment_factor = self.get_sleb128(data, pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"data_alignment_factor\", data_alignment_factor,\n                    ))\n                    pos = new_pos\n\n                    # parse augmentation data\n                    if augmentation == \"eh\":\n                        if self.elf.e_class == Elf.ELF_32_BITS:\n                            new_pos, adjust = self.read_4ubyte(data, pos)\n                        else:\n                            new_pos, adjust = self.read_8ubyte(data, pos)\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], \"eh_data\", adjust))\n                        pos = new_pos\n\n                    if version == 1:\n                        new_pos, return_address_register = self.read_1ubyte(data, pos)\n                        ra_reg_name = self.get_register_name(return_address_register)\n                        extra_s = \"Reg: {:s}\".format(ra_reg_name)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            \"return_address_register\", return_address_register, extra_s,\n                        ))\n                        pos = new_pos\n                    else:\n                        new_pos, return_address_register = self.get_uleb128(data, pos)\n                        ra_reg_name = self.get_register_name(return_address_register)\n                        extra_s = \"Reg: {:s}\".format(ra_reg_name)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            \"return_address_register\", return_address_register, extra_s,\n                        ))\n                        pos = new_pos\n\n                    if augmentation[0] == \"z\":\n                        new_pos, augmentation_len = self.get_uleb128(data, pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"augmentation_len\", augmentation_len,\n                        ))\n                        pos = new_pos\n\n                        for cp in augmentation[1:]:\n                            if cp == \"R\":\n                                new_pos, fde_encoding = self.read_1ubyte(data, pos)\n                                encoding_str = self.get_encoding_str(fde_encoding)\n                                extra_s = \"FDE address encoding: {:s}\".format(encoding_str)\n                                entries.append(self.DataEntry(\n                                    pos, data[pos:new_pos], \"augmentation_data(R)\", fde_encoding, extra_s,\n                                ))\n                                pos = new_pos\n                            elif cp == \"L\":\n                                new_pos, lsda_encoding = self.read_1ubyte(data, pos)\n                                encoding_str = self.get_encoding_str(lsda_encoding)\n                                extra_s = \"LSDA pointer encoding: {:s}\".format(encoding_str)\n                                entries.append(self.DataEntry(\n                                    pos, data[pos:new_pos], \"augmentation_data(L)\", lsda_encoding, extra_s,\n                                ))\n                                pos = new_pos\n                            elif cp == \"P\":\n                                new_pos, p_encoding = self.read_1ubyte(data, pos)\n                                encoding_str = self.get_encoding_str(p_encoding)\n                                extra_s = \"Personality pointer encoding: {:s}\".format(encoding_str)\n                                entries.append(self.DataEntry(\n                                    pos, data[pos:new_pos], \"augmentation_data(P)\", p_encoding, extra_s,\n                                ))\n                                pos = new_pos\n                                new_pos, p_addr = self.read_encoded(p_encoding, data, pos)\n                                if (p_encoding & 0x70) == self.DW_EH_PE_pcrel:\n                                    p_addr += shdr.sh_offset + pos\n                                    if self.elf.is_pie():\n                                        extra_s = \"Personality pointer address: $codebase+{:#x}\".format(\n                                            load_base + p_addr,\n                                        )\n                                    else:\n                                        extra_s = \"Personality pointer address: {:#x}\".format(\n                                            load_base + p_addr,\n                                        )\n                                else:\n                                    extra_s = \"Personality pointer address\"\n                                entries.append(self.DataEntry(\n                                    pos, data[pos:new_pos], \"augmentation_data(P)\", p_addr, extra_s,\n                                ))\n                                pos = new_pos\n                            else: # unknown\n                                new_pos, x = self.read_1ubyte(data, pos)\n                                entries.append(self.DataEntry(\n                                    pos, data[pos:new_pos], \"augmentation_data({:s})\".format(cp), x,\n                                ))\n                                pos = new_pos\n\n                    if ptr_size == 4 or ptr_size == 8:\n                        cie = {}\n                        cie[\"cie_offset\"] = offset\n                        cie[\"augmentation\"] = augmentation\n                        cie[\"fde_encoding\"] = fde_encoding\n                        cie[\"lsda_encoding\"] = lsda_encoding\n                        cie[\"address_size\"] = ptr_size\n                        cie[\"code_alignment_factor\"] = code_alignment_factor\n                        cie[\"data_alignment_factor\"] = data_alignment_factor\n                        Cie = collections.namedtuple(\"Cie\", cie.keys())\n                        cie = Cie(*cie.values())\n                        cies.append(cie)\n\n                else: # FDE parsing\n                    cie = [x for x in cies if start - cie_id == x.cie_offset][0]\n\n                    entries.append(self.SeparatorEntry(offset, \"FDE\"))\n                    entries += tmp_entries # unit_length, cie_pointer\n                    tmp_entries = []\n\n                    ptr_size = self.encoded_ptr_size(cie.fde_encoding, cie.address_size)\n                    base = pos\n\n                    # parse pc_begin\n                    if ptr_size == 4:\n                        new_pos, initial_location = self.read_4ubyte(data, pos)\n                    elif ptr_size == 8:\n                        new_pos, initial_location = self.read_8ubyte(data, pos)\n                    if (cie.fde_encoding & 0x70) == self.DW_EH_PE_pcrel:\n                        vma_base = shdr.sh_offset + base + initial_location\n                        if ptr_size == 4:\n                            vma_base &= 0xffff_ffff\n                        elif ptr_size == 8:\n                            vma_base &= 0xffff_ffff_ffff_ffff\n                        if self.elf.is_pie():\n                            extra_s = \"pc_begin vma: $codebase+{:#x}\".format(load_base + vma_base)\n                        else:\n                            extra_s = \"pc_begin vma: {:#x}\".format(load_base + vma_base)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"pc_begin\", vma_base, extra_s,\n                        ))\n                    else:\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"pc_begin\", initial_location,\n                        ))\n                    pos = new_pos\n\n                    # parse pc_range\n                    if ptr_size == 4:\n                        new_pos, pc_range = self.read_4ubyte(data, pos)\n                    elif ptr_size == 8:\n                        new_pos, pc_range = self.read_8ubyte(data, pos)\n                    if (cie.fde_encoding & 0x70) == self.DW_EH_PE_pcrel:\n                        end_off = vma_base + pc_range\n                    else:\n                        end_off = initial_location + pc_range\n                    if ptr_size == 4:\n                        end_off &= 0xffff_ffff\n                    elif ptr_size == 8:\n                        end_off &= 0xffff_ffff_ffff_ffff\n                    if self.elf.is_pie():\n                        extra_s = \"pc_end vma: $codebase+{:#x}\".format(load_base + end_off)\n                    else:\n                        extra_s = \"pc_end vma: {:#x}\".format(load_base + end_off)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"pc_range\", pc_range, extra_s,\n                    ))\n                    pos = new_pos\n\n                    # parse augmentation\n                    if cie.augmentation[0] == \"z\":\n                        new_pos, augmentation_len = self.get_uleb128(data, pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"augmentation_len\", augmentation_len,\n                        ))\n                        pos = new_pos\n\n                        aug_end = pos + augmentation_len\n                        if augmentation_len:\n                            for cp in cie.augmentation[1:]:\n                                if cp == \"L\":\n                                    new_pos, lsda_pointer = self.read_encoded(cie.lsda_encoding, data, pos)\n                                    if (cie.lsda_encoding & 0x70) == self.DW_EH_PE_pcrel:\n                                        lsda_pointer += shdr.sh_offset + pos\n                                        if self.elf.is_pie():\n                                            extra_s = \"LSDA pointer vma: $codebase+{:#x}\".format(\n                                                load_base + lsda_pointer,\n                                            )\n                                        else:\n                                            extra_s = \"LSDA pointer vma: {:#x}\".format(\n                                                load_base + lsda_pointer,\n                                            )\n                                        entries.append(self.DataEntry(\n                                            pos, data[pos:new_pos],\n                                            \"augmentation_data(L)\", lsda_pointer, extra_s,\n                                        ))\n                                    else:\n                                        entries.append(self.DataEntry(\n                                            pos, data[pos:new_pos],\n                                            \"augmentation_data(L)\", lsda_pointer, \"LSDA pointer\",\n                                        ))\n                                    pos = new_pos\n                            if pos < aug_end:\n                                entries.append(self.DataEntry(pos, data[pos:aug_end], \"?\"))\n                            pos = aug_end\n\n                # common\n                entries += self.parse_cfa_program(data, pos, cie_end, vma_base, version, cie)\n                pos = cie_end\n        except (IndexError, ValueError):\n            _exc_type, exc_value, _exc_traceback = sys.exc_info()\n            entries.append(self.ErrorEntry(\"Parse Error\", exc_value))\n        return entries\n\n    DW_CFA_advance_loc                  = 0x40\n    DW_CFA_offset                       = 0x80\n    DW_CFA_restore                      = 0xc0\n    DW_CFA_nop                          = 0x00\n    DW_CFA_set_loc                      = 0x01\n    DW_CFA_advance_loc1                 = 0x02\n    DW_CFA_advance_loc2                 = 0x03\n    DW_CFA_advance_loc4                 = 0x04\n    DW_CFA_offset_extended              = 0x05\n    DW_CFA_restore_extended             = 0x06\n    DW_CFA_undefined                    = 0x07\n    DW_CFA_same_value                   = 0x08\n    DW_CFA_register                     = 0x09\n    DW_CFA_remember_state               = 0x0a\n    DW_CFA_restore_state                = 0x0b\n    DW_CFA_def_cfa                      = 0x0c\n    DW_CFA_def_cfa_register             = 0x0d\n    DW_CFA_def_cfa_offset               = 0x0e\n    DW_CFA_def_cfa_expression           = 0x0f\n    DW_CFA_expression                   = 0x10\n    DW_CFA_offset_extended_sf           = 0x11\n    DW_CFA_def_cfa_sf                   = 0x12\n    DW_CFA_def_cfa_offset_sf            = 0x13\n    DW_CFA_val_offset                   = 0x14\n    DW_CFA_val_offset_sf                = 0x15\n    DW_CFA_val_expression               = 0x16\n    DW_CFA_low_user                     = 0x1c # noqa: F841\n    DW_CFA_MIPS_advance_loc8            = 0x1d\n    DW_CFA_GNU_window_save              = 0x2d # dup\n    DW_CFA_AARCH64_negate_ra_state      = 0x2d # noqa: F841\n    DW_CFA_GNU_args_size                = 0x2e\n    DW_CFA_GNU_negative_offset_extended = 0x2f # noqa: F841\n    DW_CFA_high_user                    = 0x3f # noqa: F841\n\n    def get_register_name(self, reg):\n        if self.elf.e_machine == Elf.EM_X86_64:\n            REG_LIST = [\n                \"rax\", \"rdx\", \"rcx\", \"rbx\", \"rsi\", \"rdi\", \"rbp\", \"rsp\",\n                \"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"r13\", \"r14\", \"r15\",\n                \"rip\", \"xmm0\", \"xmm1\", \"xmm2\", \"xmm3\", \"xmm4\", \"xmm5\", \"xmm6\",\n                \"xmm7\", \"xmm8\", \"xmm9\", \"xmm10\", \"xmm11\", \"xmm12\", \"xmm13\", \"xmm14\",\n                \"xmm15\", \"st0\", \"st1\", \"st2\", \"st3\", \"st4\", \"st5\", \"st6\", \"st7\",\n                \"mm0\", \"mm1\", \"mm2\", \"mm3\", \"mm4\", \"mm5\", \"mm6\", \"mm7\",\n                \"rflags\", \"es\", \"cs\", \"ss\", \"ds\", \"fs\", \"gs\", \"???\",\n                \"???\", \"fs.base\", \"gs.base\", \"???\", \"???\", \"tr\", \"ldtr\", \"mxcsr\",\n                \"fcw\", \"fsw\",\n            ]\n        elif self.elf.e_machine == Elf.EM_386:\n            REG_LIST = [\n                \"eax\", \"ecx\", \"edx\", \"rbx\", \"esp\", \"ebp\", \"esi\", \"edi\",\n                \"eip\", \"eflags\", \"trapno\", \"st0\", \"st1\", \"st2\", \"st3\", \"st4\",\n                \"st5\", \"st6\", \"st7\", \"???\", \"???\", \"xmm0\", \"xmm1\", \"xmm2\",\n                \"xmm3\", \"xmm4\", \"xmm5\", \"xmm6\", \"xmm7\", \"mm0\", \"mm1\", \"mm2\",\n                \"mm3\", \"mm4\", \"mm5\", \"mm6\", \"mm7\", \"fctrl\", \"fstat\", \"mxcsr\",\n                \"es\", \"cs\", \"ss\", \"ds\", \"fs\", \"gs\",\n            ]\n        elif self.elf.e_machine == Elf.EM_ARM:\n            REG_LIST = [\n                \"r0\", \"r1\", \"r2\", \"r3\", \"r4\", \"r5\", \"r6\", \"r7\",\n                \"r8\", \"r9\", \"r10\", \"r11\", \"r12\", \"sp\", \"lr\", \"pc\",\n                \"f0\", \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\",\n            ] + [\"???\"] * 40 + [\n                \"s0\", \"s1\", \"s2\", \"s3\", \"s4\", \"s5\", \"s6\", \"s7\",\n                \"s8\", \"s9\", \"s10\", \"s11\", \"s12\", \"s13\", \"s14\", \"s15\",\n                \"s16\", \"s17\", \"s18\", \"s19\", \"s20\", \"s21\", \"s22\", \"s23\",\n                \"s24\", \"s25\", \"s26\", \"s27\", \"s28\", \"s29\", \"s30\", \"s31\",\n                \"f0\", \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\",\n                \"wcgr0\", \"wcgr1\", \"wcgr2\", \"wcgr3\", \"wcgr4\", \"wcgr5\", \"wcgr6\", \"wcgr7\",\n                \"wr0\", \"wr1\", \"wr2\", \"wr3\", \"wr4\", \"wr5\", \"wr6\", \"wr7\",\n                \"wr8\", \"wr9\", \"wr10\", \"wr11\", \"wr12\", \"wr13\", \"wr14\", \"wr15\",\n                \"spsr\", \"spsr_fiq\", \"spsr_irq\", \"spsr_abt\", \"spsr_und\", \"spsr_svc\",\n            ] + [\"???\"] * 10 + [\n                \"r8_usr\", \"r9_usr\", \"r10_usr\", \"r11_usr\", \"r12_usr\", \"r13_usr\", \"r14_usr\", \"r8_fiq\",\n                \"r9_fiq\", \"r10_fiq\", \"r11_fiq\", \"r12_fiq\", \"r13_fiq\", \"r14_fiq\", \"r13_irq\", \"r14_irq\",\n                \"r13_abt\", \"r14_abt\", \"r13_und\", \"r14_und\", \"r13_svc\", \"r14_svc\",\n            ] + [\"???\"] * 26 + [\n                \"wc0\", \"wc1\", \"wc2\", \"wc3\", \"wc4\", \"wc5\", \"wc6\", \"wc7\",\n            ]\n        elif self.elf.e_machine == Elf.EM_AARCH64:\n            REG_LIST = [\n                \"x0\", \"x1\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\", \"x7\",\n                \"x8\", \"x9\", \"x10\", \"x11\", \"x12\", \"x13\", \"x14\", \"x15\",\n                \"x16\", \"x17\", \"x18\", \"x19\", \"x20\", \"x21\", \"x22\", \"x23\",\n                \"x24\", \"x25\", \"x26\", \"x27\", \"x28\", \"x29\", \"x30\", \"sp\",\n                \"???\", \"elr\",\n            ] + [\"???\"] * 30 + [\n                \"v0\", \"v1\", \"v2\", \"v3\", \"v4\", \"v5\", \"v6\", \"v7\",\n                \"v8\", \"v9\", \"v10\", \"v11\", \"v12\", \"v13\", \"v14\", \"v15\",\n                \"v16\", \"v17\", \"v18\", \"v19\", \"v20\", \"v21\", \"v22\", \"v23\",\n                \"v24\", \"v25\", \"v26\", \"v27\", \"v28\", \"v29\", \"v30\", \"v31\",\n            ]\n        else:\n            # other arch is unimplemented\n            return \"r{:d}\".format(reg)\n\n        if reg < len(REG_LIST):\n            return REG_LIST[reg]\n        return \"???\"\n\n    def parse_cfa_program(self, data, pos, pos_end, vma_base, version, cie):\n        encoding = cie.fde_encoding\n        ptr_size = cie.address_size\n        code_align = cie.code_alignment_factor\n        data_align = cie.data_alignment_factor\n        pc = vma_base\n        indent = \" \" * 4\n\n        entries = []\n        entries.append(self.DataEntry(pos, None, \"program\"))\n        try:\n            while pos < pos_end:\n                new_pos, opcode = self.read_1ubyte(data, pos)\n\n                if opcode < self.DW_CFA_advance_loc:\n                    if opcode == self.DW_CFA_nop:\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], indent + \"nop\"))\n                    elif opcode == self.DW_CFA_set_loc:\n                        new_pos, op1 = self.read_encoded(encoding, data, new_pos)\n                        pc = vma_base + op1\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"set_loc {:#x} to {:#x}\".format(op1, pc),\n                        ))\n                    elif opcode == self.DW_CFA_advance_loc1:\n                        op1 = data[new_pos]\n                        new_pos += 1\n                        pc += op1 * code_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"advance_loc1 {:#x} to {:#x}\".format(op1, pc),\n                        ))\n                    elif opcode == self.DW_CFA_advance_loc2:\n                        new_pos, op1 = self.read_2ubyte(data, new_pos)\n                        pc += op1 * code_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"advance_loc2 {:#x} to {:#x}\".format(op1, pc),\n                        ))\n                    elif opcode == self.DW_CFA_advance_loc4:\n                        new_pos, op1 = self.read_4ubyte(data, new_pos)\n                        pc += op1 * code_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"advance_loc4 {:#x} to {:#x}\".format(op1, pc),\n                        ))\n                    elif opcode == self.DW_CFA_offset_extended:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        off = op2 * data_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"offset_extended r{:d} ({:s}) at cfa{:+#x}\".format(op1, regname, off),\n                        ))\n                    elif opcode == self.DW_CFA_restore_extended:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"restore_extended r{:d} ({:s})\".fomart(op1, regname),\n                        ))\n                    elif opcode == self.DW_CFA_undefined:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"undefined r{:d} ({:s})\".format(op1, regname),\n                        ))\n                    elif opcode == self.DW_CFA_same_value:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"same_value r{:d} ({:s})\".format(op1, regname),\n                        ))\n                    elif opcode == self.DW_CFA_register:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname1 = self.get_register_name(op1)\n                        regname2 = self.get_register_name(op2)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"register r{:d} ({:s}) in r{:d} ({:s})\".format(op1, regname1, op2, regname2),\n                        ))\n                    elif opcode == self.DW_CFA_remember_state:\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], indent + \"remember_state\"))\n                    elif opcode == self.DW_CFA_restore_state:\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], indent + \"restore_state\"))\n                    elif opcode == self.DW_CFA_def_cfa:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa r{:d} ({:s}) at offset {:#x}\".format(op1, regname, op2),\n                        ))\n                    elif opcode == self.DW_CFA_def_cfa_register:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa_register r{:d} ({:s})\".format(op1, regname),\n                        ))\n                    elif opcode == self.DW_CFA_def_cfa_offset:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa_offset {:#x}\".format(op1),\n                        ))\n                    elif opcode == self.DW_CFA_def_cfa_expression:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa_expression {:#x}\".format(op1),\n                        ))\n                        entries += self.parse_ops(version, ptr_size, op1, data, new_pos)\n                        new_pos += op1\n                    elif opcode == self.DW_CFA_expression:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"expression r{:d} ({:s})\".format(op1, regname),\n                        ))\n                        entries += self.parse_ops(version, ptr_size, op2, data, new_pos)\n                        new_pos += op2\n                    elif opcode == self.DW_CFA_offset_extended_sf:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        off = op2 * data_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"offset_extended_sf r{:d} ({:s}) at cfa{:+#x}\".format(op1, regname, off),\n                        ))\n                    elif opcode == self.DW_CFA_def_cfa_sf:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        off = op2 * data_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa_sf r{:d} ({:s}) at offset {:#x}\".format(op1, regname, off),\n                        ))\n                    elif opcode == self.DW_CFA_def_cfa_offset_sf:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"def_cfa_offset_sf {:#x}\".format(op1 * data_align),\n                        ))\n                    elif opcode == self.DW_CFA_val_offset:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        off = op2 * data_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"val_offset {:#x} at offset {:#x}\".format(op1, off),\n                        ))\n                    elif opcode == self.DW_CFA_val_offset_sf:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        off = op2 * data_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"val_offset_sf {:#x} at offset {:#x}\".format(op1, off),\n                        ))\n                    elif opcode == self.DW_CFA_val_expression:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        new_pos, op2 = self.get_uleb128(data, new_pos)\n                        regname = self.get_register_name(op1)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"val_expression r{:d} ({:s})\".format(op1, regname),\n                        ))\n                        entries += self.parse_ops(version, ptr_size, op2, data, new_pos)\n                        new_pos += op2\n                    elif opcode == self.DW_CFA_MIPS_advance_loc8:\n                        new_pos, op1 = self.read_8ubyte(data, new_pos)\n                        pc += op1 * code_align\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"MIPS_advance_loc8 {:#x} to {:#x}\".format(op1, pc),\n                        ))\n                    elif opcode == self.DW_CFA_GNU_window_save:\n                        if self.elf.e_machine == Elf.EM_AARCH64:\n                            entries.append(self.DataEntry(\n                                pos, data[pos:new_pos],\n                                indent + \"AARCH64_negate_ra_state\",\n                            ))\n                        else:\n                            entries.append(self.DataEntry(\n                                pos, data[pos:new_pos],\n                                indent + \"GNU_window_save\",\n                            ))\n                    elif opcode == self.DW_CFA_GNU_args_size:\n                        new_pos, op1 = self.get_uleb128(data, new_pos)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"args_size {:#x}\".format(op1),\n                        ))\n                    else:\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos],\n                            indent + \"??? {:#x}\".format(opcode),\n                        ))\n                elif opcode < self.DW_CFA_offset:\n                    op1 = opcode & 0x3f\n                    pc += op1 * code_align\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"advance_loc {:d} to {:#x}\".format(op1, pc),\n                    ))\n                elif opcode < self.DW_CFA_restore:\n                    op1 = opcode & 0x3f\n                    new_pos, op2 = self.get_uleb128(data, new_pos)\n                    regname = self.get_register_name(op1)\n                    off = op2 * data_align\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"offset r{:d} ({:s}) at cfa{:+#x}\".format(op1, regname, off),\n                    ))\n                else:\n                    op1 = opcode & 0x3f\n                    regname = self.get_register_name(op1)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"restore r{:d}\".format(op1),\n                    ))\n                pos = new_pos\n        except (IndexError, ValueError):\n            _exc_type, exc_value, _exc_traceback = sys.exc_info()\n            entries.append(self.ErrorEntry(\"Parse Error\", exc_value))\n        return entries\n\n    DW_OP_addr                 = 0x03  # Constant address\n    DW_OP_deref                = 0x06  #\n    DW_OP_const1u              = 0x08  # Unsigned 1-byte constant\n    DW_OP_const1s              = 0x09  # Signed 1-byte constant\n    DW_OP_const2u              = 0x0a  # Unsigned 2-byte constant\n    DW_OP_const2s              = 0x0b  # Signed 2-byte constant\n    DW_OP_const4u              = 0x0c  # Unsigned 4-byte constant\n    DW_OP_const4s              = 0x0d  # Signed 4-byte constant\n    DW_OP_const8u              = 0x0e  # Unsigned 8-byte constant\n    DW_OP_const8s              = 0x0f  # Signed 8-byte constant\n    DW_OP_constu               = 0x10  # Unsigned LEB128 constant\n    DW_OP_consts               = 0x11  # Signed LEB128 constant\n    DW_OP_dup                  = 0x12  #\n    DW_OP_drop                 = 0x13  #\n    DW_OP_over                 = 0x14  #\n    DW_OP_pick                 = 0x15  # 1-byte stack index\n    DW_OP_swap                 = 0x16  #\n    DW_OP_rot                  = 0x17  #\n    DW_OP_xderef               = 0x18  #\n    DW_OP_abs                  = 0x19  #\n    DW_OP_and                  = 0x1a  #\n    DW_OP_div                  = 0x1b  #\n    DW_OP_minus                = 0x1c  #\n    DW_OP_mod                  = 0x1d  #\n    DW_OP_mul                  = 0x1e  #\n    DW_OP_neg                  = 0x1f  #\n    DW_OP_not                  = 0x20  #\n    DW_OP_or                   = 0x21  #\n    DW_OP_plus                 = 0x22  #\n    DW_OP_plus_uconst          = 0x23  # Unsigned LEB128 addend\n    DW_OP_shl                  = 0x24  #\n    DW_OP_shr                  = 0x25  #\n    DW_OP_shra                 = 0x26  #\n    DW_OP_xor                  = 0x27  #\n    DW_OP_bra                  = 0x28  # Signed 2-byte constant\n    DW_OP_eq                   = 0x29  #\n    DW_OP_ge                   = 0x2a  #\n    DW_OP_gt                   = 0x2b  #\n    DW_OP_le                   = 0x2c  #\n    DW_OP_lt                   = 0x2d  #\n    DW_OP_ne                   = 0x2e  #\n    DW_OP_skip                 = 0x2f  # Signed 2-byte constant\n    DW_OP_lit0                 = 0x30  # Literal 0\n    DW_OP_lit1                 = 0x31  # Literal 1\n    DW_OP_lit2                 = 0x32  # Literal 2\n    DW_OP_lit3                 = 0x33  # Literal 3\n    DW_OP_lit4                 = 0x34  # Literal 4\n    DW_OP_lit5                 = 0x35  # Literal 5\n    DW_OP_lit6                 = 0x36  # Literal 6\n    DW_OP_lit7                 = 0x37  # Literal 7\n    DW_OP_lit8                 = 0x38  # Literal 8\n    DW_OP_lit9                 = 0x39  # Literal 9\n    DW_OP_lit10                = 0x3a  # Literal 10\n    DW_OP_lit11                = 0x3b  # Literal 11\n    DW_OP_lit12                = 0x3c  # Literal 12\n    DW_OP_lit13                = 0x3d  # Literal 13\n    DW_OP_lit14                = 0x3e  # Literal 14\n    DW_OP_lit15                = 0x3f  # Literal 15\n    DW_OP_lit16                = 0x40  # Literal 16\n    DW_OP_lit17                = 0x41  # Literal 17\n    DW_OP_lit18                = 0x42  # Literal 18\n    DW_OP_lit19                = 0x43  # Literal 19\n    DW_OP_lit20                = 0x44  # Literal 20\n    DW_OP_lit21                = 0x45  # Literal 21\n    DW_OP_lit22                = 0x46  # Literal 22\n    DW_OP_lit23                = 0x47  # Literal 23\n    DW_OP_lit24                = 0x48  # Literal 24\n    DW_OP_lit25                = 0x49  # Literal 25\n    DW_OP_lit26                = 0x4a  # Literal 26\n    DW_OP_lit27                = 0x4b  # Literal 27\n    DW_OP_lit28                = 0x4c  # Literal 28\n    DW_OP_lit29                = 0x4d  # Literal 29\n    DW_OP_lit30                = 0x4e  # Literal 30\n    DW_OP_lit31                = 0x4f  # Literal 31\n    DW_OP_reg0                 = 0x50  # Register 0\n    DW_OP_reg1                 = 0x51  # Register 1\n    DW_OP_reg2                 = 0x52  # Register 2\n    DW_OP_reg3                 = 0x53  # Register 3\n    DW_OP_reg4                 = 0x54  # Register 4\n    DW_OP_reg5                 = 0x55  # Register 5\n    DW_OP_reg6                 = 0x56  # Register 6\n    DW_OP_reg7                 = 0x57  # Register 7\n    DW_OP_reg8                 = 0x58  # Register 8\n    DW_OP_reg9                 = 0x59  # Register 9\n    DW_OP_reg10                = 0x5a  # Register 10\n    DW_OP_reg11                = 0x5b  # Register 11\n    DW_OP_reg12                = 0x5c  # Register 12\n    DW_OP_reg13                = 0x5d  # Register 13\n    DW_OP_reg14                = 0x5e  # Register 14\n    DW_OP_reg15                = 0x5f  # Register 15\n    DW_OP_reg16                = 0x60  # Register 16\n    DW_OP_reg17                = 0x61  # Register 17\n    DW_OP_reg18                = 0x62  # Register 18\n    DW_OP_reg19                = 0x63  # Register 19\n    DW_OP_reg20                = 0x64  # Register 20\n    DW_OP_reg21                = 0x65  # Register 21\n    DW_OP_reg22                = 0x66  # Register 22\n    DW_OP_reg23                = 0x67  # Register 24\n    DW_OP_reg24                = 0x68  # Register 24\n    DW_OP_reg25                = 0x69  # Register 25\n    DW_OP_reg26                = 0x6a  # Register 26\n    DW_OP_reg27                = 0x6b  # Register 27\n    DW_OP_reg28                = 0x6c  # Register 28\n    DW_OP_reg29                = 0x6d  # Register 29\n    DW_OP_reg30                = 0x6e  # Register 30\n    DW_OP_reg31                = 0x6f  # Register 31\n    DW_OP_breg0                = 0x70  # Base register 0\n    DW_OP_breg1                = 0x71  # Base register 1\n    DW_OP_breg2                = 0x72  # Base register 2\n    DW_OP_breg3                = 0x73  # Base register 3\n    DW_OP_breg4                = 0x74  # Base register 4\n    DW_OP_breg5                = 0x75  # Base register 5\n    DW_OP_breg6                = 0x76  # Base register 6\n    DW_OP_breg7                = 0x77  # Base register 7\n    DW_OP_breg8                = 0x78  # Base register 8\n    DW_OP_breg9                = 0x79  # Base register 9\n    DW_OP_breg10               = 0x7a  # Base register 10\n    DW_OP_breg11               = 0x7b  # Base register 11\n    DW_OP_breg12               = 0x7c  # Base register 12\n    DW_OP_breg13               = 0x7d  # Base register 13\n    DW_OP_breg14               = 0x7e  # Base register 14\n    DW_OP_breg15               = 0x7f  # Base register 15\n    DW_OP_breg16               = 0x80  # Base register 16\n    DW_OP_breg17               = 0x81  # Base register 17\n    DW_OP_breg18               = 0x82  # Base register 18\n    DW_OP_breg19               = 0x83  # Base register 19\n    DW_OP_breg20               = 0x84  # Base register 20\n    DW_OP_breg21               = 0x85  # Base register 21\n    DW_OP_breg22               = 0x86  # Base register 22\n    DW_OP_breg23               = 0x87  # Base register 23\n    DW_OP_breg24               = 0x88  # Base register 24\n    DW_OP_breg25               = 0x89  # Base register 25\n    DW_OP_breg26               = 0x8a  # Base register 26\n    DW_OP_breg27               = 0x8b  # Base register 27\n    DW_OP_breg28               = 0x8c  # Base register 28\n    DW_OP_breg29               = 0x8d  # Base register 29\n    DW_OP_breg30               = 0x8e  # Base register 30\n    DW_OP_breg31               = 0x8f  # Base register 31\n    DW_OP_regx                 = 0x90  # Unsigned LEB128 register\n    DW_OP_fbreg                = 0x91  # Signed LEB128 offset\n    DW_OP_bregx                = 0x92  # ULEB128 register followed by SLEB128 off\n    DW_OP_piece                = 0x93  # ULEB128 size of piece addressed\n    DW_OP_deref_size           = 0x94  # 1-byte size of data retrieved\n    DW_OP_xderef_size          = 0x95  # 1-byte size of data retrieved\n    DW_OP_nop                  = 0x96  #\n    DW_OP_push_object_address  = 0x97  #\n    DW_OP_call2                = 0x98  #\n    DW_OP_call4                = 0x99  #\n    DW_OP_call_ref             = 0x9a  #\n    DW_OP_form_tls_address     = 0x9b  # TLS offset to address in current thread\n    DW_OP_call_frame_cfa       = 0x9c  # CFA as determined by CFI\n    DW_OP_bit_piece            = 0x9d  # ULEB128 size and ULEB128 offset in bits\n    DW_OP_implicit_value       = 0x9e  # DW_FORM_block follows opcode\n    DW_OP_stack_value          = 0x9f  # No operands, special like DW_OP_piece\n    #\n    DW_OP_implicit_pointer     = 0xa0  #\n    DW_OP_addrx                = 0xa1  #\n    DW_OP_constx               = 0xa2  #\n    DW_OP_entry_value          = 0xa3  #\n    DW_OP_const_type           = 0xa4  #\n    DW_OP_regval_type          = 0xa5  #\n    DW_OP_deref_type           = 0xa6  #\n    DW_OP_xderef_type          = 0xa7  #\n    DW_OP_convert              = 0xa8  #\n    DW_OP_reinterpret          = 0xa9  #\n    # GNU extensions\n    DW_OP_GNU_push_tls_address = 0xe0  #\n    DW_OP_GNU_uninit           = 0xf0  #\n    DW_OP_GNU_encoded_addr     = 0xf1  #\n    DW_OP_GNU_implicit_pointer = 0xf2  #\n    DW_OP_GNU_entry_value      = 0xf3  #\n    DW_OP_GNU_const_type       = 0xf4  #\n    DW_OP_GNU_regval_type      = 0xf5  #\n    DW_OP_GNU_deref_type       = 0xf6  #\n    DW_OP_GNU_convert          = 0xf7  #\n    DW_OP_GNU_reinterpret      = 0xf9  #\n    DW_OP_GNU_parameter_ref    = 0xfa  #\n    # GNU Debug Fission extensions\n    DW_OP_GNU_addr_index       = 0xfb  #\n    DW_OP_GNU_const_index      = 0xfc  #\n    DW_OP_GNU_variable_value   = 0xfd  #\n    DW_OP_lo_user              = 0xe0  # Implementation-defined range start\n    DW_OP_hi_user              = 0xff  # Implementation-defined range end # noqa: F841\n\n    DWARF_ONE_KNOWN_DW_OP = {\n        DW_OP_GNU_addr_index       : \"GNU_addr_index\",\n        DW_OP_GNU_const_index      : \"GNU_const_index\",\n        DW_OP_GNU_const_type       : \"GNU_const_type\",\n        DW_OP_GNU_convert          : \"GNU_convert\",\n        DW_OP_GNU_deref_type       : \"GNU_deref_type\",\n        DW_OP_GNU_encoded_addr     : \"GNU_encoded_addr\",\n        DW_OP_GNU_entry_value      : \"GNU_entry_value\",\n        DW_OP_GNU_implicit_pointer : \"GNU_implicit_pointer\",\n        DW_OP_GNU_parameter_ref    : \"GNU_parameter_ref\",\n        DW_OP_GNU_push_tls_address : \"GNU_push_tls_address\",\n        DW_OP_GNU_regval_type      : \"GNU_regval_type\",\n        DW_OP_GNU_reinterpret      : \"GNU_reinterpret\",\n        DW_OP_GNU_uninit           : \"GNU_uninit\",\n        DW_OP_GNU_variable_value   : \"GNU_variable_value\",\n        DW_OP_abs                  : \"abs\",\n        DW_OP_addr                 : \"addr\",\n        DW_OP_addrx                : \"addrx\",\n        DW_OP_and                  : \"and\",\n        DW_OP_bit_piece            : \"bit_piece\",\n        DW_OP_bra                  : \"bra\",\n        DW_OP_breg0                : \"breg0\",\n        DW_OP_breg1                : \"breg1\",\n        DW_OP_breg2                : \"breg2\",\n        DW_OP_breg3                : \"breg3\",\n        DW_OP_breg4                : \"breg4\",\n        DW_OP_breg5                : \"breg5\",\n        DW_OP_breg6                : \"breg6\",\n        DW_OP_breg7                : \"breg7\",\n        DW_OP_breg8                : \"breg8\",\n        DW_OP_breg9                : \"breg9\",\n        DW_OP_breg10               : \"breg10\",\n        DW_OP_breg11               : \"breg11\",\n        DW_OP_breg12               : \"breg12\",\n        DW_OP_breg13               : \"breg13\",\n        DW_OP_breg14               : \"breg14\",\n        DW_OP_breg15               : \"breg15\",\n        DW_OP_breg16               : \"breg16\",\n        DW_OP_breg17               : \"breg17\",\n        DW_OP_breg18               : \"breg18\",\n        DW_OP_breg19               : \"breg19\",\n        DW_OP_breg20               : \"breg20\",\n        DW_OP_breg21               : \"breg21\",\n        DW_OP_breg22               : \"breg22\",\n        DW_OP_breg23               : \"breg23\",\n        DW_OP_breg24               : \"breg24\",\n        DW_OP_breg25               : \"breg25\",\n        DW_OP_breg26               : \"breg26\",\n        DW_OP_breg27               : \"breg27\",\n        DW_OP_breg28               : \"breg28\",\n        DW_OP_breg29               : \"breg29\",\n        DW_OP_breg30               : \"breg30\",\n        DW_OP_breg31               : \"breg31\",\n        DW_OP_bregx                : \"bregx\",\n        DW_OP_call2                : \"call2\",\n        DW_OP_call4                : \"call4\",\n        DW_OP_call_frame_cfa       : \"call_frame_cfa\",\n        DW_OP_call_ref             : \"call_ref\",\n        DW_OP_const1s              : \"const1s\",\n        DW_OP_const1u              : \"const1u\",\n        DW_OP_const2s              : \"const2s\",\n        DW_OP_const2u              : \"const2u\",\n        DW_OP_const4s              : \"const4s\",\n        DW_OP_const4u              : \"const4u\",\n        DW_OP_const8s              : \"const8s\",\n        DW_OP_const8u              : \"const8u\",\n        DW_OP_const_type           : \"const_type\",\n        DW_OP_consts               : \"consts\",\n        DW_OP_constu               : \"constu\",\n        DW_OP_constx               : \"constx\",\n        DW_OP_convert              : \"convert\",\n        DW_OP_deref                : \"deref\",\n        DW_OP_deref_size           : \"deref_size\",\n        DW_OP_deref_type           : \"deref_type\",\n        DW_OP_div                  : \"div\",\n        DW_OP_drop                 : \"drop\",\n        DW_OP_dup                  : \"dup\",\n        DW_OP_entry_value          : \"entry_value\",\n        DW_OP_eq                   : \"eq\",\n        DW_OP_fbreg                : \"fbreg\",\n        DW_OP_form_tls_address     : \"form_tls_address\",\n        DW_OP_ge                   : \"ge\",\n        DW_OP_gt                   : \"gt\",\n        DW_OP_implicit_pointer     : \"implicit_pointer\",\n        DW_OP_implicit_value       : \"implicit_value\",\n        DW_OP_le                   : \"le\",\n        DW_OP_lit0                 : \"lit0\",\n        DW_OP_lit1                 : \"lit1\",\n        DW_OP_lit2                 : \"lit2\",\n        DW_OP_lit3                 : \"lit3\",\n        DW_OP_lit4                 : \"lit4\",\n        DW_OP_lit5                 : \"lit5\",\n        DW_OP_lit6                 : \"lit6\",\n        DW_OP_lit7                 : \"lit7\",\n        DW_OP_lit8                 : \"lit8\",\n        DW_OP_lit9                 : \"lit9\",\n        DW_OP_lit10                : \"lit10\",\n        DW_OP_lit11                : \"lit11\",\n        DW_OP_lit12                : \"lit12\",\n        DW_OP_lit13                : \"lit13\",\n        DW_OP_lit14                : \"lit14\",\n        DW_OP_lit15                : \"lit15\",\n        DW_OP_lit16                : \"lit16\",\n        DW_OP_lit17                : \"lit17\",\n        DW_OP_lit18                : \"lit18\",\n        DW_OP_lit19                : \"lit19\",\n        DW_OP_lit20                : \"lit20\",\n        DW_OP_lit21                : \"lit21\",\n        DW_OP_lit22                : \"lit22\",\n        DW_OP_lit23                : \"lit23\",\n        DW_OP_lit24                : \"lit24\",\n        DW_OP_lit25                : \"lit25\",\n        DW_OP_lit26                : \"lit26\",\n        DW_OP_lit27                : \"lit27\",\n        DW_OP_lit28                : \"lit28\",\n        DW_OP_lit29                : \"lit29\",\n        DW_OP_lit30                : \"lit30\",\n        DW_OP_lit31                : \"lit31\",\n        DW_OP_lt                   : \"lt\",\n        DW_OP_minus                : \"minus\",\n        DW_OP_mod                  : \"mod\",\n        DW_OP_mul                  : \"mul\",\n        DW_OP_ne                   : \"ne\",\n        DW_OP_neg                  : \"neg\",\n        DW_OP_nop                  : \"nop\",\n        DW_OP_not                  : \"not\",\n        DW_OP_or                   : \"or\",\n        DW_OP_over                 : \"over\",\n        DW_OP_pick                 : \"pick\",\n        DW_OP_piece                : \"piece\",\n        DW_OP_plus                 : \"plus\",\n        DW_OP_plus_uconst          : \"plus_uconst\",\n        DW_OP_push_object_address  : \"push_object_address\",\n        DW_OP_reg0                 : \"reg0\",\n        DW_OP_reg1                 : \"reg1\",\n        DW_OP_reg2                 : \"reg2\",\n        DW_OP_reg3                 : \"reg3\",\n        DW_OP_reg4                 : \"reg4\",\n        DW_OP_reg5                 : \"reg5\",\n        DW_OP_reg6                 : \"reg6\",\n        DW_OP_reg7                 : \"reg7\",\n        DW_OP_reg8                 : \"reg8\",\n        DW_OP_reg9                 : \"reg9\",\n        DW_OP_reg10                : \"reg10\",\n        DW_OP_reg11                : \"reg11\",\n        DW_OP_reg12                : \"reg12\",\n        DW_OP_reg13                : \"reg13\",\n        DW_OP_reg14                : \"reg14\",\n        DW_OP_reg15                : \"reg15\",\n        DW_OP_reg16                : \"reg16\",\n        DW_OP_reg17                : \"reg17\",\n        DW_OP_reg18                : \"reg18\",\n        DW_OP_reg19                : \"reg19\",\n        DW_OP_reg20                : \"reg20\",\n        DW_OP_reg21                : \"reg21\",\n        DW_OP_reg22                : \"reg22\",\n        DW_OP_reg23                : \"reg23\",\n        DW_OP_reg24                : \"reg24\",\n        DW_OP_reg25                : \"reg25\",\n        DW_OP_reg26                : \"reg26\",\n        DW_OP_reg27                : \"reg27\",\n        DW_OP_reg28                : \"reg28\",\n        DW_OP_reg29                : \"reg29\",\n        DW_OP_reg30                : \"reg30\",\n        DW_OP_reg31                : \"reg31\",\n        DW_OP_regval_type          : \"regval_type\",\n        DW_OP_regx                 : \"regx\",\n        DW_OP_reinterpret          : \"reinterpret\",\n        DW_OP_rot                  : \"rot\",\n        DW_OP_shl                  : \"shl\",\n        DW_OP_shr                  : \"shr\",\n        DW_OP_shra                 : \"shra\",\n        DW_OP_skip                 : \"skip\",\n        DW_OP_stack_value          : \"stack_value\",\n        DW_OP_swap                 : \"swap\",\n        DW_OP_xderef               : \"xderef\",\n        DW_OP_xderef_size          : \"xderef_size\",\n        DW_OP_xderef_type          : \"xderef_type\",\n        DW_OP_xor                  : \"xor\",\n    }\n\n    def dwarf_locexpr_opcode_string(self, code):\n        if code in self.DWARF_ONE_KNOWN_DW_OP:\n            return self.DWARF_ONE_KNOWN_DW_OP[code]\n        elif code >= self.DW_OP_lo_user:\n            return \"lo_user+{:#x}\".format(code - self.DW_OP_lo_user)\n        else:\n            return \"??? ({:#x})\".format(code)\n\n    def parse_ops(self, vers, addrsize, length, data, pos, indent_n=0):\n        indent = \" \" * ((indent_n + 2) * 4)\n        entries = []\n        ref_size = addrsize if vers < 3 else 0\n\n        if length == 0:\n            entries.append(self.DataEntry(pos, None, indent + \"(empty)\"))\n            return entries\n\n        offset = 0\n        try:\n            while length:\n                new_pos, op = self.read_1ubyte(data, pos)\n                op_name = self.dwarf_locexpr_opcode_string(op)\n\n                if op in [self.DW_OP_addr]:\n                    if addrsize == 4:\n                        new_pos, d = self.read_4ubyte(data, new_pos)\n                    elif addrsize == 8:\n                        new_pos, d = self.read_8ubyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_call_ref, self.DW_OP_GNU_variable_value]:\n                    if ref_size == 4:\n                        new_pos, d = self.read_4ubyte(data, new_pos)\n                    else:\n                        new_pos, d = self.read_8ubyte(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_deref]:\n                    typ = {4: \"uint\", 8: \"ulong\"}[addrsize]\n                    extra_s = \"pop; push *({:s}*)popped_value\".format(typ)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_xderef]:\n                    typ = {4: \"uint\", 8: \"ulong\"}[addrsize]\n                    extra_s = \"pop; pop; push *({:s}*)(popped_value2_as_segment:popped_value1)\".format(typ)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_deref_size]:\n                    new_pos, d = self.read_1ubyte(data, new_pos)\n                    typ = {1: \"uchar\", 2: \"ushort\", 4: \"uint\", 8: \"ulong\"}[d]\n                    extra_s = \"pop; push *({:s}*)popped_value\".format(typ)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_xderef_size]:\n                    new_pos, d = self.read_1ubyte(data, new_pos)\n                    typ = {1: \"uchar\", 2: \"ushort\", 4: \"uint\", 8: \"ulong\"}[d]\n                    extra_s = \"pop; pop; push *({:s}*)(popped_value2_as_segment:popped_value1)\".forma(typ)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_pick]:\n                    new_pos, d = self.read_1ubyte(data, new_pos)\n                    extra_s = \"push stack[{:d}]\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const1u]:\n                    new_pos, d = self.read_1ubyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const2u]:\n                    new_pos, d = self.read_2ubyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const4u]:\n                    new_pos, d = self.read_4ubyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const8u]:\n                    new_pos, d = self.read_8ubyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const1s]:\n                    new_pos, d = self.read_1sbyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const2u]:\n                    new_pos, d = self.read_2sbyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const4s]:\n                    new_pos, d = self.read_4sbyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_const8s]:\n                    new_pos, d = self.read_8sbyte(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_piece, self.DW_OP_regx, self.DW_OP_plus_uconst]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_constu]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_consts]:\n                    new_pos, d = self.get_sleb128(data, new_pos)\n                    extra_s = \"push {:#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_addrx, self.DW_OP_GNU_addr_index,\n                            self.DW_OP_constx, self.DW_OP_GNU_const_index]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_bit_piece]:\n                    new_pos, d1 = self.get_uleb128(data, new_pos)\n                    new_pos, d2 = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x},{:#x}\".format(offset, op_name, d1, d2),\n                    ))\n                elif op in [self.DW_OP_lit0, self.DW_OP_lit1, self.DW_OP_lit2, self.DW_OP_lit3,\n                            self.DW_OP_lit4, self.DW_OP_lit5, self.DW_OP_lit6, self.DW_OP_lit7,\n                            self.DW_OP_lit8, self.DW_OP_lit9, self.DW_OP_lit10, self.DW_OP_lit11,\n                            self.DW_OP_lit12, self.DW_OP_lit13, self.DW_OP_lit14, self.DW_OP_lit15,\n                            self.DW_OP_lit16, self.DW_OP_lit17, self.DW_OP_lit18, self.DW_OP_lit19,\n                            self.DW_OP_lit20, self.DW_OP_lit21, self.DW_OP_lit22, self.DW_OP_lit23,\n                            self.DW_OP_lit24, self.DW_OP_lit25, self.DW_OP_lit26, self.DW_OP_lit27,\n                            self.DW_OP_lit28, self.DW_OP_lit29, self.DW_OP_lit30, self.DW_OP_lit31]:\n                    extra_s = \"push {:#x}\".format(op - 0x30)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_reg0, self.DW_OP_reg1, self.DW_OP_reg2, self.DW_OP_reg3,\n                            self.DW_OP_reg4, self.DW_OP_reg5, self.DW_OP_reg6, self.DW_OP_reg7,\n                            self.DW_OP_reg8, self.DW_OP_reg9, self.DW_OP_reg10, self.DW_OP_reg11,\n                            self.DW_OP_reg12, self.DW_OP_reg13, self.DW_OP_reg14, self.DW_OP_reg15,\n                            self.DW_OP_reg16, self.DW_OP_reg17, self.DW_OP_reg18, self.DW_OP_reg19,\n                            self.DW_OP_reg20, self.DW_OP_reg21, self.DW_OP_reg22, self.DW_OP_reg23,\n                            self.DW_OP_reg24, self.DW_OP_reg25, self.DW_OP_reg26, self.DW_OP_reg27,\n                            self.DW_OP_reg28, self.DW_OP_reg29, self.DW_OP_reg30, self.DW_OP_reg31]:\n                    regname = self.get_register_name(op - 0x50)\n                    extra_s = \"push {:s}\".format(regname)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_breg0, self.DW_OP_breg1, self.DW_OP_breg2, self.DW_OP_breg3,\n                            self.DW_OP_breg4, self.DW_OP_breg5, self.DW_OP_breg6, self.DW_OP_breg7,\n                            self.DW_OP_breg8, self.DW_OP_breg9, self.DW_OP_breg10, self.DW_OP_breg11,\n                            self.DW_OP_breg12, self.DW_OP_breg13, self.DW_OP_breg14, self.DW_OP_breg15,\n                            self.DW_OP_breg16, self.DW_OP_breg17, self.DW_OP_breg18, self.DW_OP_breg19,\n                            self.DW_OP_breg20, self.DW_OP_breg21, self.DW_OP_breg22, self.DW_OP_breg23,\n                            self.DW_OP_breg24, self.DW_OP_breg25, self.DW_OP_breg26, self.DW_OP_breg27,\n                            self.DW_OP_breg28, self.DW_OP_breg29, self.DW_OP_breg30, self.DW_OP_breg31]:\n                    new_pos, d = self.get_sleb128(data, new_pos)\n                    regname = self.get_register_name(op - 0x70)\n                    extra_s = \"push {:s}{:+#x}\".format(regname, d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_fbreg]:\n                    new_pos, d = self.get_sleb128(data, new_pos)\n                    regname = \"push frame_base{:*#x}\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x}\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_bregx]:\n                    new_pos, d1 = self.get_uleb128(data, new_pos)\n                    new_pos, d2 = self.get_sleb128(data, new_pos)\n                    regname = self.get_register_name(d1)\n                    extra_s = \"push {:s}{:+#x}\".format(regname, d2)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x},{:#x}\".format(offset, op_name, d1, d2),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_call2]:\n                    new_pos, d = self.read_2ubyte(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_call4]:\n                    new_pos, d = self.read_4ubyte(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_bra]:\n                    new_pos, d = self.read_2sbyte(data, new_pos)\n                    d += offset + 3\n                    extra_s = \"pop; jmp to [{:#x}] if popped_value != 0\".format(d)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_skip]:\n                    new_pos, d = self.read_2sbyte(data, new_pos)\n                    d += offset + 3\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_implicit_value]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    block_s = \" \".join([\"{:02x}\".format(x) for x in data[new_pos:new_pos + d]])\n                    new_pos += d\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:s}\".format(offset, op_name, block_s),\n                    ))\n                elif op in [self.DW_OP_implicit_pointer, self.DW_OP_GNU_implicit_pointer]:\n                    if ref_size == 4:\n                        new_pos, d1 = self.read_4ubyte(data, new_pos)\n                    elif ref_size == 8:\n                        new_pos, d1 = self.read_8ubyte(data, new_pos)\n                    new_pos, d2 = self.get_sleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}] {:+#x}\".format(offset, op_name, d1, d2),\n                    ))\n                elif op in [self.DW_OP_entry_value, self.DW_OP_GNU_entry_value]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                    ))\n                    entries += self.parse_ops(vers, addrsize, d, data, new_pos, indent=indent + 1)\n                    new_pos += d\n                elif op in [self.DW_OP_const_type, self.DW_OP_GNU_const_type]:\n                    new_pos, d1 = self.get_uleb128(data, new_pos)\n                    new_pos, d2 = self.read_1ubyte(data, new_pos)\n                    block_s = \" \".join([\"{:02x}\".format(x) for x in data[new_pos:new_pos + d2]])\n                    new_pos += d2\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}] {:s}\".format(offset, op_name, d1, block_s),\n                    ))\n                elif op in [self.DW_OP_regval_type, self.DW_OP_GNU_regval_type]:\n                    new_pos, d1 = self.get_uleb128(data, new_pos)\n                    new_pos, d2 = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x} [{:#x}]\".format(offset, op_name, d1, d2),\n                    ))\n                elif op in [self.DW_OP_deref_type, self.DW_OP_GNU_deref_type]:\n                    new_pos, d1 = self.read_1ubyte(data, new_pos)\n                    new_pos, d2 = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x} [{:#x}]\".format(offset, op_name, d1, d2),\n                    ))\n                elif op in [self.DW_OP_xderef_type]:\n                    new_pos, d1 = self.read_1ubyte(data, new_pos)\n                    new_pos, d2 = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} {:#x} [{:#x}]\".format(offset, op_name, d1, d2),\n                    ))\n                elif op in [self.DW_OP_convert, self.DW_OP_GNU_convert,\n                            self.DW_OP_reinterpret, self.DW_OP_GNU_reinterpret]:\n                    new_pos, d = self.get_uleb128(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_GNU_parameter_ref]:\n                    new_pos, d = self.read_4ubyte(data, new_pos)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s} [{:#x}]\".format(offset, op_name, d),\n                    ))\n                elif op in [self.DW_OP_drop]:\n                    extra_s = \"pop\"\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_dup]:\n                    extra_s = \"push stack[0]\"\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_over]:\n                    extra_s = \"push stack[1]\"\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_swap]:\n                    extra_s = \"stack[0],stack[1] = stack[1],stack[0]\"\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                elif op in [self.DW_OP_rot]:\n                    extra_s = \"stack[0],stack[1],stack[2] = stack[1],stack[2],stack[0]\"\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                        None, extra_s,\n                    ))\n                else:\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        indent + \"[{:#04x}] {:s}\".format(offset, op_name),\n                    ))\n                length -= new_pos - pos\n                offset += new_pos - pos\n                pos = new_pos\n        except (KeyError, IndexError, ValueError):\n            _exc_type, exc_value, _exc_traceback = sys.exc_info()\n            entries.append(self.ErrorEntry(\"Parse Error\", exc_value))\n        return entries\n\n    def parse_gcc_except_table(self, gcc_except_table, eh_frame_entries):\n\n        def get_lsda_info(eh_frame_entries):\n            dic = {}\n            is_fde = False\n            for entry in eh_frame_entries:\n                if entry.tag != \"data\":\n                    continue\n                if entry.name == \"cie_pointer\":\n                    is_fde = True\n                    continue\n                if entry.name == \"cie_id\":\n                    is_fde = False\n                    continue\n                if is_fde:\n                    if entry.name == \"pc_begin\":\n                        pc_begin = entry.value\n                        continue\n                    if entry.name != \"augmentation_data(L)\":\n                        continue\n                    dic[entry.value - load_base] = pc_begin + load_base\n            return dic\n\n        section_base = gcc_except_table.offset\n        data = gcc_except_table.data\n        shdr = self.elf.get_shdr(\".gcc_except_table\")\n        load_base = self.elf.get_phdr(Elf.Phdr.PT_LOAD).p_vaddr\n        ptr_size = 4 if self.elf.e_class == Elf.ELF_32_BITS else 8\n        lsda_pos_info = get_lsda_info(eh_frame_entries)\n\n        entries = []\n        pos = 0\n        lsda_table_cnt = 0\n\n        try:\n            lsda_pos_padding = 0\n            while data[pos:]:\n                # search LSDA start address\n                if (section_base + pos) not in lsda_pos_info:\n                    lsda_pos_padding += 1\n                    pos += 1\n                    continue\n\n                # Found\n                if lsda_pos_padding:\n                    entries.append(self.SeparatorEntry(pos - lsda_pos_padding, \"Padding\"))\n                    entries.append(self.DataEntry(\n                        pos - lsda_pos_padding, data[pos - lsda_pos_padding:pos], \"padding\",\n                    ))\n                    lsda_pos_padding = 0\n\n                entries.append(self.SeparatorEntry(pos, \"LSDA Table[{:4d}]\".format(lsda_table_cnt)))\n                lpstart = lsda_pos_info[section_base + pos]\n\n                # parse lpstart_encoding\n                new_pos, lpstart_encoding = self.read_1ubyte(data, pos)\n                encoding_str = self.get_encoding_str(lpstart_encoding)\n                entries.append(self.DataEntry(\n                    pos, data[pos:new_pos],\n                    \"landing_pad_start_encoding\", lpstart_encoding,\n                    \"encoding: {:s}\".format(encoding_str),\n                ))\n                pos = new_pos\n\n                # parse lpstart\n                if lpstart_encoding != self.DW_EH_PE_omit:\n                    new_pos, lpstart = self.read_encoded(lpstart_encoding, data, pos) # overwrite lpstart\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        \"landing_pad_start\", lpstart,\n                    ))\n                    pos = new_pos\n\n                # parse ttype_encoding\n                new_pos, ttype_encoding = self.read_1ubyte(data, pos)\n                encoding_str = self.get_encoding_str(ttype_encoding)\n                entries.append(self.DataEntry(\n                    pos, data[pos:new_pos],\n                    \"ttype_encoding\", ttype_encoding,\n                    \"encoding: {:s}\".format(encoding_str),\n                ))\n                pos = new_pos\n\n                # parse ttype_base_offset\n                ttype_base = None\n                if ttype_encoding != self.DW_EH_PE_omit:\n                    new_pos, ttype_base_offset = self.get_uleb128(data, pos)\n                    ttype_base = new_pos + ttype_base_offset\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos],\n                        \"ttype_base_offset\", ttype_base_offset,\n                        \"ttype_base: {:#x}\".format(ttype_base),\n                    ))\n                    pos = new_pos\n\n                # parse call_site_encoding\n                new_pos, call_site_encoding = self.read_1ubyte(data, pos)\n                encoding_str = self.get_encoding_str(call_site_encoding)\n                entries.append(self.DataEntry(\n                    pos, data[pos:new_pos],\n                    \"call_site_encoding\", call_site_encoding,\n                    \"encoding: {:s}\".format(encoding_str),\n                ))\n                pos = new_pos\n\n                # parse call_site_table_len\n                new_pos, call_site_table_len = self.get_uleb128(data, pos)\n                entries.append(self.DataEntry(\n                    pos, data[pos:new_pos],\n                    \"call_site_table_len\", call_site_table_len,\n                ))\n                pos = new_pos\n\n                # parse call_site_table\n                action_table_pos = pos + call_site_table_len\n                table_cnt = 0\n                max_action = 0\n                while pos < action_table_pos:\n                    entries.append(self.SeparatorEntry(pos, \"Call site table[{:4d}]\".format(table_cnt)))\n\n                    new_pos, call_site_start = self.read_encoded(call_site_encoding, data, pos)\n                    if self.elf.is_pie():\n                        extra_s = \"try-start vma: $codebase+{:#x}\".format(lpstart + call_site_start)\n                    else:\n                        extra_s = \"try-start vma: {:#x}\".format(lpstart + call_site_start)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"call_site_start\", call_site_start, extra_s,\n                    ))\n                    pos = new_pos\n\n                    new_pos, call_site_length = self.read_encoded(call_site_encoding, data, pos)\n                    if self.elf.is_pie():\n                        extra_s = \"try-end vma: $codebase+{:#x}\".format(lpstart + call_site_start + call_site_length)\n                    else:\n                        extra_s = \"try-end vma: {:#x}\".format(lpstart + call_site_start + call_site_length)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"call_site_length\", call_site_length, extra_s,\n                    ))\n                    pos = new_pos\n\n                    new_pos, call_site_lpad = self.read_encoded(call_site_encoding, data, pos)\n                    if call_site_lpad == 0:\n                        extra_s = \"\"\n                    elif self.elf.is_pie():\n                        extra_s = \"catch vma: $codebase+{:#x}\".format(lpstart + call_site_lpad)\n                    else:\n                        extra_s = \"catch vma: {:#x}\".format(lpstart + call_site_lpad)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"landing_pad\", call_site_lpad, extra_s,\n                    ))\n                    pos = new_pos\n\n                    new_pos, action = self.get_uleb128(data, pos)\n                    max_action = max(action, max_action)\n                    if action == 0:\n                        extra_s = \"no action\"\n                    else:\n                        extra_s = \"action: {:#x}\".format(action_table_pos + action - 1)\n                    entries.append(self.DataEntry(\n                        pos, data[pos:new_pos], \"action\", action, extra_s,\n                    ))\n                    pos = new_pos\n\n                    table_cnt += 1\n\n                # parse action_table\n                max_ar_filter = 0\n                table_cnt = 0\n                if max_action:\n                    action_table_end_pos = action_table_pos + max_action + 1\n                    while pos < action_table_end_pos:\n                        entries.append(self.SeparatorEntry(pos, \"Action table[{:4d}]\".format(table_cnt)))\n\n                        new_pos, ar_filter = self.get_sleb128(data, pos)\n                        if ar_filter == 0:\n                            extra_s = \"cleanup\"\n                        else:\n                            enc_size = self.encoded_ptr_size(ttype_encoding, ptr_size)\n                            extra_s = \"catch typeinfo: {:#x}\".format(ttype_base - ar_filter * enc_size)\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"action_record_filter\", ar_filter, extra_s,\n                        ))\n                        max_ar_filter = max(ar_filter, max_ar_filter)\n                        pos = new_pos\n\n                        new_pos, ar_disp = self.get_sleb128(data, pos)\n                        if ar_disp & 1:\n                            extra_s = \"-> Action Table[{:4d}]\".format(table_cnt + (ar_disp + 1) // 2)\n                        elif ar_disp:\n                            extra_s = \"-> ???\"\n                        else:\n                            extra_s = \"list end\"\n                        entries.append(self.DataEntry(\n                            pos, data[pos:new_pos], \"action_record_next\", ar_disp, extra_s,\n                        ))\n                        pos = new_pos\n\n                        table_cnt += 1\n\n                # parse ttype_table\n                if max_ar_filter > 0 and ttype_base is not None:\n                    enc_size = self.encoded_ptr_size(ttype_encoding, ptr_size)\n                    new_pos = ttype_base - max_ar_filter * enc_size\n                    if pos != new_pos:\n                        entries.append(self.SeparatorEntry(pos, \"Padding\"))\n                        entries.append(self.DataEntry(pos, data[pos:new_pos], \"padding\"))\n                        pos = new_pos\n                    current_ar_filter = max_ar_filter\n                    while pos < ttype_base:\n                        entries.append(self.SeparatorEntry(pos, \"TType table[{:4d}]\".format(current_ar_filter)))\n                        new_pos, ttype = self.read_encoded(ttype_encoding, data, pos)\n                        if (ttype_encoding & 0x70) == self.DW_EH_PE_pcrel:\n                            ttype_pointer = shdr.sh_offset + pos + ttype\n                            if ttype:\n                                if self.elf.is_pie():\n                                    extra_s = \"TType pointer vma: $codebase+{:#x}\".format(load_base + ttype_pointer)\n                                else:\n                                    extra_s = \"TType pointer vma: {:#x}\".format(load_base + ttype_pointer)\n                            else:\n                                extra_s = \"\"\n                            entries.append(self.DataEntry(pos, data[pos:new_pos], \"ttype\", ttype, extra_s))\n                        else:\n                            entries.append(self.DataEntry(pos, data[pos:new_pos], \"ttype\", ttype, \"TType pointer\"))\n                        pos = new_pos\n                        current_ar_filter -= 1\n                if ttype_base is not None:\n                    entries.append(self.SeparatorEntry(ttype_base, \"TType table base (Stored upwards)\"))\n\n                # next LSDA\n                if ttype_base is None:\n                    pass\n                else:\n                    pos = ttype_base\n                lsda_table_cnt += 1\n        except (KeyError, IndexError, ValueError):\n            _exc_type, exc_value, _exc_traceback = sys.exc_info()\n            entries.append(self.ErrorEntry(\"Parse Error\", exc_value))\n        return entries\n\n    def read_section(self, section_name):\n        shdr = self.elf.get_shdr(section_name)\n        if shdr is None:\n            err(\"Could not find {} section\".format(section_name))\n            return None\n\n        f = open(self.elf.filename, \"rb\")\n        f.seek(shdr.sh_offset)\n        data = f.read(shdr.sh_size)\n        f.close()\n        info(\"Found {} section\".format(section_name))\n\n        dic = {\"name\": section_name, \"offset\": shdr.sh_offset, \"data\": data}\n        Section = collections.namedtuple(\"Section\", dic.keys())\n        return Section(*dic.values())\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        local_filepath = None\n        remote_filepath = None\n        tmp_filepath = None\n\n        if args.remote:\n            if not is_remote_debug():\n                err(\"-r option is allowed only remote debug\")\n                return\n\n            if args.file:\n                remote_filepath = args.file # if specified, assume it is remote\n            elif gdb.current_progspace().filename:\n                f = gdb.current_progspace().filename\n                if f.startswith(\"target:\"): # gdbserver\n                    f = f[7:]\n                remote_filepath = f\n            elif Pid.get_pid(remote=True):\n                remote_filepath = \"/proc/{:d}/exe\".format(Pid.get_pid(remote=True))\n            else:\n                err(\"File name could not be determined\")\n                return\n\n            data = Path.read_remote_file(remote_filepath, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                err(\"Failed to read remote filepath\")\n                return\n            tmp_fd, tmp_filepath = GefUtil.mkstemp(prefix=\"dwarf-exception-handler\", suffix=\".elf\")\n            os.fdopen(tmp_fd, \"wb\").write(data)\n            local_filepath = tmp_filepath\n            del data\n\n        elif args.file:\n            local_filepath = args.file\n\n        elif args.file is None:\n            if is_qemu_system():\n                err(\"Argument-less calls are unsupported under qemu-system\")\n                return\n            local_filepath = Path.get_filepath()\n\n        if local_filepath is None:\n            err(\"File name could not be determined\")\n            return\n\n        def unlink_tmp_filepath(tmp_filepath):\n            if tmp_filepath and os.path.exists(tmp_filepath):\n                os.unlink(tmp_filepath)\n            return\n\n        self.elf = Elf.get_elf(local_filepath)\n        if self.elf is None or not self.elf.is_valid():\n            err(\"Failed to parse ELF\")\n            unlink_tmp_filepath(tmp_filepath)\n            return\n\n        # read section\n        eh_frame_hdr = self.read_section(\".eh_frame_hdr\")\n        if eh_frame_hdr is None:\n            unlink_tmp_filepath(tmp_filepath)\n            return\n\n        eh_frame = self.read_section(\".eh_frame\")\n        if eh_frame is None:\n            unlink_tmp_filepath(tmp_filepath)\n            return\n\n        gcc_except_table = self.read_section(\".gcc_except_table\")\n        if gcc_except_table is None:\n            unlink_tmp_filepath(tmp_filepath)\n            return\n\n        # parse section\n        self.out = []\n        entries1 = self.parse_eh_frame_hdr(eh_frame_hdr)\n        self.out += self.format_entry(eh_frame_hdr, entries1)\n\n        entries2 = self.parse_eh_frame(eh_frame)\n        self.out += self.format_entry(eh_frame, entries2)\n\n        entries3 = self.parse_gcc_except_table(gcc_except_table, entries2)\n        self.out += self.format_entry(gcc_except_table, entries3)\n\n        # print\n        self.print_output()\n        unlink_tmp_filepath(tmp_filepath)\n        return\n\n\n@register_command\nclass MultiBreakCommand(GenericCommand):\n    \"\"\"Set multiple breakpoints easily.\"\"\"\n\n    _cmdline_ = \"multi-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_, add_help=False)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"+\", type=AddressUtil.parse_address,\n                        help=\"the address(es) to set breakpoint.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command is intended to improve the readability of history\",\n        \"by allowing you to set multiple breakpoints on a single line.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    def do_invoke(self, args):\n        for bp in args.location:\n            gdb.execute(\"b *{:#x}\".format(bp))\n        return\n\n\n@register_command\nclass MainBreakCommand(GenericCommand):\n    \"\"\"Set a breakpoint at the beginning of main with or without symbols, then continue.\"\"\"\n\n    _cmdline_ = \"main-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_, add_help=False)\n    _syntax_ = parser.format_help()\n\n    def get_libc_start_main(self):\n        try:\n            return AddressUtil.parse_address(\"__libc_start_main\")\n        except gdb.error:\n            pass\n\n        ret = gdb.execute(\"got --no-pager --quiet __libc_start_main\", to_string=True)\n        ret = ret.strip()\n        if not ret:\n            err(\"Failed to resolve __libc_start_main\")\n            return None\n        elem = Color.remove_color(ret).splitlines()[0].split()\n        if elem[-1].endswith(\">\"):\n            return int(elem[-2], 16)\n        else:\n            return int(elem[-1], 16)\n\n    def search_main(self):\n        libc_start_main = self.get_libc_start_main()\n        if libc_start_main is None:\n            return None\n\n        if libc_start_main == 0:\n            elf = Elf.get_elf()\n            if elf is None or not elf.is_valid():\n                return None\n\n            entry = elf.e_entry\n            if elf.is_pie():\n                codebase = ProcessMap.get_codebase()\n                if codebase is None:\n                    return None\n                entry += codebase\n            EntryBreakBreakpoint(\"*{:#x}\".format(entry))\n            ContextCommand.hide_context()\n            gdb.execute(\"continue\") # do not use c wrapper\n            ContextCommand.unhide_context()\n            libc_start_main = self.get_libc_start_main()\n\n        if libc_start_main == 0:\n            # something is wrong\n            return None\n\n        EntryBreakBreakpoint(\"*{:#x}\".format(libc_start_main))\n        ContextCommand.hide_context()\n        gdb.execute(\"continue\") # do not use c wrapper\n        ContextCommand.unhide_context()\n\n        # get first arg when break at __libc_start_main\n        _, val = current_arch.get_ith_parameter(0)\n        return val\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        try:\n            main_address = AddressUtil.parse_address(\"main\")\n        except gdb.error:\n            main_address = self.search_main()\n\n        if main_address is None:\n            err(\"Failed to set a breakpoint to main\")\n            return\n\n        EntryBreakBreakpoint(\"*{:#x}\".format(main_address))\n        ContextCommand.hide_context()\n        try:\n            gdb.execute(\"continue\") # do not use c wrapper\n        except gdb.error as e:\n            err(str(e))\n            ContextCommand.unhide_context()\n            return\n        ContextCommand.unhide_context()\n        gdb.execute(\"context\")\n        return\n\n\n@register_command\nclass LoadBreakCommand(GenericCommand):\n    \"\"\"Break if something is loaded (wrapper of `set stop-on-solib-events 1`).\"\"\"\n\n    _cmdline_ = \"load-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n    _repeat_ = True\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if gdb.parameter(\"stop-on-solib-events\"):\n            err(\"stop-on-solib-events is already 1\")\n            return\n\n        before = gdb.execute(\"vmmap --quiet --no-pager\", to_string=True)\n        gdb.execute(\"set stop-on-solib-events 1\")\n\n        gdb.execute(\"continue\")\n\n        if not is_alive():\n            return\n\n        gdb.execute(\"set stop-on-solib-events 0\")\n        after = gdb.execute(\"vmmap --quiet --no-pager\", to_string=True)\n\n        import difflib\n        res = difflib.ndiff(before.splitlines(), after.splitlines())\n        res = [line for line in res if line.startswith((\"+\", \"-\"))]\n        if res:\n            gef_print(titlify(\"Memory map diff\"))\n            gef_print(\"\\n\".join(res))\n        return\n\n\nclass EntryBreakBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint used internally to stop execution at the most convenient entry point.\"\"\"\n\n    def __init__(self, location):\n        super().__init__(location, gdb.BP_BREAKPOINT, internal=True, temporary=True)\n        self.silent = True\n        return\n\n    def stop(self):\n        EventHandler.__gef_check_disabled_bp__ = True\n        self.enabled = False\n        Cache.reset_gef_caches()\n        return True\n\n\n@register_command\nclass EntryBreakCommand(GenericCommand):\n    \"\"\"Try to find best entry point and set a temporary breakpoint on it.\"\"\"\n\n    _cmdline_ = \"entry-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n    _aliases_ = [\"start\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_, add_help=False)\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        self.add_setting(\n            \"entrypoint_symbols\",\n            \" \".join([\n                \"main\", # glibc\n                \"__libc_start_main\", # glibc\n                \"__uClibc_main\", # uClibc\n                \"_start\", # glibc\n                \"__start\", # used by MIPS\n                \"'main.main'\", # Golang\n                \"'start._start'\", # zig\n            ]),\n            \"Possible symbols for entry points\",\n        )\n        return\n\n    @staticmethod\n    def stop_callback(_):\n        # unhook\n        EventHooking.gef_on_new_unhook(EntryBreakCommand.stop_callback)\n        ContextCommand.unhide_context()\n\n        # get section\n        fpath = Path.get_filepath()\n        executable_section = ProcessMap.process_lookup_path(fpath, perm_mask=Permission.EXECUTE)\n\n        if executable_section is None:\n            # for context.disable_vmmap\n            next_insn = get_insn_next(current_arch.pc)\n            info(\"Breaking at: {:#x}\".format(next_insn.address))\n            EntryBreakBreakpoint(\"*{:#x}\".format(next_insn.address))\n        elif executable_section.page_start <= current_arch.pc < executable_section.page_end:\n            # already stopped around entry point.\n            # However, it automatically resumes execution, so we need a breakpoint.\n            next_insn = get_insn_next(current_arch.pc)\n            info(\"Breaking at: {:#x}\".format(next_insn.address))\n            EntryBreakBreakpoint(\"*{:#x}\".format(next_insn.address))\n        else:\n            # stopped in ld, so continue to entry-point.\n            base_address = ProcessMap.process_lookup_path(fpath).page_start\n            entry_address = base_address + Elf.get_elf(fpath).e_entry\n            info(\"Breaking at entry-point: {:#x}\".format(entry_address))\n            EntryBreakBreakpoint(\"*{:#x}\".format(entry_address))\n\n        # automatically continue\n        return\n\n    # Need not @parse_args because argparse can't stop interpreting argument for start.\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, argv):\n        if is_alive():\n            if is_remote_debug():\n                err(\"Unsupported gdb mode\")\n                return\n            gdb.execute(\"kill\", to_string=True)\n\n        fpath = Path.get_filepath()\n        if fpath is None:\n            warn(\"No executable to debug, use `file` to load a binary\")\n            return\n\n        if not os.access(fpath, os.X_OK):\n            warn(\"The file {!r} is not executable\".format(fpath))\n            return\n\n        elf = Elf.get_elf(fpath)\n        if elf is None or not elf.is_valid():\n            warn(\"Invalid ELF\")\n            return\n\n        # use symbol if loaded\n        entrypoints = Config.get_gef_setting(\"entry_break.entrypoint_symbols\").split()\n        for sym in entrypoints:\n            try:\n                value = AddressUtil.parse_address(sym)\n            except gdb.error:\n                continue\n\n            # symbol found\n            info(\"Breaking at {:#x} ({:s})\".format(value, sym))\n            EntryBreakBreakpoint(sym)\n            gdb.execute(\"run {:s}\".format(\" \".join(argv)))\n            return\n\n        # no symbols. use elf entry point\n        # non-PIE\n        if not elf.is_pie():\n            entry = elf.e_entry\n            info(\"Breaking at entry-point: {:#x}\".format(entry))\n            EntryBreakBreakpoint(\"*{:#x}\".format(entry))\n            gdb.execute(\"run {}\".format(\" \".join(argv)))\n            return\n\n        # PIE\n        warn(\"PIC binary detected, retrieving text base address\")\n        # Some ELF does not use ld. (e.g., ELF built by zig)\n        # So use gef_on_new_hook (use gdb.events.new_objfile internally),\n        # instead of `set stop-on-solib-events 1` because shared object are never loaded.\n        # At least gdb 10.1 (Ubuntu 18.04) supports gdb.events.new_objfile.\n        ContextCommand.hide_context()\n        EventHooking.gef_on_new_hook(EntryBreakCommand.stop_callback)\n        gdb.execute(\"run {}\".format(\" \".join(argv)))\n        return\n\n\nclass CommandBreakBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint which executes user-defined command silently and continue.\"\"\"\n\n    def __init__(self, loc, cmd):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False, temporary=False)\n        self.cmd = cmd\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n        gdb.execute(self.cmd)\n        return False\n\n\n@register_command\nclass CommandBreakCommand(GenericCommand):\n    \"\"\"Set a breakpoint which executes user-defined command silently and continue, if hit.\"\"\"\n\n    _cmdline_ = \"command-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address to set a breakpoint. (default: current_arch.pc)\")\n    parser.add_argument(\"command\", metavar=\"COMMAND\", type=str, help=\"the command executed if breakpoint is hit.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} 0x55555555aab9 \"hexdump -n $sp+0x120\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    def do_invoke(self, args):\n        location = args.location\n        if location is None:\n            location = current_arch.pc\n        CommandBreakBreakpoint(location, args.command)\n        return\n\n\nclass RegisterDumpBreakBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint which dump registers silently and continue.\"\"\"\n\n    def __init__(self, loc, tag, regs):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False, temporary=False)\n        self.loc = loc\n        self.tag = tag\n        self.regs = regs\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n        out = []\n        for r in self.regs:\n            try:\n                v = get_register(r)\n            except gdb.error:\n                continue\n            out.append(\"{:s}={:#x}\".format(r, v))\n\n        colored_addr = Color.colorify_hex(self.loc, \"bold yellow\")\n        tag = \"\"\n        if self.tag:\n            tag = \"{:s}: \".format(self.tag)\n        gef_print(\"{:s}: {:s}{:s}\".format(colored_addr, tag, \", \".join(out)))\n        return False\n\n\n@register_command\nclass RegisterDumpBreakCommand(GenericCommand):\n    \"\"\"Set a breakpoint which dumps registers silently and continue, if hit.\"\"\"\n\n    _cmdline_ = \"regdump-break\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address to set a breakpoint. (default: current_arch.pc)\")\n    parser.add_argument(\"-t\", \"--tag\", help=\"the tag if breakpoint is hit.\")\n    parser.add_argument(\"-r\", \"--regs\", action=\"append\", help=\"the register name dumped if breakpoint is hit.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x55555555aab9 -r rax\",\n        '{0:s} 0x55555555aab9 -t \"state changed\" -r rax',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        if not args.regs:\n            self.usage()\n            return\n        location = args.location\n        if location is None:\n            location = current_arch.pc\n        RegisterDumpBreakBreakpoint(location, args.tag, args.regs)\n        return\n\n\nclass TakenOrNotBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint which only branch is taken or not.\"\"\"\n\n    def __init__(self, loc, taken, is_hwbp):\n        if is_hwbp:\n            bp_type = gdb.BP_HARDWARE_BREAKPOINT\n        else:\n            bp_type = gdb.BP_BREAKPOINT\n        super().__init__(\"*{:#x}\".format(loc), bp_type, internal=False)\n        self.loc = loc\n        self.taken = taken\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n        insn = get_insn()\n\n        if not current_arch.is_conditional_branch(insn):\n            return False # continue\n\n        taken, _ = current_arch.is_branch_taken(insn)\n        if self.taken:\n            return taken\n        else:\n            return not taken\n\n\n@register_command\nclass BreakIfTakenCommand(GenericCommand):\n    \"\"\"Set a breakpoint which breaks if branch is taken.\"\"\"\n\n    _cmdline_ = \"break-if-taken\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to set breakpoint.\")\n    parser.add_argument(\"--hw\", action=\"store_true\", help=\"use hardware breakpoint.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        TakenOrNotBreakpoint(args.location, True, args.hw)\n        return\n\n\n@register_command\nclass BreakIfNotTakenCommand(GenericCommand):\n    \"\"\"Set a breakpoint which breaks if branch is not taken.\"\"\"\n\n    _cmdline_ = \"break-if-not-taken\"\n    _category_ = \"01-b. Debugging Support - Breakpoint\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address to set breakpoint.\")\n    parser.add_argument(\"--hw\", action=\"store_true\", help=\"use hardware breakpoint.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        TakenOrNotBreakpoint(args.location, False, args.hw)\n        return\n\n\n@register_command\nclass ContextCommand(GenericCommand):\n    \"\"\"Display various information every time GDB hits a breakpoint.\"\"\"\n\n    _cmdline_ = \"context\"\n    _category_ = \"01-a. Debugging Support - Context\"\n    _aliases_ = [\"ctx\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    commands = [\n        [],\n        \"legend\",\n        \"regs\",\n        \"stack\",\n        \"code\",\n        \"mem_access\",\n        \"args\",\n        \"source\",\n        \"mem_watch\",\n        \"trace\",\n        \"threads\",\n        \"extra\",\n        \"on\",\n        \"off\",\n    ]\n    parser.add_argument(\"commands\", nargs=\"*\", choices=commands, default=[],\n                        metavar=\"{legend,regs,stack,code,mem_access,args,source,mem_watch,trace,threads,extra}|{on,off}\",\n                        help=\"invoke each pane individually, or temporarily control the output.\")\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        'If \"on\" or \"off\" is specified, that operation takes precedence.',\n        \"`context XXX YYY` invokes the `context-XXX` command and then the `context-YYY` command, in that order.\",\n        \"There are various configuration options that modify the behavior of context. You can list them with gef config context.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    context_hidden = False\n\n    @staticmethod\n    def hide_context():\n        ContextCommand.context_hidden = True\n        return\n\n    @staticmethod\n    def unhide_context():\n        ContextCommand.context_hidden = False\n        return\n\n    @staticmethod\n    def is_hide():\n        if ContextCommand.context_hidden:\n            return True\n        enabled = Config.get_gef_setting(\"context.enable\")\n        if not enabled:\n            return True\n        return False\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        self.add_setting(\"enable\", True, \"Enable/disable printing the context when breaking\")\n        self.add_setting(\"nb_max_string_length\", 0x40, \"Number of bytes of strings to show\")\n        self.add_setting(\"clear_screen\", True, \"Clear the screen before printing the context\")\n        default_legend = \"legend regs stack code mem_access args source mem_watch threads trace extra\"\n        self.add_setting(\"layout\", default_legend, \"Order of sections (add '-' to skip: trace -> -trace)\")\n        self.add_setting(\"smart_cpp_function_name\", False, \"Print cpp function name without args if demangled\")\n        self.add_setting(\"enable_auto_switch_for_i8086\", True, \"Enable auto architecture switching for i8086 <-> x86-32\")\n        self.add_setting(\"disable_vmmap\", False, \"Disable memory map generation to speed up (e.g., for firmware debugging)\")\n        self.add_setting(\"disable_auxv\", False, \"Disable scanning auxv from memory to speed up (e.g., for firmware debugging)\")\n        self.add_setting(\"redirect\", \"\", \"Default target tty name to redirect `context` to\")\n        EventHooking.gef_on_continue_hook(ContextRegistersCommand.update_registers)\n        EventHooking.gef_on_continue_hook(ContextExtraCommand.empty_extra_messages)\n        return\n\n    def complete(self, text, word): # noqa\n        if text == \"\":\n            # no prefix\n            return [s for s in self.commands if ((word is None) or (s and word in s))]\n\n        if text.strip().split()[-1] in self.commands:\n            # already matched, but repeat again\n            return [s for s in self.commands if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.commands if s and s.startswith(text.strip().split()[-1])]\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_redirect(section, ignore_redirect):\n        if ignore_redirect:\n            return None\n        redirect = Config.get_gef_setting(\"context_{:s}.redirect\".format(section))\n        if redirect:\n            return redirect\n        redirect = Config.get_gef_setting(\"context.redirect\")\n        if redirect:\n            return redirect\n        return None\n\n    @staticmethod\n    def context_title(m, redirect=None):\n        line_color = Config.get_gef_setting(\"theme.context_title_line\")\n        msg_color = Config.get_gef_setting(\"theme.context_title_message\")\n        HORIZONTAL_LINE = \"-\"\n\n        _, tty_columns = GefUtil.get_terminal_size(redirect=redirect)\n\n        if not m:\n            title = Color.colorify(HORIZONTAL_LINE * tty_columns, line_color)\n        else:\n            trail_len = len(m) + 6\n            width = max(tty_columns - trail_len, 0)\n            title = \"\"\n            title += Color.colorify(HORIZONTAL_LINE * width + \" \", line_color)\n            title += Color.colorify(m, msg_color)\n            title += Color.colorify(\" \" + HORIZONTAL_LINE * 4, line_color)\n\n        gef_print(title, redirect=redirect)\n        return\n\n    @staticmethod\n    def execute_command(cmd, redirect=None):\n        if redirect:\n            res = gdb.execute(cmd, to_string=True)\n            gef_print(res.rstrip(), redirect=redirect)\n        else:\n            gdb.execute(cmd)\n        return\n\n    def i386_auto_switch(self):\n        if not Config.get_gef_setting(\"context.enable_auto_switch_for_i8086\"):\n            return\n\n        # check whether protected mode or not.\n        # even if `CR0.PE=1`, it will not switch until `ljmp`.\n        # so it is better to judge whether `$cs=0x8` or not.\n        # https://wiki.osdev.org/Protected_Mode\n        cs = get_register(\"$cs\")\n        if cs is None or cs == 8:\n            set_arch(\"x86\")\n        else:\n            set_arch(\"i8086\")\n        return\n\n    @Cache.cache_this_session\n    def get_order_in_each_pane(self, current_layout, ignore_redirect):\n        order_in_pane = {}\n        for section in current_layout:\n            # target layout is disabled\n            if section[0] == \"-\":\n                continue\n\n            redirect = ContextCommand.get_redirect(section, ignore_redirect)\n            order_in_pane[redirect] = order_in_pane.get(redirect, []) + [section]\n\n        order_info = {}\n        for redirect, order in order_in_pane.items():\n            for i, section in enumerate(order):\n                is_head = i == 0\n                is_tail = i == len(order) - 1\n                order_info[section] = [is_head, is_tail, redirect]\n        return order_info\n\n    def clear_screen(self, redirect):\n        if not Config.get_gef_setting(\"context.clear_screen\"):\n            return\n\n        if redirect:\n            gef_print(\"\\x1b[H\\x1b[2J\", end=\"\", redirect=redirect)\n            return\n\n        if len(self.args.commands) == 0:\n            # this is more faster than executing \"shell clear -x\"\n            print(\"\\x1b[H\\x1b[2J\", end=\"\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        # check on/off\n        if \"off\" in args.commands:\n            if len(args.commands) > 1:\n                self.usage()\n                return\n            ContextCommand.hide_context()\n            return\n        if \"on\" in args.commands:\n            if len(args.commands) > 1:\n                self.usage()\n                return\n            ContextCommand.unhide_context()\n            return\n\n        # check config\n        if ContextCommand.is_hide():\n            return\n\n        # check running or not\n        if not is_alive():\n            warn(\"No debugging session active\")\n            return\n\n        if gdb.selected_thread().is_running():\n            # If the thread is running, do nothing (just to be safe)\n            return\n\n        # check layout\n        if len(args.commands) > 0:\n            current_layout = args.commands\n        else:\n            current_layout = Config.get_gef_setting(\"context.layout\").strip().split()\n        if not current_layout:\n            return\n\n        # get info for clear_screen and last line\n        order_info = self.get_order_in_each_pane(tuple(current_layout), args.ignore_redirect)\n\n        # for create command\n        if args.ignore_redirect:\n            opts = \"-i\"\n        else:\n            opts = \"\"\n\n        # i386 auto switch\n        if is_qemu_system() and get_arch() == \"i8086\":\n            self.i386_auto_switch()\n\n        # do each layout\n        for section in current_layout:\n            # If a process is terminated while the context command is executing,\n            # the output will be distorted, so it is a good idea to check by every loop.\n            if not is_alive():\n                break\n\n            # target layout is disabled\n            if section[0] == \"-\":\n                continue\n\n            is_head, is_tail, redirect = order_info[section]\n\n            # clear screen\n            if is_head:\n                self.clear_screen(redirect)\n\n            # call each context sub command\n            try:\n                gdb.execute(\"context-{:s} {:s}\".format(section, opts))\n            except gdb.error:\n                exc_type, exc_value, exc_traceback = sys.exc_info()\n                gef_print(exc_value, redirect=redirect)\n\n            # for time measurement\n            #from cProfile import Profile\n            #import pstats\n            #pr = Profile()\n            #pr.runcall(lambda: gdb.execute(\"context-{:s} {:s}\".format(section, opts)))\n            #stats = pstats.Stats(pr)\n            #stats.sort_stats(\"tottime\")\n            #stats.print_stats(10)\n\n            # last line\n            if is_tail:\n                ContextCommand.context_title(\"\", redirect)\n        return\n\n\n@register_command\nclass ContextLegendCommand(GenericCommand):\n    \"\"\"Context internal command to display the legend.\"\"\"\n\n    _cmdline_ = \"context-legend\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context legend` to\")\n        return\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_context_legend():\n        if is_qemu_system() or is_kgdb() or is_vmware():\n            return None\n\n        if Config.get_gef_setting(\"gef.disable_color\"):\n            return None\n\n        legend = \"[ Legend: {:s} ]\".format(\n            \" | \".join([\n                Color.colorify(\"Modified register\", Config.get_gef_setting(\"theme.registers_value_changed\")),\n                Color.colorify(\"Code\", Config.get_gef_setting(\"theme.address_code\")),\n                Color.colorify(\"Heap\", Config.get_gef_setting(\"theme.address_heap\")),\n                Color.colorify(\"Stack\", Config.get_gef_setting(\"theme.address_stack\")),\n                Color.colorify(\"Writable\", Config.get_gef_setting(\"theme.address_writable\")),\n                Color.colorify(\"ReadOnly\", Config.get_gef_setting(\"theme.address_readonly\")),\n                Color.colorify(\"None\", Config.get_gef_setting(\"theme.address_valid_but_none\")),\n                Color.colorify(\"RWX\", Config.get_gef_setting(\"theme.address_rwx\")),\n                Color.colorify(\"String\", Config.get_gef_setting(\"theme.dereference_string\")),\n            ]),\n        )\n        return legend\n\n    def context_legend(self, redirect):\n        legend = ContextLegendCommand.get_context_legend()\n        if legend:\n            gef_print(legend, redirect=redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"legend\", args.ignore_redirect)\n        try:\n            self.context_legend(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextRegistersCommand(GenericCommand):\n    \"\"\"Context internal command to display registers.\"\"\"\n\n    _cmdline_ = \"context-regs\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    old_registers = {}\n    previous_extra_regs = {}\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context regs` to\")\n        self.add_setting(\"show_registers_raw\", False, \"Show the registers pane with raw values (no dereference)\")\n        self.add_setting(\"ignore_registers\", \"\", \"Space-separated list of registers not to display (e.g., '$cs $ds $gs')\")\n        self.add_setting(\"show_errno\", True, \"Show errno after a syscall instruction\")\n        self.add_setting(\"show_mmx_xmm_ymm_fpu\", True, \"Show MMX/XMM/YMM/FPU registers when stopped at a related instruction\")\n        return\n\n    @staticmethod\n    def update_registers(_event):\n        if current_arch is None:\n            return\n\n        for reg in current_arch.all_registers:\n            try:\n                ContextRegistersCommand.old_registers[reg] = get_register(reg)\n            except Exception:\n                ContextRegistersCommand.old_registers[reg] = 0\n\n        if is_x86():\n            for reg in current_arch.virtual_registers:\n                try:\n                    ContextRegistersCommand.old_registers[reg] = gdb.parse_and_eval(reg)\n                except gdb.error:\n                    ContextRegistersCommand.old_registers[reg] = 0\n\n        if is_x86_16():\n            for regname, (seg, reg) in current_arch.seg_extended_registers.items():\n                segval = get_register(seg) & 0xffff\n                regval = get_register(reg) & 0xffff\n                value = current_arch.real2phys(segval, regval)\n                ContextRegistersCommand.old_registers[regname] = value\n        return\n\n    RE_SUB_OPERAND1 = re.compile(r\"<.*?>\")\n    RE_SUB_OPERAND2 = re.compile(r\"\\[.*?\\]\")\n    RE_FINDALL_SSE = re.compile(r\"(xmm\\d+)\")\n    RE_FINDALL_AVX = re.compile(r\"(ymm\\d+)\")\n    RE_FINDALL_MMX = re.compile(r\"([^xy]mm\\d+)\")\n    RE_FINDALL_FPU = re.compile(r\"(st\\(\\d\\))\")\n\n    def context_regs_extra(self, redirect):\n        if not Config.get_gef_setting(\"context_regs.show_mmx_xmm_ymm_fpu\"):\n            return\n\n        if not is_x86():\n            return\n\n        try:\n            insn = get_insn()\n            insn_prev = get_insn_prev()\n        except gdb.MemoryError:\n            self.previous_extra_regs = {}\n            return\n\n        if insn is None:\n            return\n\n        if insn_prev is None:\n            return\n\n        operands = \", \".join(insn.operands)\n        operands = self.RE_SUB_OPERAND1.sub(\"\", operands)\n        operands = self.RE_SUB_OPERAND2.sub(\"\", operands)\n\n        if self.previous_extra_regs:\n            if self.previous_extra_regs[\"pc\"] != insn_prev.address:\n                self.previous_extra_regs = {}\n\n        printed_extra_regs = {\"pc\": current_arch.pc}\n\n        # sse register\n        to_save_regs = self.RE_FINDALL_SSE.findall(operands)\n        to_print_regs = to_save_regs + self.previous_extra_regs.get(\"xmm\", [])\n        if to_print_regs:\n            to_print_regs = sorted(set(to_print_regs))\n            lines = gdb.execute(\"xmm\", to_string=True).splitlines()\n            for reg in to_print_regs:\n                for line in lines:\n                    if (\"$\" + reg) in line.split(\":\")[0]:\n                        gef_print(line, redirect=redirect)\n                        if reg in to_save_regs:\n                            printed_extra_regs[\"xmm\"] = printed_extra_regs.get(\"xmm\", []) + [reg]\n                        break\n\n        # avx register\n        to_save_regs = self.RE_FINDALL_AVX.findall(operands)\n        to_print_regs = to_save_regs + self.previous_extra_regs.get(\"ymm\", [])\n        if to_print_regs:\n            to_print_regs = sorted(set(to_print_regs))\n            lines = gdb.execute(\"ymm\", to_string=True).splitlines()\n            for reg in to_print_regs:\n                for line in lines:\n                    if (\"$\" + reg) in line.split(\":\")[0]:\n                        gef_print(line, redirect=redirect)\n                        if reg in to_save_regs:\n                            printed_extra_regs[\"ymm\"] = printed_extra_regs.get(\"ymm\", []) + [reg]\n                        break\n\n        # mmx register\n        to_save_regs = self.RE_FINDALL_MMX.findall(operands)\n        to_print_regs = to_save_regs + self.previous_extra_regs.get(\"mmx\", [])\n        if to_print_regs:\n            to_print_regs = sorted(set(to_print_regs))\n            lines = gdb.execute(\"mmx\", to_string=True).splitlines()\n            for reg in to_print_regs:\n                for line in lines:\n                    if (\"$\" + reg) in line.split(\":\")[0]:\n                        gef_print(line, redirect=redirect)\n                        if reg in to_save_regs:\n                            printed_extra_regs[\"mmx\"] = printed_extra_regs.get(\"mmx\", []) + [reg]\n                        break\n\n        # fpu register\n        if insn.mnemonic[0] == \"f\":\n            to_save_regs = self.RE_FINDALL_FPU.findall(operands)\n            to_print_regs = to_save_regs + self.previous_extra_regs.get(\"fpu\", [])\n            if to_print_regs:\n                to_print_regs = sorted(set(to_print_regs))\n                lines = gdb.execute(\"fpu\", to_string=True).splitlines()\n                for reg in to_print_regs:\n                    for line in lines:\n                        if (\"$\" + re.sub(r\"[()]\", reg, \"\")) in line.split(\":\")[0]:\n                            gef_print(line, redirect=redirect)\n                            if reg in to_save_regs:\n                                printed_extra_regs[\"fpu\"] = printed_extra_regs.get(\"fpu\", []) + [reg]\n                            break\n\n        self.previous_extra_regs = printed_extra_regs\n        return\n\n    def context_regs_syscall_errno(self, redirect):\n        if not Config.get_gef_setting(\"context_regs.show_errno\"):\n            return\n\n        if is_qemu_system() or is_kgdb() or is_kdb() or is_vmware() or is_wine():\n            return\n\n        if current_arch is None:\n            return\n        if current_arch.return_register is None:\n            return\n        if current_arch.ptrsize not in [4, 8]:\n            return\n\n        regvalue = get_register(current_arch.return_register)\n        if not AddressUtil.is_msb_on(regvalue):\n            return\n\n        try:\n            insn_prev = get_insn_prev()\n        except gdb.MemoryError:\n            return\n        if insn_prev is None:\n            return\n        if not current_arch.is_syscall(insn_prev):\n            return\n\n        if current_arch.ptrsize == 4:\n            val = struct.unpack(\"<i\", struct.pack(\"<I\", regvalue))[0]\n        elif current_arch.ptrsize == 8:\n            val = struct.unpack(\"<q\", struct.pack(\"<Q\", regvalue))[0]\n        val = -val\n\n        einfo = ErrnoCommand.get_errno_dict().get(val)\n        if not einfo:\n            return\n\n        line = \"{:s}: -{:d} {:s} ({:s})\".format(current_arch.return_register, val, einfo[0], einfo[1])\n        gef_print(line, redirect=redirect)\n        return\n\n    @Cache.cache_this_session\n    def get_target_registers(self):\n        if is_x86():\n            all_registers = current_arch.all_registers + current_arch.virtual_registers\n        else:\n            all_registers = current_arch.all_registers\n\n        ignored_registers = Config.get_gef_setting(\"context_regs.ignore_registers\").split()\n\n        # fast path\n        if not ignored_registers:\n            return \" \".join(all_registers)\n\n        # slow path\n        target_registers = []\n        for regs in all_registers:\n            if regs in ignored_registers:\n                continue\n            target_registers.append(regs)\n        return \" \".join(target_registers)\n\n    def context_registers_default(self, redirect):\n\n        def compact_info_registers():\n            res = gdb.execute(\"info registers\", to_string=True)\n            lines = []\n            special_lines = []\n            for line in res.splitlines():\n                s = line.split()\n\n                if len(s) > 3:\n                    # e.g., eflags 0x206 [ PF IF ]\n                    special_lines.append(line)\n                    continue\n\n                lines.append(s[:2])\n\n            if len(lines) <= len(special_lines):\n                # something is wrong\n                ContextCommand.execute_command(\"info registers\", redirect)\n                return\n\n            while len(lines) % 3:\n                lines.append(\"\")\n            first_half = lines[:len(lines) // 3]\n            second_half = lines[len(lines) // 3:][:len(lines) // 3]\n            third_half = lines[len(lines) // 3:]\n\n            pipe = Color.cyanify(\"|\")\n\n            final_lines = []\n            for f, s, t in zip(first_half, second_half, third_half):\n                final_lines.append(\"{:10s} {:20s} {:s}  {:10s} {:20s}  {:s} {:10s} {:20s}\".format(\n                    *f, pipe, *s, pipe, *t,\n                ))\n\n            final_lines = \"\\n\".join(final_lines + special_lines)\n            gef_print(final_lines, redirect=redirect)\n            return\n\n        try:\n            compact_info_registers()\n        except Exception:\n            ContextCommand.execute_command(\"info registers\", redirect)\n        return\n\n    def context_registers(self, redirect):\n        ContextCommand.context_title(\"registers\", redirect)\n\n        if current_arch is None:\n            self.context_registers_default(redirect)\n            return\n\n        target_registers = self.get_target_registers()\n\n        # exec registers\n        if Config.get_gef_setting(\"context_regs.show_registers_raw\"):\n            opt = \"-s\"\n        else:\n            opt = \"\"\n        ContextCommand.execute_command(\"registers {:s} {:s}\".format(opt, target_registers), redirect)\n\n        # for extra regs\n        self.context_regs_extra(redirect) # for x86 only (xmm, ymm, ...)\n        self.context_regs_syscall_errno(redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"regs\", args.ignore_redirect)\n        try:\n            self.context_registers(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextStackCommand(GenericCommand):\n    \"\"\"Context internal command to display stack.\"\"\"\n\n    _cmdline_ = \"context-stack\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context stack` to\")\n        self.add_setting(\"show_stack_raw\", False, \"Show the stack pane as raw hexdump (no dereference)\")\n        self.add_setting(\"nb_lines\", 8, \"Number of line in the stack pane\")\n        return\n\n    def context_stack_default(self, redirect):\n        try:\n            res = gdb.execute(\"info register $sp\", to_string=True)\n        except gdb.error:\n            err(\"Failed to get value of $SP\", redirect=redirect)\n            return\n\n        try:\n            sp = int(res.split()[1], 0)\n        except (IndexError, ValueError):\n            err(\"Failed to get value of $SP\", redirect=redirect)\n            return\n\n        try:\n            data = read_memory(sp, 0x40)\n        except gdb.MemoryError:\n            err(\"Failed to read from $sp\", redirect)\n            return\n\n        unit = AddressUtil.get_memory_alignment()\n        hexdata = hexdump(data, base=sp, unit=unit)\n        gef_print(hexdata, redirect=redirect)\n        return\n\n    def context_stack(self, redirect):\n        ContextCommand.context_title(\"stack\", redirect)\n\n        if current_arch is None:\n            self.context_stack_default(redirect)\n            return\n\n        if current_arch.sp is None:\n            err(\"Failed to get value of $SP\", redirect=redirect)\n            return\n\n        show_raw = Config.get_gef_setting(\"context_stack.show_stack_raw\")\n        nb_lines = Config.get_gef_setting(\"context_stack.nb_lines\")\n\n        if show_raw is True:\n            try:\n                mem = read_memory(current_arch.sp, 0x10 * nb_lines)\n                gef_print(hexdump(mem, base=current_arch.sp), redirect=redirect)\n            except gdb.MemoryError:\n                err(\"Cannot read memory from $SP (corrupted stack pointer?)\", redirect=redirect)\n            return\n\n        if current_arch.stack_grow_down:\n            nb_lines *= -1\n\n        ContextCommand.execute_command(\n            \"dereference {:#x} {:d} --no-pager\".format(current_arch.sp, nb_lines), redirect,\n        )\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"stack\", args.ignore_redirect)\n        try:\n            self.context_stack(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextCodeCommand(GenericCommand):\n    \"\"\"Context internal command to display code.\"\"\"\n\n    _cmdline_ = \"context-code\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    context_comments = {}\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context code` to\")\n        self.add_setting(\"show_opcodes_size\", 8, \"Number of bytes of opcodes to display next to the disassembly\")\n        self.add_setting(\"show_opcodes_size_x64_x86\", 10, \"Number of bytes of opcodes to display next to the disassembly\")\n        self.add_setting(\"peek_call\", True, \"Peek into call opcode\")\n        self.add_setting(\"peek_conditional_branch\", True, \"Emulates a conditional branch and peeks if it is taken\")\n        self.add_setting(\"peek_jump\", True, \"Peek into jump opcode\")\n        self.add_setting(\"peek_ret\", True, \"Peek into ret opcode\")\n        self.add_setting(\"use_native_x_command\", False, \"Use x/16i instead of Disasm.gef_disassemble\")\n        self.add_setting(\"use_capstone\", False, \"Use capstone as disassembler in the code pane (instead of GDB)\")\n        self.add_setting(\"nb_lines\", 6, \"Number of instruction after $pc\")\n        self.add_setting(\"nb_lines_prev\", 3, \"Number of instruction before $pc\")\n        return\n\n    RE_SUB_BRANCH_ADDR1 = re.compile(r\".*# (0x[a-fA-F0-9]+).*\")\n    RE_SUB_BRANCH_ADDR2 = re.compile(r\".*# (0x[a-fA-F0-9]+).*\")\n    RE_SUB_BRANCH_ADDR3 = re.compile(r\".* (PTR|ptr) \\[(.+?)\\].*\")\n    RE_SUB_BRANCH_ADDR4 = re.compile(r\".* (PTR|ptr) fs:\\[?(0x[a-fA-F0-9]+)\\]?.*\")\n    RE_SUB_BRANCH_ADDR5 = re.compile(r\".* (PTR|ptr) gs:\\[?(0x[a-fA-F0-9]+)\\]?.*\")\n    RE_SUB_BRANCH_ADDR6 = re.compile(r\"^.*\\s+([-0-9]+)$\")\n    RE_SUB_BRANCH_ADDR7 = re.compile(r\".*(0x[a-fA-F0-9]+).*\")\n\n    @staticmethod\n    def get_branch_addr(insn, to_str=False):\n        ops = \" \".join(insn.operands)\n        ops = re.sub(r\"<.*?>\", \"\", ops)\n\n        # is there an evaluated immediate value?\n        #   x86/x64 (default): call ... [rip+0x1111] # 0xAABBCCDD\n        if \" # 0x\" in ops and not is_loongarch64():\n            addr = ContextCodeCommand.RE_SUB_BRANCH_ADDR1.sub(r\"\\1\", ops)\n            ptr = to_unsigned_long(gdb.parse_and_eval(addr))\n            try:\n                if to_str:\n                    return \"{:#x}\".format(read_int_from_memory(ptr))\n                else:\n                    return read_int_from_memory(ptr)\n            except gdb.MemoryError:\n                if to_str:\n                    return \"*{:#x}\".format(ptr)\n                else:\n                    return None\n\n        # is there an evaluated immediate value?\n        #   loongarch64: bnez $t1, -8 (0x7ffff8) # 0x120000868\n        if \" # 0x\" in ops and is_loongarch64():\n            addr = ContextCodeCommand.RE_SUB_BRANCH_ADDR2.sub(r\"\\1\", ops)\n            ptr = to_unsigned_long(gdb.parse_and_eval(addr))\n            if to_str:\n                return \"{:#x}\".format(ptr)\n            else:\n                return ptr\n\n        # is there a memory reference by register?\n        #   x86/x64 (default): call ... PTR [rbx]\n        #   x86/x64 (capstone): call ... ptr [rbx]\n        #   x64 (capstone): call ... ptr [rip + 0x1111]\n        if is_x86():\n            if \" PTR [\" in ops or \" ptr [\" in ops:\n                addr = ContextCodeCommand.RE_SUB_BRANCH_ADDR3.sub(r\"\\2\", ops)\n                for gr in current_arch.general_registers:\n                    addr = addr.replace(gr.replace(\"$\", \"\"), gr)\n                if is_x86_64():\n                    addr = addr.replace(\"$rip\", \"$rip+{:#x}\".format(len(insn.opcodes)))\n                try:\n                    ptr = to_unsigned_long(gdb.parse_and_eval(addr))\n                except gdb.error:\n                    return None\n                try:\n                    if to_str:\n                        return \"{:#x}\".format(read_int_from_memory(ptr))\n                    else:\n                        return read_int_from_memory(ptr)\n                except gdb.MemoryError:\n                    if to_str:\n                        return \"*{:#x}\".format(ptr)\n                    else:\n                        return None\n\n        # is there a segment relative?\n        #   x64 (default): call ... PTR fs:0x10\n        #   x64 (capstone): call ... ptr fs:[0x10]\n        if is_x86_64():\n            if \" PTR fs:\" in ops or \" ptr fs:\" in ops:\n                ofs = ContextCodeCommand.RE_SUB_BRANCH_ADDR4.sub(r\"\\2\", ops)\n                ofs = to_unsigned_long(gdb.parse_and_eval(ofs))\n                fs = current_arch.get_fs()\n                try:\n                    if to_str:\n                        return \"{:#x}\".format(read_int_from_memory(fs + ofs))\n                    else:\n                        return read_int_from_memory(fs + ofs)\n                except gdb.MemoryError:\n                    if to_str:\n                        return \"*{:#x}\".format(fs + ofs)\n                    else:\n                        return None\n\n        # is there a segment relative?\n        #   x86 (default): call ... PTR gs:0x10\n        #   x86 (capstone): call ... ptr gs:[0x10]\n        if is_x86_32():\n            if \" PTR gs:\" in ops or \" ptr gs:\" in ops:\n                ofs = ContextCodeCommand.RE_SUB_BRANCH_ADDR5.sub(r\"\\2\", ops)\n                ofs = to_unsigned_long(gdb.parse_and_eval(ofs))\n                gs = current_arch.get_gs()\n                try:\n                    if to_str:\n                        return \"{:#x}\".format(read_int_from_memory(gs + ofs))\n                    else:\n                        return read_int_from_memory(gs + ofs)\n                except gdb.MemoryError:\n                    if to_str:\n                        return \"*{:#x}\".format(gs + ofs)\n                    else:\n                        return None\n\n        # is there a relative immediate?\n        #   microblaze:  brlid  r15, -136\n        #   microblaze:  bneid  r4, -8    // 3ffe9848\n        if is_microblaze():\n            addr = ContextCodeCommand.RE_SUB_BRANCH_ADDR6.sub(r\"\\1\", ops.split(\"//\")[0].strip())\n            try:\n                addr = int(addr) + insn.address\n                if to_str:\n                    return \"{:#x}\".format(addr)\n                else:\n                    return addr\n            except Exception:\n                pass\n\n        # is there a absolute immediate value (with segment)?\n        #   x86_16:  ljmp   0xf000:0xe05b\n        if is_x86_16() and \":0x\" in ops:\n            seg, val = [int(x, 16) for x in ops.split(\":\")]\n            if ops.startswith(\"0x\"):\n                addr = current_arch.real2phys(seg, val)\n            else:\n                addr = val\n            if to_str:\n                return \"{:#x}\".format(addr)\n            else:\n                return addr\n\n        # is there a absolute immediate value?\n        #   s390x:   bra    0x3ffdfc60\n        #   s390x:   brasl  %r14, 0x1020b50\n        #   RISCV:   jal    ra, 0x13894\n        #   RISCV:   bgeu   t1, a2, 0x10350\n        if \"0x\" in ops:\n            addr = ContextCodeCommand.RE_SUB_BRANCH_ADDR7.sub(r\"\\1\", ops)\n            if to_str:\n                return \"{:#x}\".format(to_unsigned_long(gdb.parse_and_eval(addr)))\n            else:\n                return to_unsigned_long(gdb.parse_and_eval(addr))\n\n        # is there register(s)?\n        #   x86/x64: call   rax\n        #   s390x:   basr   %lr, %r1\n        #   sh4:     jsr    @r1\n        #   alpha:   jmp    (t0)\n        if insn.operands[-1].split():\n            maybe_reg = insn.operands[-1].split()[0]\n            if len(maybe_reg) <= 5 and maybe_reg[0] == \"(\" and maybe_reg[-1] == \")\":\n                maybe_reg = maybe_reg[1:-1]\n            ptr = get_register(maybe_reg)\n            if ptr is not None:\n                if to_str:\n                    return \"{:#x}\".format(ptr)\n                else:\n                    return ptr\n\n        # bctr?\n        #   ppc: bctr\n        if is_ppc32() or is_ppc64():\n            if insn.mnemonic == \"bctr\":\n                addr = get_register(\"ctr\")\n                if addr is None:\n                    return None\n                if to_str:\n                    return \"{:#x}\".format(addr)\n                else:\n                    return addr\n\n        # jirl?\n        #   loongarch64: jirl $ra, $ra, 0\n        if is_loongarch64():\n            if insn.mnemonic == \"jirl\":\n                if len(insn.operands) >= 3:\n                    reg = insn.operands[1]\n                    off = int(insn.operands[2], 0)\n                    addr = get_register(reg) + off\n                    if to_str:\n                        return \"{:#x}\".format(addr)\n                    else:\n                        return addr\n\n        return None\n\n    def get_breakpoints(self):\n        breakpoints = gdb.breakpoints()\n        if not breakpoints:\n            return []\n        bp_locations = []\n        for b in breakpoints:\n            if hasattr(b, \"locations\"): # gdb 13.1~\n                for bl in b.locations:\n                    if bl and bl.address is not None:\n                        bp_locations.append(bl.address)\n            else: # for old gdb\n                if b.location and b.location.startswith(\"*\"):\n                    pos = b.location.lstrip(\"*\")\n                    try:\n                        x = int(pos, 16)\n                        bp_locations.append(x)\n                    except ValueError:\n                        pass\n        return bp_locations\n\n    def context_code_default(self, redirect):\n        ContextCommand.execute_command(\"x/8i $pc\", redirect)\n        return\n\n    def context_code(self, redirect):\n        if current_arch is None:\n            ContextCommand.context_title(\"code\", redirect)\n            self.context_code_default(redirect)\n            return\n\n        use_native_x_command = Config.get_gef_setting(\"context_code.use_native_x_command\")\n        nb_insn = Config.get_gef_setting(\"context_code.nb_lines\")\n        nb_insn_prev = Config.get_gef_setting(\"context_code.nb_lines_prev\")\n        if is_x86():\n            show_opcodes_size = Config.get_gef_setting(\"context_code.show_opcodes_size_x64_x86\")\n        else:\n            show_opcodes_size = Config.get_gef_setting(\"context_code.show_opcodes_size\")\n        past_lines_color = Config.get_gef_setting(\"theme.context_code_past\")\n        future_lines_color = Config.get_gef_setting(\"theme.context_code_future\")\n        use_capstone = Config.get_gef_setting(\"context_code.use_capstone\")\n\n        pc = current_arch.pc\n        bp_locations = self.get_breakpoints()\n\n        try:\n            frame = gdb.selected_frame()\n            arch_name = \"{:s}:{:s}\".format(current_arch.arch.lower(), current_arch.mode)\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            frame = None\n            arch_name = \"{:s}:{:s}\".format(current_arch.arch.lower(), \"???\")\n\n        if use_native_x_command:\n            arch_name += \" (gdb-native)\"\n        elif use_capstone:\n            arch_name += \" (capstone)\"\n        else:\n            arch_name += \" (gdb-native)\"\n\n        ContextCommand.context_title(\"code: {:s}\".format(arch_name), redirect)\n        if use_native_x_command:\n            ContextCommand.execute_command(\"x/16i {:#x}\".format(current_arch.pc), redirect)\n            return\n\n        for insn in Disasm.gef_disassemble(pc, nb_insn, nb_prev=nb_insn_prev):\n            line = \"\"\n            is_taken = False\n            target = None\n            delay_slot = None\n\n            # bp prefix\n            if insn.address in bp_locations:\n                bp_prefix = Color.redify(\"*\")\n            else:\n                bp_prefix = \" \"\n\n            # insn to string with coloring by address against pc\n            if insn.address < pc:\n                if past_lines_color:\n                    text = insn.colored_text(show_opcodes_size, highlight=False, disable_color=True)\n                    text = Color.colorify(text, past_lines_color)\n                else:\n                    text = insn.colored_text(show_opcodes_size, highlight=False)\n            elif insn.address == pc:\n                text = insn.colored_text(show_opcodes_size, highlight=True)\n            else:\n                if future_lines_color:\n                    text = insn.colored_text(show_opcodes_size, highlight=False, disable_color=True)\n                    text = Color.colorify(text, future_lines_color)\n                else:\n                    text = insn.colored_text(show_opcodes_size, highlight=False)\n\n            # bp prefix and branch info\n            if insn.address != pc:\n                line += \"{:s}   {:s}\".format(bp_prefix, text)\n\n            elif insn.address == pc:\n                line += \"{:s}-> {:s}\".format(bp_prefix, text)\n\n                # branch info\n                if current_arch.is_conditional_branch(insn):\n                    if Config.get_gef_setting(\"context_code.peek_conditional_branch\") is True:\n                        is_taken, reason = current_arch.is_branch_taken(insn)\n                        if is_taken:\n                            target = ContextCodeCommand.get_branch_addr(insn)\n                            reason = \"[Reason: {:s}]\".format(reason) if reason else \"\"\n                            line += \"\\t\" + Color.colorify(\"TAKEN {:s}\".format(reason), \"bold green\")\n                            delay_slot = current_arch.has_delay_slot\n                        else:\n                            reason = \"[Reason: !({:s})]\".format(reason) if reason else \"\"\n                            line += \"\\t\" + Color.colorify(\"NOT taken {:s}\".format(reason), \"bold red\")\n                elif current_arch.is_jump(insn):\n                    if Config.get_gef_setting(\"context_code.peek_jump\") is True:\n                        target = ContextCodeCommand.get_branch_addr(insn)\n                        delay_slot = current_arch.has_delay_slot\n                elif current_arch.is_call(insn):\n                    if Config.get_gef_setting(\"context_code.peek_call\") is True:\n                        target = ContextCodeCommand.get_branch_addr(insn)\n                        delay_slot = current_arch.has_delay_slot\n                elif current_arch.is_ret(insn):\n                    if Config.get_gef_setting(\"context_code.peek_ret\") is True:\n                        target = current_arch.get_ra(insn, frame)\n                        delay_slot = current_arch.has_ret_delay_slot\n\n                if is_arc32() or is_arc64():\n                    delay_slot = insn.mnemonic.endswith(\".d\") or insn.mnemonic.endswith(\".d.nt\")\n\n            # comment\n            if insn.address in self.context_comments:\n                line += \"\\t\\t\" + Color.grayify(\"// \" + \"; \".join(self.context_comments[insn.address]))\n\n            gef_print(line, redirect=redirect)\n\n            # add extra branch info\n            if target:\n                # for delay slot\n                try:\n                    if delay_slot:\n                        next_insn = list(Disasm.gef_disassemble(insn.address, 2))[-1]\n                        text = \"{:s}   {:s}\\t{:s}\".format(\n                            bp_prefix,\n                            next_insn.colored_text(show_opcodes_size, highlight=False),\n                            Color.colorify(\"Maybe delay-slot\", \"bold yellow\"),\n                        )\n                        gef_print(text, redirect=redirect)\n                except Exception:\n                    pass\n\n                # branch target address\n                try:\n                    for i, tinsn in enumerate(Disasm.gef_disassemble(target, nb_insn)):\n                        text = tinsn.colored_text(show_opcodes_size, highlight=False)\n                        if i == 0:\n                            gef_print(\"\", redirect=redirect) # need blank line\n                            text = \"   -> {}\".format(text)\n                        else:\n                            text = \"      {}\".format(text)\n                        gef_print(text, redirect=redirect)\n                    gef_print(\"\", redirect=redirect) # need blank line\n                except Exception:\n                    pass\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"code\", args.ignore_redirect)\n        try:\n            self.context_code(redirect)\n        except Exception as e:\n            # In ARM64, before and after the transition to EL3,\n            # there are cases where read_memory fails but the x command works.\n            try:\n                ContextCommand.execute_command(\"x/8i $pc\", redirect)\n            except Exception:\n                err(str(e), redirect=redirect) # use first Exception string\n        return\n\n\n@register_command\nclass ContextMemoryAccessCommand(GenericCommand):\n    \"\"\"Context internal command to display accessing memory.\"\"\"\n\n    _cmdline_ = \"context-mem-access\"\n    _category_ = \"01-a. Debugging Support - Context\"\n    _aliases_ = [\"context-mem_access\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context mem_access` to\")\n        return\n\n    RE_SUB_OPERAND3 = re.compile(r\"<.*?>\")\n    RE_FINDALL_SEG1 = re.compile(r\"[^:](\\[.+?\\])\")\n    RE_MATCH_REG1 = re.compile(r\"r\\d+d?\")\n    RE_MATCH_REG2 = re.compile(r\"r\\d+\")\n    RE_MATCH_REG3 = re.compile(r\"[xw]\\d+\")\n\n    def context_memory_access1(self, redirect):\n        if not (is_x86() or is_arm32() or is_arm32_cortex_m() or is_arm64()):\n            return\n\n        inst_iter = Disasm.gef_disassemble(current_arch.pc, 2)\n        try:\n            insn_here = inst_iter.__next__()\n        except StopIteration:\n            return\n\n        if insn_here.operands == []:\n            return\n        if insn_here.mnemonic == \"nop\":\n            return\n\n        insn = \",\".join(insn_here.operands)\n        insn = self.RE_SUB_OPERAND3.sub(\"\", insn)\n        r = self.RE_FINDALL_SEG1.findall(str(insn)) # Unsupported: seg:[reg]\n        if not r:\n            return\n\n        insn_next = inst_iter.__next__()\n        codesize = insn_next.address - insn_here.address\n\n        for code in r:\n            code = code[1:-1] # skip \"[\" and \"]\"\n\n            if is_x86():\n                # add \"$\" to resiter\n                code = code.replace(\"+\", \" + \")\n                code = code.replace(\"-\", \" - \")\n                code = code.replace(\"*\", \" * \")\n                code = code.replace(\"eiz\", \" 0 \") # $eiz is always 0x0\n                code = code.split()\n                code = [\"$\" + x if x.isalpha() or self.RE_MATCH_REG1.match(x) else x for x in code]\n                code = \"\".join(code)\n                # $rip/$eip points next instruction\n                code_orig, code = code, code.replace(\"$rip\", \"$rip+{:#x}\".format(codesize))\n\n            elif is_arm32() or is_arm32_cortex_m():\n                # add \"$\" to resiter\n                code = code.replace(\" \", \"\")\n                code = code.replace(\"#\", \"\")\n                code = code.replace(\"lsl\", \"<<\")\n                code = code.split(\",\")\n                code = [\"$\" + x if x.isalpha() or self.RE_MATCH_REG2.match(x) else x for x in code]\n                if \"<<\" in code[-1]:\n                    code = code[:-2] + [\"(\" + code[-2] + code[-1] + \")\"]\n                code = \"+\".join(code)\n                # $pc points next next instruction\n                code_orig, code = code, code.replace(\"$pc\", \"$pc+{:#x}\".format(codesize * 2))\n\n            elif is_arm64():\n                # add \"$\" to resiter\n                code = code.replace(\" \", \"\")\n                code = code.replace(\"#\", \"\")\n                code = code.replace(\"lsl\", \"<<\").replace(\"sxtw\", \"<<\").replace(\"uxtw\", \"<<\")\n                code = code.replace(\"xzr\", \" 0 \") # $xzr is always 0x0\n                code = code.replace(\"wzr\", \" 0 \") # $wzr is always 0x0\n                code = code.replace(\"wsp\", \" ($sp&0xffff) \") # $wsp is a half of $sp\n                code = code.split(\",\")\n                code = [\"$\" + x if x.isalpha() or self.RE_MATCH_REG3.match(x) else x for x in code]\n                if \"<<\" == code[-1]:\n                    code[-1] += \"0\"\n                if \"<<\" in code[-1]:\n                    code = code[:-2] + [\"(\" + code[-2] + code[-1] + \")\"]\n                code = \"+\".join(code)\n                # $pc points next next instruction\n                code_orig, code = code, code.replace(\"$pc\", \"$pc+{:#x}\".format(codesize * 2))\n\n            # print\n            try:\n                code = code.replace(\"$\", \"(long)$\")\n                addr = AddressUtil.parse_address(code)\n            except gdb.error:\n                # some binary fails to resolve \"(long)\"\n                try:\n                    addr = AddressUtil.parse_address(code_orig)\n                except gdb.error:\n                    return\n            ContextCommand.context_title(\"memory access: {:s} = {:#x}\".format(code_orig, addr), redirect)\n            self.is_context_title_written = True\n            ContextCommand.execute_command(\"dereference {:#x} 4 --no-pager\".format(addr), redirect)\n        return\n\n    RE_FINDALL_SEG2 = re.compile(r\"((fs|gs):\\[?([^,\\]]+)\\]?)\")\n    RE_MATCH_REG4 = re.compile(r\"r\\d+d?\")\n\n    def context_memory_access2(self, redirect):\n        if not is_x86():\n            return\n\n        inst_iter = Disasm.gef_disassemble(current_arch.pc, 2)\n        try:\n            insn_here = inst_iter.__next__()\n        except StopIteration:\n            return\n\n        if insn_here.operands == []:\n            return\n\n        insn = \",\".join(insn_here.operands)\n        insn = re.sub(r\"<.+>\", \"\", insn)\n\n        try:\n            insn_next = inst_iter.__next__()\n        except StopIteration:\n            return\n        codesize = insn_next.address - insn_here.address\n\n        r = self.RE_FINDALL_SEG2.findall(str(insn))\n        if r:\n            code, fsgs, offset = r[0][0], r[0][1], r[0][2]\n            if fsgs == \"fs\":\n                fsgs_val = current_arch.get_fs()\n            else:\n                fsgs_val = current_arch.get_gs()\n            if fsgs_val is None:\n                return\n            offset = offset.replace(\"+\", \" + \")\n            offset = offset.replace(\"-\", \" - \")\n            offset = offset.replace(\"*\", \" * \")\n            offset = offset.replace(\"eiz\", \" 0 \") # $eiz is always 0x0\n            offset = offset.split()\n            offset = [\"$\" + x if x.isalpha() or self.RE_MATCH_REG4.match(x) else x for x in offset]\n            offset = \"\".join(offset)\n            # $rip/$eip points next instruction\n            offset = offset.replace(\"$rip\", \"$rip+{:#x}\".format(codesize))\n            offset = AddressUtil.parse_address(offset)\n            addr = AddressUtil.align_address(fsgs_val + offset)\n            ContextCommand.context_title(\"memory access: {:s} = {:#x}\".format(code, addr), redirect)\n            self.is_context_title_written = True\n            ContextCommand.execute_command(\"dereference {:#x} 4 --no-pager\".format(addr), redirect)\n        return\n\n    RE_FINDALL_SEG3 = re.compile(r\"((es|ds|ss|cs):\\[?([^,\\]]+)\\]?)\")\n    RE_MATCH_REG5 = re.compile(r\"r\\d+d?\")\n\n    def context_memory_access3(self, redirect):\n        if not is_x86():\n            return\n\n        inst_iter = Disasm.gef_disassemble(current_arch.pc, 1)\n        try:\n            insn_here = inst_iter.__next__()\n        except StopIteration:\n            return\n\n        if insn_here.operands == []:\n            return\n\n        insn = \",\".join(insn_here.operands)\n        insn = re.sub(r\"<.+>\", \"\", insn)\n\n        r = self.RE_FINDALL_SEG3.findall(str(insn))\n        for rr in r:\n            code, addr = rr[0], rr[2]\n            addr = addr.replace(\"+\", \" + \")\n            addr = addr.replace(\"-\", \" - \")\n            addr = addr.replace(\"*\", \" * \")\n            addr = addr.replace(\"eiz\", \" 0 \") # $eiz is always 0x0\n            addr = addr.split()\n            addr = [\"$\" + x if x.isalpha() or self.RE_MATCH_REG5.match(x) else x for x in addr]\n            addr = AddressUtil.parse_address(\"\".join(addr))\n            ContextCommand.context_title(\"memory access: {:s} = {:#x}\".format(code, addr), redirect)\n            self.is_context_title_written = True\n            ContextCommand.execute_command(\"dereference {:#x} 4 --no-pager\".format(addr), redirect)\n        return\n\n    def context_memory_access(self, redirect):\n        self.context_memory_access1(redirect)\n        self.context_memory_access2(redirect) # for x86/x64 - fs/gs\n        self.context_memory_access3(redirect) # for x86/x64 - cs/ss/ds/es\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"mem_access\", args.ignore_redirect)\n        self.is_context_title_written = False\n        try:\n            self.context_memory_access(redirect)\n        except Exception as e:\n            if not self.is_context_title_written:\n                ContextCommand.context_title(\"memory access\", redirect)\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextArgumentsCommand(GenericCommand):\n    \"\"\"Context internal command to display arguments.\"\"\"\n\n    _cmdline_ = \"context-args\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context args` to\")\n        self.add_setting(\"nb_guessed_arguments\", 6, \"Number to display when guessing functions arguments\")\n        return\n\n    def get_got_value(self, addr):\n        # GOT cannot be detected in kernel mode\n        if is_qemu_system() or is_vmware() or is_kgdb():\n            return None\n\n        # GOT Cannot be detected if no file is specified\n        addr_obj = ProcessMap.lookup_address(addr)\n        if not addr_obj:\n            return None\n        if not addr_obj.section:\n            return None\n        if not addr_obj.section.path:\n            return None\n        filepath = addr_obj.section.path\n        if not os.path.exists(filepath):\n            return None\n\n        # something is wrong\n        ret = Symbol.gdb_get_location(addr)\n        if not ret:\n            return None\n\n        # check if PLT\n        func_name = ret[0]\n        if not func_name.endswith(\"@plt\"):\n            return None\n        func_name = func_name[:-4]\n\n        # use `got` command to obtain function address\n        try:\n            ret = gdb.execute(\"got -q -f {!r} --exact {:s}\".format(filepath, func_name), to_string=True)\n            ret = Color.remove_color(ret).splitlines()\n            if len(ret) != 1:\n                return None\n            ret = ret[0]\n            got_value = int(ret.split(\"|\")[-1].split()[0], 16)\n        except Exception:\n            return None\n\n        return got_value\n\n    def get_call_destination_function_block(self, insn):\n        # call insn -> destination addr\n        addr = ContextCodeCommand.get_branch_addr(insn)\n        if addr is None:\n            return None\n\n        # check if addr is PLT or not\n        ret = self.get_got_value(addr)\n        if ret:\n            # use got value\n            addr = ret\n            # Even if the GOT is unresolved in Partial RELRO, there is no problem.\n            # This is because the subsequent gdb.block_for_pc(addr) returns None.\n\n        # addr -> block\n        block = gdb.block_for_pc(addr)\n        if block and not block.function:\n            return None\n        return block\n\n    def print_arguments_from_symbol_x86(self, block, redirect):\n        suffix_words = (\"_avx2\", \"_avx\", \"_avx512\", \"_sse\", \"_sse2\", \"_ssse3\", \"_sse4_1\", \"_sse42\")\n        inner_words = (\"_avx2_\", \"_avx_\", \"_avx512_\", \"_sse2_\")\n\n        if block.function.name.endswith(suffix_words):\n            match = True\n        elif any(x in block.function.name for x in inner_words):\n            match = True\n        else:\n            match = False\n\n        if match:\n            function_name = \"{:#x} <{:s}>\".format(block.start, block.function.name)\n            self.print_guessed_arguments(function_name, redirect)\n            return True\n\n        return False\n\n    def print_arguments_from_symbol(self, block, redirect):\n        \"\"\"If symbols were found, parse them and print the argument adequately.\"\"\"\n\n        # setup iterator\n        args_info = [x for x in block if x.is_argument]\n        if len(args_info) == len(block.function.type.fields()):\n            # new implementation; get args information from the block.\n            # we can get both type names and variable names.\n            iterator = args_info\n            title = \"arguments (from block)\"\n\n            # special case\n            if len(args_info) == 0:\n                # Some string processing functions are implemented in assembly for speed.\n                # Since there is no type information for these arguments, the number of arguments is always 0.\n                # Here, if a function name matches the blacklist, type information is not used and\n                # print_guessed_arguments is forcibly called to display context_args.nb_guessed_arguments arguments.\n                if is_x86():\n                    if self.print_arguments_from_symbol_x86(block, redirect):\n                        return\n        else:\n            # old implementation.\n            # we can get type names, but not variable names\n            iterator = block.function.type.fields()\n            title = \"arguments (from fields)\"\n\n        # helper function\n        def get_type_name(t):\n            try:\n                pointer_nest = 0\n                while t.code == gdb.TYPE_CODE_PTR:\n                    pointer_nest += 1\n                    t = t.target()\n                if not t.name:\n                    return None\n                return t.name + \"*\" * pointer_nest\n            except Exception:\n                return None\n\n        # get each values\n        args = []\n        for i, f in enumerate(iterator):\n            # value\n            value = current_arch.get_ith_parameter(i, in_func=False)[1]\n            if value is None:\n                break\n            value = AddressUtil.recursive_dereference_to_string(value)\n\n            # name\n            name = f.name or \"var_{:d}\".format(i)\n\n            # type name\n            typ = get_type_name(f.type)\n            if typ is None:\n                typ = {1: \"BYTE\", 2: \"WORD\", 4: \"DWORD\", 8: \"QWORD\"}[f.type.sizeof]\n\n            # ok\n            args.append(\"{:s} {:s} = {:s}\".format(typ, name, value))\n\n        # output\n        ContextCommand.context_title(title, redirect)\n        gef_print(\"{:#x} <{:s}> (\".format(block.start, block.function.name), redirect=redirect)\n        for a in args:\n            gef_print(\"   {:s},\".format(a), redirect=redirect)\n        gef_print(\")\", redirect=redirect)\n        return\n\n    def print_guessed_arguments(self, function_name, redirect):\n        \"\"\"When no symbol, print six arguments.\"\"\"\n        arg_key_color = Config.get_gef_setting(\"theme.registers_register_name\")\n        nb_argument = Config.get_gef_setting(\"context_args.nb_guessed_arguments\")\n\n        # get each values\n        args = []\n        for i in range(nb_argument):\n            try:\n                key, value = current_arch.get_ith_parameter(i, in_func=False)\n                value = AddressUtil.recursive_dereference_to_string(value)\n            except Exception:\n                break\n            args.append(\"{:s} = {:s}\".format(Color.colorify(key, arg_key_color), value))\n\n        # output\n        ContextCommand.context_title(\"arguments (guessed)\", redirect)\n        gef_print(\"{:s} (\".format(function_name), redirect=redirect)\n        for a in args:\n            gef_print(\"   {:s},\".format(a), redirect=redirect)\n        gef_print(\")\", redirect=redirect)\n        return\n\n    def context_args(self, redirect):\n        if current_arch is None:\n            return\n\n        # get insn\n        try:\n            insn = get_insn()\n        except gdb.MemoryError:\n            return\n        if insn is None:\n            return\n\n        # syscall case\n        if current_arch.is_syscall(insn):\n            ContextCommand.context_title(\"arguments\", redirect)\n            ContextCommand.execute_command(\"syscall-args\", redirect)\n            return\n\n        # non-call case\n        if not current_arch.is_call(insn):\n            return\n\n        # call case (from symbol)\n        block = self.get_call_destination_function_block(insn)\n        if block:\n            # okay, it has symbols and not in blacklist\n            self.print_arguments_from_symbol(block, redirect)\n            return\n\n        # call case (guessing)\n        # no symbols, try extract target address\n        addr = ContextCodeCommand.get_branch_addr(insn)\n        if addr is not None:\n            function_name = \"{:#x}{:s}\".format(\n                addr, Symbol.get_symbol_string(addr, nosymbol_string=\" <NO_SYMBOL>\"),\n            )\n        else:\n            # failed, use raw operands\n            function_name = \" \".join(insn.operands)\n        self.print_guessed_arguments(function_name, redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"args\", args.ignore_redirect)\n        try:\n            self.context_args(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextSourceCommand(GenericCommand):\n    \"\"\"Context internal command to display source.\"\"\"\n\n    _cmdline_ = \"context-source\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"nb_lines\", metavar=\"NB_LINES\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"temporarily overrides context_source.nb_lines.\")\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context source` to\")\n        self.add_setting(\"show_source_code_variable_values\", True, \"Show extra PC context info in the source code\")\n        self.add_setting(\"nb_lines\", 6, \"Number of source code after $pc\")\n        return\n\n    def get_source_breakpoints(self, file_base_name):\n        breakpoints = gdb.breakpoints()\n        if not breakpoints:\n            return []\n        bp_locations = []\n        for b in breakpoints:\n            if hasattr(b, \"locations\") and b.locations:\n                for bl in b.locations:\n                    if bl and bl.source:\n                        bp_locations.append(\"{:s}:{:d}\".format(bl.source[0], bl.source[1]))\n            else: # for old gdb\n                bp_locations.append(b.location)\n        return bp_locations\n\n    def line_has_breakpoint(self, file_name, line_number, bp_locations):\n        if not bp_locations:\n            return False\n        filename_line = \"{}:{}\".format(file_name, line_number)\n        return any(filename_line in loc for loc in bp_locations)\n\n    def get_pc_context_info(self, pc, line):\n        try:\n            current_block = gdb.block_for_pc(pc)\n        except gdb.error:\n            return []\n\n        if not current_block or not current_block.is_valid():\n            return []\n\n        m = []\n        seen_symbol = []\n        while current_block and not current_block.is_static:\n            for sym in current_block:\n                if sym.is_function:\n                    continue\n                if re.search(r\"\\W{}\\W\".format(sym.name), line):\n                    try:\n                        val = gdb.parse_and_eval(sym.name)\n                    except gdb.error:\n                        continue\n                    if val.type.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY):\n                        if val.address is None:\n                            continue\n                        addr = int(val.address)\n                        val = AddressUtil.recursive_dereference_to_string(addr)\n                    elif val.type.code == gdb.TYPE_CODE_INT:\n                        try:\n                            val = hex(int(val))\n                        except gdb.error:\n                            continue\n                    else:\n                        continue\n\n                    if sym.name not in seen_symbol:\n                        seen_symbol.append(sym.name)\n                        msg = \"{} = {}\".format(Color.yellowify(sym.name), val)\n                        m.append(msg)\n            current_block = current_block.superblock\n        return m\n\n    def context_source(self, redirect):\n        if current_arch is None:\n            return\n\n        try:\n            pc = current_arch.pc\n            symtabline = gdb.find_pc_line(pc)\n            symtab = symtabline.symtab\n            line_num = symtabline.line - 1 # we subtract one because line number returned by gdb start at 1\n            if not symtab.is_valid():\n                return\n            fpath = symtab.fullname()\n            with open(fpath, \"r\") as f:\n                lines = [x.rstrip() for x in f.readlines()]\n        except Exception:\n            return\n\n        ContextCommand.context_title(\n            \"source: {}+{}\".format(os.path.normpath(symtab.filename), line_num + 1), redirect,\n        )\n\n        if self.args.nb_lines is not None:\n            nb_lines = self.args.nb_lines\n        else:\n            nb_lines = Config.get_gef_setting(\"context_source.nb_lines\")\n        past_lines_color = Config.get_gef_setting(\"theme.context_code_past\")\n        cur_line_color = Config.get_gef_setting(\"theme.source_current_line\")\n        future_lines_color = Config.get_gef_setting(\"theme.context_code_future\")\n        show_extra_info = Config.get_gef_setting(\"context_source.show_source_code_variable_values\")\n\n        file_base_name = os.path.basename(symtab.filename)\n        bp_locations = self.get_source_breakpoints(file_base_name)\n\n        for i in range(line_num - nb_lines + 1, line_num + nb_lines):\n            if i < 0:\n                continue\n\n            if len(lines) <= i:\n                break\n\n            if self.line_has_breakpoint(file_base_name, i + 1, bp_locations):\n                bp_prefix = Color.redify(\"*\")\n            else:\n                bp_prefix = \" \"\n\n            if i < line_num:\n                past_line = \"{:4d}   {:s}\".format(i + 1, lines[i])\n                past_line = Color.colorify(past_line, past_lines_color)\n                gef_print(\"{:1s}{:2s}{:s}\".format(bp_prefix, \"\", past_line), redirect=redirect)\n\n            elif i == line_num:\n                prefix = \"{:1s}->{:4d}   \".format(bp_prefix, i + 1)\n                leading = len(lines[i]) - len(lines[i].lstrip())\n                if show_extra_info:\n                    extra_info = self.get_pc_context_info(pc, lines[i])\n                    for ext in extra_info:\n                        gef_print(\"{}// {}\".format(\" \" * (len(prefix) + leading), ext), redirect=redirect)\n                gef_print(Color.colorify(\"{}{:s}\".format(prefix, lines[i]), cur_line_color), redirect=redirect)\n\n            elif i > line_num:\n                future_line = \"{:4d}   {:s}\".format(i + 1, lines[i])\n                future_line = Color.colorify(future_line, future_lines_color)\n                gef_print(\"{:1s}{:2s}{:s}\".format(bp_prefix, \"\", future_line), redirect=redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"source\", args.ignore_redirect)\n        try:\n            self.context_source(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextMemoryWatchCommand(GenericCommand):\n    \"\"\"Context internal command to display watching memory.\"\"\"\n\n    _cmdline_ = \"context-mem-watch\"\n    _category_ = \"01-a. Debugging Support - Context\"\n    _aliases_ = [\"context-mem_watch\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context mem_watch` to\")\n        return\n\n    def context_memory_watch(self, redirect):\n        if current_arch is None:\n            return\n\n        for address, opt in sorted(MemoryWatchCommand.mem_watches.items()):\n            count, fmt = opt[0:2]\n            ContextCommand.context_title(\"memory:{:#x}\".format(address), redirect)\n            if fmt == \"pointers\":\n                cmd = \"dereference {:#x} {:d} --no-pager\".format(address, count)\n            else:\n                cmd = \"hexdump {:s} {:#x} {:d} --no-pager\".format(fmt, address, count)\n            ContextCommand.execute_command(cmd, redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"mem_watch\", args.ignore_redirect)\n        try:\n            self.context_memory_watch(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextTraceCommand(GenericCommand):\n    \"\"\"Context internal command to display backtrace.\"\"\"\n\n    _cmdline_ = \"context-trace\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"nb_lines\", metavar=\"NB_LINES\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"temporarily overrides context_trace.nb_lines.\")\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context trace` to\")\n        self.add_setting(\"nb_lines\", 10, \"Number of line in the backtrace pane\")\n        self.add_setting(\"nb_lines_before\", 2, \"Number of line in the backtrace pane before selected frame\")\n        return\n\n    def context_trace(self, redirect):\n        ContextCommand.context_title(\"trace\", redirect)\n\n        if self.args.nb_lines is not None:\n            nb_lines = self.args.nb_lines\n        else:\n            nb_lines = Config.get_gef_setting(\"context_trace.nb_lines\")\n        if nb_lines <= 0:\n            return\n\n        try:\n            orig_frame = gdb.selected_frame()\n            current_frame = gdb.newest_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            err(\"Failed to get frame information\", redirect=redirect)\n            return\n\n        frames = [current_frame]\n        while current_frame != orig_frame:\n            current_frame = current_frame.older()\n            frames.append(current_frame)\n\n        nb_lines_before = Config.get_gef_setting(\"context_trace.nb_lines_before\")\n        level = max(len(frames) - nb_lines_before - 1, 0)\n        current_frame = frames[level]\n\n        while current_frame and nb_lines:\n            current_frame.select()\n            if not current_frame.is_valid():\n                break\n\n            # address and symbol\n            pc = current_frame.pc()\n            if is_x86_16():\n                pc = current_arch.real2phys(\"$cs\", pc)\n            sym = Symbol.get_symbol_string(pc, nosymbol_string=\" <NO_SYMBOL>\")\n\n            # frame name\n            \"\"\"\n            Frame names (=current_frmae.name()) and symbols (=Symbol.get_symbol_string(current_frame.pc()))\n            usually match, but sometimes they don't. This is an example.\n\n            gef> bt\n            #0  __futex_abstimed_wait_common64\n            #1  __futex_abstimed_wait_common\n            #2  __GI___futex_abstimed_wait_cancelable64\n            #3  0x00007f0635e93f1b in __pthread_cond_wait_common\n            #4  ___pthread_cond_timedwait64\n\n            gef> context trace\n            [#0] 0x7f0635e9119d <__futex_abstimed_wait_cancelable64+0xed>\n            [#1] 0x7f0635e9119d <__futex_abstimed_wait_cancelable64+0xed>\n            [#2] 0x7f0635e9119d <__futex_abstimed_wait_cancelable64+0xed>\n            [#3] 0x7f0635e93f1b <pthread_cond_timedwait+0x23b>\n            [#4] 0x7f0635e93f1b <pthread_cond_timedwait+0x23b>\n\n            This likely occurs when each symbol exists but is inlined into a single function by optimization.\n            Therefore, the frame name is also displayed if it differs.\n            \"\"\"\n            try:\n                ret = Symbol.gdb_get_location(pc)\n                if ret is None:\n                    frame_name = None\n                elif ret[0] == current_frame.name():\n                    frame_name = None\n                else:\n                    frame_name = Instruction.smartify_text(current_frame.name())\n            except (ValueError, gdb.error):\n                frame_name = None\n\n            # current index coloring\n            if current_frame == orig_frame:\n                idx = Color.colorify(\"#{:d}\".format(level), \"bold green\")\n                current_frame_symbol = \"*\"\n            else:\n                idx = Color.colorify(\"#{:d}\".format(level), \"bold magenta\")\n                current_frame_symbol = \" \"\n\n            # print\n            if frame_name:\n                frame_name = Color.colorify(frame_name, \"bold yellow\")\n                gef_print(\"[{:s}{:s}] {!s}{:s} (frame name: {:s})\".format(\n                    current_frame_symbol, idx, ProcessMap.lookup_address(pc), sym, frame_name,\n                ), redirect=redirect)\n            else:\n                gef_print(\"[{:s}{:s}] {!s}{:s}\".format(\n                    current_frame_symbol, idx, ProcessMap.lookup_address(pc), sym,\n                ), redirect=redirect)\n\n            # go next frame\n            try:\n                current_frame = current_frame.older()\n            except gdb.error:\n                break\n            level += 1\n            nb_lines -= 1\n\n        if nb_lines == 0:\n            if current_frame:\n                gef_print(\"[...]\", redirect=redirect)\n\n        orig_frame.select()\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"trace\", args.ignore_redirect)\n        try:\n            self.context_trace(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextThreadsCommand(GenericCommand):\n    \"\"\"Context internal command to display threads.\"\"\"\n\n    _cmdline_ = \"context-threads\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"nb_lines\", metavar=\"NB_LINES\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"temporarily overrides context_threads.nb_lines.\")\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context threads` to\")\n        self.add_setting(\"nb_lines\", 4, \"Number of line in the threads pane (-1: infinity)\")\n        return\n\n    def reason(self):\n        try:\n            res = gdb.execute(\"info program\", to_string=True).splitlines()\n        except gdb.error:\n            return \"STOPPED\"\n\n        if not res:\n            return \"NOT RUNNING\"\n\n        for line in res:\n            line = line.strip()\n            if line.startswith(\"It stopped with signal \"):\n                return line.replace(\"It stopped with signal \", \"\").split(\",\", 1)[0]\n            if line == \"The program being debugged is not being run.\":\n                return \"NOT RUNNING\"\n            if line == \"It stopped at a breakpoint that has since been deleted.\":\n                return \"TEMPORARY BREAKPOINT\"\n            if line.startswith(\"It stopped at breakpoint \"):\n                return \"BREAKPOINT\"\n            if line == \"It stopped after being stepped.\":\n                return \"SINGLE STEP\"\n\n        return \"STOPPED\"\n\n    def context_threads(self, redirect):\n        if self.args.nb_lines is not None:\n            nb_lines = self.args.nb_lines\n        else:\n            nb_lines = Config.get_gef_setting(\"context_threads.nb_lines\")\n\n        # get all threads\n        threads = gdb.selected_inferior().threads()\n        # Note that the order of the list returned by gdb.selected_inferior().threads()\n        # may differ depending on the version of gdb.\n        threads = sorted(threads, key=lambda t: t.num)\n\n        # title\n        if nb_lines < 0:\n            shown_threads = len(threads)\n        else:\n            shown_threads = nb_lines\n        if shown_threads < len(threads):\n            ContextCommand.context_title(\n                \"threads (shown:{:d} / all:{:d})\".format(shown_threads, len(threads)), redirect,\n            )\n        else:\n            ContextCommand.context_title(\"threads\", redirect)\n\n        # check max threads\n        if nb_lines == 0:\n            return\n        if nb_lines > 0:\n            # bring selected thread to the top\n            selected_thread = gdb.selected_thread()\n            for i, t in enumerate(threads):\n                if t.num == selected_thread.num:\n                    threads = [threads[i]] + threads[:i] + threads[i + 1:]\n                    break\n            # cut off\n            threads = threads[:nb_lines]\n            # re-sort\n            threads = sorted(threads, key=lambda t: t.num)\n\n        if not threads:\n            err(\"No thread selected\", redirect)\n            return\n\n        # get selected frame\n        selected_thread = gdb.selected_thread()\n        try:\n            selected_frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            selected_frame = None\n\n        # walk threads\n        lines = []\n        for thread in threads:\n            # selected, tid\n            tid = str(thread.ptid[1]) or str(thread.ptid[2]) or \"???\"\n            if thread == selected_thread:\n                line = \"[*{:s}] \".format(\n                    Color.colorify(\"Thread Id:{:d}, tid:{:s}\".format(thread.num, tid), \"bold green\"),\n                )\n            else:\n                line = \"[ {:s}] \".format(\n                    Color.colorify(\"Thread Id:{:d}, tid:{:s}\".format(thread.num, tid), \"bold magenta\"),\n                )\n\n            # name\n            if thread.name:\n                line += 'Name: \"{:s}\", '.format(thread.name)\n\n            # status\n            if thread.is_running():\n                line += Color.colorify(\"running\", \"bold green\")\n            elif thread.is_exited():\n                line += Color.colorify(\"exited\", \"bold yellow\")\n            elif thread.is_stopped():\n                line += Color.colorify(\"stopped\", \"bold red\")\n                # switch test\n                try:\n                    thread.switch()\n                except Exception:\n                    line += \" - Failed to switch to this thread\"\n                    gef_print(line, redirect=redirect)\n                    continue\n                # get pc\n                try:\n                    frame = gdb.selected_frame()\n                    pc = frame.pc()\n                except gdb.error:\n                    # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n                    # if failed, print thread information without frame (but with $pc).\n                    pc = get_register(\"$pc\")\n                # make reason\n                sym = Symbol.get_symbol_string(pc, nosymbol_string=\" <NO_SYMBOL>\")\n                line += \" at {!s}{:s}\".format(ProcessMap.lookup_address(pc), sym)\n                line += \", reason: {:s}\".format(Color.colorify(self.reason(), \"bold magenta\"))\n\n            lines.append([thread.num, line])\n\n        # print\n        for _, line in sorted(lines):\n            gef_print(line, redirect=redirect)\n\n        # revert\n        selected_thread.switch()\n        if selected_frame is not None:\n            try:\n                selected_frame.select()\n                # A gdb.error will occur if the user patches a range that includes the ret instruction.\n            except gdb.error:\n                pass\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"threads\", args.ignore_redirect)\n        try:\n            self.context_threads(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass ContextExtraCommand(GenericCommand):\n    \"\"\"Context internal command to display extra information or execute command.\"\"\"\n\n    _cmdline_ = \"context-extra\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-i\", \"--ignore-redirect\", action=\"store_true\", help=\"ignore redirect settings.\")\n    _syntax_ = parser.format_help()\n\n    context_messages = []\n    context_extra_commands = []\n\n    def __init__(self):\n        super().__init__()\n        self.add_setting(\"redirect\", \"\", \"The target tty name to redirect `context extra` to\")\n        return\n\n    @staticmethod\n    def push_context_message(level, message):\n        \"\"\"Push the message to be displayed the next time the context is invoked.\"\"\"\n        if level not in (\"error\", \"warn\", \"ok\", \"info\"):\n            err(\"Invalid level '{}', discarding message\".format(level))\n            return\n        ContextExtraCommand.context_messages.append((level, message))\n        return\n\n    @staticmethod\n    def empty_extra_messages(_event):\n        ContextExtraCommand.context_messages = []\n        return\n\n    def context_extra(self, redirect):\n        if not self.context_messages and not self.context_extra_commands:\n            return\n\n        ContextCommand.context_title(\"extra\", redirect)\n\n        for level, text in self.context_messages:\n            if level == \"error\":\n                err(text, redirect=redirect)\n            elif level == \"warn\":\n                warn(text, redirect=redirect)\n            elif level == \"ok\":\n                ok(text, redirect=redirect)\n            elif level == \"info\":\n                info(text, redirect=redirect)\n\n        for command in self.context_extra_commands:\n            gef_print(titlify(command), redirect)\n            try:\n                ContextCommand.execute_command(command, redirect)\n            except Exception as e:\n                err(str(e), redirect=redirect)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        redirect = ContextCommand.get_redirect(\"extra\", args.ignore_redirect)\n        try:\n            self.context_extra(redirect)\n        except Exception as e:\n            err(str(e), redirect=redirect)\n        return\n\n\n@register_command\nclass MemoryCommand(GenericCommand):\n    \"\"\"The base command to watch the memory.\"\"\"\n\n    _cmdline_ = \"memory\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"watch\")\n    subparsers.add_parser(\"unwatch\")\n    subparsers.add_parser(\"reset\")\n    subparsers.add_parser(\"list\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass MemoryWatchCommand(GenericCommand):\n    \"\"\"Add address ranges to the memory view.\"\"\"\n\n    _cmdline_ = \"memory watch\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the memory address to register for display in `context memory`.\")\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", type=AddressUtil.parse_address, default=0x10,\n                        help=\"the count of displayed units. (default: %(default)s)\")\n    parser.add_argument(\"unit\", nargs=\"?\", default=\"pointers\",\n                        choices=[\"byte\", \"word\", \"dword\", \"qword\", \"pointers\"],\n                        help=\"the size of unit. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x603000 0x100 byte\",\n        \"{0:s} $sp\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    mem_watches = {}\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        MemoryWatchCommand.mem_watches[args.address] = (args.count, args.unit)\n        ok(\"Adding memwatch to {:#x}\".format(args.address))\n        return\n\n\n@register_command\nclass MemoryUnwatchCommand(GenericCommand):\n    \"\"\"Remove address ranges from the memory view.\"\"\"\n\n    _cmdline_ = \"memory unwatch\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the memory address to deregister for display in `context memory`.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x603000\",\n        \"{0:s} $sp\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        res = MemoryWatchCommand.mem_watches.pop(args.address, None)\n        if not res:\n            warn(\"You weren't watching {:#x}\".format(args.address))\n        else:\n            ok(\"Removed memwatch of {:#x}\".format(args.address))\n        return\n\n\n@register_command\nclass MemoryResetCommand(GenericCommand):\n    \"\"\"Remove all watchpoints.\"\"\"\n\n    _cmdline_ = \"memory reset\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        MemoryWatchCommand.mem_watches.clear()\n        ok(\"Memory watches cleared\")\n        return\n\n\n@register_command\nclass MemoryWatchListCommand(GenericCommand):\n    \"\"\"List all watchpoints to display in context layout.\"\"\"\n\n    _cmdline_ = \"memory list\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if not MemoryWatchCommand.mem_watches:\n            info(\"No memory watches\")\n            return\n\n        info(\"Memory watches:\")\n        for address, opt in sorted(MemoryWatchCommand.mem_watches.items()):\n            gef_print(\"- {:#x} ({}, {})\".format(address, opt[0], opt[1]))\n        return\n\n\n@register_command\nclass HexdumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display the hexdump from the memory location specified.\"\"\"\n\n    _cmdline_ = \"hexdump\"\n    _category_ = \"03-b. Memory - View\"\n    _repeat_ = True\n    _aliases_ = [\"hd\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [\"byte\", \"word\", \"dword\", \"qword\", \"b\", \"w\", \"d\", \"q\"]\n    parser.add_argument(\"format\", choices=modes, nargs=\"?\", default=\"byte\",\n                        metavar=\"{byte,word,dword,qword}\",\n                        help=\"dump mode. It also works if you specify the first character. (default: %(default)s)\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to dump.\")\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", type=AddressUtil.parse_address, default=0x100,\n                        help=\"the count of displayed units. (default: %(default)s)\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"-r\", \"--reverse\", action=\"store_true\", help=\"display in reverse order line by line.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\", help=\"display the same line without omitting.\")\n    parser.add_argument(\"-s\", \"--symbol\", action=\"store_true\", help=\"display the symbol.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    @staticmethod\n    def merge_lines(lines_unmerged, nb_skip_merge=1):\n        lines = []\n        keep_asterisk = 0\n\n        for i, line in enumerate(lines_unmerged):\n            # about first line\n            if i < nb_skip_merge:\n                lines.append(line)\n                continue\n            # don't merge error string etc.\n            if \"    \" not in lines[-1] or \"    \" not in line:\n                lines.append(line)\n                continue\n            # check if mergeable\n            if re.split(\"    +\", lines[-1])[1] == re.split(\"    +\", line)[1]:\n                keep_asterisk += 1\n                prev_line = line\n                continue\n            # append line\n            if keep_asterisk == 1:\n                lines.append(prev_line)\n                keep_asterisk = 0\n            elif keep_asterisk > 1:\n                lines.append(\"*\")\n                keep_asterisk = 0\n            lines.append(line)\n\n        # final process\n        if keep_asterisk == 1:\n            lines.append(prev_line)\n        elif keep_asterisk > 1:\n            lines.append(\"*\")\n        return lines\n\n    def read_memory(self, read_from, read_len):\n        if read_len > 0x0100_0000: # Too large\n            return None\n\n        try:\n            if self.args.phys:\n                mem = read_physmem(read_from, read_len)\n            else:\n                mem = read_memory(read_from, read_len)\n            return mem\n        except (gdb.MemoryError, ValueError, OverflowError):\n            pass\n\n        # If you get an error, you probably read outside a valid memory page.\n        # Read in page size units.\n        read_end = read_from + read_len\n        read_end &= get_pagesize_mask_high()\n        while read_end - read_from > 0:\n            try:\n                if self.args.phys:\n                    mem = read_physmem(read_from, read_end - read_from)\n                else:\n                    mem = read_memory(read_from, read_end - read_from)\n                return mem\n            except (gdb.MemoryError, ValueError, OverflowError):\n                pass\n            read_end -= get_pagesize()\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system() and not is_vmware() and not is_kgdb():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        from_idx = args.count * self.repeat_count\n        to_idx = args.count * (self.repeat_count + 1)\n        if args.reverse:\n            from_idx *= -1\n            from_idx += args.count\n            to_idx *= -1\n            to_idx += args.count\n\n        memalign_size = None\n        if is_x86_16():\n            memalign_size = 2.5\n\n        read_from = AddressUtil.align_address(args.location, memalign_size=memalign_size) + min(from_idx, to_idx)\n        mem = self.read_memory(read_from, args.count)\n        if mem is None:\n            err(\"Cannot access memory\")\n            return\n\n        unit = {\"byte\": 1, \"word\": 2, \"dword\": 4, \"qword\": 8, \"b\": 1, \"w\": 2, \"d\": 4, \"q\": 8}[args.format]\n        lines = hexdump(mem, show_symbol=args.symbol, base=read_from, unit=unit).splitlines()\n\n        if not args.full:\n            lines = HexdumpCommand.merge_lines(lines)\n\n        if args.reverse:\n            lines.reverse()\n\n        self.out = lines\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XxdCommand(HexdumpCommand):\n    \"\"\"Display the hexdump from the memory location specified (shortcut for `hexdump byte`).\"\"\"\n\n    _cmdline_ = \"xxd\"\n    _category_ = \"03-b. Memory - View\"\n    _repeat_ = True\n    _aliases_ = [] # re-overwrite\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to dump.\")\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", type=AddressUtil.parse_address, default=0x100,\n                        help=\"the count of displayed units. (default: %(default)s)\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"-r\", \"--reverse\", action=\"store_true\", help=\"display in reverse order line by line.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\", help=\"display the same line without omitting.\")\n    parser.add_argument(\"-s\", \"--symbol\", action=\"store_true\", help=\"display the symbol.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        flags = []\n        if args.phys:\n            flags.append(\"--phys\")\n        if args.reverse:\n            flags.append(\"--reverse\")\n        if args.full:\n            flags.append(\"--full\")\n        if args.symbol:\n            flags.append(\"--symbol\")\n        if args.symbol:\n            flags.append(\"--no-pager\")\n\n        if args.reverse:\n            location = args.location - (args.count * self.repeat_count)\n        else:\n            location = args.location + (args.count * self.repeat_count)\n        flags = \" \".join(flags)\n        gdb.execute(\"hexdump byte {:#x} {:#x} {:s}\".format(location, args.count, flags))\n        return\n\n\n@register_command\nclass HexdumpFlexibleCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display the hexdump with user-defined format.\"\"\"\n\n    _cmdline_ = \"hexdump-flexible\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"format\", metavar=\"FORMAT\", help=\"dump format.\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to dump.\")\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", type=AddressUtil.parse_address, default=1,\n                        help=\"the count of displayed units. (default: %(default)s)\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"-t\", \"--tag\", nargs=2, action=\"append\", metavar=(\"IDX\", \"TAG\"),\n                        help=\"display with tags.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n\n    _example_ = [\n        '{0:s} \"2Q2I2H2B\" $rsp 4  # \"Show qword*2, dword*2, short*2, byte*2\" from $rsp and repeat 4 times',\n        '{0:s} \"4Q-2Q\" $rsp 4     # \"Show qword*4 and skip qword*2\" from $rsp and repeat 4 times',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def extract_each_type(self, fmt):\n        out = []\n        repeat = 1\n        for r in re.split(r\"(-?\\d+|)\", fmt):\n            if r == \"\":\n                continue\n            try:\n                repeat = int(r)\n                continue\n            except ValueError:\n                if 0 < repeat:\n                    out.extend([r] * repeat)\n                else:\n                    out.extend([\"-\" + r] * -repeat)\n                repeat = 1\n        return out\n\n    def do_dump(self, fmt, size, each_type):\n        base_address_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n\n        # parse tag\n        max_tag_width = 0\n        tags_dic = {}\n        if self.args.tag:\n            for idx, tag in self.args.tag:\n                idx = int(idx, 0)\n                tags_dic[idx] = tag\n                max_tag_width = max(max_tag_width, len(tag))\n\n        for i in range(self.args.count):\n            # read content\n            address = self.args.location + size * i\n            try:\n                if self.args.phys:\n                    data = read_physmem(address, size)\n                else:\n                    data = read_memory(address, size)\n            except (gdb.MemoryError, ValueError, OverflowError):\n                self.err_add_out(\"Failed to read memory\")\n                break\n\n            # unpack\n            values = struct.unpack(fmt.replace(\"-\", \"\"), data)\n\n            # make address line\n            if max_tag_width == 0:\n                line = \"{:s}|{:+#06x}|{:+04d}:   \".format(\n                    Color.colorify(AddressUtil.format_address(address), base_address_color),\n                    size * i, i,\n                )\n            else:\n                tag_i = tags_dic.get(i, \"\")\n                line = \"{:s}|{:+#06x}|{:+04d}: {:{:d}s}:\".format(\n                    Color.colorify(AddressUtil.format_address(address), base_address_color),\n                    size * i, i,\n                    tag_i, max_tag_width,\n                )\n\n            # dump each element\n            for t, v in zip(each_type, values):\n                if t.startswith(\"-\"):\n                    continue\n                if t in \"BHILQ\":\n                    line += \" {:#0{:d}x}\".format(v, 2 + struct.calcsize(t) * 2)\n                elif t in \"bhilq\":\n                    line += \" {:+#0{:d}x}\".format(v, 2 + struct.calcsize(t) * 2 + 1)\n                elif t in \"fd\":\n                    line += \" {:20e}\".format(v)\n                else:\n                    self.err_add_out(\"Unsupported format: {:s}\".format(t))\n                    return\n\n            self.out.append(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system() and not is_vmware() and not is_kgdb():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        fmt = args.format\n        if not fmt.startswith((\"<\", \">\")):\n            fmt = Endian.endian_str() + fmt\n        try:\n            size = struct.calcsize(fmt.replace(\"-\", \"\"))\n        except struct.error:\n            err(\"Format error\")\n            return\n\n        each_type = self.extract_each_type(args.format)\n\n        self.out = []\n        self.do_dump(fmt, size, each_type)\n        self.print_output()\n        return\n\n\n@register_command\nclass LoadFileCommand(GenericCommand):\n    \"\"\"Load the file into memory.\"\"\"\n\n    _cmdline_ = \"load-file\"\n    _category_ = \"03-f. Memory - Dump/Load\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to load.\")\n    parser.add_argument(\"file_path\", metavar=\"FILE_PATH\", help=\"the filepath to load.\")\n    parser.add_argument(\"file_offset\", metavar=\"FILE_OFFSET\", nargs=\"?\", type=AddressUtil.parse_address, default=0,\n                        help=\"the offset of the file to load.\")\n    parser.add_argument(\"load_size\", metavar=\"LOAD_SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size of the data to load.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"+-memory------+\",\n        \"|             |             +-file_start--+\",\n        \"|             |             | ^           |\",\n        \"|             |             | |           |\",\n        \"|             |             | v           |\",\n        \"| LOCATION <----------------- FILE_OFFSET |\",\n        \"| ...         | ^           | ...         |\",\n        \"|             | | LOAD_SIZE |             |\",\n        \"| ...         | v           | ...         |\",\n        \"| end <---------------------- end         |\",\n        \"|             |             |             |\",\n        \"|             |             |             |\",\n        \"|             |             +-file_end----+\",\n        \"|             |\",\n        \"+-------------+\",\n        \"If there is not enough space, the load will fail halfway.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if not os.path.exists(args.file_path):\n            err(\"Could not find {:s}\".format(args.file_path))\n            return\n\n        if args.load_size is None:\n            data_size = os.path.getsize(args.file_path)\n            if data_size == 0:\n                err(\"Unsupported zero size mapping\")\n                return\n        elif args.load_size < 0:\n            err(\"Invalid LOAD_SIZE\")\n            return\n        else:\n            data_size = args.load_size\n\n        if args.file_offset < 0:\n            err(\"Invalid FILE_OFFSET\")\n            return\n\n        # read file and write to memory\n        fd = open(args.file_path, \"rb\")\n        if args.file_offset > 0:\n            fd.seek(args.file_offset, 0)\n\n        pos = args.location\n        remain_size = data_size\n        while remain_size > 0:\n            data = fd.read(min(0x1000, remain_size))\n            if len(data) == 0:\n                break\n            write_memory(pos, data)\n            pos += len(data)\n            remain_size -= len(data)\n        return\n\n\n@register_command\nclass LoadFileMmapCommand(GenericCommand):\n    \"\"\"Load the file into memory that allocated by `mmap`.\"\"\"\n\n    _cmdline_ = \"load-file-mmap\"\n    _category_ = \"03-f. Memory - Dump/Load\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to load.\")\n    parser.add_argument(\"file_path\", metavar=\"FILE_PATH\", help=\"the filepath to load.\")\n    parser.add_argument(\"file_offset\", metavar=\"FILE_OFFSET\", nargs=\"?\", type=AddressUtil.parse_address, default=0,\n                        help=\"the offset of the file to load.\")\n    parser.add_argument(\"load_size\", metavar=\"LOAD_SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size of the data to load.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"+-mmap_start--+\",\n        \"|             |             +-file_start--+\",\n        \"|             |             | ^           |\",\n        \"|             |             | |           |\",\n        \"|             |             | v           |\",\n        \"| LOCATION <----------------- FILE_OFFSET |\",\n        \"| ...         | ^           | ...         |\",\n        \"|             | | LOAD_SIZE |             |\",\n        \"| ...         | v           | ...         |\",\n        \"| end <---------------------- end         |\",\n        \"|             |             |             |\",\n        \"|             |             |             |\",\n        \"|             |             +-file_end----+\",\n        \"|             |\",\n        \"+-mmap_end----+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if not os.path.exists(args.file_path):\n            err(\"Could not find {:s}\".format(args.file_path))\n            return\n\n        if args.load_size is None:\n            data_size = os.path.getsize(args.file_path)\n            if data_size == 0:\n                err(\"Unsupported zero size mapping\")\n                return\n        elif args.load_size < 0:\n            err(\"Invalid LOAD_SIZE\")\n            return\n        else:\n            data_size = args.load_size\n\n        if args.file_offset < 0:\n            err(\"Invalid FILE_OFFSET\")\n            return\n\n        # +-mmap_start--+               ^             ^\n        # |             |               |             |\n        # |             |               |             | page_size\n        # | data_start  | ^             |             |\n        # | ...         | |             |             |\n        # +-------------+ | data_size   | mmap_size   v\n        # | ...         | |             |\n        # | data_end    | v             |\n        # |             |               |\n        # |             |               |\n        # +-mmap_end----+               v\n\n        mmap_start = args.location & get_pagesize_mask_high()\n        data_start = args.location\n        data_end = data_start + data_size\n        mmap_end = align_to_pagesize(data_end)\n        mmap_size = mmap_end - mmap_start\n\n        # mmap\n        res = gdb.execute(\"mmap {:#x} {:#x}\".format(mmap_start, mmap_size), to_string=True)\n        if \"[!]\" in res:\n            err(\"Failed to mmap\")\n            return\n\n        output_line = res.splitlines()[-1]\n        ret = int(output_line.split()[2], 0)\n\n        if AddressUtil.is_msb_on(ret):\n            err(\"Failed to mmap\")\n            return\n\n        # read file and write to memory\n        fd = open(args.file_path, \"rb\")\n        if args.file_offset > 0:\n            fd.seek(args.file_offset, 0)\n\n        pos = data_start\n        remain_size = data_size\n        while remain_size > 0:\n            data = fd.read(min(0x1000, remain_size))\n            if len(data) == 0:\n                break\n            write_memory(pos, data)\n            pos += len(data)\n            remain_size -= len(data)\n        return\n\n\n@register_command\nclass PatchCommand(GenericCommand):\n    \"\"\"The base command to write specified values to the specified address.\"\"\"\n\n    _cmdline_ = \"patch\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"byte\")\n    subparsers.add_parser(\"word\")\n    subparsers.add_parser(\"dword\")\n    subparsers.add_parser(\"qword\")\n    subparsers.add_parser(\"string\")\n    subparsers.add_parser(\"hex\")\n    subparsers.add_parser(\"pattern\")\n    subparsers.add_parser(\"nop\")\n    subparsers.add_parser(\"inf\")\n    subparsers.add_parser(\"trap\")\n    subparsers.add_parser(\"ret\")\n    subparsers.add_parser(\"syscall\")\n    subparsers.add_parser(\"range-replace\")\n    subparsers.add_parser(\"history\")\n    subparsers.add_parser(\"revert\")\n    _syntax_ = parser.format_help()\n\n    patch_history = [] # [ [patch1a, patch1b], [patch2a], ...]\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        self.format = None\n        return\n\n    class PatchInfo:\n        def __init__(self, addr, data, length=None, phys=None, tag=None):\n            if not isinstance(addr, int):\n                raise ValueError\n            self.addr = addr\n\n            if not isinstance(data, bytes):\n                raise ValueError\n            self.data = data\n\n            if length is None:\n                self.length = len(self.data)\n            else:\n                self.length = length\n\n            self.phys = phys\n\n            # tag: A key to group multiple patches together\n            if tag is None:\n                self.tag = PatchCommand.PatchInfo.get_unique_tag()\n            else:\n                self.tag = tag\n            return\n\n        def __repr__(self):\n            return '<{:s}.{:s} object at {:#x}, addr={:#x}, data={}, length={:#x}, phys={}, tag={}>'.format(\n                self.__module__, self.__class__.__name__, id(self),\n                self.addr, self.data, self.length, self.phys,\n                hex(self.tag) if isinstance(self.tag, int) else self.tag,\n            )\n\n        @staticmethod\n        def get_unique_tag():\n            import random\n            tags = PatchCommand.PatchInfo.get_tag_set()\n            while True:\n                v = random.randint(1, 0xffff_ffff)\n                if v not in tags:\n                    break\n            return v\n\n        @staticmethod\n        def get_tag_set():\n            return {x[0].tag for x in PatchCommand.patch_history}\n\n        def a(self):\n            a = \" \".join([\"{:02x}\".format(x) for x in self.after_data[:0x10]])\n            if len(self.after_data) > 0x10:\n                a += \" ...\"\n            return a\n\n        def b(self):\n            b = \" \".join([\"{:02x}\".format(x) for x in self.before_data[:0x10]])\n            if len(self.before_data) > 0x10:\n                b += \" ...\"\n            return b\n\n        def patch(self, silent=False):\n            orig_mode = QemuMonitor.get_current_mmu_mode()\n            if orig_mode == \"virt\" and self.phys:\n                enable_phys()\n                self.before_data = read_memory(self.addr, self.length)\n                write_memory(self.addr, self.data)\n                self.after_data = read_memory(self.addr, self.length)\n                disable_phys()\n            elif orig_mode == \"phys\" and not self.phys:\n                disable_phys()\n                self.before_data = read_memory(self.addr, self.length)\n                write_memory(self.addr, self.data)\n                self.after_data = read_memory(self.addr, self.length)\n                enable_phys()\n            else:\n                self.before_data = read_memory(self.addr, self.length)\n                write_memory(self.addr, self.data)\n                self.after_data = read_memory(self.addr, self.length)\n\n            # print\n            if not silent:\n                ok(\"Patch success: {!s}{:s}: {:s} -> {:s}\".format(\n                    ProcessMap.lookup_address(self.addr), Symbol.get_symbol_string(self.addr),\n                    self.b(), self.a(),\n                ))\n\n            # history\n            self.insert_history()\n            return\n\n        def insert_history(self):\n            for i in range(len(PatchCommand.patch_history)):\n                if PatchCommand.patch_history[i][0].tag == self.tag:\n                    PatchCommand.patch_history[i].append(self)\n                    break\n            else:\n                PatchCommand.patch_history.insert(0, [self])\n            return\n\n        def revert(self, silent=False):\n            orig_mode = QemuMonitor.get_current_mmu_mode()\n            if orig_mode == \"virt\" and self.phys:\n                enable_phys()\n                write_memory(self.addr, self.before_data)\n                disable_phys()\n            elif orig_mode == \"phys\" and not self.phys:\n                disable_phys()\n                write_memory(self.addr, self.before_data)\n                enable_phys()\n            else:\n                write_memory(self.addr, self.before_data)\n\n            # print\n            if not silent:\n                ok(\"Revert success: {!s}{:s}: {:s} -> {:s}\".format(\n                    ProcessMap.lookup_address(self.addr), Symbol.get_symbol_string(self.addr),\n                    self.a(), self.b(),\n                ))\n\n            # history\n            self.remove_history()\n            return\n\n        def remove_history(self):\n            for i in range(len(PatchCommand.patch_history)):\n                if PatchCommand.patch_history[i][0].tag == self.tag:\n                    PatchCommand.patch_history[i].remove(self)\n                    if PatchCommand.patch_history[i] == []:\n                        PatchCommand.patch_history.pop(i)\n                    break\n            return\n\n        @staticmethod\n        def revert_to_tag(tag, silent=False):\n            tags = PatchCommand.PatchInfo.get_tag_set()\n            if tag not in tags:\n                err(\"Not found tag\")\n                return None\n            while PatchCommand.patch_history:\n                hist = PatchCommand.patch_history.pop(0)\n                for patch_info in hist:\n                    try:\n                        patch_info.revert(silent)\n                    except Exception as e:\n                        err(e)\n                        return\n                if tag == hist[0].tag:\n                    break\n            return\n\n    # for qword, dword, word, byte sub-commands\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        SUPPORTED_SIZES = {\n            \"qword\": (8, \"Q\"),\n            \"dword\": (4, \"L\"),\n            \"word\": (2, \"H\"),\n            \"byte\": (1, \"B\"),\n        }\n        if self.format not in SUPPORTED_SIZES:\n            self.usage()\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        addr = args.location\n        size, fcode = SUPPORTED_SIZES[self.format]\n\n        if args.endian_reverse is False:\n            d = \"<\" if Endian.is_little_endian() else \">\"\n        else:\n            d = \">\" if Endian.is_little_endian() else \"<\"\n\n        tag = PatchCommand.PatchInfo.get_unique_tag()\n        for value in args.values:\n            value = AddressUtil.parse_address(value) & ((1 << size * 8) - 1)\n            vstr = struct.pack(d + fcode, value)\n            try:\n                self.PatchInfo(addr, vstr, size, phys=args.phys, tag=tag).patch()\n            except Exception as e:\n                err(e)\n                return\n            addr += size\n        return\n\n\n@register_command\nclass PatchQwordCommand(PatchCommand):\n    \"\"\"Write specified QWORD to the specified address.\"\"\"\n\n    _cmdline_ = \"patch qword\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"patch q\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-e\", dest=\"endian_reverse\", action=\"store_true\", help=\"reverse endian.\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"values\", metavar=\"QWORD\", nargs=\"+\", help=\"the value to patch.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}    $rip 0x4142434445464748  # write `HGFEDCBA` to [rip]\",\n        \"{0:s} -e $rip 0x4142434445464748  # write `ABCDEFGH` to [rip]\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        self.format = \"qword\"\n        return\n\n\n@register_command\nclass PatchDwordCommand(PatchCommand):\n    \"\"\"Write specified DWORD to the specified address.\"\"\"\n\n    _cmdline_ = \"patch dword\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"patch d\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-e\", dest=\"endian_reverse\", action=\"store_true\", help=\"reverse endian.\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"values\", metavar=\"DWORD\", nargs=\"+\", help=\"the value to patch.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}    $rip 0x41424344  # write `DCBA` to [rip]\",\n        \"{0:s} -e $rip 0x41424344  # write `ABCD` to [rip]\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        self.format = \"dword\"\n        return\n\n\n@register_command\nclass PatchWordCommand(PatchCommand):\n    \"\"\"Write specified WORD to the specified address.\"\"\"\n\n    _cmdline_ = \"patch word\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"patch w\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-e\", dest=\"endian_reverse\", action=\"store_true\", help=\"reverse endian.\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"values\", metavar=\"WORD\", nargs=\"+\", help=\"the value to patch.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}    $rip 0x4142  # write `BA` to [rip]\",\n        \"{0:s} -e $rip 0x4142  # write `AB` to [rip]\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        self.format = \"word\"\n        return\n\n\n@register_command\nclass PatchByteCommand(PatchCommand):\n    \"\"\"Write specified BYTE to the specified address.\"\"\"\n\n    _cmdline_ = \"patch byte\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"patch b\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-e\", dest=\"endian_reverse\", action=\"store_true\", help=\"reverse endian.\")\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"values\", metavar=\"BYTE\", nargs=\"+\", help=\"the value to patch.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}    $rip 0x41 0x41 0x41 0x41 0x41\",\n        \"{0:s} -e $rip 0x41 0x41 0x41 0x41 0x41  # -e is ignored\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        self.format = \"byte\"\n        return\n\n\n@register_command\nclass PatchStringCommand(PatchCommand):\n    \"\"\"Write specified string to the specified memory address.\"\"\"\n\n    _cmdline_ = \"patch string\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"vstr\", metavar='\"double backslash-escaped string\"',\n                        type=lambda x: codecs.escape_decode(x)[0], help=\"the string to write to memory.\")\n    parser.add_argument(\"length\", metavar=\"LENGTH\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the number of bytes to patch. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} $sp \"AAAABBBB\"',\n        '{0:s} $sp \"\\\\\\\\x41\\\\\\\\x41\\\\\\\\x41\\\\\\\\x41\\\\\\\\x42\\\\\\\\x42\\\\\\\\x42\\\\\\\\x42\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.length:\n            vstr = args.vstr * (args.length // len(args.vstr) + 1)\n            vstr = vstr[:args.length]\n        else:\n            vstr = args.vstr\n\n        try:\n            self.PatchInfo(args.location, vstr, phys=args.phys).patch()\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchHexCommand(PatchCommand):\n    \"\"\"Write specified hex string to the specified address.\"\"\"\n\n    _cmdline_ = \"patch hex\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"hstr\", metavar='\"hex-string\"', type=lambda x: bytes.fromhex(x),\n                        help=\"the string to write to memory.\")\n    parser.add_argument(\"length\", metavar=\"LENGTH\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the number of bytes to patch. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} $sp \"4141414142424242\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.length:\n            hstr = args.hstr * (args.length // len(args.hstr) + 1)\n            hstr = hstr[:args.length]\n        else:\n            hstr = args.hstr\n\n        try:\n            self.PatchInfo(args.location, hstr, phys=args.phys).patch()\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchPatternCommand(PatchCommand):\n    \"\"\"Write a pattern string to the specified memory address.\"\"\"\n\n    _cmdline_ = \"patch pattern\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"-c\", \"--charset\", help=\"the charset of the pattern. (default: abc..z)\")\n    parser.add_argument(\"-d\", \"--dry-run\", action=\"store_true\",\n                        help=\"only generate patterns (do not patch memory).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch.\")\n    parser.add_argument(\"length\", metavar=\"LENGTH\", type=AddressUtil.parse_address,\n                        help=\"the number of bytes to patch. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $sp 128\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        pats = PatternCreateCommand.generate_cyclic_pattern(args.length, args.charset)\n        if args.dry_run:\n            info(\"Generated pattern: {}\".format(pats))\n            return\n\n        try:\n            self.PatchInfo(args.location, pats, phys=args.phys).patch()\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchNopCommand(PatchCommand):\n    \"\"\"Patch the instruction(s) at the given address with NOP.\"\"\"\n\n    _cmdline_ = \"patch nop\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"nop\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch. (default: current_arch.pc)\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-b\", dest=\"byte_length\", type=AddressUtil.parse_address,\n                       help=\"the patch length in bytes. (default: %(default)s)\")\n    group.add_argument(\"-i\", dest=\"inst_count\", type=AddressUtil.parse_address, default=1,\n                       help=\"the number of instructions to patch. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc -i 2\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def get_insns_size(self, addr, num_insts):\n        addr_after_n = Disasm.gef_instruction_n(addr, num_insts)\n        return addr_after_n.address - addr\n\n    def patch_nop(self, addr, num_bytes):\n        if num_bytes == 0:\n            info(\"Not patching since num_bytes == 0\")\n            return\n\n        if (is_arm32() or is_arm32_cortex_m()) and current_arch.is_thumb() and addr & 1:\n            addr -= 1\n\n        nop_op_len = len(current_arch.nop_insn)\n\n        if nop_op_len > num_bytes:\n            err(\"Cannot patch instruction at {:#x} (nop_size is {:d}, insn_size is {:d})\".format(\n                addr, nop_op_len, num_bytes,\n            ))\n            return\n\n        count = num_bytes // nop_op_len\n        patch_bytes = nop_op_len * count\n\n        if patch_bytes != num_bytes:\n            err(\"Cannot patch instruction at {:#x} (nop instruction does not evenly fit in requested size)\".format(addr))\n            return\n\n        if Endian.is_big_endian():\n            insn = current_arch.nop_insn[::-1]\n        else:\n            insn = current_arch.nop_insn\n\n        self.PatchInfo(addr, insn * count, length=patch_bytes, phys=self.args.phys).patch()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.nop_insn is None:\n            err(\"This command is not supported on this architecture\")\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        try:\n            if args.byte_length is not None:\n                num_bytes = args.byte_length\n            else:\n                num_bytes = self.get_insns_size(location, args.inst_count)\n        except Exception:\n            err(\"Failed to get patch bytes\")\n            return\n\n        try:\n            self.patch_nop(location, num_bytes)\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchInfloopCommand(PatchCommand):\n    \"\"\"Patch the instruction(s) at the given address with an infinite loop.\"\"\"\n\n    _cmdline_ = \"patch inf\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch. (default: current_arch.pc)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def patch_infloop(self, addr):\n        if (is_arm32() or is_arm32_cortex_m()) and current_arch.is_thumb() and addr & 1:\n            addr -= 1\n\n        if Endian.is_big_endian():\n            insn = current_arch.infloop_insn[::-1]\n            if current_arch.has_delay_slot:\n                insn += current_arch.nop_insn[::-1]\n        else:\n            insn = current_arch.infloop_insn\n            if is_arc32() or is_arc64():\n                if addr % 4 == 2:\n                    insn = current_arch.infloop_insn2\n            else:\n                if current_arch.has_delay_slot:\n                    insn += current_arch.nop_insn\n\n        self.PatchInfo(addr, insn, phys=self.args.phys).patch()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.infloop_insn is None:\n            err(\"This command is not supported on this architecture\")\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        try:\n            self.patch_infloop(location)\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchTrapCommand(PatchCommand):\n    \"\"\"Patch the instruction(s) at the given address with breakpoint or trap (if available).\"\"\"\n\n    _cmdline_ = \"patch trap\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch. (default: current_arch.pc)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def patch_trap(self, addr):\n        if (is_arm32() or is_arm32_cortex_m()) and current_arch.is_thumb() and addr & 1:\n            addr -= 1\n\n        if Endian.is_big_endian():\n            insn = current_arch.trap_insn[::-1]\n            if current_arch.has_delay_slot:\n                insn += current_arch.nop_insn[::-1]\n        else:\n            insn = current_arch.trap_insn\n            if current_arch.has_delay_slot:\n                insn += current_arch.nop_insn\n\n        self.PatchInfo(addr, insn, phys=self.args.phys).patch()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.trap_insn is None:\n            err(\"This command is not supported on this architecture\")\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        try:\n            self.patch_trap(location)\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchRetCommand(PatchCommand):\n    \"\"\"Patch the instruction(s) at the given address with return.\"\"\"\n\n    _cmdline_ = \"patch ret\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch. (default: current_arch.pc)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def patch_ret(self, addr):\n        if (is_arm32() or is_arm32_cortex_m()) and current_arch.is_thumb() and addr & 1:\n            addr -= 1\n\n        if Endian.is_big_endian():\n            insn = current_arch.ret_insn[::-1]\n            if current_arch.has_delay_slot:\n                insn += current_arch.nop_insn[::-1]\n        else:\n            insn = current_arch.ret_insn\n            if current_arch.has_delay_slot:\n                insn += current_arch.nop_insn\n\n        self.PatchInfo(addr, insn, phys=self.args.phys).patch()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.ret_insn is None:\n            err(\"This command is not supported on this architecture\")\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        try:\n            self.patch_ret(location)\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchSyscallCommand(PatchCommand):\n    \"\"\"Patch the instruction(s) at the given address with syscall instruction.\"\"\"\n\n    _cmdline_ = \"patch syscall\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to patch. (default: current_arch.pc)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def patch_syscall(self, addr):\n        if (is_arm32() or is_arm32_cortex_m()) and current_arch.is_thumb() and addr & 1:\n            addr -= 1\n\n        if Endian.is_big_endian():\n            insn = current_arch.syscall_insn[::-1]\n            if current_arch.has_syscall_delay_slot:\n                insn += current_arch.nop_insn[::-1]\n        else:\n            insn = current_arch.syscall_insn\n            if current_arch.has_syscall_delay_slot:\n                insn += current_arch.nop_insn\n\n        self.PatchInfo(addr, insn, phys=self.args.phys).patch()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if current_arch.syscall_insn is None:\n            err(\"This command is not supported on this architecture\")\n            return\n\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        try:\n            self.patch_syscall(location)\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass PatchHistoryCommand(PatchCommand, BufferingOutput):\n    \"\"\"Display the patch history stack.\"\"\"\n\n    _cmdline_ = \"patch history\"\n    _category_ = \"03-d. Memory - Patch\"\n    _aliases_ = [\"patch list\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        self.out = []\n\n        if PatchCommand.patch_history:\n            self.out.append(titlify(\"NEW\"))\n            self.out.append(\"[{:s}] (current state)\".format(Color.boldify(\"0\")))\n            for i, hist in enumerate(PatchCommand.patch_history, start=1):\n                for j, patch_info in enumerate(hist):\n                    if not self.args.verbose:\n                        if j > 8:\n                            self.out.append(\"    ...\")\n                            break\n                    self.out.append(\"    {!s}{:s}: {:s} -> {:s}\".format(\n                        ProcessMap.lookup_address(patch_info.addr),\n                        Symbol.get_symbol_string(patch_info.addr),\n                        patch_info.b(), patch_info.a(),\n                    ))\n                self.out.append(\"[{:s}]\".format(Color.boldify(\"{:d}\".format(i))))\n            self.out.append(titlify(\"OLD\"))\n        else:\n            self.info_add_out(\"Patch history stack is empty\")\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PatchRevertCommand(PatchCommand):\n    \"\"\"Revert patches recorded in the patch history stack.\"\"\"\n\n    _cmdline_ = \"patch revert\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"target_state\", metavar=\"TARGET_STATE\", nargs=\"?\", type=int,\n                        help=\"the history state index number to revert.\")\n    group.add_argument(\"--all\", action=\"store_true\", help=\"revert all patches.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0  # do nothing (keep the current state).\",\n        \"{0:s} 2  # roll back to history state [2].\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        if len(PatchCommand.patch_history) == 0:\n            info(\"Patch history stack is empty\")\n            return\n\n        if args.all:\n            revert_count = len(PatchCommand.patch_history) + 1\n        else:\n            if not (0 <= args.target_state < len(PatchCommand.patch_history) + 1):\n                err(\"Invalid target index\")\n                gef_print(titlify(\"Patch history stack\"))\n                gdb.execute(\"patch history\")\n                return\n            revert_count = args.target_state\n\n        while PatchCommand.patch_history and revert_count > 0:\n            hist = PatchCommand.patch_history.pop(0)\n            for patch_info in hist:\n                try:\n                    patch_info.revert()\n                except Exception as e:\n                    err(e)\n                    return\n            revert_count -= 1\n        return\n\n\n@register_command\nclass PatchRangeReplaceCommand(PatchCommand):\n    \"\"\"Replace all occurrences of a specific byte sequence in the specified range with another byte sequence.\"\"\"\n\n    _cmdline_ = \"patch range-replace\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address (qemu-system only).\")\n    parser.add_argument(\"range_start\", metavar=\"START_ADDR\", type=AddressUtil.parse_address,\n                        help=\"start address to search.\")\n    parser.add_argument(\"range_end\", metavar=\"END_ADDR\", type=AddressUtil.parse_address,\n                        help=\"end address to search.\")\n    parser.add_argument(\"hstr_from\", metavar=\"HEX_STR_FROM\", type=lambda x: bytes.fromhex(x),\n                        help=\"the hex string to search for (source pattern).\")\n    parser.add_argument(\"hstr_to\", metavar=\"HEX_STR_TO\", type=lambda x: bytes.fromhex(x),\n                        help=\"the hex string to replace it with (replacement pattern).\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} 0x400000 0x401000 \"ebfe\" \"9090\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def patch_range_replace(self):\n        try:\n            data = read_memory(self.args.range_start, self.args.range_end - self.args.range_start)\n        except gdb.MemoryError:\n            err(\"Memory read error\")\n            return\n\n        tag = PatchCommand.PatchInfo.get_unique_tag()\n        pos = 0\n        while True:\n            found_pos = data.find(self.args.hstr_from, pos)\n            if found_pos == -1:\n                break\n            self.PatchInfo(self.args.range_start + found_pos, self.args.hstr_to, tag=tag).patch()\n            pos = found_pos + len(self.args.hstr_from)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported in this gdb mode.\")\n                return\n\n        try:\n            self.patch_range_replace()\n        except Exception as e:\n            err(e)\n        return\n\n\n@register_command\nclass DereferenceCommand(GenericCommand):\n    \"\"\"Dereference recursively from an address and display information.\"\"\"\n\n    _cmdline_ = \"dereference\"\n    _category_ = \"01-a. Debugging Support - Context\"\n    _repeat_ = True\n    _aliases_ = [\"telescope\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the memory address to dump. (default: current_arch.sp)\")\n    parser.add_argument(\"nb_lines\", metavar=\"NB_LINES\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the count of lines.\")\n    parser.add_argument(\"-a\", \"--is-addr\", action=\"store_true\",\n                        help=\"display only valid addresses.\")\n    parser.add_argument(\"-A\", \"--is-not-addr\", action=\"store_true\",\n                        help=\"display only invalid addresses.\")\n    parser.add_argument(\"-P\", \"--perm\", type=str,\n                        help=\"display only specified permission.\")\n    parser.add_argument(\"-z\", \"--is-zero\", action=\"store_true\",\n                        help=\"display only zero values.\")\n    parser.add_argument(\"-Z\", \"--is-not-zero\", action=\"store_true\",\n                        help=\"display only non-zero values.\")\n    parser.add_argument(\"-m\", \"--mask-hits\", nargs=\"+\", action=\"append\", type=AddressUtil.parse_address,\n                        metavar=(\"MASK\", \"VALUE\"), help=\"display only mask hits.\")\n    parser.add_argument(\"-M\", \"--no-mask-hits\", nargs=\"+\", action=\"append\", type=AddressUtil.parse_address,\n                        metavar=(\"MASK\", \"VALUE\"), help=\"display only mask non-hits.\")\n    parser.add_argument(\"-t\", \"--tag\", nargs=2, action=\"append\", metavar=(\"IDX\", \"TAG\"),\n                        help=\"display with tags.\")\n    parser.add_argument(\"-T\", \"--tag-offset\", type=AddressUtil.parse_address, default=0,\n                        help=\"the slide offset of all tag positions.\")\n    parser.add_argument(\"-r\", \"--reverse\", action=\"store_true\",\n                        help=\"display in reverse order line by line.\")\n    parser.add_argument(\"-f\", \"--frame-split\", action=\"store_true\",\n                        help=\"display with frame split lines (heuristics).\")\n    parser.add_argument(\"-u\", \"--uniq\", action=\"store_true\",\n                        help=\"display with uniq.\")\n    parser.add_argument(\"-i\", \"--interval\", type=AddressUtil.parse_address, default=1,\n                        help=\"the line number of the interval for showing.\")\n    parser.add_argument(\"-d\", \"--depth\", type=AddressUtil.parse_address, default=1,\n                        help=\"depth of recursive. (default: %(default)s)\")\n    parser.add_argument(\"-D\", \"--depth-nb-lines\", type=AddressUtil.parse_address, default=4,\n                        help=\"NB_LINES when recursive. (default: %(default)s)\")\n    parser.add_argument(\"-p\", \"--phys\", action=\"store_true\",\n                        help=\"treat LOCATION as a physical address. (qemu-system only)\")\n    parser.add_argument(\"-l\", \"--list-head\", action=\"store_true\",\n                        help=\"display if LIST_HEAD or not.\")\n    parser.add_argument(\"-s\", \"--slab-contains\", action=\"store_true\",\n                        help=\"display slab_cache name if available.\")\n    parser.add_argument(\"-S\", \"--slab-contains-unaligned\", action=\"store_true\",\n                        help=\"display slab_cache name (allow unaligned) if available.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\",\n                        help=\"do not display other than addresses and values.\")\n    parser.add_argument(\"-Q\", \"--quiet-offset\", action=\"store_true\",\n                        help=\"do not display offset and index values.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                         # dereference $sp 64\",\n        \"{0:s} $sp 20                  # specify location and number of elements to display\",\n        \"{0:s} $sp -20                 # display memory backwards\",\n        \"{0:s} --reverse $sp 20        # display reverse order\",\n        \"{0:s} --depth 2 $sp 20        # display recursively if valid aligned address\",\n        \"{0:s} --is-addr $sp 20        # display elements which is valid address\",\n        \"{0:s} --slab-contains $sp 20  # with slab-contains result (available under qemu-system)\",\n        \"{0:s} --tag 0 next $sp 20     # with tags\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Use blacklist feature if reading the address causes process crash.\",\n        'e.g., `gef config dereference.blacklist \"[ [0xffffffffc9000000, 0xffffffffc9001000], ]\"',\n        \"then `gef save`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        self.add_setting(\"max_recursion\", 4, \"Maximum level of pointer recursion\")\n        self.add_setting(\"blacklist\", \"[]\",\n                         'Dereference black list address ranges (e.g., \"[[from1, to1], [from2, to2]]\")')\n        self.add_setting(\"nb_lines\", 64, \"Number of lines to display\")\n        self.add_setting(\"no_pager\", False,\n                         \"Always enable --no-pager option for this telescope command only\")\n        return\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_frame_pcs():\n        frames = []\n        try:\n            frame = gdb.newest_frame()\n            no_ret_addr = [0, 0xffff_ffff, 0xffff_ffff_ffff_ffff]\n            while frame:\n                pc = frame.pc()\n                if pc in no_ret_addr:\n                    break\n                if pc in frames:\n                    break\n                frames.append(pc)\n                frame = frame.older()\n        except gdb.error:\n            pass\n        return frames\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_target_registers():\n        regs = []\n        for reg in current_arch.all_registers:\n            # skip if not ggeneral registers\n            if current_arch.flag_register == reg:\n                continue\n            if current_arch.special_registers and reg in current_arch.special_registers:\n                continue\n            regs.append(reg)\n        return regs\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_target_registers_value():\n        regs = []\n        for regname in DereferenceCommand.get_target_registers():\n            regvalue = get_register(regname)\n            if regvalue is None:\n                continue\n            if regvalue == 0: # too noisy, so skip\n                continue\n            regs.append((regname, regvalue))\n        return regs\n\n    @staticmethod\n    def pprint_dereferenced(addr, idx, tag=None, phys=False, quiet=False, quiet_offset=False):\n        \"\"\"Format and display a single dereferenced memory entry, including pointer\n        chains and optional annotations such as retaddr, canary, cookie, or registers.\n        \"\"\"\n        base_address_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n        registers_color = Config.get_gef_setting(\"theme.dereference_register_value\")\n        memalign = current_arch.ptrsize\n        offset = idx * memalign\n\n        # used as first element\n        memalign_size = None\n        if is_x86_16():\n            memalign_size = 2.5\n\n        current_address = AddressUtil.align_address(addr + offset, memalign_size=memalign_size)\n\n        addrs, error = AddressUtil.recursive_dereference(current_address, phys=phys)\n        if len(addrs) == 1 and not error: # cannot access this area\n            raise\n\n        # create address link list\n        link = AddressUtil.recursive_dereference_to_string(\n            current_address, skip_idx=1, phys=phys, quiet=quiet,\n        )\n\n        # create line of one entry\n        addr_formatted = AddressUtil.format_address(addrs[0], memalign_size=memalign_size)\n        addr_colored = Color.colorify(addr_formatted, base_address_color)\n        if quiet_offset:\n            line = \"{:s}: \".format(addr_colored)\n        else:\n            line = \"{:s}|{:+#07x}|{:+04d}: \".format(addr_colored, offset, idx)\n        if tag:\n            line += \"{:s}: \".format(tag)\n        line += \"{:{:d}s}\".format(link, memalign * 2 + 2)\n\n        if len(addrs) == 1:\n            return line\n\n        if quiet:\n            return line\n\n        # add extra info (retaddr, canary, cookie, register)\n        extra = []\n        current_address_value = addrs[1]\n\n        # retaddr info\n        for i, frame_pc in enumerate(DereferenceCommand.get_frame_pcs()):\n            if not is_valid_addr(frame_pc):\n                continue\n            if current_address_value == frame_pc:\n                extra.append(\"retaddr[{:d}]\".format(i))\n                break\n\n        # canary info\n        if not is_qemu_system() and not is_vmware() and not is_kgdb():\n            res = CanaryCommand.gef_read_canary()\n            if res:\n                canary, location = res\n                if canary != 0: # when Golang binary, canary is 0\n                    if current_address_value == canary:\n                        extra.append(\"canary\")\n\n        # mangle cookie\n        if not is_qemu_system() and not is_vmware() and not is_kgdb():\n            res = PtrDemangleCommand.get_cookie()\n            if res:\n                cookie = res\n                if cookie != 0:\n                    if current_address_value == cookie:\n                        extra.append(\"PTR_MANGLE cookie\")\n\n        # register info\n        if not phys:\n            # for the physical address, 0x0 may be valid,\n            # which tends to clutter the result, so skip\n            if is_valid_addr(current_address_value):\n                for regname, regvalue in DereferenceCommand.get_target_registers_value():\n                    if current_address_value == regvalue:\n                        extra.append(regname)\n\n        # add extra to end of line\n        if extra:\n            extra_str = \"  <-  {:s}\".format(\", \".join(extra))\n            line += Color.colorify(extra_str, registers_color)\n        return line\n\n    def check_list_head(self, start_address, from_idx, to_idx, step):\n        for idx in range(from_idx, to_idx, step):\n            current_address = start_address + idx * current_arch.ptrsize\n            if is_double_link_list(current_address):\n                # next\n                tag = self.tags_dict.get(idx + 0, \"\")\n                if tag:\n                    tag += \", \"\n                tag += Color.colorify(\"list_head.next\", \"bold magenta\")\n                self.tags_dict[idx + 0] = tag\n                self.max_tag_width = max(self.max_tag_width, len(Color.remove_color(tag)))\n\n                # prev\n                tag = self.tags_dict.get(idx + 1, \"\")\n                if tag:\n                    tag += \", \"\n                tag += Color.colorify(\"list_head.prev\", \"bold magenta\")\n                self.tags_dict[idx + 1] = tag\n                self.max_tag_width = max(self.max_tag_width, len(Color.remove_color(tag)))\n        return\n\n    def check_slab_contains(self, start_address, from_idx, to_idx, step):\n        for idx in range(from_idx, to_idx, step):\n            current_address = start_address + idx * current_arch.ptrsize\n            if not is_valid_addr(current_address):\n                continue\n            v = read_int_from_memory(current_address)\n            ret = Kernel.get_slab_contains(\n                v, allow_unaligned=self.args.slab_contains_unaligned, keep_color=True,\n            )\n            if ret:\n                tag = self.tags_dict.get(idx, \"\")\n                if tag:\n                    tag += \", \"\n                tag += ret.split()[1]\n                if \"unaligned?\" in ret:\n                    tag += \"(unaligned)\"\n                self.tags_dict[idx] = tag\n                self.max_tag_width = max(self.max_tag_width, len(Color.remove_color(tag)))\n        return\n\n    def dereference_line_by_line(self, start_address, from_idx, to_idx, step):\n        if self.args.list_head:\n            self.check_list_head(start_address, from_idx, to_idx, step)\n\n        if self.args.slab_contains or self.args.slab_contains_unaligned:\n            self.check_slab_contains(start_address, from_idx, to_idx, step)\n\n        has_tag = bool(self.args.tag)\n        has_tag |= bool(self.args.list_head)\n        has_tag |= bool(self.args.slab_contains)\n        has_tag |= bool(self.args.slab_contains_unaligned)\n\n        out = []\n        seen = []\n        for idx in range(from_idx, to_idx, step):\n            current_address = start_address + idx * current_arch.ptrsize\n            try:\n                # uniq filtering\n                if self.args.uniq:\n                    v = self.read_int_from_memory(current_address)\n                    if v in seen:\n                        if out == [] or out[-1] != \"*\":\n                            out.append(\"*\")\n                        continue\n                    seen.append(v)\n\n                # valid address filtering\n                if self.args.is_addr:\n                    v = self.read_int_from_memory(current_address)\n                    if not is_valid_addr(v):\n                        continue\n\n                # invalid address filtering\n                if self.args.is_not_addr:\n                    v = self.read_int_from_memory(current_address)\n                    if is_valid_addr(v):\n                        continue\n\n                # zero filtering\n                if self.args.is_zero:\n                    v = self.read_int_from_memory(current_address)\n                    if v != 0:\n                        continue\n\n                # non-zero filtering\n                if self.args.is_not_zero:\n                    v = self.read_int_from_memory(current_address)\n                    if v == 0:\n                        continue\n\n                # mask hits filtering\n                if self.args.mask_hits is not None:\n                    v = self.read_int_from_memory(current_address)\n                    hit = False\n                    for m in self.args.mask_hits:\n                        masked = v & m[0]\n                        if (len(m) == 1 and masked != 0) or (len(m) != 1 and masked in m[1:]):\n                            hit = True\n                            break\n                    if not hit:\n                        continue\n\n                # mask no-hits filtering\n                if self.args.no_mask_hits is not None:\n                    v = self.read_int_from_memory(current_address)\n                    hit = False\n                    for m in self.args.no_mask_hits:\n                        masked = v & m[0]\n                        if (len(m) == 1 and masked == 0) or (len(m) != 1 and masked not in m[1:]):\n                            hit = True\n                            break\n                    if not hit:\n                        continue\n\n                # permission filtering\n                if self.args.perm is not None:\n                    v = self.read_int_from_memory(current_address)\n                    try:\n                        pm = ProcessMap.lookup_address(v)\n                        if not pm.section.permission.match(self.args.perm):\n                            continue\n                    except Exception:\n                        continue\n\n                # tags\n                if has_tag:\n                    tag = self.tags_dict.get(idx, \"\")\n                    padlen = self.max_tag_width - len(Color.remove_color(tag))\n                    tag += \" \" * padlen\n                else:\n                    tag = None\n\n                # create line\n                line = DereferenceCommand.pprint_dereferenced(\n                    start_address, idx,\n                    tag=tag, phys=self.args.phys, quiet=self.args.quiet, quiet_offset=self.args.quiet_offset,\n                )\n\n                # most left registers info\n                if not self.args.quiet:\n                    # register info\n                    regs_info = []\n                    for regname, regvalue in DereferenceCommand.get_target_registers_value():\n                        if current_address == regvalue:\n                            regs_info.append(regname)\n                    regs_info_str = regs_info[0] if regs_info else \"\"\n                    regs_info_ex = \"+\" if len(regs_info) > 1 else \" \"\n                    line = \"{:>{:d}s}{:s} {:s}\".format(\n                        regs_info_str, current_arch.get_registers_name_max(), regs_info_ex, line,\n                    )\n\n                # add line\n                out.append(line)\n\n                # horizontal line\n                if self.args.frame_split:\n                    if \"<-  retaddr[\" in line:\n                        out.append(titlify(\"\"))\n\n            except (RuntimeError, gdb.MemoryError):\n                # e.g., nop DWORD PTR [rax+rax*1+0x0]\n                msg = \"Cannot access memory at address {:#x}\".format(current_address)\n                out.append(\"{} {}\".format(Color.colorify(\"[!]\", \"bold red\"), msg))\n                break\n\n            # multiple level dump\n            if self.args.depth - 1 > 0:\n                v = self.read_int_from_memory(current_address)\n                if v % current_arch.ptrsize == 0 and is_valid_addr(v):\n                    args = self.args # backup\n                    cmd = \"dereference --depth {:d} --no-pager {:#x} {:#x}\".format(\n                        self.args.depth - 1, v, self.args.depth_nb_lines,\n                    )\n                    ret = gdb.execute(cmd, to_string=True)\n                    self.args = args # revert\n                    for line in ret.splitlines():\n                        out.append(\"      \" + line)\n\n        if self.args.reverse:\n            out.reverse()\n        return out\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.slab_contains or args.slab_contains_unaligned or args.phys:\n            if not (is_qemu_system() or is_kgdb() or is_vmware()):\n                err(\"Unsupported gdb mode\")\n                return\n\n        if (args.slab_contains or args.slab_contains_unaligned) and args.phys:\n            err(\"Unsupported option pairs\")\n            return\n\n        # perm\n        if args.perm:\n            if len(args.perm) != 3:\n                err(\"Invalid permission length\")\n                return\n            if args.perm[0] not in \"rR-_?\":\n                err(\"Invalid permission\")\n                return\n            if args.perm[1] not in \"wW-_?\":\n                err(\"Invalid permission\")\n                return\n            if args.perm[2] not in \"xX-_?\":\n                err(\"Invalid permission\")\n                return\n\n        # tags\n        self.tags_dict = {}\n        self.max_tag_width = 0\n        if args.tag:\n            for tag_idx, tag in args.tag:\n                try:\n                    tag_idx = int(tag_idx, 0) + args.tag_offset\n                except ValueError:\n                    err(\"Invalid tag idx\")\n                    return\n                self.tags_dict[tag_idx] = tag\n                self.max_tag_width = max(self.max_tag_width, len(tag))\n\n        # read memory function\n        if args.phys:\n            unpack = u32 if is_32bit() else u64\n            self.read_int_from_memory = lambda x: unpack(read_physmem(x, current_arch.ptrsize))\n        else:\n            self.read_int_from_memory = read_int_from_memory\n\n        # start address\n        if args.location is None:\n            start_address = current_arch.sp\n        else:\n            start_address = args.location\n\n        # line numbers\n        nb_lines = args.nb_lines or Config.get_gef_setting(\"dereference.nb_lines\")\n        from_idx = nb_lines * self.repeat_count\n        to_idx = nb_lines * (self.repeat_count + 1)\n\n        if from_idx <= to_idx:\n            step = 1 * args.interval\n        else:\n            step = -1 * args.interval\n            if args.depth > 1:\n                err(\"Unsupported using together -NB_LINES and -d DEPTH\")\n                return\n\n        # doit\n        out = self.dereference_line_by_line(start_address, from_idx, to_idx, step)\n\n        # Because there is a special configuration, the BufferingOutput class is not inherited\n        no_pager = args.no_pager | Config.get_gef_setting(\"dereference.no_pager\")\n        gef_print(\"\\n\".join(out), less=not no_pager)\n        return\n\n\n@register_command\nclass ASLRCommand(GenericCommand):\n    \"\"\"View / modify the ASLR setting of GDB.\"\"\"\n\n    _cmdline_ = \"aslr\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [None, \"on\", \"off\"]\n    parser.add_argument(\"command\", nargs=\"?\", default=None, choices=modes, metavar=\"{on,off}\",\n                        help=\"set gdb aslr settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    @parse_args\n    @only_if_gdb_target_local\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if is_attach() or is_remote_debug():\n            warn(\"ASLR setting is ignored because it is remote or attached process\")\n\n        if args.command is None:\n            aslr = gdb.parameter(\"disable-randomization\")\n            if aslr:\n                msg = \"ASLR is currently \" + Color.redify(\"disabled\")\n            else:\n                msg = \"ASLR is currently \" + Color.greenify(\"enabled\")\n            gef_print(msg)\n        elif args.command == \"on\":\n            info(\"Enabling ASLR\")\n            gdb.execute(\"set disable-randomization off\")\n        elif args.command == \"off\":\n            info(\"Disabling ASLR\")\n            gdb.execute(\"set disable-randomization on\")\n        return\n\n\n@register_command\nclass FollowCommand(GenericCommand):\n    \"\"\"View / modify the follow-fork-mode setting of GDB.\"\"\"\n\n    _cmdline_ = \"follow\"\n    _category_ = \"01-i. Debugging Support - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [None, \"child\", \"parent\"]\n    parser.add_argument(\"command\", nargs=\"?\", default=None, choices=modes,\n                        metavar=\"{child,parent}\", help=\"set gdb follow settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        if args.command is None:\n            follow = gdb.parameter(\"follow-fork-mode\")\n            if follow == \"child\":\n                msg = \"follow \" + Color.redify(\"Child\")\n            else:\n                msg = \"follow \" + Color.redify(\"Parent\")\n            gef_print(msg)\n        elif args.command == \"child\":\n            info(\"Follow child\")\n            gdb.execute(\"set follow-fork-mode child\")\n        elif args.command == \"parent\":\n            info(\"Follow parent\")\n            gdb.execute(\"set follow-fork-mode parent\")\n        return\n\n\n@register_command\nclass SmartCppFunctionNameCommand(GenericCommand):\n    \"\"\"Toggle the setting of `context.smart_cpp_function_name`.\"\"\"\n\n    _cmdline_ = \"smart-cpp-function-name\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n    _aliases_ = [\"cpp\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        setting = Config.get_gef_setting(\"context.smart_cpp_function_name\")\n        gdb.execute(\"gef config context.smart_cpp_function_name {!s}\".format(not setting), to_string=True)\n        return\n\n\n@register_command\nclass ExtraCommand(GenericCommand):\n    \"\"\"The base command to add, remove, list or clear user specified command to `context extra`.\"\"\"\n\n    _cmdline_ = \"extra\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"add\")\n    subparsers.add_parser(\"remove\")\n    subparsers.add_parser(\"list\")\n    subparsers.add_parser(\"clear\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass ExtraAddCommand(ExtraCommand):\n    \"\"\"Add user specified command to execute when each step.\"\"\"\n\n    _cmdline_ = \"extra add\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"cmd\", metavar=\"CMD\", nargs=\"+\", help=\"the command to execute when each step.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        ContextExtraCommand.context_extra_commands.append(\" \".join(args.cmd))\n        return\n\n\n@register_command\nclass ExtraListCommand(ExtraCommand):\n    \"\"\"List user specified command to execute when each step.\"\"\"\n\n    _cmdline_ = \"extra list\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if not ContextExtraCommand.context_extra_commands:\n            warn(\"Nothing to display\")\n            return\n        for i, command in enumerate(ContextExtraCommand.context_extra_commands):\n            gef_print(\"[{:3d}] {:s}\".format(i, command))\n        return\n\n\n@register_command\nclass ExtraRemoveCommand(ExtraCommand):\n    \"\"\"Remove user specified command to execute when each step.\"\"\"\n\n    _cmdline_ = \"extra remove\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"index\", metavar=\"INDEX\", type=int,\n                        help=\"the index of command to remove from automatically execution each step.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.index < len(ContextExtraCommand.context_extra_commands):\n            ContextExtraCommand.context_extra_commands.pop(args.index)\n        else:\n            err(\"Out of index\")\n        return\n\n\n@register_command\nclass ExtraClearCommand(ExtraCommand):\n    \"\"\"Clear all user specified commands to execute when each step.\"\"\"\n\n    _cmdline_ = \"extra clear\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        ContextExtraCommand.context_extra_commands = []\n        return\n\n\n@register_command\nclass CommentCommand(GenericCommand):\n    \"\"\"The base command to add, remove, list or clear the comment.\"\"\"\n\n    _cmdline_ = \"comment\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"add\")\n    subparsers.add_parser(\"remove\")\n    subparsers.add_parser(\"list\")\n    subparsers.add_parser(\"clear\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Comments are temporary only. Note that it will be deleted when GDB exits.\",\n    ]\n    _note_= \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        return\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass CommentAddCommand(CommentCommand):\n    \"\"\"Add a comment to specific address.\"\"\"\n\n    _cmdline_ = \"comment add\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address for comment.\")\n    parser.add_argument(\"comment\", metavar=\"COMMENT\", help=\"the comment to print when hit.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        comms = ContextCodeCommand.context_comments.get(args.location, [])\n        ContextCodeCommand.context_comments[args.location] = comms + [args.comment]\n        return\n\n\n@register_command\nclass CommentLsCommand(CommentCommand):\n    \"\"\"List the comments.\"\"\"\n\n    _cmdline_ = \"comment list\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        if not ContextCodeCommand.context_comments:\n            warn(\"Nothing to display\")\n            return\n        for loc, comms in sorted(ContextCodeCommand.context_comments.items()):\n            for i, comm in enumerate(comms):\n                gef_print(\"{:#x}: [{:3d}] {:s}\".format(loc, i, comm))\n        return\n\n\n@register_command\nclass CommentRemoveCommand(CommentCommand):\n    \"\"\"Remove the specified comment.\"\"\"\n\n    _cmdline_ = \"comment remove\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address for comment.\")\n    parser.add_argument(\"index\", metavar=\"INDEX\", nargs=\"?\", type=int,\n                        help=\"the index of comment to remove. If omitted, all comments for that address will be deleted.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.location not in ContextCodeCommand.context_comments:\n            err(\"Invalid location\")\n            return\n        if args.index is None:\n            del ContextCodeCommand.context_comments[args.location]\n        else:\n            if args.index >= len(ContextCodeCommand.context_comments[args.location]):\n                err(\"Out of index\")\n                return\n            ContextCodeCommand.context_comments[args.location].pop(args.index)\n            if len(ContextCodeCommand.context_comments[args.location]) == 0:\n                del ContextCodeCommand.context_comments[args.location]\n        return\n\n\n@register_command\nclass CommentClearCommand(CommentCommand):\n    \"\"\"Clear all comments.\"\"\"\n\n    _cmdline_ = \"comment clear\"\n    _category_ = \"01-f. Debugging Support - Context Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @require_arch_set\n    def do_invoke(self, args):\n        ContextCodeCommand.context_comments = {}\n        return\n\n\n@register_command\nclass VMMapCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display a comprehensive layout of the virtual memory mapping.\"\"\"\n\n    _cmdline_ = \"vmmap\"\n    _category_ = \"02-c. Process Information - Memory/Section\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--outer\", action=\"store_true\",\n                        help=\"display qemu-user's memory map instead of emulated process's memory map.\")\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"?\", help=\"filter string.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"do not display register information.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} libc             # show only lines containing the string `libc`\",\n        \"{0:s} binary           # 'binary' means the area executable itself\",\n        \"{0:s} 0x555555577ab0   # show only lines included specified address\",\n        \"{0:s} --outer          # show qemu-user memory map; only valid in qemu-user mode\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def dump_entry(self, entry, print_offset=False):\n        # get color\n        line_color = \"\"\n        if entry.path.startswith(\"[stack]\"):\n            line_color = Config.get_gef_setting(\"theme.address_stack\")\n        elif entry.path.startswith(\"[heap]\"):\n            line_color = Config.get_gef_setting(\"theme.address_heap\")\n        elif entry.permission.value & Permission.EXECUTE:\n            line_color = Config.get_gef_setting(\"theme.address_code\")\n        elif entry.permission.value & Permission.WRITE:\n            line_color = Config.get_gef_setting(\"theme.address_writable\")\n        elif entry.permission.value & Permission.READ:\n            line_color = Config.get_gef_setting(\"theme.address_readonly\")\n        elif entry.permission.value == Permission.NONE:\n            line_color = Config.get_gef_setting(\"theme.address_valid_but_none\")\n        if entry.permission.value == (Permission.READ | Permission.WRITE | Permission.EXECUTE):\n            line_color += \" \" + Config.get_gef_setting(\"theme.address_rwx\")\n\n        # if qemu-xxx(32bit arch) runs on x86-64 machine, memalign_size does not match\n        # AddressUtil.get_memory_alignment()\n        memalign_size = 8 if self.args.outer else None\n\n        # make line\n        lines = []\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.page_start, memalign_size, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.page_end, memalign_size, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.size, memalign_size, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.offset, memalign_size, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            str(entry.permission), line_color,\n        ))\n        if entry.path:\n            lines.append(Color.colorify(entry.path, line_color))\n        line = \" \".join(lines)\n\n        # offset info\n        if not self.args.quiet:\n            if print_offset is not False:\n                line += Color.colorify(\" {:+#x}\".format(print_offset), line_color)\n\n        # register info\n        if not self.args.quiet:\n            register_hints = []\n            for regname in current_arch.all_registers:\n                regvalue = get_register(regname)\n                if entry.page_start <= regvalue < entry.page_end:\n                    register_hints.append(regname)\n            if register_hints:\n                m = \"  <-  {:s}\".format(\", \".join(list(register_hints)))\n                registers_color = Config.get_gef_setting(\"theme.dereference_register_value\")\n                line += Color.colorify(m, registers_color)\n\n        self.out.append(line)\n        return\n\n    def show_legend(self):\n        legend = \"[ Legend: {:s} ]\".format(\n            \" | \".join([\n                Color.colorify(\"Code\", Config.get_gef_setting(\"theme.address_code\")),\n                Color.colorify(\"Heap\", Config.get_gef_setting(\"theme.address_heap\")),\n                Color.colorify(\"Stack\", Config.get_gef_setting(\"theme.address_stack\")),\n                Color.colorify(\"Writable\", Config.get_gef_setting(\"theme.address_writable\")),\n                Color.colorify(\"ReadOnly\", Config.get_gef_setting(\"theme.address_readonly\")),\n                Color.colorify(\"None\", Config.get_gef_setting(\"theme.address_valid_but_none\")),\n                Color.colorify(\"RWX\", Config.get_gef_setting(\"theme.address_rwx\")),\n            ]),\n        )\n        self.out.append(legend)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    def do_invoke(self, args):\n        if is_qemu_system() or is_vmware():\n            if is_arm32_cortex_m():\n                info(\"Redirect to `xfiles` (args are ignored)\")\n                gdb.execute(\"xfiles\")\n                return\n            elif is_in_kernel():\n                info(\"Redirect to `kvmmap` (args are ignored; use `pagewalk` to show phys addr)\")\n                gdb.execute(\"kvmmap\")\n                return\n            else:\n                info(\"Redirect to `pagewalk` (args are ignored)\")\n                gdb.execute(\"pagewalk --quiet\")\n                return\n\n        if args.outer and not is_qemu_user():\n            err(\"Unsupported `--outer` option in this gdb mode\")\n            return\n\n        if is_qemu_user():\n            # the memory map may be changed, so retry memory exploring in get_process_maps()\n            Cache.reset_gef_caches(all=True)\n\n        # get maps\n        vmmap = ProcessMap.get_process_maps(args.outer)\n        if not vmmap:\n            for line in gdb.execute(\"info files\", to_string=True).splitlines():\n                if line.startswith(\"Symbols from\"):\n                    break\n            else:\n                err(\"Missing info about architecture. Please set: `file /path/to/target_binary`\")\n            err(\"No address mapping information found\")\n            return\n\n        # color legend\n        self.out = []\n        if not Config.get_gef_setting(\"gef.disable_color\"):\n            self.show_legend()\n\n        # legend\n        fmt = \"{:{:d}s} {:{:d}s} {:{:d}s} {:{:d}s} {:4s} {:s}\"\n        memalign_size = 8 if args.outer else AddressUtil.get_memory_alignment()\n        width =  memalign_size * 2 + 2\n        legend = [\"Start\", width, \"End\", width, \"Size\", width, \"Offset\", width, \"Perm\", \"Path\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # for filter\n        filter_addr1 = None\n        filter_addr2 = None\n        if args.filter is not None:\n            try:\n                filter_addr1 = AddressUtil.parse_address(args.filter)\n            except gdb.error:\n                pass\n            try:\n                filter_addr2 = int(args.filter, 0)\n            except ValueError:\n                pass\n\n        # show each entry\n        for entry in vmmap:\n            # no filter\n            if not args.filter:\n                self.dump_entry(entry)\n                continue\n\n            # includes address\n            if filter_addr1 is not None:\n                if entry.page_start <= filter_addr1 < entry.page_end:\n                    self.dump_entry(entry, print_offset=filter_addr1 - entry.page_start)\n                    filter_addr1 = None # It never matches a different region\n                    continue\n\n            # range match\n            if filter_addr2 is not None:\n                if entry.page_start <= filter_addr2 < entry.page_end:\n                    self.dump_entry(entry, print_offset=filter_addr2 - entry.page_start)\n                    filter_addr2 = None # It never matches a different region\n                    continue\n\n            # `binary` case\n            if args.filter == \"binary\":\n                if Path.get_filepath(append_proc_root_prefix=False) == entry.path:\n                    self.dump_entry(entry)\n                    continue\n\n            # A simple match to the filter string\n            if args.filter in entry.path:\n                self.dump_entry(entry)\n                continue\n\n        # warning message\n        if is_qemu_user() and not args.outer:\n            if ProcessMap.__gef_use_info_proc_mappings__ is False:\n                self.info_add_out(\"Some areas may be undetectable due to heuristic search (auxv, registers, stack)\")\n                self.info_add_out(\"Permissions use ELF header or default rw-; dynamic changes undetectable\")\n\n        # print\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XFilesCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display all libraries (and sections) loaded by binary.\"\"\"\n\n    _cmdline_ = \"xfiles\"\n    _category_ = \"02-c. Process Information - Memory/Section\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", help=\"regex filter string.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} libc\",\n        \"{0:s} got plt\",\n        \"{0:s} IO_vtables\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        self.out = []\n\n        fmt = \"{:{:d}s} {:{:d}s} {:<21s} {:s}\"\n        width = AddressUtil.get_format_address_width()\n        legend = [\"Start\", width, \"End\", width, \"Name\", \"File\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for xfile in ProcessMap.get_info_files():\n            lines = []\n            lines.append(str(ProcessMap.lookup_address(xfile.zone_start)))\n            lines.append(str(ProcessMap.lookup_address(xfile.zone_end)))\n            lines.append(\"{:<21s}\".format(xfile.name))\n            lines.append(xfile.filename)\n            line = \" \".join(lines)\n\n            if not args.filter:\n                self.out.append(line)\n                continue\n\n            for filt in args.filter:\n                if re.search(filt, line):\n                    self.out.append(line)\n                    break\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XInfoCommand(GenericCommand):\n    \"\"\"Retrieve and display runtime information for the location(s) given as parameter.\"\"\"\n\n    _cmdline_ = \"xinfo\"\n    _category_ = \"02-c. Process Information - Memory/Section\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"*\", type=AddressUtil.parse_address,\n                        help=\"the memory address to show the information. (default: current_arch.pc)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def xinfo(self, address):\n        addr = ProcessMap.lookup_address(address)\n        if not addr.valid:\n            warn(\"Cannot reach {:#x} in memory space\".format(address))\n            return\n\n        gdb.execute(\"vmmap {:#x}\".format(address))\n\n        if addr.section:\n            page_start = ProcessMap.lookup_address(addr.section.page_start)\n            gef_print(\"Offset (from mapped):  {!s} + {:#x}\".format(\n                page_start, addr.value - addr.section.page_start,\n            ))\n\n            if addr.section.path and addr.section.path.startswith(\"/\"):\n                base_start = ProcessMap.lookup_address(ProcessMap.get_section_base_address(addr.section.path))\n                gef_print(\"Offset (from base):    {!s} + {:#x}\".format(\n                    base_start, addr.value - base_start.section.page_start,\n                ))\n\n        if addr.info:\n            zone_start = ProcessMap.lookup_address(addr.info.zone_start)\n            gef_print(\"Offset (from segment): {!s} ({:s}) + {:#x}\".format(\n                zone_start, addr.info.name, addr.value - addr.info.zone_start,\n            ))\n\n        sym = Symbol.get_symbol_string(address)\n        if sym:\n            msg = \"Symbol:                {:s}\".format(sym.strip())\n            gef_print(msg)\n\n        if addr.section and addr.section.inode:\n            gef_print(\"Inode:                 {:d}\".format(addr.section.inode))\n\n        return\n\n    def xinfo_kernel_pagewalk(self, address):\n        ret = gdb.execute(\"pagewalk --vrange {:#x} --no-pager --quiet\".format(address), to_string=True)\n        ret = [x for x in ret.splitlines() if not Color.remove_color(x).startswith((\"---\", \"[+]\"))]\n\n        if not ret:\n            err(\"Not found\")\n            return\n\n        gef_print(\"\\n\".join(ret))\n\n        if ret[-1].startswith(\"0x\"):\n            virt, phys, *_ = ret[-1].split()\n            vstart = int(virt.split(\"-\")[0], 16)\n            pstart = int(phys.split(\"-\")[0], 16)\n            offset = address - vstart\n            gef_print(\"Offset (from virt mapped):  {:#x} + {:#x}\".format(vstart, offset))\n            gef_print(\"Offset (from phys mapped):  {:#x} + {:#x}\".format(pstart, offset))\n        return\n\n    def xinfo_kernel_kvmmap(self, address):\n        ret = gdb.execute(\"kvmmap {:#x} --no-pager --quiet\".format(address), to_string=True)\n        gef_print(ret.rstrip())\n        return\n\n    def xinfo_kernel_slab(self, address):\n        ret = gdb.execute(\"slab-contains {:#x}\".format(address), to_string=True)\n        gef_print(ret.rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.location == []:\n            locations = [current_arch.pc]\n        else:\n            locations = args.location\n\n        # kernel xinfo\n        if is_qemu_system() or is_vmware():\n            for location in locations:\n                gef_print(titlify(\"xinfo (from pagewalk): {:#x}\".format(location)))\n                self.xinfo_kernel_pagewalk(location)\n                gef_print(titlify(\"xinfo (from kvmmap): {:#x}\".format(location)))\n                self.xinfo_kernel_kvmmap(location)\n                gef_print(titlify(\"xinfo (from slab-contains): {:#x}\".format(location)))\n                self.xinfo_kernel_slab(location)\n            return\n\n        # userland xinfo\n        for location in locations:\n            try:\n                gef_print(titlify(\"xinfo: {:#x}\".format(location)))\n                self.xinfo(location)\n            except gdb.error as gdb_error:\n                err(str(gdb_error))\n        return\n\n\n@register_command\nclass XorMemoryCommand(GenericCommand):\n    \"\"\"The base command to xor a block of memory.\"\"\"\n\n    _cmdline_ = \"xor-memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"display\")\n    subparsers.add_parser(\"patch\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass XorMemoryDisplayCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display a block of memory by xor-ing each byte with specified key.\"\"\"\n\n    _cmdline_ = \"xor-memory display\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address of data to xor.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size of data to xor.\")\n    parser.add_argument(\"key\", metavar=\"KEY\", type=lambda x: bytes.fromhex(x),\n                        help=\"the data to xor as key.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $sp 16 41414141\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        self.out = []\n\n        start_addr = args.location\n        end_addr = args.location + args.size\n        try:\n            block = read_memory(start_addr, args.size)\n        except gdb.MemoryError:\n            err(\"Failed to read memory\")\n            return\n\n        self.info_add_out(\"Displaying XOR-ing {:#x}-{:#x} with {:s}\".format(start_addr, end_addr, repr(args.key)))\n\n        self.out.append(titlify(\"Original block\"))\n        self.out.append(hexdump(block, base=start_addr))\n\n        self.out.append(titlify(\"XOR-ed block\"))\n        xored_block = xor(block, args.key)\n        self.out.append(hexdump(xored_block, base=start_addr))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XorMemoryPatchCommand(GenericCommand):\n    \"\"\"Patch a block of memory by xor-ing each byte with specified key.\"\"\"\n\n    _cmdline_ = \"xor-memory patch\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the address of data to xor.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size of data to xor.\")\n    parser.add_argument(\"key\", metavar=\"KEY\", type=lambda x: bytes.fromhex(x),\n                        help=\"the data to xor as key.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $sp 16 41414141\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        start_addr = args.location\n        end_addr = args.location + args.size\n        try:\n            block = read_memory(start_addr, args.size)\n        except gdb.MemoryError:\n            err(\"Failed to read memory\")\n            return\n        info(\"Patching XOR-ing {:#x}-{:#x} with '{:s}'\".format(start_addr, end_addr, repr(args.key)))\n        xored_block = xor(block, args.key)\n        gdb.execute(\"patch hex {:#x} {:s}\".format(start_addr, xored_block.hex()))\n        return\n\n\n@register_command\nclass PatternCommand(GenericCommand):\n    \"\"\"The base command to create or search for a De Bruijn cyclic pattern (used pwntools).\"\"\"\n\n    _cmdline_ = \"pattern\"\n    _category_ = \"07-c. Misc - Generation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"create\")\n    subparsers.add_parser(\"search\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(prefix=True)\n        self.add_setting(\"length\", 1024, \"Initial length of a cyclic buffer to generate\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass PatternCreateCommand(GenericCommand):\n    \"\"\"Generate a de Bruijn cyclic pattern.\"\"\"\n\n    _cmdline_ = \"pattern create\"\n    _category_ = \"07-c. Misc - Generation\"\n    _aliases_ = [\"pattc\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-c\", \"--charset\", help=\"the charset of pattern. (default: abc..z)\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, nargs=\"?\",\n                        help=\"the size of pattern. (default: 1024)\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def de_bruijn(alphabet, n):\n        \"\"\"De Bruijn sequence for alphabet and subsequences of length n (for compat. w/ pwnlib).\"\"\"\n        k = len(alphabet)\n        a = [0] * k * n\n\n        def db(t, p):\n            if t > n:\n                if n % p == 0:\n                    for j in range(1, p + 1):\n                        yield alphabet[a[j]]\n            else:\n                a[t] = a[t - p]\n                for c in db(t + 1, p):\n                    yield c\n\n                for j in range(a[t - p] + 1, k):\n                    a[t] = j\n                    for c in db(t + 1, t):\n                        yield c\n\n        return db(1, 1)\n\n    @staticmethod\n    def generate_cyclic_pattern(length, charset=None):\n        \"\"\"Create a `length` byte bytearray of a de Bruijn cyclic pattern.\"\"\"\n        if charset is None:\n            charset = bytearray(b\"abcdefghijklmnopqrstuvwxyz\")\n        elif isinstance(charset, str):\n            charset = String.str2bytes(charset)\n\n        cycle = AddressUtil.get_memory_alignment()\n        return bytes(itertools.islice(PatternCreateCommand.de_bruijn(charset, cycle), length))\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.size is None:\n            size = Config.get_gef_setting(\"pattern.length\")\n        else:\n            size = args.size\n\n        info(\"Generating a pattern of {:d} bytes\".format(size))\n        pattern_str = PatternCreateCommand.generate_cyclic_pattern(size, args.charset)\n        gef_print(pattern_str)\n\n        conv_var = GefUtil.gef_convenience(String.bytes2str(pattern_str))\n        ok(\"Saved as '{:s}'\".format(conv_var))\n        return\n\n\n@register_command\nclass PatternSearchCommand(GenericCommand):\n    \"\"\"Search for the cyclic de Bruijn pattern generated by the `pattern create`.\"\"\"\n\n    _cmdline_ = \"pattern search\"\n    _category_ = \"07-c. Misc - Generation\"\n    _aliases_ = [\"patto\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-c\", \"--charset\", help=\"the charset of pattern. (default: abc..z)\")\n    parser.add_argument(\"pattern\", metavar=\"PATTERN\", help=\"the pattern to offset search.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, nargs=\"?\",\n                        help=\"the size of pattern. (default: 0x10000)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $pc\",\n        \"{0:s} 0x61616164\",\n        \"{0:s} aaab\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def search(self, tag, cyclic_pattern, pattern):\n        gef_print(titlify(tag))\n\n        def search_pattern(pattern):\n            info(\"Searching for {}\".format(pattern))\n            found = 0\n            off = 0\n            while found < 10:\n                off = cyclic_pattern.find(pattern, off)\n                if off == -1:\n                    break\n                ok(\"Found at offset {:d} ({:#x})\".format(off, off))\n                found += 1\n                off += 1\n\n            if found == 0:\n                err(\"Not found\")\n\n            if found == 10:\n                ok(\"...\")\n            return\n\n        # little endian\n        search_pattern(pattern)\n\n        # big endian\n        inv_pattern = pattern[::-1]\n        if pattern != inv_pattern:\n            search_pattern(inv_pattern)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.size is None:\n            size = Config.get_gef_setting(\"pattern.length\") * 64\n        else:\n            size = args.size\n\n        cyclic_pattern = PatternCreateCommand.generate_cyclic_pattern(size, args.charset)\n        pack = p32 if is_32bit() else p64\n\n        # 1. check if it's a symbol (like \"$sp\")\n        try:\n            address = AddressUtil.parse_address(args.pattern)\n            value = read_int_from_memory(address)\n            self.search(\"As symbol (with dereference)\", cyclic_pattern, pack(value))\n        except gdb.error:\n            pass\n\n        # 2. check if it's a not symbol, but value (like \"0x1337\")\n        try:\n            value = AddressUtil.parse_address(args.pattern)\n            self.search(\"As value (without dereference)\", cyclic_pattern, pack(value))\n        except gdb.error:\n            pass\n\n        # 3. plain text\n        pattern = String.str2bytes(args.pattern)\n        if set(pattern) - set(cyclic_pattern) == set():\n            self.search(\"As string\", cyclic_pattern, pattern)\n        return\n\n\n@register_command\nclass SigreturnCommand(GenericCommand):\n    \"\"\"Display stack values for sigreturn syscall.\"\"\"\n\n    _cmdline_ = \"sigreturn\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as the beginning of a sigframe. (default: current_arch.sp)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if args.location is None:\n            base = current_arch.sp\n        else:\n            base = args.location\n\n        if is_x86_64():\n            sigreturn_defines = [\n                \"rt_sigframe.pretcode\",\n                \"rt_sigframe.uc.uc_flags\",\n                \"rt_sigframe.uc.uc_link\",\n                \"rt_sigframe.uc.uc_stack.ss_sp\",\n                \"rt_sigframe.uc.uc_stack.ss_flags|ss_size\",\n                \"rt_sigframe.uc.uc_mcontext.r8\",\n                \"rt_sigframe.uc.uc_mcontext.r9\",\n                \"rt_sigframe.uc.uc_mcontext.r10\",\n                \"rt_sigframe.uc.uc_mcontext.r11\",\n                \"rt_sigframe.uc.uc_mcontext.r12\",\n                \"rt_sigframe.uc.uc_mcontext.r13\",\n                \"rt_sigframe.uc.uc_mcontext.r14\",\n                \"rt_sigframe.uc.uc_mcontext.r15\",\n                \"rt_sigframe.uc.uc_mcontext.rdi\",\n                \"rt_sigframe.uc.uc_mcontext.rsi\",\n                \"rt_sigframe.uc.uc_mcontext.rbp\",\n                \"rt_sigframe.uc.uc_mcontext.rbx\",\n                \"rt_sigframe.uc.uc_mcontext.rdx\",\n                \"rt_sigframe.uc.uc_mcontext.rax\",\n                \"rt_sigframe.uc.uc_mcontext.rcx\",\n                \"rt_sigframe.uc.uc_mcontext.rsp\",\n                \"rt_sigframe.uc.uc_mcontext.rip\",\n                \"rt_sigframe.uc.uc_mcontext.rflags\",\n                \"rt_sigframe.uc.uc_mcontext.cs|gs|fs|__pad0\",\n                \"rt_sigframe.uc.uc_mcontext.err\",\n                \"rt_sigframe.uc.uc_mcontext.trapno\",\n                \"rt_sigframe.uc.uc_mcontext.oldmask\",\n                \"rt_sigframe.uc.uc_mcontext.cr2\",\n                \"rt_sigframe.uc.uc_mcontext.fpstate\",\n                \"rt_sigframe.uc.uc_mcontext.reserved[8]\",\n                \"rt_sigframe.uc.uc_sigmask\",\n                \"rt_sigframe.info\",\n            ]\n        elif is_x86_32():\n            sigreturn_defines = [\n                \"sigframe.sc.gs\",\n                \"sigframe.sc.fs\",\n                \"sigframe.sc.es\",\n                \"sigframe.sc.ds\",\n                \"sigframe.sc.edi\",\n                \"sigframe.sc.esi\",\n                \"sigframe.sc.ebp\",\n                \"sigframe.sc.esp\",\n                \"sigframe.sc.ebx\",\n                \"sigframe.sc.edx\",\n                \"sigframe.sc.ecx\",\n                \"sigframe.sc.eax\",\n                \"sigframe.sc.trapno\",\n                \"sigframe.sc.err\",\n                \"sigframe.sc.eip\",\n                \"sigframe.sc.cs\",\n                \"sigframe.sc.eflags\",\n                \"sigframe.sc.esp_at_signal\",\n                \"sigframe.sc.ss\",\n                \"sigframe.sc.fpstate\",\n                \"sigframe.sc.oldmask\",\n                \"sigframe.sc.cr2\",\n            ]\n        elif is_arm32():\n            sigreturn_defines = [\n                \"sigframe.uc.uc_flags\",\n                \"sigframe.uc.uc_link\",\n                \"sigframe.uc.uc_stack.ss_sp\",\n                \"sigframe.uc.uc_stack.ss_flags\",\n                \"sigframe.uc.uc_stack.ss_size\",\n                \"sigframe.uc.uc_mcontext.trapno\",\n                \"sigframe.uc.uc_mcontext.error_code\",\n                \"sigframe.uc.uc_mcontext.oldmask\",\n                \"sigframe.uc.uc_mcontext.arm_r0\",\n                \"sigframe.uc.uc_mcontext.arm_r1\",\n                \"sigframe.uc.uc_mcontext.arm_r2\",\n                \"sigframe.uc.uc_mcontext.arm_r3\",\n                \"sigframe.uc.uc_mcontext.arm_r4\",\n                \"sigframe.uc.uc_mcontext.arm_r5\",\n                \"sigframe.uc.uc_mcontext.arm_r6\",\n                \"sigframe.uc.uc_mcontext.arm_r7\",\n                \"sigframe.uc.uc_mcontext.arm_r8\",\n                \"sigframe.uc.uc_mcontext.arm_r9\",\n                \"sigframe.uc.uc_mcontext.arm_r10\",\n                \"sigframe.uc.uc_mcontext.arm_fp\",\n                \"sigframe.uc.uc_mcontext.arm_ip\",\n                \"sigframe.uc.uc_mcontext.arm_sp\",\n                \"sigframe.uc.uc_mcontext.arm_lr\",\n                \"sigframe.uc.uc_mcontext.arm_pc\",\n                \"sigframe.uc.uc_mcontext.arm_cpsr\",\n                \"sigframe.uc.uc_mcontext.fault_address\",\n                \"sigframe.uc.uc_sigmask\",\n            ]\n        elif is_arm64():\n            sigreturn_defines = [\n                \"rt_sigframe.info+0x00\",\n                \"rt_sigframe.info+0x08\",\n                \"rt_sigframe.info+0x10\",\n                \"rt_sigframe.info+0x18\",\n                \"rt_sigframe.info+0x20\",\n                \"rt_sigframe.info+0x28\",\n                \"rt_sigframe.info+0x30\",\n                \"rt_sigframe.info+0x38\",\n                \"rt_sigframe.info+0x40\",\n                \"rt_sigframe.info+0x48\",\n                \"rt_sigframe.info+0x50\",\n                \"rt_sigframe.info+0x58\",\n                \"rt_sigframe.info+0x60\",\n                \"rt_sigframe.info+0x68\",\n                \"rt_sigframe.info+0x70\",\n                \"rt_sigframe.info+0x78\",\n                \"rt_sigframe.uc.uc_flags\",\n                \"rt_sigframe.uc.uc_link\",\n                \"rt_sigframe.uc.uc_stack.ss_sp\",\n                \"rt_sigframe.uc.uc_stack.ss_flags\",\n                \"rt_sigframe.uc.uc_stack.ss_size\",\n                \"rt_sigframe.uc.uc_stack.__unused\",\n                \"rt_sigframe.uc.uc_sigmask\",\n                \"rt_sigframe.uc.__unused[120]+0x00\",\n                \"rt_sigframe.uc.__unused[120]+0x08\",\n                \"rt_sigframe.uc.__unused[120]+0x10\",\n                \"rt_sigframe.uc.__unused[120]+0x18\",\n                \"rt_sigframe.uc.__unused[120]+0x20\",\n                \"rt_sigframe.uc.__unused[120]+0x28\",\n                \"rt_sigframe.uc.__unused[120]+0x30\",\n                \"rt_sigframe.uc.__unused[120]+0x38\",\n                \"rt_sigframe.uc.__unused[120]+0x40\",\n                \"rt_sigframe.uc.__unused[120]+0x48\",\n                \"rt_sigframe.uc.__unused[120]+0x50\",\n                \"rt_sigframe.uc.__unused[120]+0x58\",\n                \"rt_sigframe.uc.__unused[120]+0x60\",\n                \"rt_sigframe.uc.__unused[120]+0x68\",\n                \"rt_sigframe.uc.__unused[120]+0x70\",\n                \"rt_sigframe.uc.uc_mcontext.fault_address\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x0\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x1\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x2\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x3\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x4\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x5\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x6\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x7\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x8\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x9\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x10\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x11\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x12\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x13\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x14\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x15\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x16\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x17\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x18\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x19\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x20\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x21\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x22\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x23\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x24\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x25\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x26\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x27\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x28\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x29\",\n                \"rt_sigframe.uc.uc_mcontext.regs[31].x30\",\n                \"rt_sigframe.uc.uc_mcontext.sp\",\n                \"rt_sigframe.uc.uc_mcontext.pc\",\n                \"rt_sigframe.uc.uc_mcontext.pstate\",\n            ]\n\n        max_name_width = max(len(x) for x in sigreturn_defines)\n\n        out = []\n        for i, tag in enumerate(sigreturn_defines):\n            line = DereferenceCommand.pprint_dereferenced(base, i, tag.ljust(max_name_width))\n            out.append(line)\n\n        gef_print(\"\\n\".join(out), less=not args.no_pager)\n        return\n\n\n@register_command\nclass SropHintCommand(GenericCommand):\n    \"\"\"Hint for sigreturn oriented programming.\"\"\"\n\n    _cmdline_ = \"srop-hint\"\n    _category_ = \"07-d. Misc - Show Example\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    architectures = [None, \"x86\", \"x64\", \"arm\", \"aarch64\"]\n    parser.add_argument(\"arch\", nargs=\"?\", default=None, choices=architectures, metavar=\"{x86,x64,arm,aarch64}\",\n                        help=\"the target architecture.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.architectures:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.architectures if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.architectures if s and s.startswith(text.strip())]\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    def do_invoke(self, args):\n        if args.arch is None:\n            if is_x86_64():\n                mode = \"x64\"\n            elif is_x86_32():\n                mode = \"x86\"\n            elif is_arm32():\n                mode = \"arm\"\n            elif is_arm64():\n                mode = \"aarch64\"\n            else:\n                mode = \"x64\" # default\n        else:\n            mode = args.arch\n\n        s = \"\"\n        if mode == \"x64\":\n            s += 'exp  = struct.pack(\"<Q\", syscall)    # rax = 15 (rt_sigreturn)\\n'\n            s += 'exp += struct.pack(\"<Q\", 0xcafebabe) # rt_sigframe.pretcode\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_flags\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_link\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_stack.ss_sp\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # rt_sigframe.uc.uc_stack.ss_flags\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # rt_sigframe.uc.uc_stack.ss_size\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x08)       # rt_sigframe.uc.uc_mcontext.r8\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x09)       # rt_sigframe.uc.uc_mcontext.r9\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0a)       # rt_sigframe.uc.uc_mcontext.r10\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0b)       # rt_sigframe.uc.uc_mcontext.r11\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0c)       # rt_sigframe.uc.uc_mcontext.r12\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0d)       # rt_sigframe.uc.uc_mcontext.r13\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0e)       # rt_sigframe.uc.uc_mcontext.r14\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0f)       # rt_sigframe.uc.uc_mcontext.r15\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x07)       # rt_sigframe.uc.uc_mcontext.rdi\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x06)       # rt_sigframe.uc.uc_mcontext.rsi\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x05)       # rt_sigframe.uc.uc_mcontext.rbp\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x02)       # rt_sigframe.uc.uc_mcontext.rbx\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x04)       # rt_sigframe.uc.uc_mcontext.rdx\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x01)       # rt_sigframe.uc.uc_mcontext.rax\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x03)       # rt_sigframe.uc.uc_mcontext.rcx\\n'\n            s += 'exp += struct.pack(\"<Q\", 0xdeadface) # rt_sigframe.uc.uc_mcontext.rsp\\n'\n            s += 'exp += struct.pack(\"<Q\", 0xdeadbeef) # rt_sigframe.uc.uc_mcontext.rip\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x00)       # rt_sigframe.uc.uc_mcontext.rflags\\n'\n            s += 'exp += struct.pack(\"<H\", 0x33)       # rt_sigframe.uc.uc_mcontext.cs\\n'\n            s += 'exp += struct.pack(\"<H\", 0x00)       # rt_sigframe.uc.uc_mcontext.gs\\n'\n            s += 'exp += struct.pack(\"<H\", 0x00)       # rt_sigframe.uc.uc_mcontext.fs\\n'\n            s += 'exp += struct.pack(\"<H\", 0x00)       # rt_sigframe.uc.uc_mcontext.__pad0\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.err\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.trapno\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.oldmask\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.cr2\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.fpstate # fpu/xmm are not restored if NULL\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.reserved[8]\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_sigmask\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.info\\n'\n        elif mode == \"x86\":\n            s += 'exp  = struct.pack(\"<I\", syscall)    # eax = 119 (sigreturn)\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.gs\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.fs\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.es\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.ds\\n'\n            s += 'exp += struct.pack(\"<I\", 0x7)        # sigframe.sc.edi\\n'\n            s += 'exp += struct.pack(\"<I\", 0x6)        # sigframe.sc.esi\\n'\n            s += 'exp += struct.pack(\"<I\", 0x5)        # sigframe.sc.ebp\\n'\n            s += 'exp += struct.pack(\"<I\", 0xdeadface) # sigframe.sc.esp\\n'\n            s += 'exp += struct.pack(\"<I\", 0x2)        # sigframe.sc.ebx\\n'\n            s += 'exp += struct.pack(\"<I\", 0x4)        # sigframe.sc.edx\\n'\n            s += 'exp += struct.pack(\"<I\", 0x3)        # sigframe.sc.ecx\\n'\n            s += 'exp += struct.pack(\"<I\", 0x1)        # sigframe.sc.eax\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.trapno\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.err\\n'\n            s += 'exp += struct.pack(\"<I\", 0xdeadbeef) # sigframe.sc.eip\\n'\n            s += 'exp += struct.pack(\"<I\", 0x23)       # sigframe.sc.cs # use 0x73 if 32bit native machine\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.eflags\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.esp_at_signal\\n'\n            s += 'exp += struct.pack(\"<I\", 0x2b)       # sigframe.sc.ss # use 0x7b if 32bit native machine\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.fpstate # fpu/xmm are not restored if NULL\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.oldmask\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.sc.cr2\\n'\n            s += '\\n'\n        elif mode == \"arm\":\n            s += 'exp += struct.pack(\"<I\", pop_r7_pc)  # pop {r7, pc};\\n'\n            s += 'exp += struct.pack(\"<I\", 119)        # r7 = 119 (sigreturn)\\n'\n            s += 'exp += struct.pack(\"<I\", call_svc)   #\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_flags\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_link\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_stack.ss_sp\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_stack.ss_flags\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_stack.ss_size\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_mcontext.trapno\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_mcontext.error_code\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_mcontext.oldmask\\n'\n            s += 'exp += struct.pack(\"<I\", 0x00)       # sigframe.uc.uc_mcontext.arm_r0\\n'\n            s += 'exp += struct.pack(\"<I\", 0x01)       # sigframe.uc.uc_mcontext.arm_r1\\n'\n            s += 'exp += struct.pack(\"<I\", 0x02)       # sigframe.uc.uc_mcontext.arm_r2\\n'\n            s += 'exp += struct.pack(\"<I\", 0x03)       # sigframe.uc.uc_mcontext.arm_r3\\n'\n            s += 'exp += struct.pack(\"<I\", 0x04)       # sigframe.uc.uc_mcontext.arm_r4\\n'\n            s += 'exp += struct.pack(\"<I\", 0x05)       # sigframe.uc.uc_mcontext.arm_r5\\n'\n            s += 'exp += struct.pack(\"<I\", 0x06)       # sigframe.uc.uc_mcontext.arm_r6\\n'\n            s += 'exp += struct.pack(\"<I\", 0x07)       # sigframe.uc.uc_mcontext.arm_r7\\n'\n            s += 'exp += struct.pack(\"<I\", 0x08)       # sigframe.uc.uc_mcontext.arm_r8\\n'\n            s += 'exp += struct.pack(\"<I\", 0x09)       # sigframe.uc.uc_mcontext.arm_r9\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0a)       # sigframe.uc.uc_mcontext.arm_r10\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0b)       # sigframe.uc.uc_mcontext.arm_fp\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0c)       # sigframe.uc.uc_mcontext.arm_ip\\n'\n            s += 'exp += struct.pack(\"<I\", 0xdeadface) # sigframe.uc.uc_mcontext.arm_sp\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0d)       # sigframe.uc.uc_mcontext.arm_lr\\n'\n            s += 'exp += struct.pack(\"<I\", 0xdeadbeef) # sigframe.uc.uc_mcontext.arm_pc\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_mcontext.arm_cpsr\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_mcontext.fault_address\\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)        # sigframe.uc.uc_sigmask\\n'\n        elif mode == \"aarch64\":\n            s += 'exp += struct.pack(\"<Q\", ldp_x8_x9)  # ldp x8, x9, [sp], #16; ret x9;\\n'\n            s += 'exp += struct.pack(\"<Q\", 139)        # x8 = 139\\n'\n            s += 'exp += struct.pack(\"<Q\", call_svc)   # \\n'\n            s += 'exp += struct.pack(\"<I\", 0x0)*32     # rt_sigframe.info\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_flags\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_link\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_stack.ss_sp\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_stack.ss_flags\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_stack.ss_size\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_stack.__unused\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_sigmask\\n'\n            s += 'exp += struct.pack(\"<B\", 0x0)*120    # rt_sigframe.uc.__unused[120]\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0)        # rt_sigframe.uc.uc_mcontext.fault_address\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x00)       # rt_sigframe.uc.uc_mcontext.regs[31].x0\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x01)       # rt_sigframe.uc.uc_mcontext.regs[31].x1\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x02)       # rt_sigframe.uc.uc_mcontext.regs[31].x2\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x03)       # rt_sigframe.uc.uc_mcontext.regs[31].x3\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x04)       # rt_sigframe.uc.uc_mcontext.regs[31].x4\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x05)       # rt_sigframe.uc.uc_mcontext.regs[31].x5\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x06)       # rt_sigframe.uc.uc_mcontext.regs[31].x6\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x07)       # rt_sigframe.uc.uc_mcontext.regs[31].x7\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x08)       # rt_sigframe.uc.uc_mcontext.regs[31].x8\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x09)       # rt_sigframe.uc.uc_mcontext.regs[31].x9\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0a)       # rt_sigframe.uc.uc_mcontext.regs[31].x10\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0b)       # rt_sigframe.uc.uc_mcontext.regs[31].x11\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0c)       # rt_sigframe.uc.uc_mcontext.regs[31].x12\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0d)       # rt_sigframe.uc.uc_mcontext.regs[31].x13\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0e)       # rt_sigframe.uc.uc_mcontext.regs[31].x14\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x0f)       # rt_sigframe.uc.uc_mcontext.regs[31].x15\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x10)       # rt_sigframe.uc.uc_mcontext.regs[31].x16\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x11)       # rt_sigframe.uc.uc_mcontext.regs[31].x17\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x12)       # rt_sigframe.uc.uc_mcontext.regs[31].x18\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x13)       # rt_sigframe.uc.uc_mcontext.regs[31].x19\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x14)       # rt_sigframe.uc.uc_mcontext.regs[31].x20\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x15)       # rt_sigframe.uc.uc_mcontext.regs[31].x21\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x16)       # rt_sigframe.uc.uc_mcontext.regs[31].x22\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x17)       # rt_sigframe.uc.uc_mcontext.regs[31].x23\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x18)       # rt_sigframe.uc.uc_mcontext.regs[31].x24\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x19)       # rt_sigframe.uc.uc_mcontext.regs[31].x25\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x1a)       # rt_sigframe.uc.uc_mcontext.regs[31].x26\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x1b)       # rt_sigframe.uc.uc_mcontext.regs[31].x27\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x1c)       # rt_sigframe.uc.uc_mcontext.regs[31].x28\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x1d)       # rt_sigframe.uc.uc_mcontext.regs[31].x29\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x1e)       # rt_sigframe.uc.uc_mcontext.regs[31].x30\\n'\n            s += 'exp += struct.pack(\"<Q\", 0xdeadface) # rt_sigframe.uc.uc_mcontext.sp\\n'\n            s += 'exp += struct.pack(\"<Q\", 0xdeadbeef) # rt_sigframe.uc.uc_mcontext.pc\\n'\n            s += 'exp += struct.pack(\"<Q\", 0x00)       # rt_sigframe.uc.uc_mcontext.pstate\\n'\n        gef_print(s.rstrip())\n        return\n\n\n@register_command\nclass Ret2dlHintCommand(GenericCommand):\n    \"\"\"Hint for return-to-dl-resolve.\"\"\"\n\n    _cmdline_ = \"ret2dl-hint\"\n    _category_ = \"07-d. Misc - Show Example\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        s = \"\"\n        s += \"  +-.got/.got.plt @ itself---------+\\n\"\n        s += \"  | GOT[0]: _DYNAMIC               |\\n\"\n        s += \"  | GOT[1]: link_map               |\\n\"\n        s += \"  | GOT[2]: _dl_runtime_resolve@ld |\\n\"\n        s += \"  | GOT[3]: func1                  |\\n\"\n        s += \"  | GOT[4]: func2                  |\\n\"\n        s += \"  | GOT[5]: func3                  |\\n\"\n        s += \"  | ...                            |\\n\"\n        s += \"  +--------------------------------+\\n\"\n        s += \"\\n\"\n        s += \"If `link_map` and `_dl_runtime_resolve` are non-zero, just use them.\\n\"\n        s += \"If they are zero, you have to resolve them from DT_DEBUG entry of _DYNAMIC.\\n\"\n        s += \"\\n\"\n        s += \"  +-_DYNAMIC @ itself--------+     +---->+-r_debug----------+\\n\"\n        s += \"  | QWORD tag                |     |     | QWORD r_version  |\\n\"\n        s += \"  | QWORD value              |     |     | QWORD link_map   |<-- HERE\\n\"\n        s += \"  +--------------------------+     |     | QWORD r_brk      |\\n\"\n        s += \"  | ...                      |     |     | QWORD r_ldbase   |\\n\"\n        s += \"  +--------------------------+     |     +------------------+\\n\"\n        s += \"  | QWORD tag(0x15:DT_DEBUG) |     |\\n\"\n        s += \"  | QWORD value              |-----+\\n\"\n        s += \"  +--------------------------+\\n\"\n        s += \"\\n\"\n        s += \"  (binary itself)              (libc.so)                    (ld-linux.so)\\n\"\n        s += \"  +-link_map-----+     +------>+-link_map-----+     +------>+-link_map-----+\\n\"\n        s += \"  | QWORD l_addr |     |       | QWORD l_addr |     |       | QWORD l_addr |\\n\"\n        s += \"  | QWORD l_name |     |       | QWORD l_name |     |       | QWORD l_name |\\n\"\n        s += \"  | QWORD l_ld   |     |       | QWORD l_ld   |---+ |       | QWORD l_ld   |\\n\"\n        s += \"  | QWORD l_next |-----+       | QWORD l_next |---|-+       | QWORD l_next |\\n\"\n        s += \"  | QWORD l_prev |             | QWORD l_prev |   |         | QWORD l_prev |\\n\"\n        s += \"  +--------------+             +--------------+   |         +--------------+\\n\"\n        s += \"                                                  |\\n\"\n        s += \"   +----------------------------------------------+\\n\"\n        s += \"   |\\n\"\n        s += \"   +-->+-_DYNAMIC @ libc----------+   +-->+-.got/.got.plt @ libc-----------+\\n\"\n        s += \"       | QWORD tag                |   |   | GOT[0]: _DYNAMIC               |\\n\"\n        s += \"       | QWORD value              |   |   | GOT[1]: link_map               |\\n\"\n        s += \"       +--------------------------+   |   | GOT[2]: _dl_runtime_resolve@ld |<-- HERE\\n\"\n        s += \"       | ...                      |   |   | GOT[3]: func1                  |\\n\"\n        s += \"       +--------------------------+   |   | GOT[4]: func2                  |\\n\"\n        s += \"       | QWORD tag(0x3:DT_PLTGOT) |   |   | GOT[5]: func3                  |\\n\"\n        s += \"       | QWORD value              |---+   | ...                            |\\n\"\n        s += \"       +--------------------------+       +--------------------------------+\\n\"\n        s += \"\\n\"\n        s += \"\\n\"\n        s += \"  _dl_runtime_resolve@.plt.got(link_map, reloc_arg)\\n\"\n        s += \"    -> _dl_fixup@ld(link_map, reloc_arg)\\n\"\n        s += \"                                   |\\n\"\n        s += \"                                   |\\n\"\n        if is_32bit():\n            s = s.replace(\"QWORD\", \"DWORD\")\n            s += \"  +-------reloc_arg as offset------+\\n\"\n            s += \"  |\\n\"\n            s += \"  |   +-.rel.plt--------------------+              +-.dynsym------------+      +-.dynstr-------+\\n\"\n            s += \"  |   | DWORD r_offset              |              | DWORD st_name      |      | char[] symbol |\\n\"\n            s += \"  |   | DWORD r_info                |              | DWORD st_value     |      | char[] symbol |\\n\"\n            s += \"  |   +-----------------------------+              | DWORD st_size      |  +-->| char[] symbol |\\n\"\n            s += \"  +-->| DWORD r_offset              | (r_info>>8)  | BYTE  st_info      |  |   | char[] symbol |\\n\"\n            s += \"      |         =writable area      |        *0x10 | BYTE  st_other     |  |   | ...           |\\n\"\n            s += \"      | DWORD r_info                |-------+      | WORD  st_shndx     |  |   +---------------+\\n\"\n            s += \"      |         =(dynsym_idx<<8)|7  |       +----->+--------------------+  |\\n\"\n            s += \"      +-----------------------------+              | DWORD st_name      |--+\\n\"\n            s += \"      | ...                         |              | DWORD st_value     |\\n\"\n            s += \"      +-----------------------------+              | DWORD st_size      |\\n\"\n            s += \"                                                   | BYTE  st_info      |\\n\"\n            s += \"                                                   | BYTE  st_other(=0) |\\n\"\n            s += \"                                                   | WORD  st_shndx     |\\n\"\n            s += \"                                                   +--------------------+\\n\"\n            s += \"                                                   | ...                |\\n\"\n            s += \"                                                   +--------------------+\\n\"\n        else:\n            s += \"  +---reloc_arg * 0x18 as offset---+\\n\"\n            s += \"  |\\n\"\n            s += \"  |   +-.rela.plt-------------------+              +-.dynsym------------+      +-.dynstr-------+\\n\"\n            s += \"  |   | QWORD r_offset              |              | DWORD st_name      |      | char[] symbol |\\n\"\n            s += \"  |   | QWORD r_info                |              | BYTE  st_info      |      | char[] symbol |\\n\"\n            s += \"  |   | QWORD r_addend              |              | BYTE  st_other     |  +-->| char[] symbol |\\n\"\n            s += \"  +-->+-----------------------------+              | WORD  st_shndx     |  |   | char[] symbol |\\n\"\n            s += \"      | QWORD r_offset              | (r_info>>32) | QWORD st_value     |  |   | ...           |\\n\"\n            s += \"      |         =writable area      |        *0x18 | QWORD st_size      |  |   +---------------+\\n\"\n            s += \"      | QWORD r_info                |------------->+--------------------+  |\\n\"\n            s += \"      |         =(dynsym_idx<<32)|7 |              | DWORD st_name      |--+\\n\"\n            s += \"      | QWORD r_addend              |              | BYTE  st_info      |\\n\"\n            s += \"      +-----------------------------+              | BYTE  st_other(=0) |\\n\"\n            s += \"      | ...                         |              | WORD  st_shndx     |\\n\"\n            s += \"      +-----------------------------+              | QWORD st_value     |\\n\"\n            s += \"                                                   | QWORD st_size      |\\n\"\n            s += \"                                                   +--------------------+\\n\"\n            s += \"                                                   | ...                |\\n\"\n            s += \"                                                   +--------------------+\\n\"\n        s += \"\\n\"\n        s += \"Use `dynamic` and `link-map` to display the structure.\\n\"\n        gef_print(s.rstrip())\n        return\n\n\n@register_command\nclass LinkMapCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump useful members of link_map with iterating.\"\"\"\n\n    _cmdline_ = \"link-map\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-e\", dest=\"elf_address\", type=AddressUtil.parse_address,\n                       help=\"the ELF address to parse.\")\n    group.add_argument(\"-l\", dest=\"link_map_address\", type=AddressUtil.parse_address,\n                       help=\"the link_map address to parse.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                    # dump itself\",\n        \"{0:s} -e 0x555555554000  # dump specified address as ELF\",\n        \"{0:s} -l 0x7ffff7ffe2e0  # dump specified address as link_map\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def dump_link_map(self, link_map):\n        if link_map is None:\n            info(\"Could not find link_map\")\n            return\n\n        info(\"link_map: {!s} [{!s}]\".format(link_map, link_map.section.permission))\n\n        # elf/link.h\n        members = [\"l_addr\", \"l_name\", \"l_ld\", \"l_next\", \"l_prev\"]\n\n        if self.verbose:\n            # elf/elf.h\n            # The glibc version is assumed to be identifiable.\n            # Note that static binaries do not have a link-map, so it does not need to be considered.\n            if get_libc_version() >= (2, 36):\n                DT_NUM = 38\n            else:\n                DT_NUM = 35\n            # Note that the number of elements in an array varies depending on the architecture.\n            DT_THISPROCNUM, ARCH_SPECIFIC_DT_TABLE = DynamicCommand.get_ARCH_SPECIFIC_DT_TABLE()\n            # These values do not change between versions or architectures.\n            DT_VERSIONTAGNUM = 16\n            DT_EXTRANUM = 3\n            DT_VALNUM = 12\n            DT_ADDRNUM = 11\n\n            DT_TABLE = DynamicCommand.get_DT_TABLE()\n\n            # include/link.h\n            l_info_length = DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM\n\n            # include/link.h\n            members += [\"l_real\", \"l_ns\", \"l_libname\"]\n            for i in range(l_info_length):\n                mb = \"l_info[{:d}]\".format(i)\n                if i < DT_NUM:\n                    tag = i\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                elif i < DT_NUM + DT_THISPROCNUM:\n                    tag = 0x7000_0000 + (i - DT_NUM)\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                elif i < DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM:\n                    tag = 0x6fff_ffff - (i - (DT_NUM + DT_THISPROCNUM))\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                elif i < DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM:\n                    tag = 0x7fff_ffff - (i - (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM))\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                elif i < DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM:\n                    tag = 0x6fff_fdff - (i - (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM))\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                elif i < DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM:\n                    tag = 0x6fff_feff - (i - (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM))\n                    mb += \"(={:s})\".format(DT_TABLE.get(tag, \"???\"))\n                members.append(mb)\n            members += [\"l_phdr\", \"l_entry\", \"l_ldnum || l_phnum\"]\n\n        tag_maxlen = max(len(x) for x in members) + 1\n\n        current = link_map.value\n        while True:\n            l_name = ProcessMap.lookup_address(read_int_from_memory(current + current_arch.ptrsize * 1))\n            name = read_cstring_from_memory(l_name.value)\n            l_next = ProcessMap.lookup_address(read_int_from_memory(current + current_arch.ptrsize * 3))\n\n            if not name:\n                if Path.get_filepath():\n                    name = \"(binary itself: {:s})\".format(Path.get_filepath())\n                else:\n                    name = \"(binary itself)\"\n            self.out.append(titlify(name))\n\n            for i, tag in enumerate(members):\n                line = DereferenceCommand.pprint_dereferenced(current, i, tag.ljust(tag_maxlen))\n                self.out.append(line)\n\n            if l_next.value == 0:\n                break\n            current = l_next.value\n        return\n\n    @staticmethod\n    def get_link_map(filename_or_addr=None, silent=False):\n        if not filename_or_addr:\n            # fast path\n            try:\n                link_map = AddressUtil.parse_address(\"(void*) _rtld_global\")\n                link_map = ProcessMap.lookup_address(link_map)\n                return link_map\n            except gdb.error:\n                pass\n\n        # slow path\n        dynamic = DynamicCommand.get_dynamic(filename_or_addr, silent)\n        DT_TABLE = DynamicCommand.get_DT_TABLE()\n        if dynamic is None:\n            return None\n\n        current = dynamic.value\n        while True:\n            tag = read_int_from_memory(current)\n            current += current_arch.ptrsize\n            val = ProcessMap.lookup_address(read_int_from_memory(current))\n            current += current_arch.ptrsize\n            if tag not in DT_TABLE:\n                if not silent:\n                    info(\"Could not find link_map\")\n                return None\n            if DT_TABLE[tag] == \"DT_DEBUG\":\n                dt_debug = val\n                val_addr = ProcessMap.lookup_address(current - current_arch.ptrsize)\n                val_addr_offset = val_addr.value - dynamic.value\n                if not silent:\n                    info(\"_DYNAMIC+{:#x}(=DT_DEBUG): {!s} -> {!s}\".format(\n                        val_addr_offset, val_addr, dt_debug,\n                    ))\n                link_map_ptr = ProcessMap.lookup_address(dt_debug.value + current_arch.ptrsize)\n                if not is_valid_addr(link_map_ptr.value):\n                    return None\n                link_map = ProcessMap.lookup_address(read_int_from_memory(link_map_ptr.value))\n                if not silent:\n                    info(\"DT_DEBUG+{:#x}: {!s} -> {!s}\".format(\n                        current_arch.ptrsize, link_map_ptr, link_map,\n                    ))\n                break\n        return link_map\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        Cache.reset_gef_caches(all=True)\n\n        self.verbose = False\n        if args.verbose:\n            res = gdb.execute(\"libc\", to_string=True)\n            if \"GNU C Library\" in res:\n                self.verbose = True\n\n        if args.link_map_address:\n            link_map = ProcessMap.lookup_address(args.link_map_address)\n        else:\n            try:\n                link_map = self.get_link_map(args.elf_address)\n            except gdb.error:\n                err(\"Failed to get link_map\")\n                return\n\n        self.out = []\n        try:\n            self.dump_link_map(link_map)\n        except Exception:\n            err(\"Failed to parse link_map\")\n            return\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass DynamicCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display current status of the _DYNAMIC area.\"\"\"\n\n    _cmdline_ = \"dynamic\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-f\", dest=\"filename\", help=\"the filename to parse.\")\n    group.add_argument(\"-e\", dest=\"elf_address\", type=AddressUtil.parse_address,\n                       help=\"the ELF address to parse.\")\n    group.add_argument(\"-d\", dest=\"dynamic_address\", type=AddressUtil.parse_address,\n                       help=\"the dynamic address to parse.\")\n    parser.add_argument(\"--size\", dest=\"dynamic_size\", type=AddressUtil.parse_address,\n                        help=\"use specified size of dynamic region.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                                         # dump itself\",\n        \"{0:s} -f /usr/lib/x86_64-linux-gnu/libc.so.6  # dump specified binary\",\n        \"{0:s} -e 0x555555554000                       # dump specified address as ELF\",\n        \"{0:s} -d 0x555555575a98                       # dump specified address as dynamic\",\n        \"{0:s} -d 0x555555575a98 --size 0x1c0          # dump specified address with specified size\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    DT_TABLE = {\n        0: \"DT_NULL\",\n        1: \"DT_NEEDED\",\n        2: \"DT_PLTRELSZ\",\n        3: \"DT_PLTGOT\",\n        4: \"DT_HASH\",\n        5: \"DT_STRTAB\",\n        6: \"DT_SYMTAB\",\n        7: \"DT_RELA\",\n        8: \"DT_RELASZ\",\n        9: \"DT_RELAENT\",\n        10: \"DT_STRSZ\",\n        11: \"DT_SYMENT\",\n        12: \"DT_INIT\",\n        13: \"DT_FINI\",\n        14: \"DT_SONAME\",\n        15: \"DT_RPATH\",\n        16: \"DT_SYMBOLIC\",\n        17: \"DT_REL\",\n        18: \"DT_RELSZ\",\n        19: \"DT_RELENT\",\n        20: \"DT_PLTREL\",\n        21: \"DT_DEBUG\",\n        22: \"DT_TEXTREL\",\n        23: \"DT_JMPREL\",\n        24: \"DT_BIND_NOW\",\n        25: \"DT_INIT_ARRAY\",\n        26: \"DT_FINI_ARRAY\",\n        27: \"DT_INIT_ARRAYSZ\",\n        28: \"DT_FINI_ARRAYSZ\",\n        29: \"DT_RUNPATH\",\n        30: \"DT_FLAGS\",\n        #32: \"DT_ENCODING\", # unspecified\n        32: \"DT_PREINIT_ARRAY\",\n        33: \"DT_PREINIT_ARRAYSZ\",\n        34: \"DT_SYMTAB_SHNDX\",\n        35: \"DT_RELRSZ\",\n        36: \"DT_RELR\",\n        37: \"DT_RELRENT\",\n        #0x6000000d: \"DT_LOOS\", # unspecified\n        0x6000000e: \"DT_SUNW_RTLDINF\",\n        0x6000000f: \"DT_ANDROID_REL\",\n        0x60000010: \"DT_ANDROID_RELSZ\",\n        0x60000011: \"DT_ANDROID_RELA\",\n        0x60000012: \"DT_ANDROID_RELASZ\",\n        0x6fffe000: \"DT_ANDROID_RELR\",\n        0x6fffe001: \"DT_ANDROID_RELRSZ\",\n        0x6fffe003: \"DT_ANDROID_RELRENT\",\n        0x6fffe005: \"DT_ANDROID_RELRCOUNT\",\n        #0x6ffff000: \"DT_HIOS\", # unspecified\n        #0x6ffffd00: \"DT_VALRNGLO\", # unspecified\n        0x6ffffdf5: \"DT_GNU_PRELINKED\",\n        0x6ffffdf6: \"DT_GNU_CONFLICTSZ\",\n        0x6ffffdf7: \"DT_GNU_LIBLISTSZ\",\n        0x6ffffdf8: \"DT_CHECKSUM\",\n        0x6ffffdf9: \"DT_PLTPADSZ\",\n        0x6ffffdfa: \"DT_MOVEENT\",\n        0x6ffffdfb: \"DT_MOVESZ\",\n        0x6ffffdfc: \"DT_FEATURE_1\",\n        0x6ffffdfd: \"DT_POSFLAG_1\",\n        0x6ffffdfe: \"DT_SYMINSZ\",\n        0x6ffffdff: \"DT_SYMINENT\",\n        #0x6ffffdff: \"DT_VALRNGHI\", # unspecified\n        #0x6ffffe00: \"DT_ADDRRNGLO\", # unspecified\n        0x6ffffef5: \"DT_GNU_HASH\",\n        0x6ffffef6: \"DT_TLSDESC_PLT\",\n        0x6ffffef7: \"DT_TLSDESC_GOT\",\n        0x6ffffef8: \"DT_GNU_CONFLICT\",\n        0x6ffffef9: \"DT_GNU_LIBLIST\",\n        0x6ffffefa: \"DT_CONFIG\",\n        0x6ffffefb: \"DT_DEPAUDIT\",\n        0x6ffffefc: \"DT_AUDIT\",\n        0x6ffffefd: \"DT_PLTPAD\",\n        0x6ffffefe: \"DT_MOVETAB\",\n        0x6ffffeff: \"DT_SYMINFO\",\n        #0x6ffffeff: \"DT_ADDRRNGHI\", # unspecified\n        0x6ffffff0: \"DT_VERSYM\",\n        0x6ffffff9: \"DT_RELACOUNT\",\n        0x6ffffffa: \"DT_RELCOUNT\",\n        0x6ffffffb: \"DT_FLAGS_1\",\n        0x6ffffffc: \"DT_VERDEF\",\n        0x6ffffffd: \"DT_VERDEFNUM\",\n        0x6ffffffe: \"DT_VERNEED\",\n        0x6fffffff: \"DT_VERNEEDNUM\",\n        #0x70000000: \"DT_LOPROC\", # unspecified\n        0x7ffffffd: \"DT_AUXILIARY\",\n        0x7ffffffe: \"DT_USED\",\n        0x7fffffff: \"DT_FILTER\",\n        #0x7fffffff: \"DT_HIPROC\", # unspecified\n    }\n\n    ARCH_SPECIFIC_DT_TABLE = {\n        \"arm64\": {\n            0x70000001: \"DT_AARCH64_BTI_PLT\",\n            0x70000003: \"DT_AARCH64_PAC_PLT\",\n            0x70000005: \"DT_AARCH64_VARIANT_PCS\",\n        },\n        \"alpha\": {\n            0x70000000: \"DT_ALPHA_PLTRO\",\n        },\n        \"mips\": {\n            0x70000001: \"DT_MIPS_RLD_VERSION\",\n            0x70000002: \"DT_MIPS_TIME_STAMP\",\n            0x70000003: \"DT_MIPS_ICHECKSUM\",\n            0x70000004: \"DT_MIPS_IVERSION\",\n            0x70000005: \"DT_MIPS_FLAGS\",\n            0x70000006: \"DT_MIPS_BASE_ADDRESS\",\n            0x70000007: \"DT_MIPS_MSYM\",\n            0x70000008: \"DT_MIPS_CONFLICT\",\n            0x70000009: \"DT_MIPS_LIBLIST\",\n            0x7000000a: \"DT_MIPS_LOCAL_GOTNO\",\n            0x7000000b: \"DT_MIPS_CONFLICTNO\",\n            0x70000010: \"DT_MIPS_LIBLISTNO\",\n            0x70000011: \"DT_MIPS_SYMTABNO\",\n            0x70000012: \"DT_MIPS_UNREFEXTNO\",\n            0x70000013: \"DT_MIPS_GOTSYM\",\n            0x70000014: \"DT_MIPS_HIPAGENO\",\n            0x70000016: \"DT_MIPS_RLD_MAP\",\n            0x70000017: \"DT_MIPS_DELTA_CLASS\",\n            0x70000018: \"DT_MIPS_DELTA_CLASS_NO\",\n            0x70000019: \"DT_MIPS_DELTA_INSTANCE\",\n            0x7000001a: \"DT_MIPS_DELTA_INSTANCE_NO\",\n            0x7000001b: \"DT_MIPS_DELTA_RELOC\",\n            0x7000001c: \"DT_MIPS_DELTA_RELOC_NO\",\n            0x7000001d: \"DT_MIPS_DELTA_SYM\",\n            0x7000001e: \"DT_MIPS_DELTA_SYM_NO\",\n            0x70000020: \"DT_MIPS_DELTA_CLASSSYM\",\n            0x70000021: \"DT_MIPS_DELTA_CLASSSYM_NO\",\n            0x70000022: \"DT_MIPS_CXX_FLAGS\",\n            0x70000023: \"DT_MIPS_PIXIE_INIT\",\n            0x70000024: \"DT_MIPS_SYMBOL_LIB\",\n            0x70000025: \"DT_MIPS_LOCALPAGE_GOTIDX\",\n            0x70000026: \"DT_MIPS_LOCAL_GOTIDX\",\n            0x70000027: \"DT_MIPS_HIDDEN_GOTIDX\",\n            0x70000028: \"DT_MIPS_PROTECTED_GOTIDX\",\n            0x70000029: \"DT_MIPS_OPTIONS\",\n            0x7000002a: \"DT_MIPS_INTERFACE\",\n            0x7000002b: \"DT_MIPS_DYNSTR_ALIGN\",\n            0x7000002c: \"DT_MIPS_INTERFACE_SIZE\",\n            0x7000002d: \"DT_MIPS_RLD_TEXT_RESOLVE_ADDR\",\n            0x7000002e: \"DT_MIPS_PERF_SUFFIX\",\n            0x7000002f: \"DT_MIPS_COMPACT_SIZE\",\n            0x70000030: \"DT_MIPS_GP_VALUE\",\n            0x70000031: \"DT_MIPS_AUX_DYNAMIC\",\n            0x70000032: \"DT_MIPS_PLTGOT\",\n            0x70000034: \"DT_MIPS_RWPLT\",\n            0x70000035: \"DT_MIPS_RLD_MAP_REL\",\n            0x70000036: \"DT_MIPS_XHASH\",\n        },\n        \"nios2\": {\n            0x70000002: \"DT_NIOS2_GP\",\n        },\n        \"ppc32\": {\n            0x70000000: \"DT_PPC_GOT\",\n            0x70000001: \"DT_PPC_OPT\",\n        },\n        \"ppc64\": {\n            0x70000000: \"DT_PPC64_GLINK\",\n            0x70000001: \"DT_PPC64_OPD\",\n            0x70000002: \"DT_PPC64_OPDSZ\",\n            0x70000003: \"DT_PPC64_OPT\",\n        },\n        \"riscv\": {\n            0x70000001: \"DT_RISCV_VARIANT_CC\",\n        },\n        \"sparc\": {\n            0x70000001: \"DT_SPARC_REGISTER\",\n        },\n        \"x86-64\": {\n            0x70000000: \"DT_X86_64_PLT\",\n            0x70000001: \"DT_X86_64_PLTSZ\",\n            0x70000003: \"DT_X86_64_PLTENT\",\n        },\n        \"xtensa\": {\n            0x70000000: \"DT_XTENSA_GOT_LOC_OFF\",\n            0x70000001: \"DT_XTENSA_GOT_LOC_SZ\",\n        },\n    }\n\n    @staticmethod\n    def get_ARCH_SPECIFIC_DT_TABLE():\n        # default value\n        DT_THISPROCNUM = 0\n        ARCH_SPECIFIC_DT_TABLE = {}\n\n        # Considering glibc 2.20 and later\n        if is_arm64():\n            if get_libc_version() >= (2, 33):\n                DT_THISPROCNUM = 6\n                ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"arm64\"]\n        elif is_alpha():\n            DT_THISPROCNUM = 1\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"alpha\"]\n        elif is_mips32() or is_mips64() or is_mipsn32():\n            if get_libc_version() >= (2, 31):\n                DT_THISPROCNUM = 0x37\n            elif get_libc_version() >= (2, 22):\n                DT_THISPROCNUM = 0x36\n            else:\n                DT_THISPROCNUM = 0x35\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"mips\"] # 2.20~\n        elif is_nios2():\n            # DT_THISPROCNUM is not changed\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"nios2\"]\n        elif is_ppc32():\n            if get_libc_version() >= (2, 22):\n                DT_THISPROCNUM = 2\n            else:\n                DT_THISPROCNUM = 1\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"ppc32\"]\n        elif is_ppc64():\n            DT_THISPROCNUM = 4\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"ppc64\"]\n        elif is_riscv32() or is_riscv64():\n            if get_libc_version() >= (2, 36):\n                # DT_THISPROCNUM is not changed\n                ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"riscv\"]\n        elif is_sparc32() or is_sparc32plus() or is_sparc64():\n            DT_THISPROCNUM = 2\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"sparc\"]\n        elif is_x86_64():\n            if get_libc_version() >= (2, 39):\n                DT_THISPROCNUM = 4\n                ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"x86-64\"]\n        elif is_xtensa():\n            # DT_THISPROCNUM is not changed\n            ARCH_SPECIFIC_DT_TABLE = DynamicCommand.ARCH_SPECIFIC_DT_TABLE[\"xtensa\"]\n        return DT_THISPROCNUM, ARCH_SPECIFIC_DT_TABLE\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_DT_TABLE():\n        _, ARCH_SPECIFIC_DT_TABLE = DynamicCommand.get_ARCH_SPECIFIC_DT_TABLE()\n        return DynamicCommand.DT_TABLE | ARCH_SPECIFIC_DT_TABLE\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def dump_dynamic(self, dynamic, remain_size):\n        base_address_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n\n        if dynamic is None:\n            info(\"Could not find _DYNAMIC\")\n            return\n\n        width = AddressUtil.get_format_address_width()\n\n        fmt = \"{:{:d}s}  {:{:d}s} {:{:d}s}     {:s}\"\n        legend = [\"Address\", width, \"Tag\", width, \"Value\", width, \"TagName\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        DT_TABLE = DynamicCommand.get_DT_TABLE()\n\n        current = dynamic.value\n        while True:\n            addr = current\n            tag = read_int_from_memory(current)\n            current += current_arch.ptrsize\n            val = read_int_from_memory(current)\n            current += current_arch.ptrsize\n\n            if remain_size is None:\n                if tag not in DT_TABLE:\n                    break\n            else:\n                remain_size -= current_arch.ptrsize * 2\n\n            val = ProcessMap.lookup_address(val)\n            tag_description = DT_TABLE.get(tag, \"Unknown\")\n            colored_addr = Color.colorify(\"{:#0{:d}x}\".format(addr, width), base_address_color)\n            self.out.append(\"{:s}: {:#0{:d}x} {!s}  |  {:s}\".format(\n                colored_addr, tag, width, val, tag_description,\n            ))\n\n            if remain_size is not None and remain_size <= 0:\n                break\n        return\n\n    @staticmethod\n    def get_dynamic(filename_or_addr=None, silent=False):\n        if not filename_or_addr:\n            # fast path\n            try:\n                dynamic = AddressUtil.parse_address(\"(void*) &_DYNAMIC\")\n                dynamic = ProcessMap.lookup_address(dynamic)\n                return dynamic\n            except gdb.error:\n                pass\n\n            # prepare slow path\n            filename_or_addr = Path.get_filepath()\n            if filename_or_addr is None:\n                if not silent:\n                    err(\"Failed to get filename\")\n                return None\n\n        # slow path\n        if isinstance(filename_or_addr, str):\n            # use as filename\n            if not silent:\n                info(\"filename: {:s}\".format(filename_or_addr))\n\n            if not os.path.exists(filename_or_addr):\n                if not silent:\n                    err(\"Could not find {:s}\".format(filename_or_addr))\n                return None\n\n            elf = Elf.get_elf(filename_or_addr)\n            if elf is None or not elf.is_valid():\n                if not silent:\n                    err(\"Invalid ELF\")\n                return None\n\n            if not elf.has_dynamic():\n                if not silent:\n                    info(\"The binary has no _DYNAMIC\")\n                return None\n\n            if ProcessMap.get_section_base_address(filename_or_addr) is None:\n                if not silent:\n                    err(\"{:s} is not loaded\".format(filename_or_addr))\n                return None\n        else:\n            # use as address\n            if not silent:\n                info(\"address: {:#x}\".format(filename_or_addr))\n\n            try:\n                elf = Elf.get_elf(filename_or_addr)\n            except gdb.MemoryError:\n                if not silent:\n                    err(\"Memory read error\")\n                return None\n            if elf is None or not elf.is_valid():\n                if not silent:\n                    err(\"Invalid ELF\")\n                return None\n\n        phdr = elf.get_phdr(Elf.Phdr.PT_DYNAMIC)\n        if phdr is None:\n            return None\n\n        if isinstance(filename_or_addr, str):\n            if elf.is_pie():\n                load_base = ProcessMap.get_section_base_address(filename_or_addr)\n                dynamic = phdr.p_vaddr + load_base\n            else:\n                dynamic = phdr.p_vaddr\n        else:\n            if phdr.p_vaddr < filename_or_addr:\n                dynamic = phdr.p_vaddr + filename_or_addr\n            else:\n                dynamic = phdr.p_vaddr\n\n        dynamic = ProcessMap.lookup_address(dynamic)\n        if not silent:\n            info(\"_DNYAMIC: {!s} [{!s}]\".format(dynamic, dynamic.section.permission))\n        return dynamic\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.dynamic_address:\n            dynamic = ProcessMap.lookup_address(args.dynamic_address)\n        else:\n            try:\n                dynamic = self.get_dynamic(args.elf_address or args.filename)\n            except gdb.error:\n                err(\"Failed to get _DYNAMIC\")\n                return\n\n        self.out = []\n        try:\n            self.dump_dynamic(dynamic, args.dynamic_size)\n        except Exception:\n            err(\"Failed to parse _DYNAMIC\")\n            return\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass DestructorDumpCommand(GenericCommand):\n    \"\"\"Display registered destructor functions.\"\"\"\n\n    _cmdline_ = \"dtor-dump\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-f\", \"--file\", help=\"the file path to parse.\")\n    parser.add_argument(\"--tdl\", type=AddressUtil.parse_address,\n                        help=\"specify the offset of `tls_dtor_list` from TLS base.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} --tdl 0x50                # specify offset of tls_dtor_list\",\n        \"{0:s} --tdl 0xffffffffffffffa8  # specify negative offset\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def C(self, addr):\n        base_address_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n        a = Color.colorify(\"{:#0{:d}x}\".format(\n            addr, AddressUtil.get_format_address_width(),\n        ), base_address_color)\n        try:\n            b = \"[{!s}]\".format(ProcessMap.lookup_address(addr).section.permission)\n            return a + b\n        except Exception:\n            return a + \"[???]\"\n\n    \"\"\"\n    glibc 2.37~\n\n    x86_32: dynamic symboled: linkmap-relative\n    x86_32: dynamic stripped: linkmap-relative\n    x86_32: static symboled: msymbols\n    x86_32: static stripped: heuristic\n\n    x86_64: dynamic symboled: linkmap-relative\n    x86_64: dynamic stripped: linkmap-relative\n    x86_64: static symboled: msymbols\n    x86_64: static stripped: heuristic\n\n    arm32: dynamic symboled: linkmap-relative\n    arm32: dynamic stripped: linkmap-relative\n    arm32: static symboled: msymbols\n    arm32: static stripped: heuristic\n\n    arm64: dynamic symboled: linkmap-relative\n    arm64: dynamic stripped: linkmap-relative\n    arm64: static symboled: msymbols\n    arm64: static stripped: heuristic\n\n    sparc64: dynamic symboled: linkmap-relative\n    sparc64: dynamic stripped: linkmap-relative\n    sparc64: static symboled: msymbols\n    sparc64: static stripped: heuristic\n\n    s390x: dynamic symboled: linkmap-relative\n    s390x: dynamic stripped: linkmap-relative\n    s390x: static symboled: msymbols\n    s390x: static stripped: heuristic\n\n    loongarch64: dynamic symboled: linkmap-relative\n    loongarch64: dynamic stripped: linkmap-relative\n    loongarch64: static symboled: msymbols\n    loongarch64: static stripped: heuristic\n\n    sh4: dynamic symboled: heuristic (link_map is not in TLS)\n    sh4: dynamic stripped: heuristic (link_map is not in TLS)\n    sh4: static symboled: msymbols\n    sh4: static stripped: heuristic\n\n    ppc32: dynamic symboled: heuristic (link_map is not in TLS)\n    ppc32: dynamic stripped: heuristic (link_map is not in TLS)\n    ppc32: static symboled: heuristic\n    ppc32: static stripped: heuristic\n\n    ppc64: dynamic symboled: heuristic (link_map is not in TLS)\n    ppc64: dynamic stripped: heuristic (link_map is not in TLS)\n    ppc64: static symboled: msymbols\n    ppc64: static stripped: heuristic\n\n    nios2: dynamic symboled: heuristic (link_map is not in TLS)\n    nios2: dynamic stripped: heuristic (link_map is not in TLS)\n    nios2: static symboled: msymbols\n    nios2: static stripped: heuristic\n\n    alpha: dynamic symboled: heuristic (link_map is not in TLS)\n    alpha: dynamic stripped: heuristic (link_map is not in TLS)\n    alpha: static symboled: msymbols\n    alpha: static stripped: heuristic\n\n    riscv64: dynamic symboled: linkmap-relative\n    riscv64: dynamic stripped: linkmap-relative\n    riscv64: static symboled: msymbols\n    riscv64: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    riscv32: dynamic symboled: linkmap-relative\n    riscv32: dynamic stripped: linkmap-relative\n    riscv32: static symboled: msymbols\n    riscv32: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    or1k: dynamic symboled: linkmap-relative\n    or1k: dynamic stripped: linkmap-relative\n    or1k: static symboled: msymbols\n    or1k: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    arc32: dynamic symboled: linkmap-relative\n    arc32: dynamic stripped: linkmap-relative\n    arc32: static symboled: msymbols\n    arc32: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    m68k: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    m68k: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    m68k: static symboled: msymbols\n    m68k: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    mips32: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    mips32: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    mips32: static symboled: msymbols\n    mips32: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    mips64: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    mips64: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    mips64: static symboled: msymbols\n    mips64: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    hppa32: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    hppa32: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    hppa32: static symboled: msymbols\n    hppa32: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    microblaze: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    microblaze: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    microblaze: static symboled: msymbols\n    microblaze: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    arc64: dynamic symboled: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    arc64: dynamic stripped: NG (link_map is not in TLS and PTR_MANGLE is no-XOR)\n    arc64: static symboled: msymbols\n    arc64: static stripped: NG (PTR_MANGLE is no-XOR)\n\n    csky: dynamic symboled: ???\n    csky: dynamic stripped: ???\n    csky: static symboled: msymbols\n    csky: static stripped: heuristic\n    \"\"\"\n\n    def get_dtor_list_from_msymbols(self):\n        # Statically linked binaries cannot resolve the address of thread-local storage variables.\n        # Therefore, identify it from the output of the msymbols command and the offset of thread_arena.\n\n        # thread_arena address of main thread\n        main_thread_main_arena = GlibcHeap.search_for_main_arena_from_tls()\n        if main_thread_main_arena is None:\n            return None\n\n        # thread_arena offset from .tbss\n        ret = gdb.execute(\"maintenance print msymbols\", to_string=True)\n        m = re.search(r\"(0x\\S+) thread_arena section .tbss\", ret)\n        if not m:\n            return None\n        thread_arena_offset = int(m.group(1), 16)\n\n        # tls_dtor_list offset from .tbss\n        m = re.search(r\"(0x\\S+) tls_dtor_list section .tbss\", ret)\n        if not m:\n            return None\n        tls_dtor_list_offset = int(m.group(1), 16)\n\n        # tls_dtor_list offset from TLS\n        main_thread_tbss_base = main_thread_main_arena - thread_arena_offset\n        main_thread_tls_dtor_list = main_thread_tbss_base + tls_dtor_list_offset\n\n        # TLS address of main thread\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        main_thread = [th for th in threads if th.num == 1][0]\n        main_thread.switch() # switch temporarily\n        main_tls = current_arch.get_tls()\n        orig_thread.switch() # revert thread\n        orig_frame.select()\n\n        # tls_dotr_list of current thread\n        tls_dtor_list = main_thread_tls_dtor_list - main_tls + current_arch.get_tls()\n        return tls_dtor_list\n\n    def get_dtor_list_from_linkmap_relative(self):\n        if self.codebase is None:\n            return None\n\n        direction = TlsCommand.get_direction()\n\n        \"\"\"\n        --- TLS-0x80 ---\n        0x7ffff7fa06c0|+0x0000|+000: 0x0000000000000000\n        0x7ffff7fa06c8|+0x0008|+001: 0x00007ffff7d9b4c0 <_nl_C_LC_CTYPE_tolower+0x200>  ->  0x0000000100000000\n        0x7ffff7fa06d0|+0x0010|+002: 0x00007ffff7d9bac0 <_nl_C_LC_CTYPE_toupper+0x200>  ->  0x0000000100000000\n        0x7ffff7fa06d8|+0x0018|+003: 0x00007ffff7d9c3c0 <_nl_C_LC_CTYPE_class+0x100>  ->  0x0002000200020002\n        0x7ffff7fa06e0|+0x0020|+004: 0x00007ffff7ffe2c0  ->  0x0000555555554000  ->  0x00010102464c457f <- link_map\n        0x7ffff7fa06e8|+0x0028|+005: 0x00005555555592a0  ->  0x3c56fdd6341540d8                         <- tls_dtor_list\n        0x7ffff7fa06f0|+0x0030|+006: 0x0000000000000000\n        0x7ffff7fa06f8|+0x0038|+007: 0x0000555555559010  ->  0x0000000000000000\n        0x7ffff7fa0700|+0x0040|+008: 0x0000000000000000\n        0x7ffff7fa0708|+0x0048|+009: 0x00007ffff7df6c80 <main_arena>  ->  0x0000000000000000\n        0x7ffff7fa0710|+0x0050|+010: 0x0000000000000000\n        0x7ffff7fa0718|+0x0058|+011: 0x0000000000000000\n        0x7ffff7fa0720|+0x0060|+012: 0x0000000000000000\n        0x7ffff7fa0728|+0x0068|+013: 0x0000000000000000\n        0x7ffff7fa0730|+0x0070|+014: 0x0000000000000000\n        0x7ffff7fa0738|+0x0078|+015: 0x0000000000000000\n        --- TLS ---\n        ...\n        \"\"\"\n        tls = current_arch.get_tls()\n        for i in range(1, 16):\n            addr = tls + (current_arch.ptrsize * i) * direction\n\n            if not is_valid_addr(addr):\n                break\n\n            candidate_link_map = read_int_from_memory(addr)\n            if not is_valid_addr(candidate_link_map):\n                continue\n\n            candidate_codebase = read_int_from_memory(candidate_link_map)\n            if candidate_codebase == self.codebase:\n                # found\n                if is_s390x():\n                    tls_dtor_list = tls + (current_arch.ptrsize * (i + 1)) * direction\n                else:\n                    tls_dtor_list = tls + (current_arch.ptrsize * (i - 1)) * direction\n                if is_valid_addr(tls_dtor_list):\n                    # maybe valid\n                    return tls_dtor_list\n                else:\n                    # invalid\n                    return None\n        return None\n\n    def get_dtor_list_from_heuristic(self):\n        direction = TlsCommand.get_direction()\n\n        \"\"\"\n        --- TLS-0x80 ---\n        0x0000004af340|+0x0000|+000: 0x0000000000000000\n        0x0000004af348|+0x0008|+001: 0x0000000000000000\n        0x0000004af350|+0x0010|+002: 0x00000000004a83e0  ->  0x00000000004a4ae0  ->  0x000000000047e150  ->  ...\n        0x0000004af358|+0x0018|+003: 0x00000000004a83e8  ->  0x00000000004a5020  ->  0x000000000047e150  ->  ...\n        0x0000004af360|+0x0020|+004: 0x00000000004a83e0  ->  0x00000000004a4ae0  ->  0x000000000047e150  ->  ...\n        0x0000004af368|+0x0028|+005: 0x0000000000000000  <-  $r13\n        0x0000004af370|+0x0030|+006: 0x0000000000000000\n        0x0000004af378|+0x0038|+007: 0x0000000000000000\n        0x0000004af380|+0x0040|+008: 0x00000000004b0210  ->  0xac500ef775892689  <- tls_dtor_list\n        0x0000004af388|+0x0048|+009: 0x00000000004afd50  ->  0x0000000000000000\n        0x0000004af390|+0x0050|+010: 0x0000000000000000\n        0x0000004af398|+0x0058|+011: 0x00000000004a71e0  ->  0x0000000000000000\n        0x0000004af3a0|+0x0060|+012: 0x0000000000484e60  ->  0x0000000100000000\n        0x0000004af3a8|+0x0068|+013: 0x0000000000485460  ->  0x0000000100000000\n        0x0000004af3b0|+0x0070|+014: 0x0000000000485d60  ->  0x0002000200020002\n        0x0000004af3b8|+0x0078|+015: 0x0000000000000000\n        --- TLS ---\n        ...\n        \"\"\"\n        tls = current_arch.get_tls()\n        for i in range(1, 16):\n            addr = tls + (current_arch.ptrsize * i) * direction\n\n            if not is_valid_addr(addr):\n                break\n\n            x = read_int_from_memory(addr)\n            if not is_valid_addr(x):\n                continue\n\n            y = read_int_from_memory(x)\n            if is_valid_addr(y):\n                continue\n\n            yb = bytearray(read_memory(x, 8))\n            if yb.count(b\"\\x00\") <= 2:\n                # statistically ok\n                return addr\n        return None\n\n    def dump_tls_dtors(self, offset_tls_dtor_list):\n        info(\"Probably only exists in glibc\")\n        if not self.tls:\n            err(\"Could not find the TLS\")\n            return\n\n        tls_dtor_list = None\n\n        # user specified\n        if offset_tls_dtor_list:\n            tls_dtor_list = AddressUtil.align_address(current_arch.get_tls() + offset_tls_dtor_list)\n\n        # method 1 (directly)\n        if tls_dtor_list is None:\n            try:\n                tls_dtor_list = AddressUtil.parse_address(\"&tls_dtor_list\")\n                if not is_valid_addr(tls_dtor_list):\n                    tls_dtor_list = None\n            except gdb.error:\n                pass\n\n        # method 2 (from msymbols)\n        if tls_dtor_list is None:\n            if self.elf.is_static():\n                tls_dtor_list = self.get_dtor_list_from_msymbols()\n\n        # method 3 (from link-map)\n        if tls_dtor_list is None:\n            if not self.elf.is_static():\n                tls_dtor_list = self.get_dtor_list_from_linkmap_relative()\n\n        # method 4 (from tls with likely pattern)\n        if tls_dtor_list is None:\n            if current_arch.encode_cookie(0x1, 0xdeadbeef) != 0x1: # use cookie xor\n                tls_dtor_list = self.get_dtor_list_from_heuristic()\n\n        if tls_dtor_list is None:\n            err(\"Could not find tls_dtor_list\")\n            return\n\n        # parse tls_dtor_list and print\n        head_p = tls_dtor_list\n        head = ProcessMap.lookup_address(read_int_from_memory(head_p))\n        current = head.value\n        if head.section is None:\n            gef_print(\"{:s}: {:s}: {!s}\".format(\"tls_dtor_list\", self.C(head_p), head))\n        else:\n            gef_print(\"{:s}: {:s}: {!s}[{!s}]\".format(\"tls_dtor_list\", self.C(head_p), head, head.section.permission))\n\n        ptrsize = current_arch.ptrsize\n\n        def read_fns(addr):\n            func = ProcessMap.lookup_address(read_int_from_memory(current))\n            obj = ProcessMap.lookup_address(read_int_from_memory(current + ptrsize * 1))\n            link_map = ProcessMap.lookup_address(read_int_from_memory(current + ptrsize * 2))\n            next = ProcessMap.lookup_address(read_int_from_memory(current + ptrsize * 3))\n            return func, obj, link_map, next\n\n        while current:\n            try:\n                func, obj, link_map, next = read_fns(current)\n            except gdb.MemoryError:\n                err(\"Memory read error at {:#x}\".format(current))\n                break\n\n            decoded_fn = current_arch.decode_cookie(func.value, self.cookie)\n            decoded_fn = ProcessMap.lookup_address(decoded_fn)\n            sym = Symbol.get_symbol_string(decoded_fn.value)\n\n            if is_valid_addr(decoded_fn.value):\n                valid_msg = Color.colorify(\"valid\", \"bold green\")\n            else:\n                valid_msg = Color.colorify(\"invalid\", \"bold red\")\n\n            gef_print(\"    -> func:     {:s}: {!s} (={!s}{:s}) [{:s}]\".format(\n                self.C(current), func, decoded_fn, sym, valid_msg,\n            ))\n            gef_print(\"       obj:      {:s}: {!s}\".format(\n                self.C(current + ptrsize * 1), obj,\n            ))\n            gef_print(\"       link_map: {:s}: {!s}\".format(\n                self.C(current + ptrsize * 2), link_map,\n            ))\n            gef_print(\"       next:     {:s}: {!s}\".format(\n                self.C(current + ptrsize * 3), next,\n            ))\n            current = next.value\n        return\n\n    def dump_exit_funcs(self, name):\n        try:\n            head_p = AddressUtil.parse_address(\"&\" + name)\n        except gdb.error:\n            err(\"Could not find symbol ({:s})\".format(name))\n            return\n\n        head = ProcessMap.lookup_address(read_int_from_memory(head_p))\n        current = head.value\n        if head.section is None:\n            gef_print(\"{:s}: {:s}: {!s}\".format(name, self.C(head_p), head))\n        else:\n            gef_print(\"{:s}: {:s}: {!s}[{!s}]\".format(name, self.C(head_p), head, head.section.permission))\n        if current == 0:\n            return\n\n        ptrsize = current_arch.ptrsize\n\n        try:\n            next = ProcessMap.lookup_address(read_int_from_memory(current))\n            idx = ProcessMap.lookup_address(read_int_from_memory(current + ptrsize))\n        except gdb.MemoryError:\n            err(\"Memory read error at {:#x}\".format(current))\n            return\n        current += ptrsize * 2\n        gef_print(\"    -> next:     {:s}: {!s}\".format(self.C(head.value + ptrsize * 0), next))\n        gef_print(\"       idx:      {:s}: {!s}\".format(self.C(head.value + ptrsize * 1), idx))\n\n        def read_fns(addr):\n            flavor = ProcessMap.lookup_address(read_int_from_memory(addr))\n            fn = ProcessMap.lookup_address(read_int_from_memory(addr + ptrsize * 1))\n            arg = ProcessMap.lookup_address(read_int_from_memory(addr + ptrsize * 2))\n            dso_handle = ProcessMap.lookup_address(read_int_from_memory(addr + ptrsize * 3))\n            return flavor, fn, arg, dso_handle\n\n        fns_size = ptrsize * 4 # flavor, fn, arg, dso_handle\n\n        for i in range(idx.value, -1, -1):\n            addr = AddressUtil.align_address(current + fns_size * i)\n            try:\n                flavor, fn, arg, dso_handle = read_fns(addr)\n            except gdb.MemoryError:\n                err(\"Memory read error at {:#x}\".format(addr))\n                break\n            if fn.value == 0:\n                continue\n            decoded_fn = current_arch.decode_cookie(fn.value, self.cookie)\n            decoded_fn = ProcessMap.lookup_address(decoded_fn)\n            sym = Symbol.get_symbol_string(decoded_fn.value)\n\n            if is_valid_addr(decoded_fn.value):\n                valid_msg = Color.colorify(\"valid\", \"bold green\")\n            else:\n                valid_msg = Color.colorify(\"invalid\", \"bold red\")\n\n            fns = \"       fns[{:#x}]: {:s}:\".format(i, self.C(addr))\n            width = len(fns) - 9\n            gef_print(\"{} flavor:     {!s}\".format(fns, flavor))\n            gef_print(\"{} func:       {!s} (={!s}{:s}) [{:s}]\".format(\" \" * width, fn, decoded_fn, sym, valid_msg))\n            gef_print(\"{} arg:        {!s}\".format(\" \" * width, arg))\n            gef_print(\"{} dso_handle: {!s}\".format(\" \" * width, dso_handle))\n        return\n\n    def yield_link_map(self, codebase):\n        link_map = LinkMapCommand.get_link_map(codebase, silent=True)\n        if link_map is None:\n            return\n        current = link_map.value\n        while current:\n            dic = {}\n            dic[\"load_address\"] = read_int_from_memory(current)\n            name_ptr = read_int_from_memory(current + current_arch.ptrsize * 1)\n            dic[\"name\"] = dic[\"name_org\"] = read_cstring_from_memory(name_ptr)\n            if dic[\"name_org\"] == \"\":\n                dic[\"name\"] = \"{:s}\".format(self.local_filepath)\n            dic[\"dynamic\"] = read_int_from_memory(current + current_arch.ptrsize * 2)\n            dic[\"next\"] = read_int_from_memory(current + current_arch.ptrsize * 3)\n            LinkMap = collections.namedtuple(\"LinkMap\", dic.keys())\n            link_map = LinkMap(*dic.values())\n            yield link_map\n            current = dic[\"next\"]\n        return\n\n    def dump_fini(self):\n        if not self.codebase:\n            return None\n\n        DT_TABLE = DynamicCommand.get_DT_TABLE()\n\n        if self.elf.has_dynamic():\n            # Parse all loaded libraries.\n            for link_map in self.yield_link_map(self.codebase):\n                # get dynamic\n                dynamic = DynamicCommand.get_dynamic(link_map.load_address or link_map.name, silent=True)\n                if dynamic is None:\n                    continue\n\n                # search for .fini\n                fini = None\n                current = dynamic.value\n                while True:\n                    tag = read_int_from_memory(current)\n                    if tag == 13: # DT_FINI\n                        fini = read_int_from_memory(current + current_arch.ptrsize)\n                        if fini < link_map.load_address:\n                            fini += link_map.load_address\n                        break\n                    if tag not in DT_TABLE:\n                        break\n                    current += current_arch.ptrsize * 2\n\n                if fini is None:\n                    continue\n\n                # print .fini\n                gef_print(link_map.name)\n                fini = ProcessMap.lookup_address(fini)\n                sym = Symbol.get_symbol_string(fini.value)\n                gef_print(\"    -> {!s}{:s}\".format(fini, sym))\n        else:\n            # Static binary has no _DYNAMIC, but we can resolve the target address\n            # from section name due to local file path.\n            shdr = self.elf.get_shdr(\".fini\")\n            if shdr is None:\n                err(\"Could not find .fini section\")\n                return\n\n            fini = shdr.sh_addr\n            if fini < self.codebase:\n                fini += self.codebase\n            gef_print(self.local_filepath)\n            fini = ProcessMap.lookup_address(fini)\n            sym = Symbol.get_symbol_string(fini.value)\n            gef_print(\"    -> {!s}{:s}\".format(fini, sym))\n        return\n\n    def dump_fini_array(self):\n        if not self.codebase:\n            return None\n\n        DT_TABLE = DynamicCommand.get_DT_TABLE()\n\n        if self.elf.has_dynamic():\n            # Parse all loaded libraries.\n            for link_map in self.yield_link_map(self.codebase):\n                # get dynamic\n                dynamic = DynamicCommand.get_dynamic(link_map.load_address or link_map.name, silent=True)\n                if dynamic is None:\n                    continue\n\n                # search for .fini_array, fini_array_sz\n                fini_array = None\n                fini_array_sz = None\n                current = dynamic.value\n                while True:\n                    tag = read_int_from_memory(current)\n                    if tag == 26: # DT_FINI_ARRAY\n                        fini_array = read_int_from_memory(current + current_arch.ptrsize)\n                        if fini_array < link_map.load_address:\n                            fini_array += link_map.load_address\n                    if tag == 28: # DT_FINI_ARRAY_SZ\n                        fini_array_sz = read_int_from_memory(current + current_arch.ptrsize)\n                    if fini_array is not None and fini_array_sz is not None:\n                        break\n                    if tag not in DT_TABLE:\n                        break\n                    current += current_arch.ptrsize * 2\n\n                if fini_array is None or fini_array_sz is None:\n                    continue\n\n                # parse .fini_array\n                entries = []\n                for i in range(fini_array_sz // current_arch.ptrsize):\n                    addr = fini_array + current_arch.ptrsize * i\n                    func = read_int_from_memory(addr)\n                    if not is_valid_addr(func):\n                        continue\n                    entries.append([addr, func])\n                if not entries:\n                    continue\n\n                # print .fini_array\n                gef_print(link_map.name)\n                for addr, func in entries:\n                    func = ProcessMap.lookup_address(func)\n                    sym = Symbol.get_symbol_string(func.value)\n                    gef_print(\"    -> {:s}: {!s}{:s}\".format(self.C(addr), func, sym))\n        else:\n            # Static binary has no _DYNAMIC, but we can resolve the target address\n            # from section name due to local file path.\n            shdr = self.elf.get_shdr(\".fini_array\")\n            if shdr is None:\n                err(\"Could not find .fini_array section\")\n                return\n\n            entries = []\n            vend = AddressUtil.get_vmem_end() - 1\n            for i in range(shdr.sh_size // current_arch.ptrsize):\n                addr = shdr.sh_addr + current_arch.ptrsize * i\n                func = read_int_from_memory(addr)\n                if func in [0, vend]:\n                    continue\n                entries.append([addr, func])\n            if not entries:\n                err(\"Could not find valid entry\")\n                return\n            gef_print(self.local_filepath)\n            for addr, func in entries:\n                func = ProcessMap.lookup_address(func)\n                sym = Symbol.get_symbol_string(func.value)\n                gef_print(\"    -> {:s}: {!s}{:s}\".format(self.C(addr), func, sym))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @exclude_specific_arch(arch=(\"SPARC32\", \"XTENSA\", \"CRIS\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        Cache.reset_gef_caches(all=True)\n\n        # init\n        local_filepath = None\n        remote_filepath = None\n        tmp_filepath = None\n\n        if args.remote:\n            if not is_remote_debug():\n                err(\"-r option is allowed only remote debug\")\n                return\n\n            if args.file:\n                remote_filepath = args.file # if specified, assume it is remote\n            elif gdb.current_progspace().filename:\n                f = gdb.current_progspace().filename\n                if f.startswith(\"target:\"): # gdbserver\n                    f = f[7:]\n                remote_filepath = f\n            elif Pid.get_pid(remote=True):\n                remote_filepath = \"/proc/{:d}/exe\".format(Pid.get_pid(remote=True))\n            else:\n                err(\"File name could not be determined\")\n                return\n\n            data = Path.read_remote_file(remote_filepath, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                err(\"Failed to read remote filepath\")\n                return\n            tmp_fd, tmp_filepath = GefUtil.mkstemp(prefix=\"dtor-dump\", suffix=\".elf\")\n            os.fdopen(tmp_fd, \"wb\").write(data)\n            local_filepath = tmp_filepath\n            del data\n\n        elif args.file:\n            local_filepath = args.file\n\n        elif args.file is None:\n            local_filepath = Path.get_filepath()\n\n        if local_filepath is None:\n            err(\"File name could not be determined\")\n            return\n\n        # filepath and elf\n        self.local_filepath = local_filepath\n        self.elf = Elf.get_elf(local_filepath)\n        if self.elf is None or not self.elf.is_valid():\n            err(\"Invalid ELF\")\n            return\n\n        # codebase\n        if remote_filepath:\n            self.codebase = ProcessMap.get_section_base_address(remote_filepath)\n        elif local_filepath:\n            self.codebase = ProcessMap.get_section_base_address(local_filepath)\n        if self.codebase is None:\n            self.codebase = ProcessMap.get_section_base_address(Path.get_filepath(append_proc_root_prefix=False))\n        if self.codebase is None:\n            self.codebase = ProcessMap.get_section_base_address(Path.get_filepath_from_info_proc())\n        if self.codebase is None:\n            warn(\"Could not find codebase\")\n\n        # tls\n        self.tls = current_arch.get_tls()\n        if self.tls is None or not is_valid_addr(self.tls):\n            warn(\"Could not find tls\")\n\n        # cookie\n        self.cookie = PtrDemangleCommand.get_cookie()\n        if self.cookie is None:\n            warn(\"Could not find cookie\")\n\n        # dump\n        gef_print(titlify(\"tls_dtor_list: registered by __cxa_thread_atexit_impl()\"))\n        self.dump_tls_dtors(args.tdl)\n\n        gef_print(titlify(\"__exit_funcs: registered by atexit(), on_exit()\"))\n        self.dump_exit_funcs(\"__exit_funcs\")\n\n        gef_print(titlify(\"__quick_exit_funcs: registered by at_quick_exit()\"))\n        self.dump_exit_funcs(\"__quick_exit_funcs\")\n\n        gef_print(titlify(\".fini_array section\"))\n        self.dump_fini_array()\n\n        gef_print(titlify(\".fini section\"))\n        self.dump_fini()\n\n        # cleanup\n        if tmp_filepath and os.path.exists(tmp_filepath):\n            os.unlink(tmp_filepath)\n        return\n\n\n@register_command\nclass FpChainCommand(GenericCommand):\n    \"\"\"Dump chains from __IO_list_all.\"\"\"\n\n    _cmdline_ = \"fpchain\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the _IO_list_all address to parse.\")\n    _syntax_ = parser.format_help()\n\n    def get_io_list_all(self):\n        try:\n            return AddressUtil.parse_address(\"(void*) &_IO_list_all\")\n        except gdb.error:\n            pass\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.address is None:\n            io_list_all = self.get_io_list_all()\n            if not io_list_all:\n                err(\"Could not find _IO_list_all\")\n                return\n        else:\n            io_list_all = args.address\n\n        gef_print(\"[0]    {!s}{:s}\".format(\n            ProcessMap.lookup_address(io_list_all), Symbol.get_symbol_string(io_list_all),\n        ))\n\n        if is_64bit():\n            offset_of_chain = 0x68\n        else:\n            offset_of_chain = 0x34\n\n        current = io_list_all\n        i = 1\n        while is_valid_addr(current):\n            if i == 1:\n                current = read_int_from_memory(current)\n            else:\n                current = read_int_from_memory(current + offset_of_chain)\n            gef_print(\"[{:d}] -> {!s}{:s}\".format(\n                i, ProcessMap.lookup_address(current), Symbol.get_symbol_string(current),\n            ))\n\n            i += 1\n        return\n\n\n@register_command\nclass StandardIoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump members of stdin/stdout/stderr.\"\"\"\n\n    _cmdline_ = \"stdio-dump\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n    _aliases_ = [\"fp\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", nargs=\"*\", type=AddressUtil.parse_address,\n                        help=\"the ELF address to parse (default: stdin, stdout, stderr).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_offset(self, member_name, member_defines):\n        sizes, names = zip(*member_defines)\n        member_idx = names.index(member_name)\n        member_offset = sum(sizes[:member_idx])\n        return member_offset\n\n    def get_size(self, member_name, member_defines):\n        sizes, names = zip(*member_defines)\n        member_idx = names.index(member_name)\n        member_size = sizes[member_idx]\n        return member_size\n\n    def process_member(self, member_name, member_defines, struct_array):\n        # member name\n        if not member_name:\n            return 0\n        elif member_name == \"__addr__\":\n            member_offset = 0\n            member_size = current_arch.ptrsize\n            msg = \"{:>5s} | {:16s}: \".format(\"off\", \"member\")\n        else:\n            member_offset = self.get_offset(member_name, member_defines)\n            member_size = self.get_size(member_name, member_defines)\n            msg = \"{:+#05x} | {:16s}: \".format(member_offset, member_name)\n\n        adjust = 0\n        val_width = [10, 18][is_64bit()]\n        sym_width = [25, 29][is_arm32()]\n\n        # member of each struct\n        for st in struct_array:\n            member_addr = st + member_offset\n            if member_name == \"__addr__\":\n                address_obj = ProcessMap.lookup_address(st)\n                sym = Symbol.get_symbol_string(st)\n                msg += \"{:s}{:{:d}s} \".format(address_obj.long_fmt(), sym, sym_width)\n            elif not is_valid_addr(member_addr):\n                msg += \"{:{:d}s}{:{:d}s} \".format(\"\", val_width, \"\", sym_width)\n            elif member_size == current_arch.ptrsize:\n                val = read_int_from_memory(member_addr)\n                address_obj = ProcessMap.lookup_address(val)\n                sym = Symbol.get_symbol_string(val)\n                msg += \"{:s}{:{:d}s} \".format(address_obj.long_fmt(), sym, sym_width)\n            elif member_size == 8:\n                val = read_int64_from_memory(member_addr)\n                # special case\n                if is_32bit() and member_name == \"_offset\":\n                    if Endian.is_big_endian():\n                        val_ = byteswap(val, 8)\n                    else:\n                        val_ = val\n                    if val_ == 0xffff_ffff_0000_0000:\n                        adjust = 4\n                        member_offset += adjust\n                        msg = \"{:+#05x} | {:16s}: \".format(member_offset, member_name)\n                        member_addr += adjust\n                        val = read_int64_from_memory(member_addr)\n                val_s = \"{:#018x}\".format(val)\n                msg += \"{:s}{:{:d}s} \".format(val_s, \"\", sym_width - [8, 0][is_64bit()])\n            elif member_size == 4:\n                val = read_int32_from_memory(member_addr)\n                val_s = \"{:#010x}\".format(val)\n                msg += \"{:{:d}s}{:{:d}s} \".format(val_s, val_width, \"\", sym_width)\n            elif member_size == 2:\n                val = read_int16_from_memory(member_addr)\n                val_s = \"{:#06x}\".format(val)\n                msg += \"{:{:d}s}{:{:d}s} \".format(val_s, val_width, \"\", sym_width)\n            elif member_size == 1:\n                val = read_int8_from_memory(member_addr)\n                val_s = \"{:#04x}\".format(val)\n                msg += \"{:{:d}s}{:{:d}s} \".format(val_s, val_width, \"\", sym_width)\n            else:\n                msg += \"{:{:d}s}{:{:d}s} \".format(\"...\", val_width, \"\", sym_width)\n\n        self.out.append(msg.rstrip())\n        return adjust\n\n    def stdio_dump(self, struct_io_file_array):\n        self.process_member(\"__addr__\", None, struct_io_file_array)\n\n        # _IO_FILE\n        self.out.append(titlify(\"FILE\"))\n        struct_io_file_member = [\n            [4,                    \"_flags\"],\n            [[0, 4][is_64bit()],   \"\"],\n            [current_arch.ptrsize, \"_IO_read_ptr\"],\n            [current_arch.ptrsize, \"_IO_read_end\"],\n            [current_arch.ptrsize, \"_IO_read_base\"],\n            [current_arch.ptrsize, \"_IO_write_base\"],\n            [current_arch.ptrsize, \"_IO_write_ptr\"],\n            [current_arch.ptrsize, \"_IO_write_end\"],\n            [current_arch.ptrsize, \"_IO_buf_base\"],\n            [current_arch.ptrsize, \"_IO_buf_end\"],\n            [current_arch.ptrsize, \"_IO_save_base\"],\n            [current_arch.ptrsize, \"_IO_backup_base\"],\n            [current_arch.ptrsize, \"_IO_save_end\"],\n            [current_arch.ptrsize, \"_markers\"],\n            [current_arch.ptrsize, \"_chain\"],\n            [4,                    \"_fileno\"],\n            [4,                    \"_flags2\"],\n            [current_arch.ptrsize, \"_old_offset\"],\n            [2,                    \"_cur_column\"],\n            [1,                    \"_vtable_offset\"],\n            [1,                    \"_shortbuf\"],\n            [[0, 4][is_64bit()],   \"\"],\n            [current_arch.ptrsize, \"_lock\"],\n            [0,                    \"\"], # varies depending on environment\n            [8,                    \"_offset\"],\n            [current_arch.ptrsize, \"_codecvt\"],\n            [current_arch.ptrsize, \"_wide_data\"],\n            [current_arch.ptrsize, \"_freeres_list\"],\n            [current_arch.ptrsize, \"_freeres_buf\"],\n            [current_arch.ptrsize, \"__pad5\"],\n            [4,                    \"_mode\"],\n            [[40, 20][is_64bit()], \"_unused2\"],\n            [current_arch.ptrsize, \"vtable\"],\n        ]\n        for _, m in struct_io_file_member:\n            adjust = self.process_member(m, struct_io_file_member, struct_io_file_array)\n            if adjust:\n                if is_32bit() and m == \"_offset\":\n                    struct_io_file_member[23][0] = adjust\n\n        # vtable\n        self.out.append(titlify(\"FILE->vtable\"))\n        vtable_offset = self.get_offset(\"vtable\", struct_io_file_member)\n        struct_io_jump_t_array = []\n        for x in struct_io_file_array:\n            vtable_addr = x + vtable_offset\n            if not is_valid_addr(vtable_addr):\n                struct_io_jump_t_array.append(0)\n            else:\n                vtable = read_int_from_memory(vtable_addr)\n                if not is_valid_addr(vtable):\n                    struct_io_jump_t_array.append(0)\n                else:\n                    struct_io_jump_t_array.append(vtable)\n        struct_io_jump_t_member = [\n            [current_arch.ptrsize, \"__dummy\"],\n            [current_arch.ptrsize, \"__dummy2\"],\n            [current_arch.ptrsize, \"__finish\"],\n            [current_arch.ptrsize, \"__overflow\"],\n            [current_arch.ptrsize, \"__underflow\"],\n            [current_arch.ptrsize, \"__uflow\"],\n            [current_arch.ptrsize, \"__pbackfail\"],\n            [current_arch.ptrsize, \"__xsputn\"],\n            [current_arch.ptrsize, \"__xsgetn\"],\n            [current_arch.ptrsize, \"__seekoff\"],\n            [current_arch.ptrsize, \"__seekpos\"],\n            [current_arch.ptrsize, \"__setbuf\"],\n            [current_arch.ptrsize, \"__sync\"],\n            [current_arch.ptrsize, \"__doallocate\"],\n            [current_arch.ptrsize, \"__read\"],\n            [current_arch.ptrsize, \"__write\"],\n            [current_arch.ptrsize, \"__seek\"],\n            [current_arch.ptrsize, \"__close\"],\n            [current_arch.ptrsize, \"__stat\"],\n            [current_arch.ptrsize, \"__showmanyc\"],\n            [current_arch.ptrsize, \"__imbue\"],\n        ]\n        for _, m in struct_io_jump_t_member:\n            self.process_member(m, struct_io_jump_t_member, struct_io_jump_t_array)\n\n        # wide_data\n        self.out.append(titlify(\"FILE->_wide_data\"))\n        wide_data_offset = self.get_offset(\"_wide_data\", struct_io_file_member)\n        struct_io_wide_data_array = []\n        for x in struct_io_file_array:\n            wide_data_addr = x + wide_data_offset\n            if not is_valid_addr(wide_data_addr):\n                struct_io_wide_data_array.append(0)\n            else:\n                wide_data = read_int_from_memory(wide_data_addr)\n                if not is_valid_addr(wide_data):\n                    struct_io_wide_data_array.append(0)\n                else:\n                    struct_io_wide_data_array.append(wide_data)\n        struct_io_wide_data_member = [\n            [current_arch.ptrsize,     \"_IO_read_ptr\"],\n            [current_arch.ptrsize,     \"_IO_read_end\"],\n            [current_arch.ptrsize,     \"_IO_read_base\"],\n            [current_arch.ptrsize,     \"_IO_write_base\"],\n            [current_arch.ptrsize,     \"_IO_write_ptr\"],\n            [current_arch.ptrsize,     \"_IO_write_end\"],\n            [current_arch.ptrsize,     \"_IO_buf_base\"],\n            [current_arch.ptrsize,     \"_IO_buf_end\"],\n            [current_arch.ptrsize,     \"_IO_save_base\"],\n            [current_arch.ptrsize,     \"_IO_backup_base\"],\n            [current_arch.ptrsize,     \"_IO_save_end\"],\n            [8,                        \"_IO_state\"],\n            [8,                        \"_IO_last_state\"],\n            [[0x48, 0x70][is_64bit()], \"_codecvt\"],\n            [4,                        \"_shortbuf\"],\n            [[0, 4][is_64bit()],       \"\"],\n            [current_arch.ptrsize,     \"_wide_vtable\"],\n        ]\n        for _, m in struct_io_wide_data_member:\n            self.process_member(m, struct_io_wide_data_member, struct_io_wide_data_array)\n\n        # wide_data vtable\n        self.out.append(titlify(\"FILE->_wide_data->_wide_vtable\"))\n        wide_data_vtable_offset = self.get_offset(\"_wide_vtable\", struct_io_wide_data_member)\n        struct_io_wide_data_jump_t_array = []\n        for x in struct_io_wide_data_array:\n            wide_data_vtable_addr = x + wide_data_vtable_offset\n            if not is_valid_addr(wide_data_vtable_addr):\n                struct_io_wide_data_jump_t_array.append(0)\n            else:\n                wide_data_vtable = read_int_from_memory(wide_data_vtable_addr)\n                if not is_valid_addr(wide_data_vtable):\n                    struct_io_wide_data_jump_t_array.append(0)\n                else:\n                    struct_io_wide_data_jump_t_array.append(wide_data_vtable)\n        for _, m in struct_io_jump_t_member:\n            self.process_member(m, struct_io_jump_t_member, struct_io_wide_data_jump_t_array)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.address:\n            struct_io_file_array = []\n            for x in args.address:\n                if not is_valid_addr(x):\n                    err(\"Memory read error\")\n                    return\n                struct_io_file_array.append(x)\n        else:\n            try:\n                stdin = AddressUtil.parse_address(\"(void*) stdin\")\n                stdout = AddressUtil.parse_address(\"(void*) stdout\")\n                stderr = AddressUtil.parse_address(\"(void*) stderr\")\n            except gdb.error:\n                err(\"Could not find stdin, stdout, and stderr\")\n                return\n\n            if not is_valid_addr(stdin):\n                err(\"stdin: memory read error\")\n                return\n\n            if not is_valid_addr(stdout):\n                err(\"stdout: memory read error\")\n                return\n\n            if not is_valid_addr(stderr):\n                err(\"stderr: memory read error\")\n                return\n            struct_io_file_array = [stdin, stdout, stderr]\n\n        self.out = []\n        self.stdio_dump(struct_io_file_array)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GotCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display current status of the got/plt inside the process.\"\"\"\n\n    _cmdline_ = \"got\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n    _aliases_ = [\"plt\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--file\", help=\"the filename to parse.\")\n    parser.add_argument(\"-e\", \"--elf-address\", type=AddressUtil.parse_address,\n                        help=\"the ELF address to parse.\")\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", default=[], help=\"filter string.\")\n    parser.add_argument(\"--exact\", action=\"store_true\", help=\"use exact match for function name.\")\n    parser.add_argument(\"--cppfilt\", action=\"store_true\", help=\"use c++filt to demangle.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} read print                              # filter specified keyword\",\n        \"{0:s} -f /usr/lib/x86_64-linux-gnu/libc.so.6  # specified target binary\",\n        \"{0:s} -f /bin/ls -e 0x4000000000              # use specified address, it is useful under qemu\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        self.add_setting(\"function_resolved\", \"green\",\n                         \"Line color of the got command output if the function has been resolved\")\n        self.add_setting(\"function_not_resolved\", \"yellow\",\n                         \"Line color of the got command output if the function has not been resolved\")\n        return\n\n    def get_jmp_slots(self):\n        try:\n            readelf = GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n            cmd = [readelf, \"--relocs\", \"--wide\", self.filename]\n            lines = GefUtil.gef_execute_external(cmd, as_list=True)\n        except (FileNotFoundError, subprocess.CalledProcessError):\n            return []\n\n        elf = Elf.get_elf(self.filename)\n\n        output = {}\n        section_name = None\n        reloc_count = 0\n        for line in lines:\n            # get section\n            r = re.findall(\"'(.+?)' at offset\", line)\n            if r:\n                section_name = r[0]\n                continue\n\n            # GOT entry pattern 1\n            if \"JUMP_SLOT\" in line or \"JMP_SLOT\" in line:\n                type = \"JUMP_SLOT\"\n                address, _, _, _, name = line.split()[:5]\n                address = int(address, 16)\n                name = name.split(\"@\")[0]\n            # GOT entry pattern 2 (?)\n            elif \"GLOB_DAT\" in line:\n                type = \"GLOB_DAT\"\n                address, _, _, _, name = line.split()[:5]\n                address = int(address, 16)\n                name = name.split(\"@\")[0]\n            # GOT entry pattern 3 (?)\n            elif \"IRELATIVE\" in line:\n                type = \"IRELATIVE\"\n                if is_32bit():\n                    address = line.split()[0]\n                    address = int(address, 16)\n                    name = \"*ABS*\"\n                else:\n                    address, _, _, addend = line.split()[:4]\n                    address = int(address, 16)\n                    name = \"*ABS*+{:#x}\".format(int(addend, 16))\n            # Not GOT entry\n            else:\n                continue\n\n            # count up reloc_arg\n            if elf.is_static():\n                reloc_arg = None\n            elif section_name not in [\".rel.plt\", \".rela.plt\"]:\n                reloc_arg = None\n            else:\n                reloc_arg = reloc_count * [1, 8][is_32bit()]\n                reloc_count += 1\n\n            # fix address\n            if elf.is_pie():\n                address += self.base_address\n\n            # save\n            array = output.get(type, [])\n            output[type] = array + [[address, name, section_name, type, reloc_arg]]\n\n        # flatten\n        a = output.get(\"JUMP_SLOT\", [])\n        b = output.get(\"IRELATIVE\", [])\n        c = output.get(\"GLOB_DAT\", [])\n        return a + b + c\n\n    def get_jmp_slots_arch_specific(self):\n        try:\n            readelf = GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n            cmd = [readelf, \"--arch-specific\", \"--wide\", self.filename]\n            lines = GefUtil.gef_execute_external(cmd, as_list=True)\n        except (FileNotFoundError, subprocess.CalledProcessError):\n            return []\n\n        elf = Elf.get_elf(self.filename)\n\n        output = []\n        ncol = -1\n        for line in lines:\n            r = re.search(r\"^\\s+Address\\s+.*\\s+Initial\\s+\", line)\n            if r:\n                ncol = len(line.split())\n                continue\n\n            r = re.search(r\"^\\s+[0-9a-f]+\", line)\n            if not r:\n                continue\n\n            ls = line.split()\n\n            address = int(ls[0], 16)\n            # fix address\n            if elf.is_pie():\n                address += self.base_address\n\n            if ncol == 3:\n                name = \"\"\n            elif ncol == 4:\n                name = \" \".join(ls[3:])\n            else:\n                name = ls[-1]\n\n            output.append([address, name, \".got\", \"???\", None])\n        return output\n\n    def get_plt_addresses(self):\n        try:\n            objdump = GefUtil.which(Config.get_gef_setting(\"gef.objdump_command\"))\n            cmd = [objdump, \"-j\", \".plt\", \"-j\", \".plt.sec\", \"-j\", \".plt.got\", \"-d\", self.filename]\n            lines = GefUtil.gef_execute_external(cmd, as_list=True)\n        except (FileNotFoundError, subprocess.CalledProcessError):\n            return {}\n\n        elf = Elf.get_elf(self.filename)\n\n        output = {}\n        for line in lines:\n            # get function name\n            r = re.findall(r\"^([0-9a-f]+) <(.+)@plt>:\", line)\n            if not r:\n                continue\n            address, func_name = int(r[0][0], 16), r[0][1]\n\n            # fix address\n            if elf.is_pie():\n                address += self.base_address\n\n            # save\n            # Since DT_REL (used at i386) has no r_addend, the information of identification does not exist.\n            # So there are multiple \"*ABS*\" entries, keep them in a list.\n            array = output.get(func_name, [])\n            output[func_name] = array + [address]\n        return output\n\n    def get_plt_addresses_arch_specific(self):\n        try:\n            readelf = GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n            cmd = [readelf, \"--arch-specific\", \"--wide\", self.filename]\n            lines = GefUtil.gef_execute_external(cmd, as_list=True)\n        except (FileNotFoundError, subprocess.CalledProcessError):\n            return []\n\n        elf = Elf.get_elf(self.filename)\n\n        output = {}\n        ncol = -1\n        for line in lines:\n            r = re.search(r\"^\\s+Address\\s+.*\\s+Initial\\s+\", line)\n            if r:\n                initial_idx = line.split().index(\"Initial\")\n                ncol = len(line.split())\n                continue\n\n            r = re.search(r\"^\\s+[0-9a-f]+\", line)\n            if not r:\n                continue\n\n            ls = line.split()\n\n            plt_address = int(ls[initial_idx], 16)\n            # fix address\n            if elf.is_pie():\n                plt_address += self.base_address\n            if not is_valid_addr(plt_address):\n                plt_address = 0\n\n            if ncol == 3:\n                name = \"\"\n            elif ncol == 4:\n                name = \" \".join(ls[3:])\n            else:\n                name = ls[-1]\n\n            output[name] = [plt_address]\n        return output\n\n    def get_plt_range(self):\n        # The PLT range is required to determine whether the information in the GOT is resolved or not.\n        elf = Elf.get_elf(self.filename)\n        sections = [x for x in elf.shdrs if x.sh_name in [\".plt\", \".plt.got\", \".plt.sec\", \".MIPS.stubs\"]]\n        if len(sections) == 0:\n            return 0, 0\n        plt_begin = min([x.sh_addr for x in sections])\n        plt_end = max([x.sh_addr + x.sh_size for x in sections])\n\n        # fix address\n        if elf.is_pie():\n            plt_begin += self.base_address\n            plt_end += self.base_address\n        return plt_begin, plt_end\n\n    def perm(self, addr):\n        sec = ProcessMap.lookup_address(addr).section\n        if sec is None:\n            return \"[???]\"\n        return \"[{!s}]\".format(sec.permission)\n\n    def get_shdr_range(self):\n        # Required to identify the section name.\n        elf = Elf.get_elf(self.filename)\n        ranges = []\n        for shdr in elf.shdrs:\n            sh_start = shdr.sh_addr\n            sh_end = shdr.sh_addr + shdr.sh_size\n            if elf.is_pie():\n                sh_start += self.base_address\n                sh_end += self.base_address\n            ranges.append([shdr.sh_name, sh_start, sh_end])\n        return ranges\n\n    def get_section_name(self, addr):\n        ranges = self.get_shdr_range()\n        for name, start, end in ranges:\n            if start <= addr < end:\n                return name\n        return \"???\"\n\n    def get_section_sym(self, addr):\n        ranges = self.get_shdr_range()\n        for name, start, end in ranges:\n            if start <= addr < end:\n                return \" <{:s}+{:#x}>\".format(name, addr - start)\n        return \"\"\n\n    def parse_plt_got(self):\n        # retrieve jump slots using readelf\n        jmpslots = self.get_jmp_slots()\n        if jmpslots == []:\n            # On some architectures, such as mips, the GOT detection fails.\n            # Some information will be lost, but detection will still be performed in such cases.\n            jmpslots = self.get_jmp_slots_arch_specific()\n\n        # retrieve plt address using objdump\n        plts = self.get_plt_addresses()\n        if plts == {}:\n            # On some architectures, such as mips, the PLT detection fails.\n            plts = self.get_plt_addresses_arch_specific()\n\n        # retrieve the end of plt from elf parsing\n        plt_begin, plt_end = self.get_plt_range()\n\n        # link each PLT entries and each GOT entries\n        resolved_info = []\n        for got_address, name, section_name, type, reloc_arg in jmpslots:\n            # resolve PLT from GOT name\n            if section_name != \".rel.plt\" and name == \"*ABS*\":\n                # 32-bit arch special case.\n                plt_address = None\n            else:\n                # in many other case.\n                # This includes the common *ABS* duplication pattern on 32-bit arch.\n                plt_address = plts.get(name, None)\n                if plt_address:\n                    # It is actually popped from plts[name]. plt_address is reassigned by int value.\n                    plt_address = plt_address.pop(0)\n\n            # resolve plt section\n            if plt_address:\n                plt_section = self.get_section_name(plt_address) + self.perm(plt_address)\n            else:\n                plt_section = \"\"\n\n            # resolve got section\n            got_section = self.get_section_name(got_address) + self.perm(got_address)\n\n            # resolve offset from absolute address\n            got_offset = got_address - self.base_address\n            if plt_address:\n                plt_offset = plt_address - self.base_address\n            else:\n                plt_offset = 0\n\n            # read the address of the function\n            try:\n                got_value = read_int_from_memory(got_address)\n            except gdb.error:\n                self.quiet_err(\"Memory read error\")\n                return\n\n            # resolve got value's symbol\n            if got_value == 0:\n                got_value_sym = \"\"\n            elif plt_begin <= got_value < plt_end: # Non-PIE\n                got_value_sym = self.get_section_sym(got_value)\n            elif plt_begin - self.base_address <= got_value < plt_end - self.base_address: # PIE\n                got_value_sym = self.get_section_sym(got_value)\n            else:\n                got_value_sym = Symbol.get_symbol_string(got_value)\n\n            # different colors if the function has been resolved or not\n            if got_value == 0:\n                got_value_color = Config.get_gef_setting(\"got.function_resolved\") # .rela.dyn && uninitialized, etc.\n            elif plt_begin <= got_value < plt_end: # Non-PIE\n                got_value_color = Config.get_gef_setting(\"got.function_not_resolved\")\n            elif plt_begin - self.base_address <= got_value < plt_end - self.base_address: # PIE\n                got_value_color = Config.get_gef_setting(\"got.function_not_resolved\")\n            else:\n                got_value_color = Config.get_gef_setting(\"got.function_resolved\")\n\n            # c++filt\n            if self.args.cppfilt:\n                if name.startswith(\"_Z\"):\n                    cppfilt_command = GefUtil.which(Config.get_gef_setting(\"gef.cppfilt_command\"))\n                    res = GefUtil.gef_execute_external([cppfilt_command, name], as_list=True)\n                    if len(res) == 1:\n                        name = res[0]\n\n            # aggregate\n            dic = {\n                \"name\": name,\n                \"type\": type,\n                \"section_name\": section_name,\n                \"plt_address\": plt_address,\n                \"plt_section\": plt_section,\n                \"plt_offset\": plt_offset,\n                \"reloc_arg\": reloc_arg,\n                \"got_address\": got_address,\n                \"got_section\": got_section,\n                \"got_offset\": got_offset,\n                \"got_value\": got_value,\n                \"got_value_sym\": got_value_sym,\n                \"got_value_color\": got_value_color,\n            }\n            PltGotInfo = collections.namedtuple(\"PltGotInfo\", dic.keys())\n            plt_got_info = PltGotInfo(*dic.values())\n            resolved_info.append(plt_got_info)\n        return resolved_info\n\n    def make_output(self, resolved_info):\n        # calc each width\n        width = AddressUtil.get_format_address_width()\n        name_width = min(max([len(info.name) for info in resolved_info] + [len(\"Name\")]), 50)\n        if self.args.verbose:\n            got_section_width = max([len(info.got_section) for info in resolved_info] + [len(\"Section\")])\n            plt_section_width = max([len(info.plt_section) for info in resolved_info] + [len(\"Section\")])\n            got_offset_width = max([len(hex(info.got_offset)) for info in resolved_info] + [len(\"Offset\")])\n            plt_offset_width = max([len(hex(info.plt_offset)) for info in resolved_info] + [len(\"Offset\")])\n\n        # print legend\n        if not self.args.quiet:\n            if self.args.verbose:\n                name_s = \"{:<{:d}}\".format(\"Name\", name_width)\n                type_s = \"{:9s}\".format(\"Type\")\n                plt_s = \"{:{:d}s} @{:{:d}s} {:>{:d}s} {:>9s}\".format(\n                    \"PLT\", width,\n                    \"Section\", plt_section_width,\n                    \"Offset\", plt_offset_width,\n                    \"reloc_arg\",\n                )\n                got_s = \"{:{:d}s} @{:{:d}s} {:>{:d}s}\".format(\n                    \"GOT\", width,\n                    \"Section\", got_section_width,\n                    \"Offset\", got_offset_width,\n                )\n                gotv_s = \"{:{:d}}\".format(\"GOT value\", width)\n                legend = \" | \".join([name_s, type_s, plt_s, got_s, gotv_s])\n            else:\n                name_s = \"{:<{:d}}\".format(\"Name\", name_width)\n                plt_s = \"{:{:d}s}\".format(\"PLT\", width)\n                got_s = \"{:{:d}s}\".format(\"GOT\", width)\n                gotv_s = \"{:{:d}}\".format(\"GOT value\", width)\n                legend = \" | \".join([name_s, plt_s, got_s, gotv_s])\n            self.out.append(GefUtil.make_legend(legend))\n\n        entries = []\n        for info in resolved_info:\n            # make reloc_arg format\n            if info.reloc_arg is None:\n                reloc_arg_info = \"{:>9s}\".format(\"-\")\n            else:\n                reloc_arg_info = \"{:#9x}\".format(info.reloc_arg)\n\n            # make name format\n            if len(info.name) <= name_width:\n                name_info = \"{:{:d}s}\".format(info.name, name_width)\n            else:\n                name_info = \"{:{:d}s}\".format(info.name[:name_width - 3] + \"...\", name_width)\n\n            # make plt format\n            if self.args.verbose:\n                if info.plt_address:\n                    plt_info = \"{!s} @{:{:d}s} {:#{:d}x} {:9s}\".format(\n                        ProcessMap.lookup_address(info.plt_address),\n                        info.plt_section, plt_section_width,\n                        info.plt_offset, plt_offset_width,\n                        reloc_arg_info,\n                    )\n                else:\n                    plt_info = \"{:{:d}s}  {:{:d}s} {:>{:d}s} {:9s}\".format(\n                        \"Not found\", width,\n                        \"\", plt_section_width,\n                        \"\", plt_offset_width,\n                        reloc_arg_info,\n                    )\n            else:\n                if info.plt_address:\n                    plt_info = \"{!s}\".format(ProcessMap.lookup_address(info.plt_address))\n                else:\n                    plt_info = \"{:{:d}s}\".format(\"Not found\", width)\n\n            # make got format\n            if self.args.verbose:\n                got_info = \"{!s} @{:{:d}s} {:#{:d}x}\".format(\n                    ProcessMap.lookup_address(info.got_address),\n                    info.got_section, got_section_width,\n                    info.got_offset, got_offset_width,\n                )\n            else:\n                got_info = \"{!s}\".format(ProcessMap.lookup_address(info.got_address))\n\n            # make got value format\n            got_value_info = Color.colorify(\n                \"{:#0{:d}x}{:s}\".format(info.got_value, width, info.got_value_sym),\n                info.got_value_color,\n            )\n\n            # make line\n            if self.args.verbose:\n                type_info = \"{:9s}\".format(info.type)\n                line_element = [name_info, type_info, plt_info, got_info, got_value_info]\n            else:\n                line_element = [name_info, plt_info, got_info, got_value_info]\n            line = \" | \".join(line_element)\n\n            # save temporarily\n            entries.append([info.got_address, info, line])\n\n        # sort by GOT address\n        entries = sorted(entries)\n\n        # print\n        prev_section = None\n        for _, info, line in sorted(entries):\n            # print section name\n            if prev_section != info.section_name:\n                self.quiet_add_out(titlify(info.section_name))\n            prev_section = info.section_name\n            # if we have a filter let's skip the entries that are not requested\n            if self.args.filter:\n                if self.args.exact:\n                    if not any(pattern == info.name for pattern in self.args.filter):\n                        continue\n                else:\n                    if not any(pattern in line for pattern in self.args.filter):\n                        continue\n            self.out.append(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        try:\n            GefUtil.which(Config.get_gef_setting(\"gef.objdump_command\"))\n            GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n            if args.cppfilt:\n                GefUtil.which(Config.get_gef_setting(\"gef.cppfilt_command\"))\n        except FileNotFoundError as e:\n            self.quiet_err(\"{}\".format(e))\n            return\n\n        # A valid path even if the mount namespace is different.\n        local_filepath = None\n\n        # A path in /proc/PID/maps. Ignore namespace differences.\n        # Used to find the base address.\n        vmmap_filepath = None\n\n        # A path in remote environment.\n        remote_filepath = None\n\n        # A path downloaded file from remote environment.\n        # It should be removed later.\n        tmp_filepath = None\n\n        # get local_filepath\n        if args.remote:\n            if not is_remote_debug():\n                self.quiet_err(\"-r option is allowed only remote debug\")\n                return\n\n            if args.file:\n                remote_filepath = args.file # if specified, assume it is remote\n                vmmap_filepath = args.file\n            elif gdb.current_progspace().filename:\n                f = gdb.current_progspace().filename\n                if f.startswith(\"target:\"): # gdbserver\n                    f = f[7:]\n                remote_filepath = f\n                vmmap_filepath = f\n            elif Pid.get_pid(remote=True):\n                remote_filepath = \"/proc/{:d}/exe\".format(Pid.get_pid(remote=True))\n            else:\n                self.quiet_err(\"File name could not be determined\")\n                return\n\n            data = Path.read_remote_file(remote_filepath, as_byte=True) # qemu-user is failed here, it is ok\n            if not data:\n                self.quiet_err(\"Failed to read remote filepath\")\n                return\n            tmp_fd, tmp_filepath = GefUtil.mkstemp(prefix=\"got\", suffix=\".elf\")\n            os.fdopen(tmp_fd, \"wb\").write(data)\n            local_filepath = tmp_filepath\n            del data\n\n        elif args.file:\n            local_filepath = args.file\n\n        elif args.file is None:\n            local_filepath = Path.get_filepath() # /proc/<PID>/root/path/to/binary if another mnt namespace\n            vmmap_filepath = Path.get_filepath(append_proc_root_prefix=False)\n\n        # check local filepath\n        if local_filepath is None:\n            self.quiet_err(\"File name could not be determined\")\n            return\n\n        if not os.path.exists(local_filepath):\n            self.quiet_err(\"{:s} does not exist\".format(local_filepath))\n            return\n\n        elf = Elf.get_elf(local_filepath)\n        if elf is None or not elf.is_valid():\n            self.quiet_err(\"Invalid ELF\")\n            return\n\n        # title\n        self.out = []\n        if not args.quiet:\n            if remote_filepath:\n                print_filename = \"{:s} (remote: {:s})\".format(local_filepath, remote_filepath)\n            else:\n                print_filename = local_filepath\n\n            if elf.is_relro():\n                if elf.is_full_relro():\n                    relro_status = \"Full RELRO\"\n                else:\n                    relro_status = \"Partial RELRO\"\n            else:\n                relro_status = \"No RELRO\"\n            self.out.append(titlify(\"PLT / GOT - {:s} - {:s}\".format(print_filename, relro_status)))\n\n        # get base address\n        if args.elf_address:\n            if not args.file:\n                self.quiet_err(\"-e option needs -f option: in-memory ELF lacks Shdr, preventing full information resolution\")\n                return\n            base_address = args.elf_address\n        else:\n            vmmap = ProcessMap.get_process_maps()\n            target_filepath = vmmap_filepath or local_filepath\n\n            # get the address matching the specified path\n            path_match = [x.page_start for x in vmmap if x.path == target_filepath]\n            if path_match:\n                base_address = min(path_match)\n            else:\n                # When using the -L option with qemu-user,\n                # the file path on the disk and the file path on vmmap are different.\n                #\n                # e.g., qemu-arm -g 1234 -L /usr/arm-linux-gnueabihf ./a.out\n                # gef> vmm\n                # [ Legend:  Code | Heap | Stack | Writable | ReadOnly | None | RWX ]\n                # Start      End        Size       Offset     Perm Path\n                # 0x3f694000 0x3f79f000 0x0010b000 0x00000000 r-x /lib/libc.so.6\n                # 0x3f79f000 0x3f7b9000 0x0001a000 0x0010a000 r-- /lib/libc.so.6\n                # 0x3f7b9000 0x3f7c4000 0x0000b000 0x00124000 rw- /lib/libc.so.6\n                # ...\n                path_match_end = [x.page_start for x in vmmap if x.path and target_filepath.endswith(x.path)]\n                if path_match_end:\n                    base_address = min(path_match_end)\n                else:\n                    self.quiet_err(\"Could not find {:s} in memory (Use -e option)\".format(target_filepath))\n                    return\n\n        # get the filtering parameter\n        self.filename = local_filepath\n        self.base_address = base_address\n\n        # doit\n        resolved_info = self.parse_plt_got()\n        self.make_output(resolved_info)\n        self.print_output(check_terminal_size=True)\n\n        # clean up\n        if tmp_filepath and os.path.exists(tmp_filepath):\n            os.unlink(tmp_filepath)\n        return\n\n\n@register_command\nclass GotAllCommand(GenericCommand, BufferingOutput):\n    \"\"\"Show got entries for all libraries.\"\"\"\n\n    _cmdline_ = \"got-all\"\n    _category_ = \"02-e. Process Information - Complex Structure Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\",\n                        help=\"parse remote binary if download feature is available.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", help=\"filter string.\")\n    parser.add_argument(\"--exact\", action=\"store_true\", help=\"use exact match for function name.\")\n    parser.add_argument(\"--cppfilt\", action=\"store_true\", help=\"use c++filt to demangle.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        verbose = [\"\", \"-v\"][args.verbose]\n        remote = [\"\", \"-r\"][args.remote]\n        exact = [\"\", \"--exact\"][args.exact]\n        cppfilt = [\"\", \"--cppfilt\"][args.cppfilt]\n        extra_args = \"{:s} {:s} {:s} {:s} {:s}\".format(verbose, remote, cppfilt, exact, \" \".join(args.filter))\n\n        self.out = []\n        processed = []\n        for m in ProcessMap.get_process_maps():\n            if not m.path:\n                continue\n            if m.path.startswith((\"[\", \"<\")) or m.path.endswith((\"]\", \">\")):\n                continue\n            if m.path in processed:\n                continue\n\n            if not is_valid_addr(m.page_start):\n                continue\n            x = read_memory(m.page_start, 4)\n            if x != b\"\\x7fELF\":\n                continue\n\n            ret = gdb.execute(\"got -f {!r} -n {:s}\".format(m.path, extra_args), to_string=True)\n            self.out.extend(ret.splitlines())\n            self.out.append(\"\")\n            processed.append(m.path)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\nclass FormatStringBreakpoint(gdb.Breakpoint):\n    \"\"\"Inspect stack for format string.\"\"\"\n\n    def __init__(self, func_address, func_name, num_args, verbose=False):\n        super().__init__(\"*{:#x}\".format(func_address), type=gdb.BP_BREAKPOINT, internal=not verbose)\n        self.func_name = func_name\n        self.num_args = num_args\n        self.enabled = True\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n        msg = []\n        ptr, addr = current_arch.get_ith_parameter(self.num_args)\n        addr = ProcessMap.lookup_address(addr)\n\n        if not addr.valid:\n            return False\n\n        if addr.section.permission.value & Permission.WRITE:\n            msg.append(Color.colorify(\"Format string helper\", \"bold yellow\"))\n\n            content = read_cstring_from_memory(addr.value) or \"\"\n            msg.append(\"Possible insecure format string: {:s}('{:s}'  ->  {:#x}: '{:s}')\".format(\n                self.func_name, ptr, addr.value, content,\n            ))\n\n            name = addr.info.name if addr.info else addr.section.path\n            msg.append(\"Reason: '{:s}()' with format-string arg #{:d} is in writable page {:s} ({:s})\".format(\n                self.func_name, self.num_args, str(addr), name,\n            ))\n\n            ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n            return True\n        return False\n\n\n@register_command\nclass FormatStringSearchCommand(GenericCommand):\n    \"\"\"The helper to search for exploitable format strings.\"\"\"\n\n    _cmdline_ = \"format-string-helper\"\n    _category_ = \"01-i. Debugging Support - Other\"\n    _aliases_ = [\"fmtstr-helper\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--remove-breakpoint\", action=\"store_true\",\n                        help=\"remove the format-string-helper related breakpoints.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display target functions of breakpoint.\")\n    _syntax_ = parser.format_help()\n\n    dangerous_functions = {\n        \"printf\": 0,          # int printf(const char *fmt, ...);\n        \"fprintf\": 1,         # int fprintf(FILE *stream, const char *fmt, ...);\n        \"dprintf\": 1,         # int dprintf(int fd, const char *fmt, ...);\n        \"sprintf\": 1,         # int sprintf(char *str, const char *fmt, ...);\n        \"asprintf\": 1,        # int asprintf(char **strp, const char *fmt, ...);\n        \"snprintf\": 2,        # int snprintf(char *str, size_t size, const char *fmt, ...);\n        \"wprintf\": 0,         # int wprintf(const wchar_t *fmt, ...);\n        \"fwprintf\": 1,        # int fwprintf(FILE *stream, const wchar_t *fmt, ...);\n        \"swprintf\": 2,        # int swprintf(wchar_t *str, size_t n, const wchar_t *fmt, ...);\n        \"obstack_printf\": 1,  # int obstack_printf(struct obstack *obstack, const char *fmt, ...);\n        \"__printf_chk\": 1,    # int __printf_chk(int flag, const char *fmt);\n        \"__fprintf_chk\": 2,   # int __fprintf_chk(FILE *stream, int flag, const char *fmt, ...);\n        \"__dprintf_chk\": 2,   # int __dprintf_chk(int d, int flags, const char *fmt, ...)\n        \"__sprintf_chk\": 3,   # int __sprintf_chk(char *str, int flag, size_t strlen, const char *fmt, ...);\n        \"__asprintf_chk\": 2,  # int __asprintf_chk(char **strp, int flag, const char *fmt, ...)\n        \"__snprintf_chk\": 4,  # int __snprintf_chk(char *str, size_t maxlen, int flag, size_t strlen, const char *fmt, ...);\n        \"__wprintf_chk\": 1,   # int __wprintf_chk(int flag, const wchar_t *format, ...);\n        \"__fwprintf_chk\": 2,  # int __fwprintf_chk(FILE *stream, int flag, const wchar_t *format, ...);\n        \"__swprintf_chk\": 4,  # int __swprintf_chk(wchar_t *str, size_t maxlen, int flag, size_t slen, const wchar_t *fmt, ...);\n        \"__obstack_printf_chk\": 2, # int __obstack_printf_chk(struct obstack *obstack, int flag, const char *fmt, ...);\n\n        \"vprintf\": 0,         # int vprintf(const char *fmt, va_list ap);\n        \"vfprintf\": 1,        # int vfprintf(FILE *stream, const char *fmt, va_list ap);\n        \"vdprintf\": 1,        # int vdprintf(int fd, const char *fmt, va_list ap);\n        \"vsprintf\": 1,        # int vsprintf(char *str, const char *fmt, va_list ap);\n        \"vasprintf\": 1,       # int vasprintf(char **strp, const char *fmt, va_list ap);\n        \"vsnprintf\": 2,       # int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);\n        \"vwprintf\": 0,        # int vwprintf(const wchar_t *fmt, va_list ap);\n        \"vfwprintf\": 1,       # int vfwprintf(FILE *stream, const wchar_t *fmt, va_list ap);\n        \"vswprintf\": 2,       # int vswprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap);\n        \"obstack_vprintf\": 1, # int obstack_vprintf(struct obstack *obstack, const char *fmt, va_list ap);\n        \"__vprintf_chk\": 1,   # int __vprintf_chk(int flag, const char *fmt, va_list ap);\n        \"__vfprintf_chk\": 2,  # int __vfprintf_chk(FILE *stream, int flag, const char *fmt, va_list ap);\n        \"__vdprintf_chk\": 2,  # int __vdprintf_chk(int d, int flag, const char *fmt, va_list ap);\n        \"__vsprintf_chk\": 3,  # int __vsprintf_chk(char *str, int flag, size_t slen, const char *fmt, va_list ap);\n        \"__vasprintf_chk\": 2, # int __vasprintf_chk(char **strp, int flag, const char *fmt, va_list ap);\n        \"__vsnprintf_chk\": 4, # int __vsnprintf_chk(char *str, size_t maxlen, int flag, size_t slen, const char *fmt, va_list ap);\n        \"__vwprintf_chk\": 1,  # int __vwprintf_chk(int flag, const wchar_t *fmt, va_list ap);\n        \"__vfwprintf_chk\": 2, # int __vfwprintf_chk(FILE *stream, int flag, const wchar_t *fmt, va_list ap);\n        \"__vswprintf_chk\": 4, # int __vswprintf_chk(wchar_t *str, size_t maxlen, int flag, size_t slen, const wchar_t *fmt, va_list ap);\n        \"__obstack_vprintf_chk\": 2, # int __obstack_vprintf_chk(struct obstack *obstack, int flag, const char *fmt, va_list ap);\n\n        \"syslog\": 1,          # void syslog(int priority, const char *fmt, ...);\n        \"vsyslog\": 1,         # void vsyslog(int priority, const char *fmt, va_list ap);\n        \"__syslog_chk\": 2,    # void __syslog_chk(int priority, int flag, const char *fmt, ...);\n        \"__vsyslog_chk\": 2,   # void __vsyslog_chk(int priority, int flag, const char *fmt, va_list ap);\n\n        \"scanf\": 0,           # int scanf(const char *fmt, ...);\n        \"fscanf\": 1,          # int fscanf(FILE *stream, const char *fmt, ...);\n        \"sscanf\": 1,          # int sscanf(const char *str, const char *fmt, ...);\n        \"wscanf\": 0,          # int wscanf(const wchar_t *fmt, ...);\n        \"fwscanf\": 1,         # int fwscanf(FILE *stream, const wchar_t *fmt, ...);\n        \"swscanf\": 1,         # int swscanf(const wchar_t *ws, const wchar_t *fmt, ...);\n\n        \"vscanf\": 0,          # int vscanf(const char *fmt, va_list ap);\n        \"vfscanf\": 1,         # int vfscanf(FILE *stream, const char *fmt, va_list ap);\n        \"vsscanf\": 1,         # int vsscanf(const char *str, const char *fmt, va_list ap);\n        \"vwscanf\": 0,         # int vwscanf(const wchar_t *fmt, va_list ap);\n        \"vfwscanf\": 1,        # int vfwscanf(FILE *stream, const wchar_t *fmt, va_list ap);\n        \"vswscanf\": 1,        # int vswscanf(const wchar_t *s, const wchar_t *fmt, va_list ap);\n\n        \"warn\": 0,            # void warn(const char *fmt, ...);\n        \"warnx\": 0,           # void warnx(const char *fmt, ...);\n        \"err\": 1,             # void err(int status, const char *fmt, ...);\n        \"errx\": 1,            # void errx(int status, const char *fmt, ...);\n\n        \"vwarn\": 0,           # void vwarn(const char *fmt, va_list ap);\n        \"vwarnx\": 0,          # void vwarnx(const char *fmt, va_list ap);\n        \"verr\": 1,            # void verr(int status, const char *fmt, va_list ap);\n        \"verrx\": 1,           # void verrx(int status, const char *fmt, va_list ap);\n\n        \"error\": 2,           # void error(int status, int errnum, const char *fmt, ...);\n        \"error_at_line\": 4,   # void error_at_line(int status, int errnum, const char *filename, uint linenum, const char *fmt, ...);\n\n        \"argp_error\": 1,      # void argp_error(const struct argp_state *state, const char *fmt, ...);\n        \"argp_failure\": 3,    # void argp_failure(const struct argp_state *state, int status, int errnum, const char *fmt, ...);\n\n        \"xasprintf\": 0,       # char* xasprintf(const char *fmt, ...);\n        \"xvasprintf\": 0,      # char* xvasprintf(const char *fmt, va_list ap);\n    }\n\n    breakpoints = []\n\n    def remove_breakpoints(self):\n        bp_count = 0\n        while FormatStringSearchCommand.breakpoints:\n            bp = FormatStringSearchCommand.breakpoints.pop()\n            bp.delete()\n            bp_count += 1\n        ok(\"Removed {:d} FormatStringBreakpoint\".format(bp_count))\n        return\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.remove_breakpoint:\n            self.remove_breakpoints()\n            return\n\n        if FormatStringSearchCommand.breakpoints:\n            err(\"Breakpoints have been set already\")\n            return\n\n        bp_count = 0\n        for func_name, num_arg in self.dangerous_functions.items():\n            try:\n                func_address = AddressUtil.parse_address(func_name)\n            except gdb.error:\n                continue\n            if args.verbose:\n                # The reason for the `end=\"\"` is that when you set a breakpoint,\n                # gdb automatically outputs the following message:\n                # printf: Breakpoint 1 at 0x7ffff7c63f90: file ./stdio-common/printf.c, line 28.\n                gef_print(func_name + \": \", end=\"\")\n            bp = FormatStringBreakpoint(func_address, func_name, num_arg, verbose=args.verbose)\n            FormatStringSearchCommand.breakpoints.append(bp)\n            bp_count += 1\n\n        ok(\"Enabled {:d}/{:d} FormatStringBreakpoint\".format(bp_count, len(self.dangerous_functions)))\n        return\n\n\nclass TraceMallocBreakpoint(gdb.Breakpoint):\n    \"\"\"Track allocations for malloc() etc.\"\"\"\n\n    def __init__(self, name, loc):\n        super().__init__(\"*{:#x}\".format(loc.value), gdb.BP_BREAKPOINT, internal=True)\n        self.silent = True\n        self.name = name\n        self.loc = loc\n        return\n\n    def check_nested(self):\n        tid = Pid.get_tid()\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ in [\"TraceMallocRetBreakpoint\", \"TraceReallocRetBreakpoint\"]:\n                    if tid == bp.tid:\n                        if bp.enabled:\n                            return True\n            except Exception:\n                pass\n        return False\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # fast return if nested break\n        if self.check_nested():\n            return False\n\n        # set bp to return address\n        if self.name in [\"malloc\", \"valloc\"]:\n            _, size = current_arch.get_ith_parameter(0)\n            nmemb = 1\n            memptr = None\n            alignment = None\n        elif self.name == \"calloc\":\n            _, nmemb = current_arch.get_ith_parameter(0)\n            _, size = current_arch.get_ith_parameter(1)\n            memptr = None\n            alignment = None\n        elif self.name in [\"aligned_alloc\", \"memalign\"]:\n            _, alignment = current_arch.get_ith_parameter(0)\n            _, size = current_arch.get_ith_parameter(1)\n            nmemb = 1\n            memptr = None\n        elif self.name == \"posix_memalign\":\n            _, memptr = current_arch.get_ith_parameter(0)\n            _, alignment = current_arch.get_ith_parameter(1)\n            _, size = current_arch.get_ith_parameter(2)\n            nmemb = 1\n\n        TraceMallocRetBreakpoint(self.name, nmemb, size, memptr, alignment)\n        return False\n\n\nclass TraceMallocRetBreakpoint(gdb.Breakpoint):\n    \"\"\"Internal breakpoint to retrieve the return value of malloc() etc.\"\"\"\n\n    def __init__(self, name, nmemb, size, memptr, alignment):\n        ret_addr = gdb.newest_frame().older().pc()\n        super().__init__(\"*{:#x}\".format(ret_addr), gdb.BP_BREAKPOINT, internal=True)\n        self.silent = True\n        self.name = name\n        self.nmemb = nmemb\n        self.size = size\n        self.memptr = memptr\n        self.alignment = alignment\n        self.tid = Pid.get_tid()\n        GlibcHeapTracerCommand.clear_disabled_breakpoints()\n        return\n\n    def search_allocated_index(self, addr):\n        for idx, (_action_index, allocated, _size) in enumerate(GlibcHeapTracerCommand.heap_allocated_list):\n            if allocated.value == addr.value:\n                return idx\n        return None\n\n    def search_freed_index(self, addr):\n        for idx, (_action_index, freed, _size) in enumerate(GlibcHeapTracerCommand.heap_freed_list):\n            if freed.value == addr.value:\n                return idx\n        return None\n\n    def show_information(self, allocated):\n\n        def get_offset_str(v):\n            if v == 0:\n                return \"\"\n            arenas = GlibcHeap.get_all_arenas()\n            for arena in arenas:\n                if arena.heap_base is None:\n                    return \"\"\n                heap_base = arena.heap_base\n                size = to_unsigned_long(arena.system_mem)\n                if heap_base <= v < heap_base + size:\n                    return Color.colorify(\"${:+#x}\".format(v - heap_base), \"lilac\")\n            return \"\"\n\n        # show information\n        text1 = \"{:s} - {!s}{:s}{:s}\".format(\n            Color.colorify(\"Heap-Analysis\", \"bold yellow\"),\n            allocated,\n            Color.colorify(\"#{:d}\".format(GlibcHeapTracerCommand.heap_action_index), \"bold cyan\"),\n            get_offset_str(allocated.value),\n        )\n        if self.name in [\"malloc\", \"valloc\"]:\n            text2 = \"{:s}({:#x})\".format(\n                self.name, self.size,\n            )\n        elif self.name == \"calloc\":\n            text2 = \"{:s}({:#x}, {:#x})\".format(\n                self.name, self.nmemb, self.size,\n            )\n        elif self.name in [\"aligned_alloc\", \"memalign\"]:\n            text2 = \"{:s}({:#x}, {:#x})\".format(\n                self.name, self.alignment, self.size,\n            )\n        elif self.name == \"posix_memalign\":\n            text2 = \"{:s}({:#x}, {:#x}, {:#x})\".format(\n                self.name, self.memptr, self.alignment, self.size,\n            )\n        padlen = 44 - len(Color.remove_color(text1))\n        gef_print(\"{:s}{:s} = {:s}\".format(text1, \" \" * padlen, text2))\n        return\n\n    def check_inconsistency(self, allocated):\n        idx = self.search_allocated_index(allocated)\n        if idx is None:\n            return False\n\n        msg = []\n        msg.append(Color.colorify(\"Heap-Analysis\", \"bold yellow\"))\n        msg.append(\"Heap inconsistency detected:\")\n        msg.append(\"Attempting to allocate used address: {!s}\".format(allocated))\n        ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n        return True\n\n    def update_list(self, allocated):\n        # pop from freed list if it was in it\n        idx = self.search_freed_index(allocated)\n        if idx is not None:\n            GlibcHeapTracerCommand.heap_freed_list.pop(idx)\n\n        # add it to alloc-ed list\n        item = (GlibcHeapTracerCommand.heap_action_index, allocated, self.nmemb * self.size)\n        GlibcHeapTracerCommand.heap_allocated_list.append(item)\n        return\n\n    def stop(self):\n        # check if expected thread\n        if Pid.get_tid() != self.tid:\n            return False\n\n        # invalidate\n        self.enabled = False\n        Cache.reset_gef_caches()\n\n        # count up action index\n        GlibcHeapTracerCommand.heap_action_index += 1\n\n        # get returned address\n        if self.name == \"posix_memalign\":\n            allocated = read_int_from_memory(self.memptr)\n        else:\n            allocated = AddressUtil.parse_address(current_arch.return_register)\n        allocated = ProcessMap.lookup_address(allocated)\n\n        # show information\n        self.show_information(allocated)\n\n        # fast return if NULL\n        if allocated.value == 0:\n            return False\n\n        # check inconsistency\n        ret = self.check_inconsistency(allocated)\n        if ret:\n            return True # break\n\n        # update list\n        self.update_list(allocated)\n\n        return False\n\n\nclass TraceReallocBreakpoint(gdb.Breakpoint):\n    \"\"\"Track re-allocations for realloc() etc.\"\"\"\n\n    def __init__(self, name, loc):\n        super().__init__(\"*{:#x}\".format(loc.value), gdb.BP_BREAKPOINT, internal=True)\n        self.silent = True\n        self.name = name\n        self.loc = loc\n        return\n\n    def check_nested(self):\n        tid = Pid.get_tid()\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ in [\"TraceMallocRetBreakpoint\", \"TraceReallocRetBreakpoint\"]:\n                    if tid == bp.tid:\n                        if bp.enabled:\n                            return True\n            except Exception:\n                pass\n        return False\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # fast return if nested break\n        if self.check_nested():\n            return False\n\n        # set bp to return address\n        _, old_loc = current_arch.get_ith_parameter(0)\n        old_loc = ProcessMap.lookup_address(old_loc)\n        if self.name == \"realloc\":\n            nmemb = 1\n            _, size = current_arch.get_ith_parameter(1)\n        elif self.name == \"reallocarray\":\n            _, nmemb = current_arch.get_ith_parameter(1)\n            _, size = current_arch.get_ith_parameter(2)\n\n        TraceReallocRetBreakpoint(self.name, old_loc, nmemb, size)\n        return False\n\n\nclass TraceReallocRetBreakpoint(gdb.Breakpoint):\n    \"\"\"Internal breakpoint to retrieve the return value of realloc() etc.\"\"\"\n\n    def __init__(self, name, old_loc, nmemb, size):\n        ret_addr = gdb.newest_frame().older().pc()\n        super().__init__(\"*{:#x}\".format(ret_addr), gdb.BP_BREAKPOINT, internal=True)\n        self.silent = True\n        self.name = name\n        self.old_loc = old_loc\n        self.nmemb = nmemb\n        self.size = size\n        self.tid = Pid.get_tid()\n        GlibcHeapTracerCommand.clear_disabled_breakpoints()\n        return\n\n    def search_allocated_index(self, addr):\n        for idx, (_action_index, allocated, _size) in enumerate(GlibcHeapTracerCommand.heap_allocated_list):\n            if allocated.value == addr.value:\n                return idx\n        return None\n\n    def search_freed_index(self, addr):\n        for idx, (_action_index, freed, _size) in enumerate(GlibcHeapTracerCommand.heap_freed_list):\n            if freed.value == addr.value:\n                return idx\n        return None\n\n    def show_information(self, new_loc):\n\n        def get_offset_str(v):\n            if v == 0:\n                return \"\"\n            arenas = GlibcHeap.get_all_arenas()\n            for arena in arenas:\n                if arena.heap_base is None:\n                    return \"\"\n                heap_base = arena.heap_base\n                size = to_unsigned_long(arena.system_mem)\n                if heap_base <= v < heap_base + size:\n                    return Color.colorify(\"${:+#x}\".format(v - heap_base), \"lilac\")\n            return \"\"\n\n        # get action index\n        idx = self.search_allocated_index(self.old_loc)\n        if idx is None:\n            action_index_s = \"\"\n        else:\n            action_index = GlibcHeapTracerCommand.heap_allocated_list[idx][0]\n            action_index_s = \"{:s}\".format(Color.colorify(\"#{:d}\".format(action_index), \"bold cyan\"))\n\n        # check realloc result type\n        if self.old_loc.value == 0:\n            extra = Color.colorify(\"return new chunk\", \"bold yellow\")\n        elif self.old_loc.value != new_loc.value:\n            extra = Color.colorify(\"return another chunk\", \"bold red\")\n        else:\n            extra = Color.colorify(\"return same chunk\", \"bold green\")\n\n        # show information\n        text1 = \"{:s} - {!s}{:s}{:s}\".format(\n            Color.colorify(\"Heap-Analysis\", \"bold yellow\"),\n            new_loc,\n            Color.colorify(\"#{:d}\".format(GlibcHeapTracerCommand.heap_action_index), \"bold cyan\"),\n            get_offset_str(new_loc.value),\n        )\n        if self.name == \"realloc\":\n            text2 = \"{:s}({!s}{:s}{:s}, {:#x})  // {:s}\".format(\n                self.name,\n                self.old_loc if self.old_loc.value != 0 else Color.boldify(\"NULL\"),\n                action_index_s, get_offset_str(self.old_loc.value), self.size, extra,\n            )\n        elif self.name == \"reallocarray\":\n            text2 = \"{:s}({!s}{:s}{:s}, {:#x}, {:#x})  // {:s}\".format(\n                self.name,\n                self.old_loc if self.old_loc.value != 0 else Color.boldify(\"NULL\"),\n                action_index_s, get_offset_str(self.old_loc.value), self.nmemb, self.size, extra,\n            )\n        padlen = 44 - len(Color.remove_color(text1))\n        gef_print(\"{:s}{:s} = {:s}\".format(text1, \" \" * padlen, text2))\n        return\n\n    def check_double_free(self, to_free):\n        if to_free.value == 0:\n            return False\n\n        idx = self.search_freed_index(to_free)\n        if idx is None:\n            return False\n\n        msg = []\n        msg.append(Color.colorify(\"Heap-Analysis\", \"bold yellow\"))\n        msg.append(\"Double-free detected:\")\n        msg.append(\"{!s} is freed but it is already in the freed list\".format(\n            to_free,\n        ))\n        ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n        return True\n\n    def check_inconsistency(self, new_loc):\n        if self.old_loc.value == new_loc.value:\n            return False\n\n        idx = self.search_allocated_index(new_loc)\n        if idx is None:\n            return False\n\n        msg = []\n        msg.append(Color.colorify(\"Heap-Analysis\", \"bold yellow\"))\n        msg.append(\"Heap inconsistency detected:\")\n        msg.append(\"Attempting to allocate used address: {!s}\".format(new_loc))\n        ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n        return True\n\n    def update_list(self, new_loc):\n        if self.old_loc.value == 0:\n            # pop from freed list if it was in it\n            idx = self.search_freed_index(new_loc)\n            if idx is not None:\n                GlibcHeapTracerCommand.heap_freed_list.pop(idx)\n        elif self.old_loc.value != new_loc.value:\n            # pop from allocated list if it was in it\n            idx = self.search_allocated_index(self.old_loc)\n            if idx is not None:\n                GlibcHeapTracerCommand.heap_allocated_list.pop(idx)\n            # pop from freed list if it was in it\n            idx = self.search_freed_index(new_loc)\n            if idx is not None:\n                GlibcHeapTracerCommand.heap_freed_list.pop(idx)\n        else:\n            # pop from allocated list if it was in it\n            idx = self.search_allocated_index(self.old_loc)\n            if idx is not None:\n                GlibcHeapTracerCommand.heap_allocated_list.pop(idx)\n\n        # add new item to alloc-ed list\n        item = (GlibcHeapTracerCommand.heap_action_index, new_loc, self.nmemb * self.size)\n        GlibcHeapTracerCommand.heap_allocated_list.append(item)\n        return\n\n    def stop(self):\n        # check if expected thread\n        if Pid.get_tid() != self.tid:\n            return False\n\n        # invalidate\n        self.enabled = False\n        Cache.reset_gef_caches()\n\n        # count up action index\n        GlibcHeapTracerCommand.heap_action_index += 1\n\n        # get returned address\n        new_loc = AddressUtil.parse_address(current_arch.return_register)\n        new_loc = ProcessMap.lookup_address(new_loc)\n\n        # show information\n        self.show_information(new_loc)\n\n        # fast return if NULL\n        if new_loc.value == 0:\n            return False\n\n        # check double free\n        ret = self.check_double_free(self.old_loc)\n        if ret:\n            return True # break\n\n        # check inconsistency\n        ret = self.check_inconsistency(new_loc)\n        if ret:\n            return True # break\n\n        # update list\n        self.update_list(new_loc)\n\n        return False\n\n\nclass TraceFreeBreakpoint(gdb.Breakpoint):\n    \"\"\"Track calls to free() and attempts to detect inconsistencies.\"\"\"\n\n    def __init__(self, name, loc):\n        super().__init__(\"*{:#x}\".format(loc.value), gdb.BP_BREAKPOINT, internal=True)\n        self.silent = True\n        self.name = name\n        self.loc = loc\n        return\n\n    def search_allocated_index(self, addr):\n        if addr.value == 0:\n            return None\n\n        for idx, (_action_index, allocated, _size) in enumerate(GlibcHeapTracerCommand.heap_allocated_list):\n            if allocated.value == addr.value:\n                return idx\n        return None\n\n    def search_freed_index(self, addr):\n        for idx, (_action_index, freed, _size) in enumerate(GlibcHeapTracerCommand.heap_freed_list):\n            if freed.value == addr.value:\n                return idx\n        return None\n\n    def show_information(self, to_free):\n\n        def get_offset_str(v):\n            if v == 0:\n                return \"\"\n            arenas = GlibcHeap.get_all_arenas()\n            for arena in arenas:\n                if arena.heap_base is None:\n                    return \"\"\n                heap_base = arena.heap_base\n                size = to_unsigned_long(arena.system_mem)\n                if heap_base <= v < heap_base + size:\n                    return Color.colorify(\"${:+#x}\".format(v - heap_base), \"lilac\")\n            return \"\"\n\n        # get action index\n        idx = self.search_allocated_index(to_free)\n        if idx is None:\n            action_index_s = \"\"\n        else:\n            action_index = GlibcHeapTracerCommand.heap_allocated_list[idx][0]\n            action_index_s = \"{:s}\".format(Color.colorify(\"#{:d}\".format(action_index), \"bold cyan\"))\n\n        # show information\n        text1 = \"{:s} -\".format(\n            Color.colorify(\"Heap-Analysis\", \"bold yellow\"),\n        )\n        text2 = \"free({!s}{:s}{:s})\".format(\n            to_free if to_free.value != 0 else Color.boldify(\"NULL\"),\n            action_index_s, get_offset_str(to_free.value),\n        )\n        padlen = 44 - len(Color.remove_color(text1))\n        gef_print(\"{:s}{:s} = {:s}\".format(text1, \" \" * padlen, text2))\n        return\n\n    def check_double_free(self, to_free):\n        if to_free.value == 0:\n            return False\n\n        idx = self.search_freed_index(to_free)\n        if idx is None:\n            return False\n\n        msg = []\n        msg.append(Color.colorify(\"Heap-Analysis\", \"bold yellow\"))\n        msg.append(\"Double-free detected:\")\n        msg.append(\"{!s} is freed but it is already in the freed list\".format(\n            to_free,\n        ))\n        ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n        return True\n\n    def check_inconsistency(self, to_free):\n        idx = self.search_allocated_index(to_free)\n        if idx is not None:\n            return False\n\n        msg = []\n        msg.append(Color.colorify(\"Heap-Analysis\", \"bold yellow\"))\n        msg.append(\"Heap inconsistency detected:\")\n        msg.append(\"Attempting to free an unknown value: {!s}\".format(to_free))\n        ContextExtraCommand.push_context_message(\"warn\", \"\\n\".join(msg))\n        return True\n\n    def update_list(self, to_free):\n        # move from allocated list to freed list\n        idx = self.search_allocated_index(to_free)\n        item = GlibcHeapTracerCommand.heap_allocated_list.pop(idx)\n        item = (GlibcHeapTracerCommand.heap_action_index, item[1], item[2])\n        GlibcHeapTracerCommand.heap_freed_list.append(item)\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # count up action index\n        GlibcHeapTracerCommand.heap_action_index += 1\n\n        # get the address to free\n        _, to_free = current_arch.get_ith_parameter(0)\n        to_free = ProcessMap.lookup_address(to_free)\n\n        # show information\n        self.show_information(to_free)\n\n        # fast return if free(NULL)\n        if to_free.value == 0:\n            return False\n\n        # check double free\n        ret = self.check_double_free(to_free)\n        if ret:\n            return True # break\n\n        # check free(unknown address)\n        ret = self.check_inconsistency(to_free)\n        if ret:\n            return True # break\n\n        # update list\n        self.update_list(to_free)\n\n        return False\n\n\n@register_command\nclass GlibcHeapTracerCommand(GenericCommand):\n    \"\"\"Trace malloc/free to check heap integrity for UAF / Double-Free.\"\"\"\n\n    _cmdline_ = \"heap tracer\"\n    _category_ = \"05-a. Heap - Glibc\"\n    _aliases_ = [\"heap-analysis-helper\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-d\", \"--dump-current-list\", action=\"store_true\", help=\"show the tracked allocations.\")\n    parser.add_argument(\"-r\", \"--reset\", action=\"store_true\", help=\"remove breakpoints etc.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Note that splits and consolidates (which are performed inside `malloc` and `free`) are not tracked.\",\n        \"So this is not a strict trace.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    heap_allocated_list = []\n    heap_freed_list = []\n    heap_breakpoints = []\n    heap_action_index = 0\n\n    @staticmethod\n    def clear_disabled_breakpoints(force=False):\n        names = [\n            \"TraceMallocRetBreakpoint\",\n            \"TraceReallocRetBreakpoint\",\n        ]\n\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ not in names:\n                    continue\n                if force is False and bp.enabled:\n                    continue\n                bp.delete()\n            except Exception:\n                pass\n        return\n\n    def dump_tracked_allocations(self):\n        if GlibcHeapTracerCommand.heap_allocated_list:\n            ok(\"Tracked as in-use chunks:\")\n            for action_idx, addr, sz in GlibcHeapTracerCommand.heap_allocated_list:\n                gef_print(\"{:d}: {!s} = allocate({:#x})\".format(action_idx, addr, sz))\n        else:\n            ok(\"No allocated chunk tracked\")\n\n        if GlibcHeapTracerCommand.heap_freed_list:\n            ok(\"Tracked as freed chunks:\")\n            for action_idx, addr, _sz in GlibcHeapTracerCommand.heap_freed_list:\n                gef_print(\"{:#d}: free({!s})\".format(action_idx, addr))\n        else:\n            ok(\"No freed chunk tracked\")\n        return\n\n    def setup(self):\n\n        def setup_breakpoints(bp_class, name):\n            try:\n                address = AddressUtil.parse_address(name)\n                address = ProcessMap.lookup_address(address)\n            except gdb.error:\n                warn(\"breakpoint setup failed: {:#x}\".format(name))\n                return\n            bp = bp_class(name, address)\n            GlibcHeapTracerCommand.heap_breakpoints.append(bp)\n            return\n\n        self.clean(None)\n\n        ok(\"Tracking malloc()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"malloc\")\n\n        ok(\"Tracking free()\")\n        setup_breakpoints(TraceFreeBreakpoint, \"free\")\n\n        ok(\"Tracking realloc()\")\n        setup_breakpoints(TraceReallocBreakpoint, \"realloc\")\n        ok(\"Tracking reallocarray()\")\n        setup_breakpoints(TraceReallocBreakpoint, \"reallocarray\")\n\n        ok(\"Tracking calloc()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"calloc\")\n\n        ok(\"Tracking aligned_alloc()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"aligned_alloc\")\n        ok(\"Tracking memalign()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"memalign\")\n        ok(\"Tracking posix_memalign()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"posix_memalign\")\n        ok(\"Tracking valloc()\")\n        setup_breakpoints(TraceMallocBreakpoint, \"valloc\")\n\n        EventHooking.gef_on_exit_hook(self.clean)\n        return\n\n    def clean(self, event):\n        ok(\"{:s} - Cleaning up\".format(Color.colorify(\"Heap-Analysis\", \"bold yellow\")))\n        for bp in GlibcHeapTracerCommand.heap_breakpoints:\n            try:\n                bp.delete()\n            except Exception:\n                pass\n\n        GlibcHeapTracerCommand.clear_disabled_breakpoints(force=True)\n        GlibcHeapTracerCommand.heap_breakpoints = []\n        GlibcHeapTracerCommand.heap_allocated_list = []\n        GlibcHeapTracerCommand.heap_freed_list = []\n        GlibcHeapTracerCommand.heap_action_index = 0\n\n        try:\n            EventHooking.gef_on_exit_unhook(self.clean)\n        except Exception:\n            pass\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.dump_current_list:\n            self.dump_tracked_allocations()\n            return\n\n        if args.reset:\n            self.clean(None)\n            return\n\n        self.setup()\n        return\n\n\n@register_command\nclass SyscallSearchCommand(GenericCommand, BufferingOutput):\n    \"\"\"Search for the syscall number for a specified architecture.\"\"\"\n\n    _cmdline_ = \"syscall-search\"\n    _category_ = \"01-g. Debugging Support - Syscall\"\n    _aliases_ = [\"ss\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", dest=\"arch\", help=\"specify the architecture. (default: current_arch.arch)\")\n    parser.add_argument(\"-m\", dest=\"mode\", help=\"specify the mode. (default: current_arch.mode)\")\n    parser.add_argument(\"search_pattern\", metavar=\"SYSCALL_NAME|SYSCALL_NUM\", nargs=\"?\", default=\".\",\n                        help=\"syscall name or number to search. Regex is available.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display prototype of syscall.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} -a X86 -m 64       \"^writev?\"  # amd64',\n        '{0:s} -a X86 -m 32       \"^writev?\"  # i386 on amd64',\n        '{0:s} -a X86 -m N32      \"^writev?\"  # i386 native',\n        '{0:s} -a ARM64 -m ARM    \"^writev?\"  # arm64',\n        '{0:s} -a ARM -m 32       \"^writev?\"  # arm32 on arm64',\n        '{0:s} -a ARM -m N32      \"^writev?\"  # arm32 native',\n        '{0:s} -a MIPS -m 32      \"^writev?\"  # mips32',\n        '{0:s} -a MIPS -m n32     \"^writev?\"  # mipsn32',\n        '{0:s} -a MIPS -m 64      \"^writev?\"  # mips64',\n        '{0:s} -a PPC -m 32       \"^writev?\"  # ppc32',\n        '{0:s} -a PPC -m 64       \"^writev?\"  # ppc64',\n        '{0:s} -a SPARC -m 32     \"^writev?\"  # sparc32',\n        '{0:s} -a SPARC -m 32PLUS \"^writev?\"  # sparc32plus',\n        '{0:s} -a SPARC -m 64     \"^writev?\"  # sparc64',\n        '{0:s} -a RISCV -m 32     \"^writev?\"  # riscv32',\n        '{0:s} -a RISCV -m 64     \"^writev?\"  # riscv64',\n        '{0:s} -a S390X           \"^writev?\"  # s390x',\n        '{0:s} -a SH4             \"^writev?\"  # sh4',\n        '{0:s} -a M68K -m 32      \"^writev?\"  # m68k',\n        '{0:s} -a ALPHA           \"^writev?\"  # alpha',\n        '{0:s} -a HPPA -m 32      \"^writev?\"  # hppa32',\n        '{0:s} -a HPPA -m 64      \"^writev?\"  # hppa64',\n        '{0:s} -a OR1K            \"^writev?\"  # or1k',\n        '{0:s} -a NIOS2           \"^writev?\"  # nios2',\n        '{0:s} -a MICROBLAZE      \"^writev?\"  # microblaze',\n        '{0:s} -a XTENSA          \"^writev?\"  # xtensa',\n        '{0:s} -a CRIS            \"^writev?\"  # cris',\n        '{0:s} -a LOONGARCH -m 64 \"^writev?\"  # loongarch64',\n        '{0:s} -a ARC -m 32       \"^writev?\"  # arc32',\n        '{0:s} -a ARC -m 64       \"^writev?\"  # arc64',\n        '{0:s} -a CSKY            \"^writev?\"  # csky',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def make_output(self, syscall_table, syscall_num, syscall_name_pattern):\n        self.out.append(titlify(\"arch={:s}, mode={:s}\".format(syscall_table.arch, syscall_table.mode)))\n\n        fmt = \"{:<17}{:s}\"\n        legend = [\"Syscall Num\", \"Syscall Name\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for entry in syscall_table.nr_table.values():\n            if not re.search(syscall_name_pattern, entry.name):\n                continue\n            if syscall_num is not None and entry.nr != syscall_num:\n                continue\n            params = \"\"\n            if self.args.verbose:\n                params = \"(\" + \", \".join(entry.args_full) + \");\"\n            self.out.append(\"NR={:<#14x}{:s}{:s}\".format(entry.nr, Color.boldify(entry.name), params))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        syscall_num = None\n        syscall_name_pattern = \".*\"\n\n        target_arch = args.arch\n        target_mode = args.mode\n        # force fixing\n        if target_arch and target_mode is None:\n            arch_need_not_mode = [\"SH4\", \"ALPHA\", \"OR1K\", \"NIOS2\", \"MICROBLAZE\", \"XTENSA\", \"CRIS\", \"CSKY\"]\n            if target_arch.upper() in arch_need_not_mode:\n                target_arch = target_arch.upper()\n                target_mode = target_arch.upper()\n            if target_arch.upper() in [\"S390X\"]:\n                target_arch = \"S390X\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"ARM64\", \"AARCH64\"]:\n                target_arch = \"ARM64\"\n                target_mode = \"ARM\"\n            if target_arch.upper() in [\"ARM\", \"ARM32\"]:\n                target_arch = \"ARM\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"X86_64\", \"X86-64\", \"X64\"]:\n                target_arch = \"X86\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"X86_32\", \"X86-32\", \"X86\"]:\n                target_arch = \"X86\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"MIPS32\"]:\n                target_arch = \"MIPS\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"MIPS64\"]:\n                target_arch = \"MIPS\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"PPC32\"]:\n                target_arch = \"PPC\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"PPC64\"]:\n                target_arch = \"PPC\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"SPARC32\"]:\n                target_arch = \"SPARC\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"SPARC64\"]:\n                target_arch = \"SPARC\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"RISCV32\"]:\n                target_arch = \"RISCV\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"RISCV64\"]:\n                target_arch = \"RISCV\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"ARC32\"]:\n                target_arch = \"ARC\"\n                target_mode = \"32\"\n            if target_arch.upper() in [\"ARC64\"]:\n                target_arch = \"ARC\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"LOONGARCH\"]:\n                target_arch = \"LOONGARCH\"\n                target_mode = \"64\"\n            if target_arch.upper() in [\"M68K\"]:\n                target_arch = \"M68K\"\n                target_mode = \"32\"\n\n        try:\n            syscall_num = int(args.search_pattern, 0)\n        except ValueError:\n            syscall_name_pattern = args.search_pattern\n\n        syscall_table = get_syscall_table(target_arch, target_mode)\n        if syscall_table is None:\n            err(\"Please specify the valid architecture.\")\n            self.usage()\n            return\n\n        self.out = []\n        self.make_output(syscall_table, syscall_num, syscall_name_pattern)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n# System call table (linux-6.10)\n\n# [How to make]\n# clang-format --style='{BasedOnStyle: Google, ColumnLimit: 1000}' FILENAME | grep ^asmlinkage\n#   `!` at the beginning of the line: manually fixed the argument information\n#   `#` at the beginning of the line: excluded for reasons such as duplication\n\n# include/linux/syscalls.h\nsyscall_defs = \"\"\"\nasmlinkage long sys_io_setup(unsigned nr_reqs, aio_context_t __user *ctx);\nasmlinkage long sys_io_destroy(aio_context_t ctx);\n!asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, struct iocb __user * __user *iocbpp);\nasmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, struct io_event __user *result);\nasmlinkage long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event __user *events, struct __kernel_timespec __user *timeout);\nasmlinkage long sys_io_getevents_time32(__u32 ctx_id, __s32 min_nr, __s32 nr, struct io_event __user *events, struct old_timespec32 __user *timeout);\nasmlinkage long sys_io_pgetevents(aio_context_t ctx_id, long min_nr, long nr, struct io_event __user *events, struct __kernel_timespec __user *timeout, const struct __aio_sigset __user *sig);\nasmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, long min_nr, long nr, struct io_event __user *events, struct old_timespec32 __user *timeout, const struct __aio_sigset __user *sig);\nasmlinkage long sys_io_uring_setup(u32 entries, struct io_uring_params __user *p);\nasmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, u32 min_complete, u32 flags, const void __user *argp, size_t argsz);\nasmlinkage long sys_io_uring_register(unsigned int fd, unsigned int op, void __user *arg, unsigned int nr_args);\nasmlinkage long sys_setxattr(const char __user *path, const char __user *name, const void __user *value, size_t size, int flags);\nasmlinkage long sys_setxattrat(int dfd, const char __user *path, unsigned int at_flags, const char __user *name, const struct xattr_args __user *args, size_t size);\nasmlinkage long sys_lsetxattr(const char __user *path, const char __user *name, const void __user *value, size_t size, int flags);\nasmlinkage long sys_fsetxattr(int fd, const char __user *name, const void __user *value, size_t size, int flags);\nasmlinkage long sys_getxattr(const char __user *path, const char __user *name, void __user *value, size_t size);\nasmlinkage long sys_getxattrat(int dfd, const char __user *path, unsigned int at_flags, const char __user *name, struct xattr_args __user *args, size_t size);\nasmlinkage long sys_lgetxattr(const char __user *path, const char __user *name, void __user *value, size_t size);\nasmlinkage long sys_fgetxattr(int fd, const char __user *name, void __user *value, size_t size);\nasmlinkage long sys_listxattr(const char __user *path, char __user *list, size_t size);\nasmlinkage long sys_listxattrat(int dfd, const char __user *path, unsigned int at_flags, char __user *list, size_t size);\nasmlinkage long sys_llistxattr(const char __user *path, char __user *list, size_t size);\nasmlinkage long sys_flistxattr(int fd, char __user *list, size_t size);\nasmlinkage long sys_removexattr(const char __user *path, const char __user *name);\nasmlinkage long sys_removexattrat(int dfd, const char __user *path, unsigned int at_flags, const char __user *name);\nasmlinkage long sys_lremovexattr(const char __user *path, const char __user *name);\nasmlinkage long sys_fremovexattr(int fd, const char __user *name);\nasmlinkage long sys_file_getattr(int dfd, const char __user *filename, struct file_attr __user *attr, size_t usize, unsigned int at_flags);\nasmlinkage long sys_file_setattr(int dfd, const char __user *filename, struct file_attr __user *attr, size_t usize, unsigned int at_flags);\nasmlinkage long sys_getcwd(char __user *buf, unsigned long size);\nasmlinkage long sys_eventfd2(unsigned int count, int flags);\nasmlinkage long sys_epoll_create1(int flags);\nasmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event);\nasmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, int maxevents, int timeout, const sigset_t __user *sigmask, size_t sigsetsize);\nasmlinkage long sys_epoll_pwait2(int epfd, struct epoll_event __user *events, int maxevents, const struct __kernel_timespec __user *timeout, const sigset_t __user *sigmask, size_t sigsetsize);\nasmlinkage long sys_dup(unsigned int fildes);\nasmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags);\nasmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);\nasmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);\nasmlinkage long sys_inotify_init1(int flags);\nasmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask);\nasmlinkage long sys_inotify_rm_watch(int fd, __s32 wd);\nasmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);\nasmlinkage long sys_ioprio_set(int which, int who, int ioprio);\nasmlinkage long sys_ioprio_get(int which, int who);\nasmlinkage long sys_flock(unsigned int fd, unsigned int cmd);\nasmlinkage long sys_mknodat(int dfd, const char __user *filename, umode_t mode, unsigned dev);\nasmlinkage long sys_mkdirat(int dfd, const char __user *pathname, umode_t mode);\nasmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag);\nasmlinkage long sys_symlinkat(const char __user *oldname, int newdfd, const char __user *newname);\nasmlinkage long sys_linkat(int olddfd, const char __user *oldname, int newdfd, const char __user *newname, int flags);\nasmlinkage long sys_renameat(int olddfd, const char __user *oldname, int newdfd, const char __user *newname);\nasmlinkage long sys_umount(char __user *name, int flags);\nasmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, char __user *type, unsigned long flags, void __user *data);\nasmlinkage long sys_pivot_root(const char __user *new_root, const char __user *put_old);\nasmlinkage long sys_statfs(const char __user *path, struct statfs __user *buf);\nasmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf);\nasmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf);\nasmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf);\nasmlinkage long sys_statmount(const struct mnt_id_req __user *req, struct statmount __user *buf, size_t bufsize, unsigned int flags);\nasmlinkage long sys_listmount(const struct mnt_id_req __user *req, u64 __user *mnt_ids, size_t nr_mnt_ids, unsigned int flags);\nasmlinkage long sys_listns(const struct ns_id_req __user *req, u64 __user *ns_ids, size_t nr_ns_ids, unsigned int flags);\nasmlinkage long sys_truncate(const char __user *path, long length);\nasmlinkage long sys_ftruncate(unsigned int fd, off_t length);\nasmlinkage long sys_truncate64(const char __user *path, loff_t length);\nasmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);\nasmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);\nasmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode);\nasmlinkage long sys_faccessat2(int dfd, const char __user *filename, int mode, int flags);\nasmlinkage long sys_chdir(const char __user *filename);\nasmlinkage long sys_fchdir(unsigned int fd);\nasmlinkage long sys_chroot(const char __user *filename);\nasmlinkage long sys_fchmod(unsigned int fd, umode_t mode);\nasmlinkage long sys_fchmodat(int dfd, const char __user *filename, umode_t mode);\nasmlinkage long sys_fchmodat2(int dfd, const char __user *filename, umode_t mode, unsigned int flags);\nasmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, int flag);\nasmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);\nasmlinkage long sys_openat(int dfd, const char __user *filename, int flags, umode_t mode);\nasmlinkage long sys_openat2(int dfd, const char __user *filename, struct open_how __user *how, size_t size);\nasmlinkage long sys_close(unsigned int fd);\nasmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags);\nasmlinkage long sys_vhangup(void);\nasmlinkage long sys_pipe2(int __user *fildes, int flags);\nasmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr);\nasmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id, void __user *addr);\nasmlinkage long sys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, unsigned int count);\nasmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t __user *result, unsigned int whence);\nasmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int whence);\nasmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count);\nasmlinkage long sys_write(unsigned int fd, const char __user *buf, size_t count);\nasmlinkage long sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen);\nasmlinkage long sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen);\nasmlinkage long sys_pread64(unsigned int fd, char __user *buf, size_t count, loff_t pos);\nasmlinkage long sys_pwrite64(unsigned int fd, const char __user *buf, size_t count, loff_t pos);\nasmlinkage long sys_preadv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h);\nasmlinkage long sys_pwritev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h);\nasmlinkage long sys_sendfile64(int out_fd, int in_fd, loff_t __user *offset, size_t count);\n!asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_timespec __user *tsp, void __user *sig);\n!asmlinkage long sys_pselect6_time32(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct old_timespec32 __user *tsp, void __user *sig);\n!asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, struct __kernel_timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize);\n!asmlinkage long sys_ppoll_time32(struct pollfd __user *ufds, unsigned int nfds, struct old_timespec32 __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize);\nasmlinkage long sys_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, int flags);\nasmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov, unsigned long nr_segs, unsigned int flags);\nasmlinkage long sys_splice(int fd_in, loff_t __user *off_in, int fd_out, loff_t __user *off_out, size_t len, unsigned int flags);\nasmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags);\nasmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, int bufsiz);\nasmlinkage long sys_newfstatat(int dfd, const char __user *filename, struct stat __user *statbuf, int flag);\nasmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);\nasmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);\nasmlinkage long sys_fstatat64(int dfd, const char __user *filename, struct stat64 __user *statbuf, int flag);\nasmlinkage long sys_sync(void);\nasmlinkage long sys_fsync(unsigned int fd);\nasmlinkage long sys_fdatasync(unsigned int fd);\nasmlinkage long sys_sync_file_range2(int fd, unsigned int flags, loff_t offset, loff_t nbytes);\nasmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags);\nasmlinkage long sys_timerfd_create(int clockid, int flags);\nasmlinkage long sys_timerfd_settime(int ufd, int flags, const struct __kernel_itimerspec __user *utmr, struct __kernel_itimerspec __user *otmr);\nasmlinkage long sys_timerfd_gettime(int ufd, struct __kernel_itimerspec __user *otmr);\nasmlinkage long sys_timerfd_gettime32(int ufd, struct old_itimerspec32 __user *otmr);\nasmlinkage long sys_timerfd_settime32(int ufd, int flags, const struct old_itimerspec32 __user *utmr, struct old_itimerspec32 __user *otmr);\nasmlinkage long sys_utimensat(int dfd, const char __user *filename, struct __kernel_timespec __user *utimes, int flags);\nasmlinkage long sys_utimensat_time32(unsigned int dfd, const char __user *filename, struct old_timespec32 __user *t, int flags);\nasmlinkage long sys_acct(const char __user *name);\nasmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr);\nasmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data);\nasmlinkage long sys_personality(unsigned int personality);\nasmlinkage long sys_exit(int error_code);\nasmlinkage long sys_exit_group(int error_code);\nasmlinkage long sys_waitid(int which, pid_t pid, struct siginfo __user *infop, int options, struct rusage __user *ru);\nasmlinkage long sys_set_tid_address(int __user *tidptr);\nasmlinkage long sys_unshare(unsigned long unshare_flags);\nasmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, const struct __kernel_timespec __user *utime, u32 __user *uaddr2, u32 val3);\nasmlinkage long sys_futex_time32(u32 __user *uaddr, int op, u32 val, const struct old_timespec32 __user *utime, u32 __user *uaddr2, u32 val3);\nasmlinkage long sys_get_robust_list(int pid, struct robust_list_head __user *__user *head_ptr, size_t __user *len_ptr);\nasmlinkage long sys_set_robust_list(struct robust_list_head __user *head, size_t len);\nasmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, unsigned int nr_futexes, unsigned int flags, struct __kernel_timespec __user *timeout, clockid_t clockid);\nasmlinkage long sys_futex_wake(void __user *uaddr, unsigned long mask, int nr, unsigned int flags);\nasmlinkage long sys_futex_wait(void __user *uaddr, unsigned long val, unsigned long mask, unsigned int flags, struct __kernel_timespec __user *timespec, clockid_t clockid);\nasmlinkage long sys_futex_requeue(struct futex_waitv __user *waiters, unsigned int flags, int nr_wake, int nr_requeue);\nasmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp, struct __kernel_timespec __user *rmtp);\nasmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, struct old_timespec32 __user *rmtp);\nasmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value);\nasmlinkage long sys_setitimer(int which, struct __kernel_old_itimerval __user *value, struct __kernel_old_itimerval __user *ovalue);\nasmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment __user *segments, unsigned long flags);\nasmlinkage long sys_init_module(void __user *umod, unsigned long len, const char __user *uargs);\nasmlinkage long sys_delete_module(const char __user *name_user, unsigned int flags);\nasmlinkage long sys_timer_create(clockid_t which_clock, struct sigevent __user *timer_event_spec, timer_t __user *created_timer_id);\nasmlinkage long sys_timer_gettime(timer_t timer_id, struct __kernel_itimerspec __user *setting);\nasmlinkage long sys_timer_getoverrun(timer_t timer_id);\nasmlinkage long sys_timer_settime(timer_t timer_id, int flags, const struct __kernel_itimerspec __user *new_setting, struct __kernel_itimerspec __user *old_setting);\nasmlinkage long sys_timer_delete(timer_t timer_id);\nasmlinkage long sys_clock_settime(clockid_t which_clock, const struct __kernel_timespec __user *tp);\nasmlinkage long sys_clock_gettime(clockid_t which_clock, struct __kernel_timespec __user *tp);\nasmlinkage long sys_clock_getres(clockid_t which_clock, struct __kernel_timespec __user *tp);\nasmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags, const struct __kernel_timespec __user *rqtp, struct __kernel_timespec __user *rmtp);\nasmlinkage long sys_timer_gettime32(timer_t timer_id, struct old_itimerspec32 __user *setting);\nasmlinkage long sys_timer_settime32(timer_t timer_id, int flags, struct old_itimerspec32 __user *new, struct old_itimerspec32 __user *old);\nasmlinkage long sys_clock_settime32(clockid_t which_clock, struct old_timespec32 __user *tp);\nasmlinkage long sys_clock_gettime32(clockid_t which_clock, struct old_timespec32 __user *tp);\nasmlinkage long sys_clock_getres_time32(clockid_t which_clock, struct old_timespec32 __user *tp);\nasmlinkage long sys_clock_nanosleep_time32(clockid_t which_clock, int flags, struct old_timespec32 __user *rqtp, struct old_timespec32 __user *rmtp);\nasmlinkage long sys_syslog(int type, char __user *buf, int len);\nasmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data);\nasmlinkage long sys_sched_setparam(pid_t pid, struct sched_param __user *param);\nasmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param);\nasmlinkage long sys_sched_getscheduler(pid_t pid);\nasmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param);\nasmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr);\nasmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr);\nasmlinkage long sys_sched_yield(void);\nasmlinkage long sys_sched_get_priority_max(int policy);\nasmlinkage long sys_sched_get_priority_min(int policy);\nasmlinkage long sys_sched_rr_get_interval(pid_t pid, struct __kernel_timespec __user *interval);\nasmlinkage long sys_sched_rr_get_interval_time32(pid_t pid, struct old_timespec32 __user *interval);\nasmlinkage long sys_restart_syscall(void);\nasmlinkage long sys_kill(pid_t pid, int sig);\nasmlinkage long sys_tkill(pid_t pid, int sig);\nasmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig);\nasmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, struct sigaltstack __user *uoss);\nasmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);\n!asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, size_t sigsetsize);\nasmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, sigset_t __user *oset, size_t sigsetsize);\nasmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize);\nasmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese, siginfo_t __user *uinfo, const struct __kernel_timespec __user *uts, size_t sigsetsize);\nasmlinkage long sys_rt_sigtimedwait_time32(const sigset_t __user *uthese, siginfo_t __user *uinfo, const struct old_timespec32 __user *uts, size_t sigsetsize);\nasmlinkage long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t __user *uinfo);\nasmlinkage long sys_setpriority(int which, int who, int niceval);\nasmlinkage long sys_getpriority(int which, int who);\nasmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg);\nasmlinkage long sys_setregid(gid_t rgid, gid_t egid);\nasmlinkage long sys_setgid(gid_t gid);\nasmlinkage long sys_setreuid(uid_t ruid, uid_t euid);\nasmlinkage long sys_setuid(uid_t uid);\nasmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);\nasmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid);\nasmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);\nasmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid);\nasmlinkage long sys_setfsuid(uid_t uid);\nasmlinkage long sys_setfsgid(gid_t gid);\nasmlinkage long sys_times(struct tms __user *tbuf);\nasmlinkage long sys_setpgid(pid_t pid, pid_t pgid);\nasmlinkage long sys_getpgid(pid_t pid);\nasmlinkage long sys_getsid(pid_t pid);\nasmlinkage long sys_setsid(void);\nasmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist);\nasmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist);\nasmlinkage long sys_newuname(struct new_utsname __user *name);\nasmlinkage long sys_sethostname(char __user *name, int len);\nasmlinkage long sys_setdomainname(char __user *name, int len);\nasmlinkage long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim);\nasmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim);\nasmlinkage long sys_getrusage(int who, struct rusage __user *ru);\nasmlinkage long sys_umask(int mask);\nasmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);\nasmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);\nasmlinkage long sys_gettimeofday(struct __kernel_old_timeval __user *tv, struct timezone __user *tz);\nasmlinkage long sys_settimeofday(struct __kernel_old_timeval __user *tv, struct timezone __user *tz);\nasmlinkage long sys_adjtimex(struct __kernel_timex __user *txc_p);\nasmlinkage long sys_adjtimex_time32(struct old_timex32 __user *txc_p);\nasmlinkage long sys_getpid(void);\nasmlinkage long sys_getppid(void);\nasmlinkage long sys_getuid(void);\nasmlinkage long sys_geteuid(void);\nasmlinkage long sys_getgid(void);\nasmlinkage long sys_getegid(void);\nasmlinkage long sys_gettid(void);\nasmlinkage long sys_sysinfo(struct sysinfo __user *info);\nasmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr);\nasmlinkage long sys_mq_unlink(const char __user *name);\nasmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout);\nasmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout);\nasmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification);\nasmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat);\nasmlinkage long sys_mq_timedreceive_time32(mqd_t mqdes, char __user *u_msg_ptr, unsigned int msg_len, unsigned int __user *u_msg_prio, const struct old_timespec32 __user *u_abs_timeout);\nasmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, const char __user *u_msg_ptr, unsigned int msg_len, unsigned int msg_prio, const struct old_timespec32 __user *u_abs_timeout);\nasmlinkage long sys_msgget(key_t key, int msgflg);\nasmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);\nasmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);\nasmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg);\nasmlinkage long sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg);\nasmlinkage long sys_semget(key_t key, int nsems, int semflg);\nasmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg);\nasmlinkage long sys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);\nasmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops, unsigned nsops, const struct __kernel_timespec __user *timeout);\nasmlinkage long sys_semtimedop_time32(int semid, struct sembuf __user *sops, unsigned nsops, const struct old_timespec32 __user *timeout);\nasmlinkage long sys_semop(int semid, struct sembuf __user *sops, unsigned nsops);\nasmlinkage long sys_shmget(key_t key, size_t size, int flag);\nasmlinkage long sys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);\nasmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);\nasmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg);\nasmlinkage long sys_shmdt(char __user *shmaddr);\n!asmlinkage long sys_socket(int family, int type, int protocol);\n!asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);\n!asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);\n!asmlinkage long sys_listen(int fd, int backlog);\n!asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);\n!asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);\n!asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);\n!asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);\n!asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, struct sockaddr __user *addr, int addr_len);\n!asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags, struct sockaddr __user *addr, int __user *addr_len);\nasmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);\nasmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen);\n!asmlinkage long sys_shutdown(int fd, int how);\nasmlinkage long sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags);\nasmlinkage long sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags);\nasmlinkage long sys_readahead(int fd, loff_t offset, size_t count);\nasmlinkage long sys_brk(unsigned long brk);\nasmlinkage long sys_munmap(unsigned long addr, size_t len);\nasmlinkage long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr);\nasmlinkage long sys_add_key(const char __user *_type, const char __user *_description, const void __user *_payload, size_t plen, key_serial_t destringid);\nasmlinkage long sys_request_key(const char __user *_type, const char __user *_description, const char __user *_callout_info, key_serial_t destringid);\nasmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);\n#asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, unsigned long, int __user *);\n#asmlinkage long sys_clone(unsigned long, unsigned long, int, int __user *, int __user *, unsigned long);\n#asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int __user *, unsigned long);\nasmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size);\nasmlinkage long sys_execve(const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp);\nasmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice);\nasmlinkage long sys_swapon(const char __user *specialfile, int swap_flags);\nasmlinkage long sys_swapoff(const char __user *specialfile);\nasmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot);\nasmlinkage long sys_msync(unsigned long start, size_t len, int flags);\nasmlinkage long sys_mlock(unsigned long start, size_t len);\nasmlinkage long sys_munlock(unsigned long start, size_t len);\nasmlinkage long sys_mlockall(int flags);\nasmlinkage long sys_munlockall(void);\nasmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char __user *vec);\nasmlinkage long sys_madvise(unsigned long start, size_t len, int behavior);\nasmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, size_t vlen, int behavior, unsigned int flags);\nasmlinkage long sys_process_mrelease(int pidfd, unsigned int flags);\nasmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags);\nasmlinkage long sys_mseal(unsigned long start, size_t len, unsigned long flags);\nasmlinkage long sys_mbind(unsigned long start, unsigned long len, unsigned long mode, const unsigned long __user *nmask, unsigned long maxnode, unsigned flags);\nasmlinkage long sys_get_mempolicy(int __user *policy, unsigned long __user *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags);\nasmlinkage long sys_set_mempolicy(int mode, const unsigned long __user *nmask, unsigned long maxnode);\nasmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, const unsigned long __user *from, const unsigned long __user *to);\nasmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, const void __user *__user *pages, const int __user *nodes, int __user *status, int flags);\nasmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t __user *uinfo);\nasmlinkage long sys_perf_event_open(struct perf_event_attr __user *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags);\n!asmlinkage long sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen, int flags);\nasmlinkage long sys_recvmmsg(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags, struct __kernel_timespec __user *timeout);\nasmlinkage long sys_recvmmsg_time32(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags, struct old_timespec32 __user *timeout);\nasmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru);\nasmlinkage long sys_prlimit64(pid_t pid, unsigned int resource, const struct rlimit64 __user *new_rlim, struct rlimit64 __user *old_rlim);\nasmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags);\n#asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, unsigned int mask_1, unsigned int mask_2, int dfd, const char __user *pathname);\n#asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags, u64 mask, int fd, const char __user *pathname);\nasmlinkage long sys_name_to_handle_at(int dfd, const char __user *name, struct file_handle __user *handle, void __user *mnt_id, int flag);\nasmlinkage long sys_open_by_handle_at(int mountdirfd, struct file_handle __user *handle, int flags);\nasmlinkage long sys_clock_adjtime(clockid_t which_clock, struct __kernel_timex __user *tx);\nasmlinkage long sys_clock_adjtime32(clockid_t which_clock, struct old_timex32 __user *tx);\nasmlinkage long sys_syncfs(int fd);\nasmlinkage long sys_setns(int fd, int nstype);\nasmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags);\nasmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags);\nasmlinkage long sys_process_vm_readv(pid_t pid, const struct iovec __user *lvec, unsigned long liovcnt, const struct iovec __user *rvec, unsigned long riovcnt, unsigned long flags);\nasmlinkage long sys_process_vm_writev(pid_t pid, const struct iovec __user *lvec, unsigned long liovcnt, const struct iovec __user *rvec, unsigned long riovcnt, unsigned long flags);\nasmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2);\nasmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);\nasmlinkage long sys_sched_setattr(pid_t pid, struct sched_attr __user *attr, unsigned int flags);\nasmlinkage long sys_sched_getattr(pid_t pid, struct sched_attr __user *attr, unsigned int size, unsigned int flags);\nasmlinkage long sys_renameat2(int olddfd, const char __user *oldname, int newdfd, const char __user *newname, unsigned int flags);\nasmlinkage long sys_seccomp(unsigned int op, unsigned int flags, void __user *uargs);\nasmlinkage long sys_getrandom(char __user *buf, size_t count, unsigned int flags);\nasmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags);\nasmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size);\nasmlinkage long sys_execveat(int dfd, const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp, int flags);\nasmlinkage long sys_userfaultfd(int flags);\nasmlinkage long sys_membarrier(int cmd, unsigned int flags, int cpu_id);\nasmlinkage long sys_mlock2(unsigned long start, size_t len, int flags);\nasmlinkage long sys_copy_file_range(int fd_in, loff_t __user *off_in, int fd_out, loff_t __user *off_out, size_t len, unsigned int flags);\nasmlinkage long sys_preadv2(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags);\nasmlinkage long sys_pwritev2(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags);\nasmlinkage long sys_pkey_mprotect(unsigned long start, size_t len, unsigned long prot, int pkey);\nasmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val);\nasmlinkage long sys_pkey_free(int pkey);\nasmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, unsigned mask, struct statx __user *buffer);\nasmlinkage long sys_rseq(struct rseq __user *rseq, uint32_t rseq_len, int flags, uint32_t sig);\nasmlinkage long sys_open_tree(int dfd, const char __user *path, unsigned flags);\nasmlinkage long sys_open_tree_attr(int dfd, const char __user *path, unsigned flags, struct mount_attr __user *uattr, size_t usize);\nasmlinkage long sys_move_mount(int from_dfd, const char __user *from_path, int to_dfd, const char __user *to_path, unsigned int ms_flags);\nasmlinkage long sys_mount_setattr(int dfd, const char __user *path, unsigned int flags, struct mount_attr __user *uattr, size_t usize);\nasmlinkage long sys_fsopen(const char __user *fs_name, unsigned int flags);\nasmlinkage long sys_fsconfig(int fs_fd, unsigned int cmd, const char __user *key, const void __user *value, int aux);\nasmlinkage long sys_fsmount(int fs_fd, unsigned int flags, unsigned int ms_flags);\nasmlinkage long sys_fspick(int dfd, const char __user *path, unsigned int flags);\nasmlinkage long sys_pidfd_send_signal(int pidfd, int sig, siginfo_t __user *info, unsigned int flags);\nasmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);\nasmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr __user *attr, size_t size, __u32 flags);\nasmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type, const void __user *rule_attr, __u32 flags);\nasmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags);\nasmlinkage long sys_memfd_secret(unsigned int flags);\nasmlinkage long sys_set_mempolicy_home_node(unsigned long start, unsigned long len, unsigned long home_node, unsigned long flags);\nasmlinkage long sys_cachestat(unsigned int fd, struct cachestat_range __user *cstat_range, struct cachestat __user *cstat, unsigned int flags);\nasmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags);\nasmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, u32 __user *size, u32 flags);\nasmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, u32 size, u32 flags);\nasmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags);\nasmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);\nasmlinkage long sys_uretprobe(void);\nasmlinkage long sys_uprobe(void);\nasmlinkage long sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len, void __user *buf);\nasmlinkage long sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len, void __user *buf);\nasmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn);\nasmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus);\nasmlinkage long sys_spu_create(const char __user *name, unsigned int flags, umode_t mode, int fd);\nasmlinkage long sys_open(const char __user *filename, int flags, umode_t mode);\nasmlinkage long sys_link(const char __user *oldname, const char __user *newname);\nasmlinkage long sys_unlink(const char __user *pathname);\nasmlinkage long sys_mknod(const char __user *filename, umode_t mode, unsigned dev);\nasmlinkage long sys_chmod(const char __user *filename, umode_t mode);\nasmlinkage long sys_chown(const char __user *filename, uid_t user, gid_t group);\nasmlinkage long sys_mkdir(const char __user *pathname, umode_t mode);\nasmlinkage long sys_rmdir(const char __user *pathname);\nasmlinkage long sys_lchown(const char __user *filename, uid_t user, gid_t group);\nasmlinkage long sys_access(const char __user *filename, int mode);\nasmlinkage long sys_rename(const char __user *oldname, const char __user *newname);\nasmlinkage long sys_symlink(const char __user *old, const char __user *new);\nasmlinkage long sys_stat64(const char __user *filename, struct stat64 __user *statbuf);\nasmlinkage long sys_lstat64(const char __user *filename, struct stat64 __user *statbuf);\nasmlinkage long sys_pipe(int __user *fildes);\nasmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd);\nasmlinkage long sys_epoll_create(int size);\nasmlinkage long sys_inotify_init(void);\nasmlinkage long sys_eventfd(unsigned int count);\nasmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);\nasmlinkage long sys_sendfile(int out_fd, int in_fd, off_t __user *offset, size_t count);\nasmlinkage long sys_newstat(const char __user *filename, struct stat __user *statbuf);\nasmlinkage long sys_newlstat(const char __user *filename, struct stat __user *statbuf);\nasmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice);\nasmlinkage long sys_alarm(unsigned int seconds);\nasmlinkage long sys_getpgrp(void);\nasmlinkage long sys_pause(void);\nasmlinkage long sys_time(__kernel_old_time_t __user *tloc);\nasmlinkage long sys_time32(old_time32_t __user *tloc);\nasmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times);\nasmlinkage long sys_utimes(char __user *filename, struct __kernel_old_timeval __user *utimes);\nasmlinkage long sys_futimesat(int dfd, const char __user *filename, struct __kernel_old_timeval __user *utimes);\nasmlinkage long sys_futimesat_time32(unsigned int dfd, const char __user *filename, struct old_timeval32 __user *t);\nasmlinkage long sys_utime32(const char __user *filename, struct old_utimbuf32 __user *t);\nasmlinkage long sys_utimes_time32(const char __user *filename, struct old_timeval32 __user *t);\nasmlinkage long sys_creat(const char __user *pathname, umode_t mode);\nasmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count);\nasmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_old_timeval __user *tvp);\nasmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, int timeout);\nasmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, int maxevents, int timeout);\nasmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);\nasmlinkage long sys_vfork(void);\nasmlinkage long sys_recv(int, void __user *, size_t, unsigned);\nasmlinkage long sys_send(int, void __user *, size_t, unsigned);\nasmlinkage long sys_oldumount(char __user *name);\nasmlinkage long sys_uselib(const char __user *library);\nasmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2);\nasmlinkage long sys_fork(void);\nasmlinkage long sys_stime(__kernel_old_time_t __user *tptr);\nasmlinkage long sys_stime32(old_time32_t __user *tptr);\nasmlinkage long sys_sigpending(old_sigset_t __user *uset);\nasmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, old_sigset_t __user *oset);\nasmlinkage long sys_sigsuspend(old_sigset_t mask);\n#asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask);\nasmlinkage long sys_sigaction(int, const struct old_sigaction __user *, struct old_sigaction __user *);\nasmlinkage long sys_sgetmask(void);\nasmlinkage long sys_ssetmask(int newmask);\nasmlinkage long sys_signal(int sig, __sighandler_t handler);\nasmlinkage long sys_nice(int increment);\nasmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char __user *cmdline_ptr, unsigned long flags);\nasmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);\nasmlinkage long sys_chown16(const char __user *filename, old_uid_t user, old_gid_t group);\nasmlinkage long sys_lchown16(const char __user *filename, old_uid_t user, old_gid_t group);\nasmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group);\nasmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid);\nasmlinkage long sys_setgid16(old_gid_t gid);\nasmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid);\nasmlinkage long sys_setuid16(old_uid_t uid);\nasmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid);\nasmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid);\nasmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid);\nasmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid);\nasmlinkage long sys_setfsuid16(old_uid_t uid);\nasmlinkage long sys_setfsgid16(old_gid_t gid);\nasmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist);\nasmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist);\nasmlinkage long sys_getuid16(void);\nasmlinkage long sys_geteuid16(void);\nasmlinkage long sys_getgid16(void);\nasmlinkage long sys_getegid16(void);\nasmlinkage long sys_socketcall(int call, unsigned long __user *args);\nasmlinkage long sys_stat(const char __user *filename, struct __old_kernel_stat __user *statbuf);\nasmlinkage long sys_lstat(const char __user *filename, struct __old_kernel_stat __user *statbuf);\nasmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat __user *statbuf);\nasmlinkage long sys_readlink(const char __user *path, char __user *buf, int bufsiz);\nasmlinkage long sys_old_select(struct sel_arg_struct __user *arg);\nasmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int);\nasmlinkage long sys_gethostname(char __user *name, int len);\nasmlinkage long sys_uname(struct old_utsname __user *);\nasmlinkage long sys_olduname(struct oldold_utsname __user *);\nasmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim);\nasmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, unsigned long third, void __user *ptr, long fifth);\nasmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff);\nasmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);\n#asmlinkage long sys_ni_syscall(void);\nasmlinkage long sys_ni_posix_timers(void);\n\"\"\"\n\n\n# include/linux/compat.h\nsyscall_defs_compat = \"\"\"\nasmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p);\nasmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr, u32 __user *iocb);\n!asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct old_timespec32 __user *timeout, const struct __compat_aio_sigset __user *usig); # codespell:ignore\n!asmlinkage long compat_sys_io_pgetevents_time64(compat_aio_context_t ctx_id, compat_long_t min_nr, compat_long_t nr, struct io_event __user *events, struct __kernel_timespec __user *timeout, const struct __compat_aio_sigset __user *usig); # codespell:ignore\nasmlinkage long compat_sys_epoll_pwait(int epfd, struct epoll_event __user *events, int maxevents, int timeout, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize);\nasmlinkage long compat_sys_epoll_pwait2(int epfd, struct epoll_event __user *events, int maxevents, const struct __kernel_timespec __user *timeout, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize);\nasmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd, compat_ulong_t arg);\nasmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, compat_ulong_t arg);\nasmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, compat_ulong_t arg);\nasmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf);\nasmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf);\nasmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf);\nasmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf);\nasmlinkage long compat_sys_truncate(const char __user *, compat_off_t);\nasmlinkage long compat_sys_ftruncate(unsigned int, compat_off_t);\nasmlinkage long compat_sys_openat(int dfd, const char __user *filename, int flags, umode_t mode);\nasmlinkage long compat_sys_getdents(unsigned int fd, struct compat_linux_dirent __user *dirent, unsigned int count);\nasmlinkage long compat_sys_lseek(unsigned int, compat_off_t, unsigned int);\nasmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd, const struct iovec __user *vec, compat_ulong_t vlen, u32 pos_low, u32 pos_high);\nasmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd, const struct iovec __user *vec, compat_ulong_t vlen, u32 pos_low, u32 pos_high);\nasmlinkage long compat_sys_preadv64(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, loff_t pos);\nasmlinkage long compat_sys_pwritev64(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, loff_t pos);\nasmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_size_t count);\nasmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, compat_size_t count);\nasmlinkage long compat_sys_pselect6_time32(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct old_timespec32 __user *tsp, void __user *sig);\nasmlinkage long compat_sys_pselect6_time64(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct __kernel_timespec __user *tsp, void __user *sig);\nasmlinkage long compat_sys_ppoll_time32(struct pollfd __user *ufds, unsigned int nfds, struct old_timespec32 __user *tsp, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize);\nasmlinkage long compat_sys_ppoll_time64(struct pollfd __user *ufds, unsigned int nfds, struct __kernel_timespec __user *tsp, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize);\nasmlinkage long compat_sys_signalfd4(int ufd, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize, int flags);\nasmlinkage long compat_sys_newfstatat(unsigned int dfd, const char __user *filename, struct compat_stat __user *statbuf, int flag);\nasmlinkage long compat_sys_newfstat(unsigned int fd, struct compat_stat __user *statbuf);\n!asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, struct compat_siginfo __user *waitid, int options, struct compat_rusage __user *uru);\nasmlinkage long compat_sys_set_robust_list(struct compat_robust_list_head __user *head, compat_size_t len);\nasmlinkage long compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, compat_size_t __user *len_ptr);\nasmlinkage long compat_sys_getitimer(int which, struct old_itimerval32 __user *it);\nasmlinkage long compat_sys_setitimer(int which, struct old_itimerval32 __user *in, struct old_itimerval32 __user *out);\n!asmlinkage long compat_sys_kexec_load(compat_ulong_t entry, compat_ulong_t nr_segments, struct compat_kexec_segment __user *segments, compat_ulong_t flags);\nasmlinkage long compat_sys_timer_create(clockid_t which_clock, struct compat_sigevent __user *timer_event_spec, timer_t __user *created_timer_id);\nasmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, compat_long_t addr, compat_long_t data);\nasmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, unsigned int len, compat_ulong_t __user *user_mask_ptr);\nasmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, compat_ulong_t __user *user_mask_ptr);\nasmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, compat_stack_t __user *uoss_ptr);\nasmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize);\n!asmlinkage long compat_sys_rt_sigaction(int sig, const struct compat_sigaction __user *act, struct compat_sigaction __user *oact, compat_size_t sigsetsize);\nasmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, compat_size_t sigsetsize);\nasmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, compat_size_t sigsetsize);\nasmlinkage long compat_sys_rt_sigtimedwait_time32(compat_sigset_t __user *uthese, struct compat_siginfo __user *uinfo, struct old_timespec32 __user *uts, compat_size_t sigsetsize);\nasmlinkage long compat_sys_rt_sigtimedwait_time64(compat_sigset_t __user *uthese, struct compat_siginfo __user *uinfo, struct __kernel_timespec __user *uts, compat_size_t sigsetsize);\nasmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, struct compat_siginfo __user *uinfo);\nasmlinkage long compat_sys_times(struct compat_tms __user *tbuf);\nasmlinkage long compat_sys_getrlimit(unsigned int resource, struct compat_rlimit __user *rlim);\nasmlinkage long compat_sys_setrlimit(unsigned int resource, struct compat_rlimit __user *rlim);\nasmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru);\nasmlinkage long compat_sys_gettimeofday(struct old_timeval32 __user *tv, struct timezone __user *tz);\nasmlinkage long compat_sys_settimeofday(struct old_timeval32 __user *tv, struct timezone __user *tz);\nasmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info);\nasmlinkage long compat_sys_mq_open(const char __user *u_name, int oflag, compat_mode_t mode, struct compat_mq_attr __user *u_attr);\nasmlinkage long compat_sys_mq_notify(mqd_t mqdes, const struct compat_sigevent __user *u_notification);\nasmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, const struct compat_mq_attr __user *u_mqstat, struct compat_mq_attr __user *u_omqstat);\nasmlinkage long compat_sys_msgctl(int first, int second, void __user *uptr);\nasmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg);\nasmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, int msgflg);\nasmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg);\nasmlinkage long compat_sys_shmctl(int first, int second, void __user *uptr);\nasmlinkage long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg);\nasmlinkage long compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len, unsigned flags, struct sockaddr __user *addr, int __user *addrlen);\nasmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags);\nasmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags);\nasmlinkage long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5);\nasmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp);\nasmlinkage long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, struct compat_siginfo __user *uinfo);\nasmlinkage long compat_sys_recvmmsg_time64(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags, struct __kernel_timespec __user *timeout);\nasmlinkage long compat_sys_recvmmsg_time32(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags, struct old_timespec32 __user *timeout);\nasmlinkage long compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru);\n!asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags, __u32 mask_1, __u32 mask_2, int dfd, const char __user *pathname);\nasmlinkage long compat_sys_open_by_handle_at(int mountdirfd, struct file_handle __user *handle, int flags);\nasmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags);\nasmlinkage long compat_sys_execveat(int dfd, const char __user *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp, int flags);\nasmlinkage ssize_t compat_sys_preadv2(compat_ulong_t fd, const struct iovec __user *vec, compat_ulong_t vlen, u32 pos_low, u32 pos_high, rwf_t flags);\nasmlinkage ssize_t compat_sys_pwritev2(compat_ulong_t fd, const struct iovec __user *vec, compat_ulong_t vlen, u32 pos_low, u32 pos_high, rwf_t flags);\nasmlinkage long compat_sys_preadv64v2(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, loff_t pos, rwf_t flags);\nasmlinkage long compat_sys_pwritev64v2(unsigned long fd, const struct iovec __user *vec, unsigned long vlen, loff_t pos, rwf_t flags);\nasmlinkage long compat_sys_open(const char __user *filename, int flags, umode_t mode);\nasmlinkage long compat_sys_signalfd(int ufd, const compat_sigset_t __user *sigmask, compat_size_t sigsetsize);\nasmlinkage long compat_sys_newstat(const char __user *filename, struct compat_stat __user *statbuf);\nasmlinkage long compat_sys_newlstat(const char __user *filename, struct compat_stat __user *statbuf);\nasmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct old_timeval32 __user *tvp);\nasmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);\nasmlinkage long compat_sys_recv(int fd, void __user *buf, compat_size_t len, unsigned flags);\nasmlinkage long compat_sys_old_readdir(unsigned int fd, struct compat_old_linux_dirent __user *, unsigned int count);\nasmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg);\nasmlinkage long compat_sys_ipc(u32, int, int, u32, compat_uptr_t, u32);\nasmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set);\nasmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *nset, compat_old_sigset_t __user *oset);\nasmlinkage long compat_sys_sigaction(int sig, const struct compat_old_sigaction __user *act, struct compat_old_sigaction __user *oact);\nasmlinkage long compat_sys_socketcall(int call, u32 __user *args);\nasmlinkage long compat_sys_truncate64(const char __user *pathname, compat_arg_u64(len));\nasmlinkage long compat_sys_ftruncate64(unsigned int fd, compat_arg_u64(len));\nasmlinkage long compat_sys_fallocate(int fd, int mode, compat_arg_u64(offset), compat_arg_u64(len));\nasmlinkage long compat_sys_pread64(unsigned int fd, char __user *buf, size_t count, compat_arg_u64(pos));\nasmlinkage long compat_sys_pwrite64(unsigned int fd, const char __user *buf, size_t count, compat_arg_u64(pos));\nasmlinkage long compat_sys_sync_file_range(int fd, compat_arg_u64(pos), compat_arg_u64(nbytes), unsigned int flags);\nasmlinkage long compat_sys_fadvise64_64(int fd, compat_arg_u64(pos), compat_arg_u64(len), int advice);\nasmlinkage long compat_sys_readahead(int fd, compat_arg_u64(offset), size_t count);\n\"\"\"\n\n\n# x86_64\n# - arch/x86/entry/syscalls/syscall_64.tbl\nx64_syscall_tbl = \"\"\"\n0       common  read                    sys_read\n1       common  write                   sys_write\n2       common  open                    sys_open\n3       common  close                   sys_close\n4       common  stat                    sys_newstat\n5       common  fstat                   sys_newfstat\n6       common  lstat                   sys_newlstat\n7       common  poll                    sys_poll\n8       common  lseek                   sys_lseek\n9       common  mmap                    sys_mmap\n10      common  mprotect                sys_mprotect\n11      common  munmap                  sys_munmap\n12      common  brk                     sys_brk\n13      64      rt_sigaction            sys_rt_sigaction\n14      common  rt_sigprocmask          sys_rt_sigprocmask\n15      64      rt_sigreturn            sys_rt_sigreturn\n16      64      ioctl                   sys_ioctl\n17      common  pread64                 sys_pread64\n18      common  pwrite64                sys_pwrite64\n19      64      readv                   sys_readv\n20      64      writev                  sys_writev\n21      common  access                  sys_access\n22      common  pipe                    sys_pipe\n23      common  select                  sys_select\n24      common  sched_yield             sys_sched_yield\n25      common  mremap                  sys_mremap\n26      common  msync                   sys_msync\n27      common  mincore                 sys_mincore\n28      common  madvise                 sys_madvise\n29      common  shmget                  sys_shmget\n30      common  shmat                   sys_shmat\n31      common  shmctl                  sys_shmctl\n32      common  dup                     sys_dup\n33      common  dup2                    sys_dup2\n34      common  pause                   sys_pause\n35      common  nanosleep               sys_nanosleep\n36      common  getitimer               sys_getitimer\n37      common  alarm                   sys_alarm\n38      common  setitimer               sys_setitimer\n39      common  getpid                  sys_getpid\n40      common  sendfile                sys_sendfile64\n41      common  socket                  sys_socket\n42      common  connect                 sys_connect\n43      common  accept                  sys_accept\n44      common  sendto                  sys_sendto\n45      64      recvfrom                sys_recvfrom\n46      64      sendmsg                 sys_sendmsg\n47      64      recvmsg                 sys_recvmsg\n48      common  shutdown                sys_shutdown\n49      common  bind                    sys_bind\n50      common  listen                  sys_listen\n51      common  getsockname             sys_getsockname\n52      common  getpeername             sys_getpeername\n53      common  socketpair              sys_socketpair\n54      64      setsockopt              sys_setsockopt\n55      64      getsockopt              sys_getsockopt\n56      common  clone                   sys_clone\n57      common  fork                    sys_fork\n58      common  vfork                   sys_vfork\n59      64      execve                  sys_execve\n60      common  exit                    sys_exit                        -                       noreturn\n61      common  wait4                   sys_wait4\n62      common  kill                    sys_kill\n63      common  uname                   sys_newuname\n64      common  semget                  sys_semget\n65      common  semop                   sys_semop\n66      common  semctl                  sys_semctl\n67      common  shmdt                   sys_shmdt\n68      common  msgget                  sys_msgget\n69      common  msgsnd                  sys_msgsnd\n70      common  msgrcv                  sys_msgrcv\n71      common  msgctl                  sys_msgctl\n72      common  fcntl                   sys_fcntl\n73      common  flock                   sys_flock\n74      common  fsync                   sys_fsync\n75      common  fdatasync               sys_fdatasync\n76      common  truncate                sys_truncate\n77      common  ftruncate               sys_ftruncate\n78      common  getdents                sys_getdents\n79      common  getcwd                  sys_getcwd\n80      common  chdir                   sys_chdir\n81      common  fchdir                  sys_fchdir\n82      common  rename                  sys_rename\n83      common  mkdir                   sys_mkdir\n84      common  rmdir                   sys_rmdir\n85      common  creat                   sys_creat\n86      common  link                    sys_link\n87      common  unlink                  sys_unlink\n88      common  symlink                 sys_symlink\n89      common  readlink                sys_readlink\n90      common  chmod                   sys_chmod\n91      common  fchmod                  sys_fchmod\n92      common  chown                   sys_chown\n93      common  fchown                  sys_fchown\n94      common  lchown                  sys_lchown\n95      common  umask                   sys_umask\n96      common  gettimeofday            sys_gettimeofday\n97      common  getrlimit               sys_getrlimit\n98      common  getrusage               sys_getrusage\n99      common  sysinfo                 sys_sysinfo\n100     common  times                   sys_times\n101     64      ptrace                  sys_ptrace\n102     common  getuid                  sys_getuid\n103     common  syslog                  sys_syslog\n104     common  getgid                  sys_getgid\n105     common  setuid                  sys_setuid\n106     common  setgid                  sys_setgid\n107     common  geteuid                 sys_geteuid\n108     common  getegid                 sys_getegid\n109     common  setpgid                 sys_setpgid\n110     common  getppid                 sys_getppid\n111     common  getpgrp                 sys_getpgrp\n112     common  setsid                  sys_setsid\n113     common  setreuid                sys_setreuid\n114     common  setregid                sys_setregid\n115     common  getgroups               sys_getgroups\n116     common  setgroups               sys_setgroups\n117     common  setresuid               sys_setresuid\n118     common  getresuid               sys_getresuid\n119     common  setresgid               sys_setresgid\n120     common  getresgid               sys_getresgid\n121     common  getpgid                 sys_getpgid\n122     common  setfsuid                sys_setfsuid\n123     common  setfsgid                sys_setfsgid\n124     common  getsid                  sys_getsid\n125     common  capget                  sys_capget\n126     common  capset                  sys_capset\n127     64      rt_sigpending           sys_rt_sigpending\n128     64      rt_sigtimedwait         sys_rt_sigtimedwait\n129     64      rt_sigqueueinfo         sys_rt_sigqueueinfo\n130     common  rt_sigsuspend           sys_rt_sigsuspend\n131     64      sigaltstack             sys_sigaltstack\n132     common  utime                   sys_utime\n133     common  mknod                   sys_mknod\n134     64      uselib\n135     common  personality             sys_personality\n136     common  ustat                   sys_ustat\n137     common  statfs                  sys_statfs\n138     common  fstatfs                 sys_fstatfs\n139     common  sysfs                   sys_sysfs\n140     common  getpriority             sys_getpriority\n141     common  setpriority             sys_setpriority\n142     common  sched_setparam          sys_sched_setparam\n143     common  sched_getparam          sys_sched_getparam\n144     common  sched_setscheduler      sys_sched_setscheduler\n145     common  sched_getscheduler      sys_sched_getscheduler\n146     common  sched_get_priority_max  sys_sched_get_priority_max\n147     common  sched_get_priority_min  sys_sched_get_priority_min\n148     common  sched_rr_get_interval   sys_sched_rr_get_interval\n149     common  mlock                   sys_mlock\n150     common  munlock                 sys_munlock\n151     common  mlockall                sys_mlockall\n152     common  munlockall              sys_munlockall\n153     common  vhangup                 sys_vhangup\n154     common  modify_ldt              sys_modify_ldt\n155     common  pivot_root              sys_pivot_root\n156     64      _sysctl                 sys_ni_syscall\n157     common  prctl                   sys_prctl\n158     common  arch_prctl              sys_arch_prctl\n159     common  adjtimex                sys_adjtimex\n160     common  setrlimit               sys_setrlimit\n161     common  chroot                  sys_chroot\n162     common  sync                    sys_sync\n163     common  acct                    sys_acct\n164     common  settimeofday            sys_settimeofday\n165     common  mount                   sys_mount\n166     common  umount2                 sys_umount\n167     common  swapon                  sys_swapon\n168     common  swapoff                 sys_swapoff\n169     common  reboot                  sys_reboot\n170     common  sethostname             sys_sethostname\n171     common  setdomainname           sys_setdomainname\n172     common  iopl                    sys_iopl\n173     common  ioperm                  sys_ioperm\n174     64      create_module\n175     common  init_module             sys_init_module\n176     common  delete_module           sys_delete_module\n177     64      get_kernel_syms\n178     64      query_module\n179     common  quotactl                sys_quotactl\n180     64      nfsservctl\n181     common  getpmsg\n182     common  putpmsg\n183     common  afs_syscall\n184     common  tuxcall\n185     common  security\n186     common  gettid                  sys_gettid\n187     common  readahead               sys_readahead\n188     common  setxattr                sys_setxattr\n189     common  lsetxattr               sys_lsetxattr\n190     common  fsetxattr               sys_fsetxattr\n191     common  getxattr                sys_getxattr\n192     common  lgetxattr               sys_lgetxattr\n193     common  fgetxattr               sys_fgetxattr\n194     common  listxattr               sys_listxattr\n195     common  llistxattr              sys_llistxattr\n196     common  flistxattr              sys_flistxattr\n197     common  removexattr             sys_removexattr\n198     common  lremovexattr            sys_lremovexattr\n199     common  fremovexattr            sys_fremovexattr\n200     common  tkill                   sys_tkill\n201     common  time                    sys_time\n202     common  futex                   sys_futex\n203     common  sched_setaffinity       sys_sched_setaffinity\n204     common  sched_getaffinity       sys_sched_getaffinity\n205     64      set_thread_area\n206     64      io_setup                sys_io_setup\n207     common  io_destroy              sys_io_destroy\n208     common  io_getevents            sys_io_getevents\n209     64      io_submit               sys_io_submit\n210     common  io_cancel               sys_io_cancel\n211     64      get_thread_area\n212     common  lookup_dcookie\n213     common  epoll_create            sys_epoll_create\n214     64      epoll_ctl_old\n215     64      epoll_wait_old\n216     common  remap_file_pages        sys_remap_file_pages\n217     common  getdents64              sys_getdents64\n218     common  set_tid_address         sys_set_tid_address\n219     common  restart_syscall         sys_restart_syscall\n220     common  semtimedop              sys_semtimedop\n221     common  fadvise64               sys_fadvise64\n222     64      timer_create            sys_timer_create\n223     common  timer_settime           sys_timer_settime\n224     common  timer_gettime           sys_timer_gettime\n225     common  timer_getoverrun        sys_timer_getoverrun\n226     common  timer_delete            sys_timer_delete\n227     common  clock_settime           sys_clock_settime\n228     common  clock_gettime           sys_clock_gettime\n229     common  clock_getres            sys_clock_getres\n230     common  clock_nanosleep         sys_clock_nanosleep\n231     common  exit_group              sys_exit_group                  -                       noreturn\n232     common  epoll_wait              sys_epoll_wait\n233     common  epoll_ctl               sys_epoll_ctl\n234     common  tgkill                  sys_tgkill\n235     common  utimes                  sys_utimes\n236     64      vserver\n237     common  mbind                   sys_mbind\n238     common  set_mempolicy           sys_set_mempolicy\n239     common  get_mempolicy           sys_get_mempolicy\n240     common  mq_open                 sys_mq_open\n241     common  mq_unlink               sys_mq_unlink\n242     common  mq_timedsend            sys_mq_timedsend\n243     common  mq_timedreceive         sys_mq_timedreceive\n244     64      mq_notify               sys_mq_notify\n245     common  mq_getsetattr           sys_mq_getsetattr\n246     64      kexec_load              sys_kexec_load\n247     64      waitid                  sys_waitid\n248     common  add_key                 sys_add_key\n249     common  request_key             sys_request_key\n250     common  keyctl                  sys_keyctl\n251     common  ioprio_set              sys_ioprio_set\n252     common  ioprio_get              sys_ioprio_get\n253     common  inotify_init            sys_inotify_init\n254     common  inotify_add_watch       sys_inotify_add_watch\n255     common  inotify_rm_watch        sys_inotify_rm_watch\n256     common  migrate_pages           sys_migrate_pages\n257     common  openat                  sys_openat\n258     common  mkdirat                 sys_mkdirat\n259     common  mknodat                 sys_mknodat\n260     common  fchownat                sys_fchownat\n261     common  futimesat               sys_futimesat\n262     common  newfstatat              sys_newfstatat\n263     common  unlinkat                sys_unlinkat\n264     common  renameat                sys_renameat\n265     common  linkat                  sys_linkat\n266     common  symlinkat               sys_symlinkat\n267     common  readlinkat              sys_readlinkat\n268     common  fchmodat                sys_fchmodat\n269     common  faccessat               sys_faccessat\n270     common  pselect6                sys_pselect6\n271     common  ppoll                   sys_ppoll\n272     common  unshare                 sys_unshare\n273     64      set_robust_list         sys_set_robust_list\n274     64      get_robust_list         sys_get_robust_list\n275     common  splice                  sys_splice\n276     common  tee                     sys_tee\n277     common  sync_file_range         sys_sync_file_range\n278     64      vmsplice                sys_vmsplice\n279     64      move_pages              sys_move_pages\n280     common  utimensat               sys_utimensat\n281     common  epoll_pwait             sys_epoll_pwait\n282     common  signalfd                sys_signalfd\n283     common  timerfd_create          sys_timerfd_create\n284     common  eventfd                 sys_eventfd\n285     common  fallocate               sys_fallocate\n286     common  timerfd_settime         sys_timerfd_settime\n287     common  timerfd_gettime         sys_timerfd_gettime\n288     common  accept4                 sys_accept4\n289     common  signalfd4               sys_signalfd4\n290     common  eventfd2                sys_eventfd2\n291     common  epoll_create1           sys_epoll_create1\n292     common  dup3                    sys_dup3\n293     common  pipe2                   sys_pipe2\n294     common  inotify_init1           sys_inotify_init1\n295     64      preadv                  sys_preadv\n296     64      pwritev                 sys_pwritev\n297     64      rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo\n298     common  perf_event_open         sys_perf_event_open\n299     64      recvmmsg                sys_recvmmsg\n300     common  fanotify_init           sys_fanotify_init\n301     common  fanotify_mark           sys_fanotify_mark\n302     common  prlimit64               sys_prlimit64\n303     common  name_to_handle_at       sys_name_to_handle_at\n304     common  open_by_handle_at       sys_open_by_handle_at\n305     common  clock_adjtime           sys_clock_adjtime\n306     common  syncfs                  sys_syncfs\n307     64      sendmmsg                sys_sendmmsg\n308     common  setns                   sys_setns\n309     common  getcpu                  sys_getcpu\n310     64      process_vm_readv        sys_process_vm_readv\n311     64      process_vm_writev       sys_process_vm_writev\n312     common  kcmp                    sys_kcmp\n313     common  finit_module            sys_finit_module\n314     common  sched_setattr           sys_sched_setattr\n315     common  sched_getattr           sys_sched_getattr\n316     common  renameat2               sys_renameat2\n317     common  seccomp                 sys_seccomp\n318     common  getrandom               sys_getrandom\n319     common  memfd_create            sys_memfd_create\n320     common  kexec_file_load         sys_kexec_file_load\n321     common  bpf                     sys_bpf\n322     64      execveat                sys_execveat\n323     common  userfaultfd             sys_userfaultfd\n324     common  membarrier              sys_membarrier\n325     common  mlock2                  sys_mlock2\n326     common  copy_file_range         sys_copy_file_range\n327     64      preadv2                 sys_preadv2\n328     64      pwritev2                sys_pwritev2\n329     common  pkey_mprotect           sys_pkey_mprotect\n330     common  pkey_alloc              sys_pkey_alloc\n331     common  pkey_free               sys_pkey_free\n332     common  statx                   sys_statx\n333     common  io_pgetevents           sys_io_pgetevents\n334     common  rseq                    sys_rseq\n335     common  uretprobe               sys_uretprobe\n336     common  uprobe                  sys_uprobe\n424     common  pidfd_send_signal       sys_pidfd_send_signal\n425     common  io_uring_setup          sys_io_uring_setup\n426     common  io_uring_enter          sys_io_uring_enter\n427     common  io_uring_register       sys_io_uring_register\n428     common  open_tree               sys_open_tree\n429     common  move_mount              sys_move_mount\n430     common  fsopen                  sys_fsopen\n431     common  fsconfig                sys_fsconfig\n432     common  fsmount                 sys_fsmount\n433     common  fspick                  sys_fspick\n434     common  pidfd_open              sys_pidfd_open\n435     common  clone3                  sys_clone3\n436     common  close_range             sys_close_range\n437     common  openat2                 sys_openat2\n438     common  pidfd_getfd             sys_pidfd_getfd\n439     common  faccessat2              sys_faccessat2\n440     common  process_madvise         sys_process_madvise\n441     common  epoll_pwait2            sys_epoll_pwait2\n442     common  mount_setattr           sys_mount_setattr\n443     common  quotactl_fd             sys_quotactl_fd\n444     common  landlock_create_ruleset sys_landlock_create_ruleset\n445     common  landlock_add_rule       sys_landlock_add_rule\n446     common  landlock_restrict_self  sys_landlock_restrict_self\n447     common  memfd_secret            sys_memfd_secret\n448     common  process_mrelease        sys_process_mrelease\n449     common  futex_waitv             sys_futex_waitv\n450     common  set_mempolicy_home_node sys_set_mempolicy_home_node\n451     common  cachestat               sys_cachestat\n452     common  fchmodat2               sys_fchmodat2\n453     common  map_shadow_stack        sys_map_shadow_stack\n454     common  futex_wake              sys_futex_wake\n455     common  futex_wait              sys_futex_wait\n456     common  futex_requeue           sys_futex_requeue\n457     common  statmount               sys_statmount\n458     common  listmount               sys_listmount\n459     common  lsm_get_self_attr       sys_lsm_get_self_attr\n460     common  lsm_set_self_attr       sys_lsm_set_self_attr\n461     common  lsm_list_modules        sys_lsm_list_modules\n462     common  mseal                   sys_mseal\n463     common  setxattrat              sys_setxattrat\n464     common  getxattrat              sys_getxattrat\n465     common  listxattrat             sys_listxattrat\n466     common  removexattrat           sys_removexattrat\n467     common  open_tree_attr          sys_open_tree_attr\n468     common  file_getattr            sys_file_getattr\n469     common  file_setattr            sys_file_setattr\n470     common  listns                  sys_listns\n512     x32     rt_sigaction            compat_sys_rt_sigaction\n513     x32     rt_sigreturn            compat_sys_x32_rt_sigreturn\n514     x32     ioctl                   compat_sys_ioctl\n515     x32     readv                   sys_readv\n516     x32     writev                  sys_writev\n517     x32     recvfrom                compat_sys_recvfrom\n518     x32     sendmsg                 compat_sys_sendmsg\n519     x32     recvmsg                 compat_sys_recvmsg\n520     x32     execve                  compat_sys_execve\n521     x32     ptrace                  compat_sys_ptrace\n522     x32     rt_sigpending           compat_sys_rt_sigpending\n523     x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait_time64\n524     x32     rt_sigqueueinfo         compat_sys_rt_sigqueueinfo\n525     x32     sigaltstack             compat_sys_sigaltstack\n526     x32     timer_create            compat_sys_timer_create\n527     x32     mq_notify               compat_sys_mq_notify\n528     x32     kexec_load              compat_sys_kexec_load\n529     x32     waitid                  compat_sys_waitid\n530     x32     set_robust_list         compat_sys_set_robust_list\n531     x32     get_robust_list         compat_sys_get_robust_list\n532     x32     vmsplice                sys_vmsplice\n533     x32     move_pages              sys_move_pages\n534     x32     preadv                  compat_sys_preadv64\n535     x32     pwritev                 compat_sys_pwritev64\n536     x32     rt_tgsigqueueinfo       compat_sys_rt_tgsigqueueinfo\n537     x32     recvmmsg                compat_sys_recvmmsg_time64\n538     x32     sendmmsg                compat_sys_sendmmsg\n539     x32     process_vm_readv        sys_process_vm_readv\n540     x32     process_vm_writev       sys_process_vm_writev\n541     x32     setsockopt              sys_setsockopt\n542     x32     getsockopt              sys_getsockopt\n543     x32     io_setup                compat_sys_io_setup\n544     x32     io_submit               compat_sys_io_submit\n545     x32     execveat                compat_sys_execveat\n546     x32     preadv2                 compat_sys_preadv64v2\n547     x32     pwritev2                compat_sys_pwritev64v2\n\"\"\"\n\n\n# i386 (native / compat(emulated))\n# - arch/x86/entry/syscalls/syscall_32.tbl\nx86_syscall_tbl = \"\"\"\n0       i386    restart_syscall         sys_restart_syscall\n1       i386    exit                    sys_exit                        -                       noreturn\n2       i386    fork                    sys_fork\n3       i386    read                    sys_read\n4       i386    write                   sys_write\n5       i386    open                    sys_open                        compat_sys_open\n6       i386    close                   sys_close\n7       i386    waitpid                 sys_waitpid\n8       i386    creat                   sys_creat\n9       i386    link                    sys_link\n10      i386    unlink                  sys_unlink\n11      i386    execve                  sys_execve                      compat_sys_execve\n12      i386    chdir                   sys_chdir\n13      i386    time                    sys_time32\n14      i386    mknod                   sys_mknod\n15      i386    chmod                   sys_chmod\n16      i386    lchown                  sys_lchown16\n17      i386    break\n18      i386    oldstat                 sys_stat\n19      i386    lseek                   sys_lseek                       compat_sys_lseek\n20      i386    getpid                  sys_getpid\n21      i386    mount                   sys_mount\n22      i386    umount                  sys_oldumount\n23      i386    setuid                  sys_setuid16\n24      i386    getuid                  sys_getuid16\n25      i386    stime                   sys_stime32\n26      i386    ptrace                  sys_ptrace                      compat_sys_ptrace\n27      i386    alarm                   sys_alarm\n28      i386    oldfstat                sys_fstat\n29      i386    pause                   sys_pause\n30      i386    utime                   sys_utime32\n31      i386    stty\n32      i386    gtty\n33      i386    access                  sys_access\n34      i386    nice                    sys_nice\n35      i386    ftime\n36      i386    sync                    sys_sync\n37      i386    kill                    sys_kill\n38      i386    rename                  sys_rename\n39      i386    mkdir                   sys_mkdir\n40      i386    rmdir                   sys_rmdir\n41      i386    dup                     sys_dup\n42      i386    pipe                    sys_pipe\n43      i386    times                   sys_times                       compat_sys_times\n44      i386    prof\n45      i386    brk                     sys_brk\n46      i386    setgid                  sys_setgid16\n47      i386    getgid                  sys_getgid16\n48      i386    signal                  sys_signal\n49      i386    geteuid                 sys_geteuid16\n50      i386    getegid                 sys_getegid16\n51      i386    acct                    sys_acct\n52      i386    umount2                 sys_umount\n53      i386    lock\n54      i386    ioctl                   sys_ioctl                       compat_sys_ioctl\n55      i386    fcntl                   sys_fcntl                       compat_sys_fcntl64\n56      i386    mpx\n57      i386    setpgid                 sys_setpgid\n58      i386    ulimit\n59      i386    oldolduname             sys_olduname\n60      i386    umask                   sys_umask\n61      i386    chroot                  sys_chroot\n62      i386    ustat                   sys_ustat                       compat_sys_ustat\n63      i386    dup2                    sys_dup2\n64      i386    getppid                 sys_getppid\n65      i386    getpgrp                 sys_getpgrp\n66      i386    setsid                  sys_setsid\n67      i386    sigaction               sys_sigaction                   compat_sys_sigaction\n68      i386    sgetmask                sys_sgetmask\n69      i386    ssetmask                sys_ssetmask\n70      i386    setreuid                sys_setreuid16\n71      i386    setregid                sys_setregid16\n72      i386    sigsuspend              sys_sigsuspend\n73      i386    sigpending              sys_sigpending                  compat_sys_sigpending\n74      i386    sethostname             sys_sethostname\n75      i386    setrlimit               sys_setrlimit                   compat_sys_setrlimit\n76      i386    getrlimit               sys_old_getrlimit               compat_sys_old_getrlimit\n77      i386    getrusage               sys_getrusage                   compat_sys_getrusage\n78      i386    gettimeofday            sys_gettimeofday                compat_sys_gettimeofday\n79      i386    settimeofday            sys_settimeofday                compat_sys_settimeofday\n80      i386    getgroups               sys_getgroups16\n81      i386    setgroups               sys_setgroups16\n82      i386    select                  sys_old_select                  compat_sys_old_select\n83      i386    symlink                 sys_symlink\n84      i386    oldlstat                sys_lstat\n85      i386    readlink                sys_readlink\n86      i386    uselib                  sys_uselib\n87      i386    swapon                  sys_swapon\n88      i386    reboot                  sys_reboot\n89      i386    readdir                 sys_old_readdir                 compat_sys_old_readdir\n90      i386    mmap                    sys_old_mmap                    compat_sys_ia32_mmap\n91      i386    munmap                  sys_munmap\n92      i386    truncate                sys_truncate                    compat_sys_truncate\n93      i386    ftruncate               sys_ftruncate                   compat_sys_ftruncate\n94      i386    fchmod                  sys_fchmod\n95      i386    fchown                  sys_fchown16\n96      i386    getpriority             sys_getpriority\n97      i386    setpriority             sys_setpriority\n98      i386    profil\n99      i386    statfs                  sys_statfs                      compat_sys_statfs\n100     i386    fstatfs                 sys_fstatfs                     compat_sys_fstatfs\n101     i386    ioperm                  sys_ioperm\n102     i386    socketcall              sys_socketcall                  compat_sys_socketcall\n103     i386    syslog                  sys_syslog\n104     i386    setitimer               sys_setitimer                   compat_sys_setitimer\n105     i386    getitimer               sys_getitimer                   compat_sys_getitimer\n106     i386    stat                    sys_newstat                     compat_sys_newstat\n107     i386    lstat                   sys_newlstat                    compat_sys_newlstat\n108     i386    fstat                   sys_newfstat                    compat_sys_newfstat\n109     i386    olduname                sys_uname\n110     i386    iopl                    sys_iopl\n111     i386    vhangup                 sys_vhangup\n112     i386    idle\n113     i386    vm86old                 sys_vm86old                     sys_ni_syscall\n114     i386    wait4                   sys_wait4                       compat_sys_wait4\n115     i386    swapoff                 sys_swapoff\n116     i386    sysinfo                 sys_sysinfo                     compat_sys_sysinfo\n117     i386    ipc                     sys_ipc                         compat_sys_ipc\n118     i386    fsync                   sys_fsync\n119     i386    sigreturn               sys_sigreturn                   compat_sys_sigreturn\n120     i386    clone                   sys_clone                       compat_sys_ia32_clone\n121     i386    setdomainname           sys_setdomainname\n122     i386    uname                   sys_newuname\n123     i386    modify_ldt              sys_modify_ldt\n124     i386    adjtimex                sys_adjtimex_time32\n125     i386    mprotect                sys_mprotect\n126     i386    sigprocmask             sys_sigprocmask                 compat_sys_sigprocmask\n127     i386    create_module\n128     i386    init_module             sys_init_module\n129     i386    delete_module           sys_delete_module\n130     i386    get_kernel_syms\n131     i386    quotactl                sys_quotactl\n132     i386    getpgid                 sys_getpgid\n133     i386    fchdir                  sys_fchdir\n134     i386    bdflush                 sys_ni_syscall\n135     i386    sysfs                   sys_sysfs\n136     i386    personality             sys_personality\n137     i386    afs_syscall\n138     i386    setfsuid                sys_setfsuid16\n139     i386    setfsgid                sys_setfsgid16\n140     i386    _llseek                 sys_llseek\n141     i386    getdents                sys_getdents                    compat_sys_getdents\n142     i386    _newselect              sys_select                      compat_sys_select\n143     i386    flock                   sys_flock\n144     i386    msync                   sys_msync\n145     i386    readv                   sys_readv\n146     i386    writev                  sys_writev\n147     i386    getsid                  sys_getsid\n148     i386    fdatasync               sys_fdatasync\n149     i386    _sysctl                 sys_ni_syscall\n150     i386    mlock                   sys_mlock\n151     i386    munlock                 sys_munlock\n152     i386    mlockall                sys_mlockall\n153     i386    munlockall              sys_munlockall\n154     i386    sched_setparam          sys_sched_setparam\n155     i386    sched_getparam          sys_sched_getparam\n156     i386    sched_setscheduler      sys_sched_setscheduler\n157     i386    sched_getscheduler      sys_sched_getscheduler\n158     i386    sched_yield             sys_sched_yield\n159     i386    sched_get_priority_max  sys_sched_get_priority_max\n160     i386    sched_get_priority_min  sys_sched_get_priority_min\n161     i386    sched_rr_get_interval   sys_sched_rr_get_interval_time32\n162     i386    nanosleep               sys_nanosleep_time32\n163     i386    mremap                  sys_mremap\n164     i386    setresuid               sys_setresuid16\n165     i386    getresuid               sys_getresuid16\n166     i386    vm86                    sys_vm86                        sys_ni_syscall\n167     i386    query_module\n168     i386    poll                    sys_poll\n169     i386    nfsservctl\n170     i386    setresgid               sys_setresgid16\n171     i386    getresgid               sys_getresgid16\n172     i386    prctl                   sys_prctl\n173     i386    rt_sigreturn            sys_rt_sigreturn                compat_sys_rt_sigreturn\n174     i386    rt_sigaction            sys_rt_sigaction                compat_sys_rt_sigaction\n175     i386    rt_sigprocmask          sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n176     i386    rt_sigpending           sys_rt_sigpending               compat_sys_rt_sigpending\n177     i386    rt_sigtimedwait         sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n178     i386    rt_sigqueueinfo         sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n179     i386    rt_sigsuspend           sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n180     i386    pread64                 sys_ia32_pread64\n181     i386    pwrite64                sys_ia32_pwrite64\n182     i386    chown                   sys_chown16\n183     i386    getcwd                  sys_getcwd\n184     i386    capget                  sys_capget\n185     i386    capset                  sys_capset\n186     i386    sigaltstack             sys_sigaltstack                 compat_sys_sigaltstack\n187     i386    sendfile                sys_sendfile                    compat_sys_sendfile\n188     i386    getpmsg\n189     i386    putpmsg\n190     i386    vfork                   sys_vfork\n191     i386    ugetrlimit              sys_getrlimit                   compat_sys_getrlimit\n192     i386    mmap2                   sys_mmap_pgoff\n193     i386    truncate64              sys_ia32_truncate64\n194     i386    ftruncate64             sys_ia32_ftruncate64\n195     i386    stat64                  sys_stat64                      compat_sys_ia32_stat64\n196     i386    lstat64                 sys_lstat64                     compat_sys_ia32_lstat64\n197     i386    fstat64                 sys_fstat64                     compat_sys_ia32_fstat64\n198     i386    lchown32                sys_lchown\n199     i386    getuid32                sys_getuid\n200     i386    getgid32                sys_getgid\n201     i386    geteuid32               sys_geteuid\n202     i386    getegid32               sys_getegid\n203     i386    setreuid32              sys_setreuid\n204     i386    setregid32              sys_setregid\n205     i386    getgroups32             sys_getgroups\n206     i386    setgroups32             sys_setgroups\n207     i386    fchown32                sys_fchown\n208     i386    setresuid32             sys_setresuid\n209     i386    getresuid32             sys_getresuid\n210     i386    setresgid32             sys_setresgid\n211     i386    getresgid32             sys_getresgid\n212     i386    chown32                 sys_chown\n213     i386    setuid32                sys_setuid\n214     i386    setgid32                sys_setgid\n215     i386    setfsuid32              sys_setfsuid\n216     i386    setfsgid32              sys_setfsgid\n217     i386    pivot_root              sys_pivot_root\n218     i386    mincore                 sys_mincore\n219     i386    madvise                 sys_madvise\n220     i386    getdents64              sys_getdents64\n221     i386    fcntl64                 sys_fcntl64                     compat_sys_fcntl64\n224     i386    gettid                  sys_gettid\n225     i386    readahead               sys_ia32_readahead\n226     i386    setxattr                sys_setxattr\n227     i386    lsetxattr               sys_lsetxattr\n228     i386    fsetxattr               sys_fsetxattr\n229     i386    getxattr                sys_getxattr\n230     i386    lgetxattr               sys_lgetxattr\n231     i386    fgetxattr               sys_fgetxattr\n232     i386    listxattr               sys_listxattr\n233     i386    llistxattr              sys_llistxattr\n234     i386    flistxattr              sys_flistxattr\n235     i386    removexattr             sys_removexattr\n236     i386    lremovexattr            sys_lremovexattr\n237     i386    fremovexattr            sys_fremovexattr\n238     i386    tkill                   sys_tkill\n239     i386    sendfile64              sys_sendfile64\n240     i386    futex                   sys_futex_time32\n241     i386    sched_setaffinity       sys_sched_setaffinity           compat_sys_sched_setaffinity\n242     i386    sched_getaffinity       sys_sched_getaffinity           compat_sys_sched_getaffinity\n243     i386    set_thread_area         sys_set_thread_area\n244     i386    get_thread_area         sys_get_thread_area\n245     i386    io_setup                sys_io_setup                    compat_sys_io_setup\n246     i386    io_destroy              sys_io_destroy\n247     i386    io_getevents            sys_io_getevents_time32\n248     i386    io_submit               sys_io_submit                   compat_sys_io_submit\n249     i386    io_cancel               sys_io_cancel\n250     i386    fadvise64               sys_ia32_fadvise64\n252     i386    exit_group              sys_exit_group                  -                       noreturn\n253     i386    lookup_dcookie\n254     i386    epoll_create            sys_epoll_create\n255     i386    epoll_ctl               sys_epoll_ctl\n256     i386    epoll_wait              sys_epoll_wait\n257     i386    remap_file_pages        sys_remap_file_pages\n258     i386    set_tid_address         sys_set_tid_address\n259     i386    timer_create            sys_timer_create                compat_sys_timer_create\n260     i386    timer_settime           sys_timer_settime32\n261     i386    timer_gettime           sys_timer_gettime32\n262     i386    timer_getoverrun        sys_timer_getoverrun\n263     i386    timer_delete            sys_timer_delete\n264     i386    clock_settime           sys_clock_settime32\n265     i386    clock_gettime           sys_clock_gettime32\n266     i386    clock_getres            sys_clock_getres_time32\n267     i386    clock_nanosleep         sys_clock_nanosleep_time32\n268     i386    statfs64                sys_statfs64                    compat_sys_statfs64\n269     i386    fstatfs64               sys_fstatfs64                   compat_sys_fstatfs64\n270     i386    tgkill                  sys_tgkill\n271     i386    utimes                  sys_utimes_time32\n272     i386    fadvise64_64            sys_ia32_fadvise64_64\n273     i386    vserver\n274     i386    mbind                   sys_mbind\n275     i386    get_mempolicy           sys_get_mempolicy\n276     i386    set_mempolicy           sys_set_mempolicy\n277     i386    mq_open                 sys_mq_open                     compat_sys_mq_open\n278     i386    mq_unlink               sys_mq_unlink\n279     i386    mq_timedsend            sys_mq_timedsend_time32\n280     i386    mq_timedreceive         sys_mq_timedreceive_time32\n281     i386    mq_notify               sys_mq_notify                   compat_sys_mq_notify\n282     i386    mq_getsetattr           sys_mq_getsetattr               compat_sys_mq_getsetattr\n283     i386    kexec_load              sys_kexec_load                  compat_sys_kexec_load\n284     i386    waitid                  sys_waitid                      compat_sys_waitid\n286     i386    add_key                 sys_add_key\n287     i386    request_key             sys_request_key\n288     i386    keyctl                  sys_keyctl                      compat_sys_keyctl\n289     i386    ioprio_set              sys_ioprio_set\n290     i386    ioprio_get              sys_ioprio_get\n291     i386    inotify_init            sys_inotify_init\n292     i386    inotify_add_watch       sys_inotify_add_watch\n293     i386    inotify_rm_watch        sys_inotify_rm_watch\n294     i386    migrate_pages           sys_migrate_pages\n295     i386    openat                  sys_openat                      compat_sys_openat\n296     i386    mkdirat                 sys_mkdirat\n297     i386    mknodat                 sys_mknodat\n298     i386    fchownat                sys_fchownat\n299     i386    futimesat               sys_futimesat_time32\n300     i386    fstatat64               sys_fstatat64                   compat_sys_ia32_fstatat64\n301     i386    unlinkat                sys_unlinkat\n302     i386    renameat                sys_renameat\n303     i386    linkat                  sys_linkat\n304     i386    symlinkat               sys_symlinkat\n305     i386    readlinkat              sys_readlinkat\n306     i386    fchmodat                sys_fchmodat\n307     i386    faccessat               sys_faccessat\n308     i386    pselect6                sys_pselect6_time32             compat_sys_pselect6_time32\n309     i386    ppoll                   sys_ppoll_time32                compat_sys_ppoll_time32\n310     i386    unshare                 sys_unshare\n311     i386    set_robust_list         sys_set_robust_list             compat_sys_set_robust_list\n312     i386    get_robust_list         sys_get_robust_list             compat_sys_get_robust_list\n313     i386    splice                  sys_splice\n314     i386    sync_file_range         sys_ia32_sync_file_range\n315     i386    tee                     sys_tee\n316     i386    vmsplice                sys_vmsplice\n317     i386    move_pages              sys_move_pages\n318     i386    getcpu                  sys_getcpu\n319     i386    epoll_pwait             sys_epoll_pwait\n320     i386    utimensat               sys_utimensat_time32\n321     i386    signalfd                sys_signalfd                    compat_sys_signalfd\n322     i386    timerfd_create          sys_timerfd_create\n323     i386    eventfd                 sys_eventfd\n324     i386    fallocate               sys_ia32_fallocate\n325     i386    timerfd_settime         sys_timerfd_settime32\n326     i386    timerfd_gettime         sys_timerfd_gettime32\n327     i386    signalfd4               sys_signalfd4                   compat_sys_signalfd4\n328     i386    eventfd2                sys_eventfd2\n329     i386    epoll_create1           sys_epoll_create1\n330     i386    dup3                    sys_dup3\n331     i386    pipe2                   sys_pipe2\n332     i386    inotify_init1           sys_inotify_init1\n333     i386    preadv                  sys_preadv                      compat_sys_preadv\n334     i386    pwritev                 sys_pwritev                     compat_sys_pwritev\n335     i386    rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n336     i386    perf_event_open         sys_perf_event_open\n337     i386    recvmmsg                sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n338     i386    fanotify_init           sys_fanotify_init\n339     i386    fanotify_mark           sys_fanotify_mark               compat_sys_fanotify_mark\n340     i386    prlimit64               sys_prlimit64\n341     i386    name_to_handle_at       sys_name_to_handle_at\n342     i386    open_by_handle_at       sys_open_by_handle_at           compat_sys_open_by_handle_at\n343     i386    clock_adjtime           sys_clock_adjtime32\n344     i386    syncfs                  sys_syncfs\n345     i386    sendmmsg                sys_sendmmsg                    compat_sys_sendmmsg\n346     i386    setns                   sys_setns\n347     i386    process_vm_readv        sys_process_vm_readv\n348     i386    process_vm_writev       sys_process_vm_writev\n349     i386    kcmp                    sys_kcmp\n350     i386    finit_module            sys_finit_module\n351     i386    sched_setattr           sys_sched_setattr\n352     i386    sched_getattr           sys_sched_getattr\n353     i386    renameat2               sys_renameat2\n354     i386    seccomp                 sys_seccomp\n355     i386    getrandom               sys_getrandom\n356     i386    memfd_create            sys_memfd_create\n357     i386    bpf                     sys_bpf\n358     i386    execveat                sys_execveat                    compat_sys_execveat\n359     i386    socket                  sys_socket\n360     i386    socketpair              sys_socketpair\n361     i386    bind                    sys_bind\n362     i386    connect                 sys_connect\n363     i386    listen                  sys_listen\n364     i386    accept4                 sys_accept4\n365     i386    getsockopt              sys_getsockopt                  sys_getsockopt\n366     i386    setsockopt              sys_setsockopt                  sys_setsockopt\n367     i386    getsockname             sys_getsockname\n368     i386    getpeername             sys_getpeername\n369     i386    sendto                  sys_sendto\n370     i386    sendmsg                 sys_sendmsg                     compat_sys_sendmsg\n371     i386    recvfrom                sys_recvfrom                    compat_sys_recvfrom\n372     i386    recvmsg                 sys_recvmsg                     compat_sys_recvmsg\n373     i386    shutdown                sys_shutdown\n374     i386    userfaultfd             sys_userfaultfd\n375     i386    membarrier              sys_membarrier\n376     i386    mlock2                  sys_mlock2\n377     i386    copy_file_range         sys_copy_file_range\n378     i386    preadv2                 sys_preadv2                     compat_sys_preadv2\n379     i386    pwritev2                sys_pwritev2                    compat_sys_pwritev2\n380     i386    pkey_mprotect           sys_pkey_mprotect\n381     i386    pkey_alloc              sys_pkey_alloc\n382     i386    pkey_free               sys_pkey_free\n383     i386    statx                   sys_statx\n384     i386    arch_prctl              sys_arch_prctl\n385     i386    io_pgetevents           sys_io_pgetevents_time32        compat_sys_io_pgetevents\n386     i386    rseq                    sys_rseq\n393     i386    semget                  sys_semget\n394     i386    semctl                  sys_semctl                      compat_sys_semctl\n395     i386    shmget                  sys_shmget\n396     i386    shmctl                  sys_shmctl                      compat_sys_shmctl\n397     i386    shmat                   sys_shmat                       compat_sys_shmat\n398     i386    shmdt                   sys_shmdt\n399     i386    msgget                  sys_msgget\n400     i386    msgsnd                  sys_msgsnd                      compat_sys_msgsnd\n401     i386    msgrcv                  sys_msgrcv                      compat_sys_msgrcv\n402     i386    msgctl                  sys_msgctl                      compat_sys_msgctl\n403     i386    clock_gettime64         sys_clock_gettime\n404     i386    clock_settime64         sys_clock_settime\n405     i386    clock_adjtime64         sys_clock_adjtime\n406     i386    clock_getres_time64     sys_clock_getres\n407     i386    clock_nanosleep_time64  sys_clock_nanosleep\n408     i386    timer_gettime64         sys_timer_gettime\n409     i386    timer_settime64         sys_timer_settime\n410     i386    timerfd_gettime64       sys_timerfd_gettime\n411     i386    timerfd_settime64       sys_timerfd_settime\n412     i386    utimensat_time64        sys_utimensat\n413     i386    pselect6_time64         sys_pselect6                    compat_sys_pselect6_time64\n414     i386    ppoll_time64            sys_ppoll                       compat_sys_ppoll_time64\n416     i386    io_pgetevents_time64    sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     i386    recvmmsg_time64         sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     i386    mq_timedsend_time64     sys_mq_timedsend\n419     i386    mq_timedreceive_time64  sys_mq_timedreceive\n420     i386    semtimedop_time64       sys_semtimedop\n421     i386    rt_sigtimedwait_time64  sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     i386    futex_time64            sys_futex\n423     i386    sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     i386    pidfd_send_signal       sys_pidfd_send_signal\n425     i386    io_uring_setup          sys_io_uring_setup\n426     i386    io_uring_enter          sys_io_uring_enter\n427     i386    io_uring_register       sys_io_uring_register\n428     i386    open_tree               sys_open_tree\n429     i386    move_mount              sys_move_mount\n430     i386    fsopen                  sys_fsopen\n431     i386    fsconfig                sys_fsconfig\n432     i386    fsmount                 sys_fsmount\n433     i386    fspick                  sys_fspick\n434     i386    pidfd_open              sys_pidfd_open\n435     i386    clone3                  sys_clone3\n436     i386    close_range             sys_close_range\n437     i386    openat2                 sys_openat2\n438     i386    pidfd_getfd             sys_pidfd_getfd\n439     i386    faccessat2              sys_faccessat2\n440     i386    process_madvise         sys_process_madvise\n441     i386    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     i386    mount_setattr           sys_mount_setattr\n443     i386    quotactl_fd             sys_quotactl_fd\n444     i386    landlock_create_ruleset sys_landlock_create_ruleset\n445     i386    landlock_add_rule       sys_landlock_add_rule\n446     i386    landlock_restrict_self  sys_landlock_restrict_self\n447     i386    memfd_secret            sys_memfd_secret\n448     i386    process_mrelease        sys_process_mrelease\n449     i386    futex_waitv             sys_futex_waitv\n450     i386    set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     i386    cachestat               sys_cachestat\n452     i386    fchmodat2               sys_fchmodat2\n453     i386    map_shadow_stack        sys_map_shadow_stack\n454     i386    futex_wake              sys_futex_wake\n455     i386    futex_wait              sys_futex_wait\n456     i386    futex_requeue           sys_futex_requeue\n457     i386    statmount               sys_statmount\n458     i386    listmount               sys_listmount\n459     i386    lsm_get_self_attr       sys_lsm_get_self_attr\n460     i386    lsm_set_self_attr       sys_lsm_set_self_attr\n461     i386    lsm_list_modules        sys_lsm_list_modules\n462     i386    mseal                   sys_mseal\n463     i386    setxattrat              sys_setxattrat\n464     i386    getxattrat              sys_getxattrat\n465     i386    listxattrat             sys_listxattrat\n466     i386    removexattrat           sys_removexattrat\n467     i386    open_tree_attr          sys_open_tree_attr\n468     i386    file_getattr            sys_file_getattr\n469     i386    file_setattr            sys_file_setattr\n470     i386    listns                  sys_listns\n\"\"\"\n\n\n# ARM64\n# - arch/arm64/tools/syscall_64_tbl -> scripts/syscall.tbl\narm64_syscall_tbl = \"\"\"\n0       common  io_setup                        sys_io_setup                    compat_sys_io_setup\n1       common  io_destroy                      sys_io_destroy\n2       common  io_submit                       sys_io_submit                   compat_sys_io_submit\n3       common  io_cancel                       sys_io_cancel\n4       time32  io_getevents                    sys_io_getevents_time32\n4       64      io_getevents                    sys_io_getevents\n5       common  setxattr                        sys_setxattr\n6       common  lsetxattr                       sys_lsetxattr\n7       common  fsetxattr                       sys_fsetxattr\n8       common  getxattr                        sys_getxattr\n9       common  lgetxattr                       sys_lgetxattr\n10      common  fgetxattr                       sys_fgetxattr\n11      common  listxattr                       sys_listxattr\n12      common  llistxattr                      sys_llistxattr\n13      common  flistxattr                      sys_flistxattr\n14      common  removexattr                     sys_removexattr\n15      common  lremovexattr                    sys_lremovexattr\n16      common  fremovexattr                    sys_fremovexattr\n17      common  getcwd                          sys_getcwd\n18      common  lookup_dcookie                  sys_ni_syscall\n19      common  eventfd2                        sys_eventfd2\n20      common  epoll_create1                   sys_epoll_create1\n21      common  epoll_ctl                       sys_epoll_ctl\n22      common  epoll_pwait                     sys_epoll_pwait                 compat_sys_epoll_pwait\n23      common  dup                             sys_dup\n24      common  dup3                            sys_dup3\n25      32      fcntl64                         sys_fcntl64                     compat_sys_fcntl64\n25      64      fcntl                           sys_fcntl\n26      common  inotify_init1                   sys_inotify_init1\n27      common  inotify_add_watch               sys_inotify_add_watch\n28      common  inotify_rm_watch                sys_inotify_rm_watch\n29      common  ioctl                           sys_ioctl                       compat_sys_ioctl\n30      common  ioprio_set                      sys_ioprio_set\n31      common  ioprio_get                      sys_ioprio_get\n32      common  flock                           sys_flock\n33      common  mknodat                         sys_mknodat\n34      common  mkdirat                         sys_mkdirat\n35      common  unlinkat                        sys_unlinkat\n36      common  symlinkat                       sys_symlinkat\n37      common  linkat                          sys_linkat\n38      renameat renameat                       sys_renameat\n39      common  umount2                         sys_umount\n40      common  mount                           sys_mount\n41      common  pivot_root                      sys_pivot_root\n42      common  nfsservctl                      sys_ni_syscall\n43      32      statfs64                        sys_statfs64                    compat_sys_statfs64\n43      64      statfs                          sys_statfs\n44      32      fstatfs64                       sys_fstatfs64                   compat_sys_fstatfs64\n44      64      fstatfs                         sys_fstatfs\n45      32      truncate64                      sys_truncate64                  compat_sys_truncate64\n45      64      truncate                        sys_truncate\n46      32      ftruncate64                     sys_ftruncate64                 compat_sys_ftruncate64\n46      64      ftruncate                       sys_ftruncate\n47      common  fallocate                       sys_fallocate                   compat_sys_fallocate\n48      common  faccessat                       sys_faccessat\n49      common  chdir                           sys_chdir\n50      common  fchdir                          sys_fchdir\n51      common  chroot                          sys_chroot\n52      common  fchmod                          sys_fchmod\n53      common  fchmodat                        sys_fchmodat\n54      common  fchownat                        sys_fchownat\n55      common  fchown                          sys_fchown\n56      common  openat                          sys_openat\n57      common  close                           sys_close\n58      common  vhangup                         sys_vhangup\n59      common  pipe2                           sys_pipe2\n60      common  quotactl                        sys_quotactl\n61      common  getdents64                      sys_getdents64\n62      32      llseek                          sys_llseek\n62      64      lseek                           sys_lseek\n63      common  read                            sys_read\n64      common  write                           sys_write\n65      common  readv                           sys_readv                       sys_readv\n66      common  writev                          sys_writev                      sys_writev\n67      common  pread64                         sys_pread64                     compat_sys_pread64\n68      common  pwrite64                        sys_pwrite64                    compat_sys_pwrite64\n69      common  preadv                          sys_preadv                      compat_sys_preadv\n70      common  pwritev                         sys_pwritev                     compat_sys_pwritev\n71      32      sendfile64                      sys_sendfile64\n71      64      sendfile                        sys_sendfile64\n72      time32  pselect6                        sys_pselect6_time32             compat_sys_pselect6_time32\n72      64      pselect6                        sys_pselect6\n73      time32  ppoll                           sys_ppoll_time32                compat_sys_ppoll_time32\n73      64      ppoll                           sys_ppoll\n74      common  signalfd4                       sys_signalfd4                   compat_sys_signalfd4\n75      common  vmsplice                        sys_vmsplice\n76      common  splice                          sys_splice\n77      common  tee                             sys_tee\n78      common  readlinkat                      sys_readlinkat\n79      stat64  fstatat64                       sys_fstatat64\n79      64      newfstatat                      sys_newfstatat\n80      stat64  fstat64                         sys_fstat64\n80      64      fstat                           sys_newfstat\n81      common  sync                            sys_sync\n82      common  fsync                           sys_fsync\n83      common  fdatasync                       sys_fdatasync\n84      common  sync_file_range                 sys_sync_file_range             compat_sys_sync_file_range\n85      common  timerfd_create                  sys_timerfd_create\n86      time32  timerfd_settime                 sys_timerfd_settime32\n86      64      timerfd_settime                 sys_timerfd_settime\n87      time32  timerfd_gettime                 sys_timerfd_gettime32\n87      64      timerfd_gettime                 sys_timerfd_gettime\n88      time32  utimensat                       sys_utimensat_time32\n88      64      utimensat                       sys_utimensat\n89      common  acct                            sys_acct\n90      common  capget                          sys_capget\n91      common  capset                          sys_capset\n92      common  personality                     sys_personality\n93      common  exit                            sys_exit\n94      common  exit_group                      sys_exit_group\n95      common  waitid                          sys_waitid                      compat_sys_waitid\n96      common  set_tid_address                 sys_set_tid_address\n97      common  unshare                         sys_unshare\n98      time32  futex                           sys_futex_time32\n98      64      futex                           sys_futex\n99      common  set_robust_list                 sys_set_robust_list             compat_sys_set_robust_list\n100     common  get_robust_list                 sys_get_robust_list             compat_sys_get_robust_list\n101     time32  nanosleep                       sys_nanosleep_time32\n101     64      nanosleep                       sys_nanosleep\n102     common  getitimer                       sys_getitimer                   compat_sys_getitimer\n103     common  setitimer                       sys_setitimer                   compat_sys_setitimer\n104     common  kexec_load                      sys_kexec_load                  compat_sys_kexec_load\n105     common  init_module                     sys_init_module\n106     common  delete_module                   sys_delete_module\n107     common  timer_create                    sys_timer_create                compat_sys_timer_create\n108     time32  timer_gettime                   sys_timer_gettime32\n108     64      timer_gettime                   sys_timer_gettime\n109     common  timer_getoverrun                sys_timer_getoverrun\n110     time32  timer_settime                   sys_timer_settime32\n110     64      timer_settime                   sys_timer_settime\n111     common  timer_delete                    sys_timer_delete\n112     time32  clock_settime                   sys_clock_settime32\n112     64      clock_settime                   sys_clock_settime\n113     time32  clock_gettime                   sys_clock_gettime32\n113     64      clock_gettime                   sys_clock_gettime\n114     time32  clock_getres                    sys_clock_getres_time32\n114     64      clock_getres                    sys_clock_getres\n115     time32  clock_nanosleep                 sys_clock_nanosleep_time32\n115     64      clock_nanosleep                 sys_clock_nanosleep\n116     common  syslog                          sys_syslog\n117     common  ptrace                          sys_ptrace                      compat_sys_ptrace\n118     common  sched_setparam                  sys_sched_setparam\n119     common  sched_setscheduler              sys_sched_setscheduler\n120     common  sched_getscheduler              sys_sched_getscheduler\n121     common  sched_getparam                  sys_sched_getparam\n122     common  sched_setaffinity               sys_sched_setaffinity           compat_sys_sched_setaffinity\n123     common  sched_getaffinity               sys_sched_getaffinity           compat_sys_sched_getaffinity\n124     common  sched_yield                     sys_sched_yield\n125     common  sched_get_priority_max          sys_sched_get_priority_max\n126     common  sched_get_priority_min          sys_sched_get_priority_min\n127     time32  sched_rr_get_interval           sys_sched_rr_get_interval_time32\n127     64      sched_rr_get_interval           sys_sched_rr_get_interval\n128     common  restart_syscall                 sys_restart_syscall\n129     common  kill                            sys_kill\n130     common  tkill                           sys_tkill\n131     common  tgkill                          sys_tgkill\n132     common  sigaltstack                     sys_sigaltstack                 compat_sys_sigaltstack\n133     common  rt_sigsuspend                   sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n134     common  rt_sigaction                    sys_rt_sigaction                compat_sys_rt_sigaction\n135     common  rt_sigprocmask                  sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n136     common  rt_sigpending                   sys_rt_sigpending               compat_sys_rt_sigpending\n137     time32  rt_sigtimedwait                 sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n137     64      rt_sigtimedwait                 sys_rt_sigtimedwait\n138     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n139     common  rt_sigreturn                    sys_rt_sigreturn                compat_sys_rt_sigreturn\n140     common  setpriority                     sys_setpriority\n141     common  getpriority                     sys_getpriority\n142     common  reboot                          sys_reboot\n143     common  setregid                        sys_setregid\n144     common  setgid                          sys_setgid\n145     common  setreuid                        sys_setreuid\n146     common  setuid                          sys_setuid\n147     common  setresuid                       sys_setresuid\n148     common  getresuid                       sys_getresuid\n149     common  setresgid                       sys_setresgid\n150     common  getresgid                       sys_getresgid\n151     common  setfsuid                        sys_setfsuid\n152     common  setfsgid                        sys_setfsgid\n153     common  times                           sys_times                       compat_sys_times\n154     common  setpgid                         sys_setpgid\n155     common  getpgid                         sys_getpgid\n156     common  getsid                          sys_getsid\n157     common  setsid                          sys_setsid\n158     common  getgroups                       sys_getgroups\n159     common  setgroups                       sys_setgroups\n160     common  uname                           sys_newuname\n161     common  sethostname                     sys_sethostname\n162     common  setdomainname                   sys_setdomainname\n163     rlimit  getrlimit                       sys_getrlimit                   compat_sys_getrlimit\n164     rlimit  setrlimit                       sys_setrlimit                   compat_sys_setrlimit\n165     common  getrusage                       sys_getrusage                   compat_sys_getrusage\n166     common  umask                           sys_umask\n167     common  prctl                           sys_prctl\n168     common  getcpu                          sys_getcpu\n169     time32  gettimeofday                    sys_gettimeofday                compat_sys_gettimeofday\n169     64      gettimeofday                    sys_gettimeofday\n170     time32  settimeofday                    sys_settimeofday                compat_sys_settimeofday\n170     64      settimeofday                    sys_settimeofday\n171     time32  adjtimex                        sys_adjtimex_time32\n171     64      adjtimex                        sys_adjtimex\n172     common  getpid                          sys_getpid\n173     common  getppid                         sys_getppid\n174     common  getuid                          sys_getuid\n175     common  geteuid                         sys_geteuid\n176     common  getgid                          sys_getgid\n177     common  getegid                         sys_getegid\n178     common  gettid                          sys_gettid\n179     common  sysinfo                         sys_sysinfo                     compat_sys_sysinfo\n180     common  mq_open                         sys_mq_open                     compat_sys_mq_open\n181     common  mq_unlink                       sys_mq_unlink\n182     time32  mq_timedsend                    sys_mq_timedsend_time32\n182     64      mq_timedsend                    sys_mq_timedsend\n183     time32  mq_timedreceive                 sys_mq_timedreceive_time32\n183     64      mq_timedreceive                 sys_mq_timedreceive\n184     common  mq_notify                       sys_mq_notify                   compat_sys_mq_notify\n185     common  mq_getsetattr                   sys_mq_getsetattr               compat_sys_mq_getsetattr\n186     common  msgget                          sys_msgget\n187     common  msgctl                          sys_msgctl                      compat_sys_msgctl\n188     common  msgrcv                          sys_msgrcv                      compat_sys_msgrcv\n189     common  msgsnd                          sys_msgsnd                      compat_sys_msgsnd\n190     common  semget                          sys_semget\n191     common  semctl                          sys_semctl                      compat_sys_semctl\n192     time32  semtimedop                      sys_semtimedop_time32\n192     64      semtimedop                      sys_semtimedop\n193     common  semop                           sys_semop\n194     common  shmget                          sys_shmget\n195     common  shmctl                          sys_shmctl                      compat_sys_shmctl\n196     common  shmat                           sys_shmat                       compat_sys_shmat\n197     common  shmdt                           sys_shmdt\n198     common  socket                          sys_socket\n199     common  socketpair                      sys_socketpair\n200     common  bind                            sys_bind\n201     common  listen                          sys_listen\n202     common  accept                          sys_accept\n203     common  connect                         sys_connect\n204     common  getsockname                     sys_getsockname\n205     common  getpeername                     sys_getpeername\n206     common  sendto                          sys_sendto\n207     common  recvfrom                        sys_recvfrom                    compat_sys_recvfrom\n208     common  setsockopt                      sys_setsockopt                  sys_setsockopt\n209     common  getsockopt                      sys_getsockopt                  sys_getsockopt\n210     common  shutdown                        sys_shutdown\n211     common  sendmsg                         sys_sendmsg                     compat_sys_sendmsg\n212     common  recvmsg                         sys_recvmsg                     compat_sys_recvmsg\n213     common  readahead                       sys_readahead                   compat_sys_readahead\n214     common  brk                             sys_brk\n215     common  munmap                          sys_munmap\n216     common  mremap                          sys_mremap\n217     common  add_key                         sys_add_key\n218     common  request_key                     sys_request_key\n219     common  keyctl                          sys_keyctl                      compat_sys_keyctl\n220     common  clone                           sys_clone\n221     common  execve                          sys_execve                      compat_sys_execve\n222     32      mmap2                           sys_mmap2\n222     64      mmap                            sys_mmap\n223     32      fadvise64_64                    sys_fadvise64_64                compat_sys_fadvise64_64\n223     64      fadvise64                       sys_fadvise64_64\n224     common  swapon                          sys_swapon\n225     common  swapoff                         sys_swapoff\n226     common  mprotect                        sys_mprotect\n227     common  msync                           sys_msync\n228     common  mlock                           sys_mlock\n229     common  munlock                         sys_munlock\n230     common  mlockall                        sys_mlockall\n231     common  munlockall                      sys_munlockall\n232     common  mincore                         sys_mincore\n233     common  madvise                         sys_madvise\n234     common  remap_file_pages                sys_remap_file_pages\n235     common  mbind                           sys_mbind\n236     common  get_mempolicy                   sys_get_mempolicy\n237     common  set_mempolicy                   sys_set_mempolicy\n238     common  migrate_pages                   sys_migrate_pages\n239     common  move_pages                      sys_move_pages\n240     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n241     common  perf_event_open                 sys_perf_event_open\n242     common  accept4                         sys_accept4\n243     time32  recvmmsg                        sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n243     64      recvmmsg                        sys_recvmmsg\n244     arc     cacheflush                      sys_cacheflush\n245     arc     arc_settls                      sys_arc_settls\n246     arc     arc_gettls                      sys_arc_gettls\n247     arc     sysfs                           sys_sysfs\n248     arc     arc_usr_cmpxchg                 sys_arc_usr_cmpxchg\n244     csky    set_thread_area                 sys_set_thread_area\n245     csky    cacheflush                      sys_cacheflush\n244     nios2   cacheflush                      sys_cacheflush\n244     or1k    or1k_atomic                     sys_or1k_atomic\n258     riscv   riscv_hwprobe                   sys_riscv_hwprobe\n259     riscv   riscv_flush_icache              sys_riscv_flush_icache\n260     time32  wait4                           sys_wait4                       compat_sys_wait4\n260     64      wait4                           sys_wait4\n261     common  prlimit64                       sys_prlimit64\n262     common  fanotify_init                   sys_fanotify_init\n263     common  fanotify_mark                   sys_fanotify_mark\n264     common  name_to_handle_at               sys_name_to_handle_at\n265     common  open_by_handle_at               sys_open_by_handle_at\n266     time32  clock_adjtime                   sys_clock_adjtime32\n266     64      clock_adjtime                   sys_clock_adjtime\n267     common  syncfs                          sys_syncfs\n268     common  setns                           sys_setns\n269     common  sendmmsg                        sys_sendmmsg                    compat_sys_sendmmsg\n270     common  process_vm_readv                sys_process_vm_readv\n271     common  process_vm_writev               sys_process_vm_writev\n272     common  kcmp                            sys_kcmp\n273     common  finit_module                    sys_finit_module\n274     common  sched_setattr                   sys_sched_setattr\n275     common  sched_getattr                   sys_sched_getattr\n276     common  renameat2                       sys_renameat2\n277     common  seccomp                         sys_seccomp\n278     common  getrandom                       sys_getrandom\n279     common  memfd_create                    sys_memfd_create\n280     common  bpf                             sys_bpf\n281     common  execveat                        sys_execveat                    compat_sys_execveat\n282     common  userfaultfd                     sys_userfaultfd\n283     common  membarrier                      sys_membarrier\n284     common  mlock2                          sys_mlock2\n285     common  copy_file_range                 sys_copy_file_range\n286     common  preadv2                         sys_preadv2                     compat_sys_preadv2\n287     common  pwritev2                        sys_pwritev2                    compat_sys_pwritev2\n288     common  pkey_mprotect                   sys_pkey_mprotect\n289     common  pkey_alloc                      sys_pkey_alloc\n290     common  pkey_free                       sys_pkey_free\n291     common  statx                           sys_statx\n292     time32  io_pgetevents                   sys_io_pgetevents_time32        compat_sys_io_pgetevents\n292     64      io_pgetevents                   sys_io_pgetevents\n293     common  rseq                            sys_rseq\n294     common  kexec_file_load                 sys_kexec_file_load\n403     32      clock_gettime64                 sys_clock_gettime\n404     32      clock_settime64                 sys_clock_settime\n405     32      clock_adjtime64                 sys_clock_adjtime\n406     32      clock_getres_time64             sys_clock_getres\n407     32      clock_nanosleep_time64          sys_clock_nanosleep\n408     32      timer_gettime64                 sys_timer_gettime\n409     32      timer_settime64                 sys_timer_settime\n410     32      timerfd_gettime64               sys_timerfd_gettime\n411     32      timerfd_settime64               sys_timerfd_settime\n412     32      utimensat_time64                sys_utimensat\n413     32      pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     32      ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     32      io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     32      recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     32      mq_timedsend_time64             sys_mq_timedsend\n419     32      mq_timedreceive_time64          sys_mq_timedreceive\n420     32      semtimedop_time64               sys_semtimedop\n421     32      rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     32      futex_time64                    sys_futex\n423     32      sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n447     memfd_secret    memfd_secret            sys_memfd_secret\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# ARM (compat(emulated))\n# - arch/arm64/tools/syscall_32.tbl\narm_compat_syscall_tbl = \"\"\"\n0       common  restart_syscall         sys_restart_syscall\n1       common  exit                    sys_exit\n2       common  fork                    sys_fork\n3       common  read                    sys_read\n4       common  write                   sys_write\n5       common  open                    sys_open                compat_sys_open\n6       common  close                   sys_close\n8       common  creat                   sys_creat\n9       common  link                    sys_link\n10      common  unlink                  sys_unlink\n11      common  execve                  sys_execve              compat_sys_execve\n12      common  chdir                   sys_chdir\n14      common  mknod                   sys_mknod\n15      common  chmod                   sys_chmod\n16      common  lchown                  sys_lchown16\n19      common  lseek                   sys_lseek               compat_sys_lseek\n20      common  getpid                  sys_getpid\n21      common  mount                   sys_mount\n23      common  setuid                  sys_setuid16\n24      common  getuid                  sys_getuid16\n26      common  ptrace                  sys_ptrace              compat_sys_ptrace\n29      common  pause                   sys_pause\n33      common  access                  sys_access\n34      common  nice                    sys_nice\n36      common  sync                    sys_sync\n37      common  kill                    sys_kill\n38      common  rename                  sys_rename\n39      common  mkdir                   sys_mkdir\n40      common  rmdir                   sys_rmdir\n41      common  dup                     sys_dup\n42      common  pipe                    sys_pipe\n43      common  times                   sys_times               compat_sys_times\n45      common  brk                     sys_brk\n46      common  setgid                  sys_setgid16\n47      common  getgid                  sys_getgid16\n49      common  geteuid                 sys_geteuid16\n50      common  getegid                 sys_getegid16\n51      common  acct                    sys_acct\n52      common  umount2                 sys_umount\n54      common  ioctl                   sys_ioctl               compat_sys_ioctl\n55      common  fcntl                   sys_fcntl               compat_sys_fcntl\n57      common  setpgid                 sys_setpgid\n60      common  umask                   sys_umask\n61      common  chroot                  sys_chroot\n62      common  ustat                   sys_ustat               compat_sys_ustat\n63      common  dup2                    sys_dup2\n64      common  getppid                 sys_getppid\n65      common  getpgrp                 sys_getpgrp\n66      common  setsid                  sys_setsid\n67      common  sigaction               sys_sigaction           compat_sys_sigaction\n70      common  setreuid                sys_setreuid16\n71      common  setregid                sys_setregid16\n72      common  sigsuspend              sys_sigsuspend\n73      common  sigpending              sys_sigpending          compat_sys_sigpending\n74      common  sethostname             sys_sethostname\n75      common  setrlimit               sys_setrlimit           compat_sys_setrlimit\n77      common  getrusage               sys_getrusage           compat_sys_getrusage\n78      common  gettimeofday            sys_gettimeofday        compat_sys_gettimeofday\n79      common  settimeofday            sys_settimeofday        compat_sys_settimeofday\n80      common  getgroups               sys_getgroups16\n81      common  setgroups               sys_setgroups16\n83      common  symlink                 sys_symlink\n85      common  readlink                sys_readlink\n86      common  uselib                  sys_uselib\n87      common  swapon                  sys_swapon\n88      common  reboot                  sys_reboot\n91      common  munmap                  sys_munmap\n92      common  truncate                sys_truncate            compat_sys_truncate\n93      common  ftruncate               sys_ftruncate           compat_sys_ftruncate\n94      common  fchmod                  sys_fchmod\n95      common  fchown                  sys_fchown16\n96      common  getpriority             sys_getpriority\n97      common  setpriority             sys_setpriority\n99      common  statfs                  sys_statfs              compat_sys_statfs\n100     common  fstatfs                 sys_fstatfs             compat_sys_fstatfs\n103     common  syslog                  sys_syslog\n104     common  setitimer               sys_setitimer           compat_sys_setitimer\n105     common  getitimer               sys_getitimer           compat_sys_getitimer\n106     common  stat                    sys_newstat             compat_sys_newstat\n107     common  lstat                   sys_newlstat            compat_sys_newlstat\n108     common  fstat                   sys_newfstat            compat_sys_newfstat\n111     common  vhangup                 sys_vhangup\n114     common  wait4                   sys_wait4               compat_sys_wait4\n115     common  swapoff                 sys_swapoff\n116     common  sysinfo                 sys_sysinfo             compat_sys_sysinfo\n118     common  fsync                   sys_fsync\n119     common  sigreturn               sys_sigreturn_wrapper   compat_sys_sigreturn\n120     common  clone                   sys_clone\n121     common  setdomainname           sys_setdomainname\n122     common  uname                   sys_newuname\n124     common  adjtimex                sys_adjtimex_time32\n125     common  mprotect                sys_mprotect\n126     common  sigprocmask             sys_sigprocmask         compat_sys_sigprocmask\n128     common  init_module             sys_init_module\n129     common  delete_module           sys_delete_module\n131     common  quotactl                sys_quotactl\n132     common  getpgid                 sys_getpgid\n133     common  fchdir                  sys_fchdir\n134     common  bdflush                 sys_ni_syscall\n135     common  sysfs                   sys_sysfs\n136     common  personality             sys_personality\n138     common  setfsuid                sys_setfsuid16\n139     common  setfsgid                sys_setfsgid16\n140     common  _llseek                 sys_llseek\n141     common  getdents                sys_getdents            compat_sys_getdents\n142     common  _newselect              sys_select              compat_sys_select\n143     common  flock                   sys_flock\n144     common  msync                   sys_msync\n145     common  readv                   sys_readv\n146     common  writev                  sys_writev\n147     common  getsid                  sys_getsid\n148     common  fdatasync               sys_fdatasync\n149     common  _sysctl                 sys_ni_syscall\n150     common  mlock                   sys_mlock\n151     common  munlock                 sys_munlock\n152     common  mlockall                sys_mlockall\n153     common  munlockall              sys_munlockall\n154     common  sched_setparam          sys_sched_setparam\n155     common  sched_getparam          sys_sched_getparam\n156     common  sched_setscheduler      sys_sched_setscheduler\n157     common  sched_getscheduler      sys_sched_getscheduler\n158     common  sched_yield             sys_sched_yield\n159     common  sched_get_priority_max  sys_sched_get_priority_max\n160     common  sched_get_priority_min  sys_sched_get_priority_min\n161     common  sched_rr_get_interval   sys_sched_rr_get_interval_time32\n162     common  nanosleep               sys_nanosleep_time32\n163     common  mremap                  sys_mremap\n164     common  setresuid               sys_setresuid16\n165     common  getresuid               sys_getresuid16\n168     common  poll                    sys_poll\n169     common  nfsservctl              sys_ni_syscall\n170     common  setresgid               sys_setresgid16\n171     common  getresgid               sys_getresgid16\n172     common  prctl                   sys_prctl\n173     common  rt_sigreturn            sys_rt_sigreturn_wrapper        compat_sys_rt_sigreturn\n174     common  rt_sigaction            sys_rt_sigaction        compat_sys_rt_sigaction\n175     common  rt_sigprocmask          sys_rt_sigprocmask      compat_sys_rt_sigprocmask\n176     common  rt_sigpending           sys_rt_sigpending       compat_sys_rt_sigpending\n177     common  rt_sigtimedwait         sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n178     common  rt_sigqueueinfo         sys_rt_sigqueueinfo     compat_sys_rt_sigqueueinfo\n179     common  rt_sigsuspend           sys_rt_sigsuspend       compat_sys_rt_sigsuspend\n180     common  pread64                 sys_pread64             compat_sys_aarch32_pread64\n181     common  pwrite64                sys_pwrite64            compat_sys_aarch32_pwrite64\n182     common  chown                   sys_chown16\n183     common  getcwd                  sys_getcwd\n184     common  capget                  sys_capget\n185     common  capset                  sys_capset\n186     common  sigaltstack             sys_sigaltstack         compat_sys_sigaltstack\n187     common  sendfile                sys_sendfile            compat_sys_sendfile\n190     common  vfork                   sys_vfork\n191     common  ugetrlimit              sys_getrlimit           compat_sys_getrlimit\n192     common  mmap2                   sys_mmap2               compat_sys_aarch32_mmap2\n193     common  truncate64              sys_truncate64          compat_sys_aarch32_truncate64\n194     common  ftruncate64             sys_ftruncate64         compat_sys_aarch32_ftruncate64\n195     common  stat64                  sys_stat64\n196     common  lstat64                 sys_lstat64\n197     common  fstat64                 sys_fstat64\n198     common  lchown32                sys_lchown\n199     common  getuid32                sys_getuid\n200     common  getgid32                sys_getgid\n201     common  geteuid32               sys_geteuid\n202     common  getegid32               sys_getegid\n203     common  setreuid32              sys_setreuid\n204     common  setregid32              sys_setregid\n205     common  getgroups32             sys_getgroups\n206     common  setgroups32             sys_setgroups\n207     common  fchown32                sys_fchown\n208     common  setresuid32             sys_setresuid\n209     common  getresuid32             sys_getresuid\n210     common  setresgid32             sys_setresgid\n211     common  getresgid32             sys_getresgid\n212     common  chown32                 sys_chown\n213     common  setuid32                sys_setuid\n214     common  setgid32                sys_setgid\n215     common  setfsuid32              sys_setfsuid\n216     common  setfsgid32              sys_setfsgid\n217     common  getdents64              sys_getdents64\n218     common  pivot_root              sys_pivot_root\n219     common  mincore                 sys_mincore\n220     common  madvise                 sys_madvise\n221     common  fcntl64                 sys_fcntl64             compat_sys_fcntl64\n224     common  gettid                  sys_gettid\n225     common  readahead               sys_readahead           compat_sys_aarch32_readahead\n226     common  setxattr                sys_setxattr\n227     common  lsetxattr               sys_lsetxattr\n228     common  fsetxattr               sys_fsetxattr\n229     common  getxattr                sys_getxattr\n230     common  lgetxattr               sys_lgetxattr\n231     common  fgetxattr               sys_fgetxattr\n232     common  listxattr               sys_listxattr\n233     common  llistxattr              sys_llistxattr\n234     common  flistxattr              sys_flistxattr\n235     common  removexattr             sys_removexattr\n236     common  lremovexattr            sys_lremovexattr\n237     common  fremovexattr            sys_fremovexattr\n238     common  tkill                   sys_tkill\n239     common  sendfile64              sys_sendfile64\n240     common  futex                   sys_futex_time32\n241     common  sched_setaffinity       sys_sched_setaffinity   compat_sys_sched_setaffinity\n242     common  sched_getaffinity       sys_sched_getaffinity   compat_sys_sched_getaffinity\n243     common  io_setup                sys_io_setup            compat_sys_io_setup\n244     common  io_destroy              sys_io_destroy\n245     common  io_getevents            sys_io_getevents_time32\n246     common  io_submit               sys_io_submit           compat_sys_io_submit\n247     common  io_cancel               sys_io_cancel\n248     common  exit_group              sys_exit_group\n249     common  lookup_dcookie          sys_ni_syscall\n250     common  epoll_create            sys_epoll_create\n251     common  epoll_ctl               sys_epoll_ctl\n252     common  epoll_wait              sys_epoll_wait\n253     common  remap_file_pages        sys_remap_file_pages\n256     common  set_tid_address         sys_set_tid_address\n257     common  timer_create            sys_timer_create        compat_sys_timer_create\n258     common  timer_settime           sys_timer_settime32\n259     common  timer_gettime           sys_timer_gettime32\n260     common  timer_getoverrun        sys_timer_getoverrun\n261     common  timer_delete            sys_timer_delete\n262     common  clock_settime           sys_clock_settime32\n263     common  clock_gettime           sys_clock_gettime32\n264     common  clock_getres            sys_clock_getres_time32\n265     common  clock_nanosleep         sys_clock_nanosleep_time32\n266     common  statfs64                sys_statfs64_wrapper    compat_sys_aarch32_statfs64\n267     common  fstatfs64               sys_fstatfs64_wrapper   compat_sys_aarch32_fstatfs64\n268     common  tgkill                  sys_tgkill\n269     common  utimes                  sys_utimes_time32\n270     common  arm_fadvise64_64        sys_arm_fadvise64_64    compat_sys_aarch32_fadvise64_64\n271     common  pciconfig_iobase        sys_pciconfig_iobase\n272     common  pciconfig_read          sys_pciconfig_read\n273     common  pciconfig_write         sys_pciconfig_write\n274     common  mq_open                 sys_mq_open             compat_sys_mq_open\n275     common  mq_unlink               sys_mq_unlink\n276     common  mq_timedsend            sys_mq_timedsend_time32\n277     common  mq_timedreceive         sys_mq_timedreceive_time32\n278     common  mq_notify               sys_mq_notify           compat_sys_mq_notify\n279     common  mq_getsetattr           sys_mq_getsetattr       compat_sys_mq_getsetattr\n280     common  waitid                  sys_waitid              compat_sys_waitid\n281     common  socket                  sys_socket\n282     common  bind                    sys_bind\n283     common  connect                 sys_connect\n284     common  listen                  sys_listen\n285     common  accept                  sys_accept\n286     common  getsockname             sys_getsockname\n287     common  getpeername             sys_getpeername\n288     common  socketpair              sys_socketpair\n289     common  send                    sys_send\n290     common  sendto                  sys_sendto\n291     common  recv                    sys_recv                compat_sys_recv\n292     common  recvfrom                sys_recvfrom            compat_sys_recvfrom\n293     common  shutdown                sys_shutdown\n294     common  setsockopt              sys_setsockopt\n295     common  getsockopt              sys_getsockopt\n296     common  sendmsg                 sys_sendmsg             compat_sys_sendmsg\n297     common  recvmsg                 sys_recvmsg             compat_sys_recvmsg\n298     common  semop                   sys_semop\n299     common  semget                  sys_semget\n300     common  semctl                  sys_old_semctl          compat_sys_old_semctl\n301     common  msgsnd                  sys_msgsnd              compat_sys_msgsnd\n302     common  msgrcv                  sys_msgrcv              compat_sys_msgrcv\n303     common  msgget                  sys_msgget\n304     common  msgctl                  sys_old_msgctl          compat_sys_old_msgctl\n305     common  shmat                   sys_shmat               compat_sys_shmat\n306     common  shmdt                   sys_shmdt\n307     common  shmget                  sys_shmget\n308     common  shmctl                  sys_old_shmctl          compat_sys_old_shmctl\n309     common  add_key                 sys_add_key\n310     common  request_key             sys_request_key\n311     common  keyctl                  sys_keyctl              compat_sys_keyctl\n312     common  semtimedop              sys_semtimedop_time32\n313     common  vserver                 sys_ni_syscall\n314     common  ioprio_set              sys_ioprio_set\n315     common  ioprio_get              sys_ioprio_get\n316     common  inotify_init            sys_inotify_init\n317     common  inotify_add_watch       sys_inotify_add_watch\n318     common  inotify_rm_watch        sys_inotify_rm_watch\n319     common  mbind                   sys_mbind\n320     common  get_mempolicy           sys_get_mempolicy\n321     common  set_mempolicy           sys_set_mempolicy\n322     common  openat                  sys_openat              compat_sys_openat\n323     common  mkdirat                 sys_mkdirat\n324     common  mknodat                 sys_mknodat\n325     common  fchownat                sys_fchownat\n326     common  futimesat               sys_futimesat_time32\n327     common  fstatat64               sys_fstatat64\n328     common  unlinkat                sys_unlinkat\n329     common  renameat                sys_renameat\n330     common  linkat                  sys_linkat\n331     common  symlinkat               sys_symlinkat\n332     common  readlinkat              sys_readlinkat\n333     common  fchmodat                sys_fchmodat\n334     common  faccessat               sys_faccessat\n335     common  pselect6                sys_pselect6_time32     compat_sys_pselect6_time32\n336     common  ppoll                   sys_ppoll_time32        compat_sys_ppoll_time32\n337     common  unshare                 sys_unshare\n338     common  set_robust_list         sys_set_robust_list     compat_sys_set_robust_list\n339     common  get_robust_list         sys_get_robust_list     compat_sys_get_robust_list\n340     common  splice                  sys_splice\n341     common  arm_sync_file_range     sys_sync_file_range2    compat_sys_aarch32_sync_file_range2\n342     common  tee                     sys_tee\n343     common  vmsplice                sys_vmsplice\n344     common  move_pages              sys_move_pages\n345     common  getcpu                  sys_getcpu\n346     common  epoll_pwait             sys_epoll_pwait         compat_sys_epoll_pwait\n347     common  kexec_load              sys_kexec_load          compat_sys_kexec_load\n348     common  utimensat               sys_utimensat_time32\n349     common  signalfd                sys_signalfd            compat_sys_signalfd\n350     common  timerfd_create          sys_timerfd_create\n351     common  eventfd                 sys_eventfd\n352     common  fallocate               sys_fallocate           compat_sys_aarch32_fallocate\n353     common  timerfd_settime         sys_timerfd_settime32\n354     common  timerfd_gettime         sys_timerfd_gettime32\n355     common  signalfd4               sys_signalfd4           compat_sys_signalfd4\n356     common  eventfd2                sys_eventfd2\n357     common  epoll_create1           sys_epoll_create1\n358     common  dup3                    sys_dup3\n359     common  pipe2                   sys_pipe2\n360     common  inotify_init1           sys_inotify_init1\n361     common  preadv                  sys_preadv              compat_sys_preadv\n362     common  pwritev                 sys_pwritev             compat_sys_pwritev\n363     common  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo   compat_sys_rt_tgsigqueueinfo\n364     common  perf_event_open         sys_perf_event_open\n365     common  recvmmsg                sys_recvmmsg_time32     compat_sys_recvmmsg_time32\n366     common  accept4                 sys_accept4\n367     common  fanotify_init           sys_fanotify_init\n368     common  fanotify_mark           sys_fanotify_mark       compat_sys_fanotify_mark\n369     common  prlimit64               sys_prlimit64\n370     common  name_to_handle_at       sys_name_to_handle_at\n371     common  open_by_handle_at       sys_open_by_handle_at   compat_sys_open_by_handle_at\n372     common  clock_adjtime           sys_clock_adjtime32\n373     common  syncfs                  sys_syncfs\n374     common  sendmmsg                sys_sendmmsg            compat_sys_sendmmsg\n375     common  setns                   sys_setns\n376     common  process_vm_readv        sys_process_vm_readv\n377     common  process_vm_writev       sys_process_vm_writev\n378     common  kcmp                    sys_kcmp\n379     common  finit_module            sys_finit_module\n380     common  sched_setattr           sys_sched_setattr\n381     common  sched_getattr           sys_sched_getattr\n382     common  renameat2               sys_renameat2\n383     common  seccomp                 sys_seccomp\n384     common  getrandom               sys_getrandom\n385     common  memfd_create            sys_memfd_create\n386     common  bpf                     sys_bpf\n387     common  execveat                sys_execveat            compat_sys_execveat\n388     common  userfaultfd             sys_userfaultfd\n389     common  membarrier              sys_membarrier\n390     common  mlock2                  sys_mlock2\n391     common  copy_file_range         sys_copy_file_range\n392     common  preadv2                 sys_preadv2             compat_sys_preadv2\n393     common  pwritev2                sys_pwritev2            compat_sys_pwritev2\n394     common  pkey_mprotect           sys_pkey_mprotect\n395     common  pkey_alloc              sys_pkey_alloc\n396     common  pkey_free               sys_pkey_free\n397     common  statx                   sys_statx\n398     common  rseq                    sys_rseq\n399     common  io_pgetevents           sys_io_pgetevents_time32        compat_sys_io_pgetevents\n400     common  migrate_pages           sys_migrate_pages\n401     common  kexec_file_load         sys_kexec_file_load\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     common  ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     common  io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     common  recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# ARM (native)\n# - arch/arm/tools/syscall.tbl\narm_native_syscall_tbl = \"\"\"\n0       common  restart_syscall         sys_restart_syscall\n1       common  exit                    sys_exit\n2       common  fork                    sys_fork\n3       common  read                    sys_read\n4       common  write                   sys_write\n5       common  open                    sys_open\n6       common  close                   sys_close\n8       common  creat                   sys_creat\n9       common  link                    sys_link\n10      common  unlink                  sys_unlink\n11      common  execve                  sys_execve\n12      common  chdir                   sys_chdir\n13      oabi    time                    sys_time32\n14      common  mknod                   sys_mknod\n15      common  chmod                   sys_chmod\n16      common  lchown                  sys_lchown16\n19      common  lseek                   sys_lseek\n20      common  getpid                  sys_getpid\n21      common  mount                   sys_mount\n22      oabi    umount                  sys_oldumount\n23      common  setuid                  sys_setuid16\n24      common  getuid                  sys_getuid16\n25      oabi    stime                   sys_stime32\n26      common  ptrace                  sys_ptrace\n27      oabi    alarm                   sys_alarm\n29      common  pause                   sys_pause\n30      oabi    utime                   sys_utime32\n33      common  access                  sys_access\n34      common  nice                    sys_nice\n36      common  sync                    sys_sync\n37      common  kill                    sys_kill\n38      common  rename                  sys_rename\n39      common  mkdir                   sys_mkdir\n40      common  rmdir                   sys_rmdir\n41      common  dup                     sys_dup\n42      common  pipe                    sys_pipe\n43      common  times                   sys_times\n45      common  brk                     sys_brk\n46      common  setgid                  sys_setgid16\n47      common  getgid                  sys_getgid16\n49      common  geteuid                 sys_geteuid16\n50      common  getegid                 sys_getegid16\n51      common  acct                    sys_acct\n52      common  umount2                 sys_umount\n54      common  ioctl                   sys_ioctl\n55      common  fcntl                   sys_fcntl\n57      common  setpgid                 sys_setpgid\n60      common  umask                   sys_umask\n61      common  chroot                  sys_chroot\n62      common  ustat                   sys_ustat\n63      common  dup2                    sys_dup2\n64      common  getppid                 sys_getppid\n65      common  getpgrp                 sys_getpgrp\n66      common  setsid                  sys_setsid\n67      common  sigaction               sys_sigaction\n70      common  setreuid                sys_setreuid16\n71      common  setregid                sys_setregid16\n72      common  sigsuspend              sys_sigsuspend\n73      common  sigpending              sys_sigpending\n74      common  sethostname             sys_sethostname\n75      common  setrlimit               sys_setrlimit\n76      oabi    getrlimit               sys_old_getrlimit\n77      common  getrusage               sys_getrusage\n78      common  gettimeofday            sys_gettimeofday\n79      common  settimeofday            sys_settimeofday\n80      common  getgroups               sys_getgroups16\n81      common  setgroups               sys_setgroups16\n82      oabi    select                  sys_old_select\n83      common  symlink                 sys_symlink\n85      common  readlink                sys_readlink\n86      common  uselib                  sys_uselib\n87      common  swapon                  sys_swapon\n88      common  reboot                  sys_reboot\n89      oabi    readdir                 sys_old_readdir\n90      oabi    mmap                    sys_old_mmap\n91      common  munmap                  sys_munmap\n92      common  truncate                sys_truncate\n93      common  ftruncate               sys_ftruncate\n94      common  fchmod                  sys_fchmod\n95      common  fchown                  sys_fchown16\n96      common  getpriority             sys_getpriority\n97      common  setpriority             sys_setpriority\n99      common  statfs                  sys_statfs\n100     common  fstatfs                 sys_fstatfs\n102     oabi    socketcall              sys_socketcall          sys_oabi_socketcall\n103     common  syslog                  sys_syslog\n104     common  setitimer               sys_setitimer\n105     common  getitimer               sys_getitimer\n106     common  stat                    sys_newstat\n107     common  lstat                   sys_newlstat\n108     common  fstat                   sys_newfstat\n111     common  vhangup                 sys_vhangup\n113     oabi    syscall                 sys_syscall\n114     common  wait4                   sys_wait4\n115     common  swapoff                 sys_swapoff\n116     common  sysinfo                 sys_sysinfo\n117     oabi    ipc                     sys_ipc                 sys_oabi_ipc\n118     common  fsync                   sys_fsync\n119     common  sigreturn               sys_sigreturn_wrapper\n120     common  clone                   sys_clone\n121     common  setdomainname           sys_setdomainname\n122     common  uname                   sys_newuname\n124     common  adjtimex                sys_adjtimex_time32\n125     common  mprotect                sys_mprotect\n126     common  sigprocmask             sys_sigprocmask\n128     common  init_module             sys_init_module\n129     common  delete_module           sys_delete_module\n131     common  quotactl                sys_quotactl\n132     common  getpgid                 sys_getpgid\n133     common  fchdir                  sys_fchdir\n134     common  bdflush                 sys_ni_syscall\n135     common  sysfs                   sys_sysfs\n136     common  personality             sys_personality\n138     common  setfsuid                sys_setfsuid16\n139     common  setfsgid                sys_setfsgid16\n140     common  _llseek                 sys_llseek\n141     common  getdents                sys_getdents\n142     common  _newselect              sys_select\n143     common  flock                   sys_flock\n144     common  msync                   sys_msync\n145     common  readv                   sys_readv\n146     common  writev                  sys_writev\n147     common  getsid                  sys_getsid\n148     common  fdatasync               sys_fdatasync\n149     common  _sysctl                 sys_ni_syscall\n150     common  mlock                   sys_mlock\n151     common  munlock                 sys_munlock\n152     common  mlockall                sys_mlockall\n153     common  munlockall              sys_munlockall\n154     common  sched_setparam          sys_sched_setparam\n155     common  sched_getparam          sys_sched_getparam\n156     common  sched_setscheduler      sys_sched_setscheduler\n157     common  sched_getscheduler      sys_sched_getscheduler\n158     common  sched_yield             sys_sched_yield\n159     common  sched_get_priority_max  sys_sched_get_priority_max\n160     common  sched_get_priority_min  sys_sched_get_priority_min\n161     common  sched_rr_get_interval   sys_sched_rr_get_interval_time32\n162     common  nanosleep               sys_nanosleep_time32\n163     common  mremap                  sys_mremap\n164     common  setresuid               sys_setresuid16\n165     common  getresuid               sys_getresuid16\n168     common  poll                    sys_poll\n169     common  nfsservctl\n170     common  setresgid               sys_setresgid16\n171     common  getresgid               sys_getresgid16\n172     common  prctl                   sys_prctl\n173     common  rt_sigreturn            sys_rt_sigreturn_wrapper\n174     common  rt_sigaction            sys_rt_sigaction\n175     common  rt_sigprocmask          sys_rt_sigprocmask\n176     common  rt_sigpending           sys_rt_sigpending\n177     common  rt_sigtimedwait         sys_rt_sigtimedwait_time32\n178     common  rt_sigqueueinfo         sys_rt_sigqueueinfo\n179     common  rt_sigsuspend           sys_rt_sigsuspend\n180     common  pread64                 sys_pread64             sys_oabi_pread64\n181     common  pwrite64                sys_pwrite64            sys_oabi_pwrite64\n182     common  chown                   sys_chown16\n183     common  getcwd                  sys_getcwd\n184     common  capget                  sys_capget\n185     common  capset                  sys_capset\n186     common  sigaltstack             sys_sigaltstack\n187     common  sendfile                sys_sendfile\n190     common  vfork                   sys_vfork\n191     common  ugetrlimit              sys_getrlimit\n192     common  mmap2                   sys_mmap2\n193     common  truncate64              sys_truncate64          sys_oabi_truncate64\n194     common  ftruncate64             sys_ftruncate64         sys_oabi_ftruncate64\n195     common  stat64                  sys_stat64              sys_oabi_stat64\n196     common  lstat64                 sys_lstat64             sys_oabi_lstat64\n197     common  fstat64                 sys_fstat64             sys_oabi_fstat64\n198     common  lchown32                sys_lchown\n199     common  getuid32                sys_getuid\n200     common  getgid32                sys_getgid\n201     common  geteuid32               sys_geteuid\n202     common  getegid32               sys_getegid\n203     common  setreuid32              sys_setreuid\n204     common  setregid32              sys_setregid\n205     common  getgroups32             sys_getgroups\n206     common  setgroups32             sys_setgroups\n207     common  fchown32                sys_fchown\n208     common  setresuid32             sys_setresuid\n209     common  getresuid32             sys_getresuid\n210     common  setresgid32             sys_setresgid\n211     common  getresgid32             sys_getresgid\n212     common  chown32                 sys_chown\n213     common  setuid32                sys_setuid\n214     common  setgid32                sys_setgid\n215     common  setfsuid32              sys_setfsuid\n216     common  setfsgid32              sys_setfsgid\n217     common  getdents64              sys_getdents64\n218     common  pivot_root              sys_pivot_root\n219     common  mincore                 sys_mincore\n220     common  madvise                 sys_madvise\n221     common  fcntl64                 sys_fcntl64             sys_oabi_fcntl64\n224     common  gettid                  sys_gettid\n225     common  readahead               sys_readahead           sys_oabi_readahead\n226     common  setxattr                sys_setxattr\n227     common  lsetxattr               sys_lsetxattr\n228     common  fsetxattr               sys_fsetxattr\n229     common  getxattr                sys_getxattr\n230     common  lgetxattr               sys_lgetxattr\n231     common  fgetxattr               sys_fgetxattr\n232     common  listxattr               sys_listxattr\n233     common  llistxattr              sys_llistxattr\n234     common  flistxattr              sys_flistxattr\n235     common  removexattr             sys_removexattr\n236     common  lremovexattr            sys_lremovexattr\n237     common  fremovexattr            sys_fremovexattr\n238     common  tkill                   sys_tkill\n239     common  sendfile64              sys_sendfile64\n240     common  futex                   sys_futex_time32\n241     common  sched_setaffinity       sys_sched_setaffinity\n242     common  sched_getaffinity       sys_sched_getaffinity\n243     common  io_setup                sys_io_setup\n244     common  io_destroy              sys_io_destroy\n245     common  io_getevents            sys_io_getevents_time32\n246     common  io_submit               sys_io_submit\n247     common  io_cancel               sys_io_cancel\n248     common  exit_group              sys_exit_group\n249     common  lookup_dcookie          sys_ni_syscall\n250     common  epoll_create            sys_epoll_create\n251     common  epoll_ctl               sys_epoll_ctl           sys_oabi_epoll_ctl\n252     common  epoll_wait              sys_epoll_wait\n253     common  remap_file_pages        sys_remap_file_pages\n256     common  set_tid_address         sys_set_tid_address\n257     common  timer_create            sys_timer_create\n258     common  timer_settime           sys_timer_settime32\n259     common  timer_gettime           sys_timer_gettime32\n260     common  timer_getoverrun        sys_timer_getoverrun\n261     common  timer_delete            sys_timer_delete\n262     common  clock_settime           sys_clock_settime32\n263     common  clock_gettime           sys_clock_gettime32\n264     common  clock_getres            sys_clock_getres_time32\n265     common  clock_nanosleep         sys_clock_nanosleep_time32\n266     common  statfs64                sys_statfs64_wrapper\n267     common  fstatfs64               sys_fstatfs64_wrapper\n268     common  tgkill                  sys_tgkill\n269     common  utimes                  sys_utimes_time32\n270     common  arm_fadvise64_64        sys_arm_fadvise64_64\n271     common  pciconfig_iobase        sys_pciconfig_iobase\n272     common  pciconfig_read          sys_pciconfig_read\n273     common  pciconfig_write         sys_pciconfig_write\n274     common  mq_open                 sys_mq_open\n275     common  mq_unlink               sys_mq_unlink\n276     common  mq_timedsend            sys_mq_timedsend_time32\n277     common  mq_timedreceive         sys_mq_timedreceive_time32\n278     common  mq_notify               sys_mq_notify\n279     common  mq_getsetattr           sys_mq_getsetattr\n280     common  waitid                  sys_waitid\n281     common  socket                  sys_socket\n282     common  bind                    sys_bind                sys_oabi_bind\n283     common  connect                 sys_connect             sys_oabi_connect\n284     common  listen                  sys_listen\n285     common  accept                  sys_accept\n286     common  getsockname             sys_getsockname\n287     common  getpeername             sys_getpeername\n288     common  socketpair              sys_socketpair\n289     common  send                    sys_send\n290     common  sendto                  sys_sendto              sys_oabi_sendto\n291     common  recv                    sys_recv\n292     common  recvfrom                sys_recvfrom\n293     common  shutdown                sys_shutdown\n294     common  setsockopt              sys_setsockopt\n295     common  getsockopt              sys_getsockopt\n296     common  sendmsg                 sys_sendmsg             sys_oabi_sendmsg\n297     common  recvmsg                 sys_recvmsg\n298     common  semop                   sys_semop               sys_oabi_semop\n299     common  semget                  sys_semget\n300     common  semctl                  sys_old_semctl\n301     common  msgsnd                  sys_msgsnd\n302     common  msgrcv                  sys_msgrcv\n303     common  msgget                  sys_msgget\n304     common  msgctl                  sys_old_msgctl\n305     common  shmat                   sys_shmat\n306     common  shmdt                   sys_shmdt\n307     common  shmget                  sys_shmget\n308     common  shmctl                  sys_old_shmctl\n309     common  add_key                 sys_add_key\n310     common  request_key             sys_request_key\n311     common  keyctl                  sys_keyctl\n312     common  semtimedop              sys_semtimedop_time32   sys_oabi_semtimedop\n313     common  vserver\n314     common  ioprio_set              sys_ioprio_set\n315     common  ioprio_get              sys_ioprio_get\n316     common  inotify_init            sys_inotify_init\n317     common  inotify_add_watch       sys_inotify_add_watch\n318     common  inotify_rm_watch        sys_inotify_rm_watch\n319     common  mbind                   sys_mbind\n320     common  get_mempolicy           sys_get_mempolicy\n321     common  set_mempolicy           sys_set_mempolicy\n322     common  openat                  sys_openat\n323     common  mkdirat                 sys_mkdirat\n324     common  mknodat                 sys_mknodat\n325     common  fchownat                sys_fchownat\n326     common  futimesat               sys_futimesat_time32\n327     common  fstatat64               sys_fstatat64           sys_oabi_fstatat64\n328     common  unlinkat                sys_unlinkat\n329     common  renameat                sys_renameat\n330     common  linkat                  sys_linkat\n331     common  symlinkat               sys_symlinkat\n332     common  readlinkat              sys_readlinkat\n333     common  fchmodat                sys_fchmodat\n334     common  faccessat               sys_faccessat\n335     common  pselect6                sys_pselect6_time32\n336     common  ppoll                   sys_ppoll_time32\n337     common  unshare                 sys_unshare\n338     common  set_robust_list         sys_set_robust_list\n339     common  get_robust_list         sys_get_robust_list\n340     common  splice                  sys_splice\n341     common  arm_sync_file_range     sys_sync_file_range2\n342     common  tee                     sys_tee\n343     common  vmsplice                sys_vmsplice\n344     common  move_pages              sys_move_pages\n345     common  getcpu                  sys_getcpu\n346     common  epoll_pwait             sys_epoll_pwait\n347     common  kexec_load              sys_kexec_load\n348     common  utimensat               sys_utimensat_time32\n349     common  signalfd                sys_signalfd\n350     common  timerfd_create          sys_timerfd_create\n351     common  eventfd                 sys_eventfd\n352     common  fallocate               sys_fallocate\n353     common  timerfd_settime         sys_timerfd_settime32\n354     common  timerfd_gettime         sys_timerfd_gettime32\n355     common  signalfd4               sys_signalfd4\n356     common  eventfd2                sys_eventfd2\n357     common  epoll_create1           sys_epoll_create1\n358     common  dup3                    sys_dup3\n359     common  pipe2                   sys_pipe2\n360     common  inotify_init1           sys_inotify_init1\n361     common  preadv                  sys_preadv\n362     common  pwritev                 sys_pwritev\n363     common  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo\n364     common  perf_event_open         sys_perf_event_open\n365     common  recvmmsg                sys_recvmmsg_time32\n366     common  accept4                 sys_accept4\n367     common  fanotify_init           sys_fanotify_init\n368     common  fanotify_mark           sys_fanotify_mark\n369     common  prlimit64               sys_prlimit64\n370     common  name_to_handle_at       sys_name_to_handle_at\n371     common  open_by_handle_at       sys_open_by_handle_at\n372     common  clock_adjtime           sys_clock_adjtime32\n373     common  syncfs                  sys_syncfs\n374     common  sendmmsg                sys_sendmmsg\n375     common  setns                   sys_setns\n376     common  process_vm_readv        sys_process_vm_readv\n377     common  process_vm_writev       sys_process_vm_writev\n378     common  kcmp                    sys_kcmp\n379     common  finit_module            sys_finit_module\n380     common  sched_setattr           sys_sched_setattr\n381     common  sched_getattr           sys_sched_getattr\n382     common  renameat2               sys_renameat2\n383     common  seccomp                 sys_seccomp\n384     common  getrandom               sys_getrandom\n385     common  memfd_create            sys_memfd_create\n386     common  bpf                     sys_bpf\n387     common  execveat                sys_execveat\n388     common  userfaultfd             sys_userfaultfd\n389     common  membarrier              sys_membarrier\n390     common  mlock2                  sys_mlock2\n391     common  copy_file_range         sys_copy_file_range\n392     common  preadv2                 sys_preadv2\n393     common  pwritev2                sys_pwritev2\n394     common  pkey_mprotect           sys_pkey_mprotect\n395     common  pkey_alloc              sys_pkey_alloc\n396     common  pkey_free               sys_pkey_free\n397     common  statx                   sys_statx\n398     common  rseq                    sys_rseq\n399     common  io_pgetevents           sys_io_pgetevents_time32\n400     common  migrate_pages           sys_migrate_pages\n401     common  kexec_file_load         sys_kexec_file_load\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6\n414     common  ppoll_time64                    sys_ppoll\n416     common  io_pgetevents_time64            sys_io_pgetevents\n417     common  recvmmsg_time64                 sys_recvmmsg\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# MIPS o32 (backward compatible ABI, present in /lib)\n# - arch/mips/kernel/syscalls/syscall_o32.tbl\nmips_o32_syscall_tbl = \"\"\"\n0       o32     syscall                         sys_syscall                     sys32_syscall\n1       o32     exit                            sys_exit\n2       o32     fork                            __sys_fork\n3       o32     read                            sys_read\n4       o32     write                           sys_write\n5       o32     open                            sys_open                        compat_sys_open\n6       o32     close                           sys_close\n7       o32     waitpid                         sys_waitpid\n8       o32     creat                           sys_creat\n9       o32     link                            sys_link\n10      o32     unlink                          sys_unlink\n11      o32     execve                          sys_execve                      compat_sys_execve\n12      o32     chdir                           sys_chdir\n13      o32     time                            sys_time32\n14      o32     mknod                           sys_mknod\n15      o32     chmod                           sys_chmod\n16      o32     lchown                          sys_lchown\n17      o32     break                           sys_ni_syscall\n18      o32     unused18                        sys_ni_syscall\n19      o32     lseek                           sys_lseek                       compat_sys_lseek\n20      o32     getpid                          sys_getpid\n21      o32     mount                           sys_mount\n22      o32     umount                          sys_oldumount\n23      o32     setuid                          sys_setuid\n24      o32     getuid                          sys_getuid\n25      o32     stime                           sys_stime32\n26      o32     ptrace                          sys_ptrace                      compat_sys_ptrace\n27      o32     alarm                           sys_alarm\n28      o32     unused28                        sys_ni_syscall\n29      o32     pause                           sys_pause\n30      o32     utime                           sys_utime32\n31      o32     stty                            sys_ni_syscall\n32      o32     gtty                            sys_ni_syscall\n33      o32     access                          sys_access\n34      o32     nice                            sys_nice\n35      o32     ftime                           sys_ni_syscall\n36      o32     sync                            sys_sync\n37      o32     kill                            sys_kill\n38      o32     rename                          sys_rename\n39      o32     mkdir                           sys_mkdir\n40      o32     rmdir                           sys_rmdir\n41      o32     dup                             sys_dup\n42      o32     pipe                            sysm_pipe\n43      o32     times                           sys_times                       compat_sys_times\n44      o32     prof                            sys_ni_syscall\n45      o32     brk                             sys_brk\n46      o32     setgid                          sys_setgid\n47      o32     getgid                          sys_getgid\n48      o32     signal                          sys_ni_syscall\n49      o32     geteuid                         sys_geteuid\n50      o32     getegid                         sys_getegid\n51      o32     acct                            sys_acct\n52      o32     umount2                         sys_umount\n53      o32     lock                            sys_ni_syscall\n54      o32     ioctl                           sys_ioctl                       compat_sys_ioctl\n55      o32     fcntl                           sys_fcntl                       compat_sys_fcntl\n56      o32     mpx                             sys_ni_syscall\n57      o32     setpgid                         sys_setpgid\n58      o32     ulimit                          sys_ni_syscall\n59      o32     unused59                        sys_olduname\n60      o32     umask                           sys_umask\n61      o32     chroot                          sys_chroot\n62      o32     ustat                           sys_ustat                       compat_sys_ustat\n63      o32     dup2                            sys_dup2\n64      o32     getppid                         sys_getppid\n65      o32     getpgrp                         sys_getpgrp\n66      o32     setsid                          sys_setsid\n67      o32     sigaction                       sys_sigaction                   sys_32_sigaction\n68      o32     sgetmask                        sys_sgetmask\n69      o32     ssetmask                        sys_ssetmask\n70      o32     setreuid                        sys_setreuid\n71      o32     setregid                        sys_setregid\n72      o32     sigsuspend                      sys_sigsuspend                  sys32_sigsuspend\n73      o32     sigpending                      sys_sigpending                  compat_sys_sigpending\n74      o32     sethostname                     sys_sethostname\n75      o32     setrlimit                       sys_setrlimit                   compat_sys_setrlimit\n76      o32     getrlimit                       sys_getrlimit                   compat_sys_getrlimit\n77      o32     getrusage                       sys_getrusage                   compat_sys_getrusage\n78      o32     gettimeofday                    sys_gettimeofday                compat_sys_gettimeofday\n79      o32     settimeofday                    sys_settimeofday                compat_sys_settimeofday\n80      o32     getgroups                       sys_getgroups\n81      o32     setgroups                       sys_setgroups\n82      o32     reserved82                      sys_ni_syscall\n83      o32     symlink                         sys_symlink\n84      o32     unused84                        sys_ni_syscall\n85      o32     readlink                        sys_readlink\n86      o32     uselib                          sys_uselib\n87      o32     swapon                          sys_swapon\n88      o32     reboot                          sys_reboot\n89      o32     readdir                         sys_old_readdir                 compat_sys_old_readdir\n90      o32     mmap                            sys_mips_mmap\n91      o32     munmap                          sys_munmap\n92      o32     truncate                        sys_truncate                    compat_sys_truncate\n93      o32     ftruncate                       sys_ftruncate                   compat_sys_ftruncate\n94      o32     fchmod                          sys_fchmod\n95      o32     fchown                          sys_fchown\n96      o32     getpriority                     sys_getpriority\n97      o32     setpriority                     sys_setpriority\n98      o32     profil                          sys_ni_syscall\n99      o32     statfs                          sys_statfs                      compat_sys_statfs\n100     o32     fstatfs                         sys_fstatfs                     compat_sys_fstatfs\n101     o32     ioperm                          sys_ni_syscall\n102     o32     socketcall                      sys_socketcall                  compat_sys_socketcall\n103     o32     syslog                          sys_syslog\n104     o32     setitimer                       sys_setitimer                   compat_sys_setitimer\n105     o32     getitimer                       sys_getitimer                   compat_sys_getitimer\n106     o32     stat                            sys_newstat                     compat_sys_newstat\n107     o32     lstat                           sys_newlstat                    compat_sys_newlstat\n108     o32     fstat                           sys_newfstat                    compat_sys_newfstat\n109     o32     unused109                       sys_uname\n110     o32     iopl                            sys_ni_syscall\n111     o32     vhangup                         sys_vhangup\n112     o32     idle                            sys_ni_syscall\n113     o32     vm86                            sys_ni_syscall\n114     o32     wait4                           sys_wait4                       compat_sys_wait4\n115     o32     swapoff                         sys_swapoff\n116     o32     sysinfo                         sys_sysinfo                     compat_sys_sysinfo\n117     o32     ipc                             sys_ipc                         compat_sys_ipc\n118     o32     fsync                           sys_fsync\n119     o32     sigreturn                       sys_sigreturn                   sys32_sigreturn\n120     o32     clone                           __sys_clone\n121     o32     setdomainname                   sys_setdomainname\n122     o32     uname                           sys_newuname\n123     o32     modify_ldt                      sys_ni_syscall\n124     o32     adjtimex                        sys_adjtimex_time32\n125     o32     mprotect                        sys_mprotect\n126     o32     sigprocmask                     sys_sigprocmask                 compat_sys_sigprocmask\n127     o32     create_module                   sys_ni_syscall\n128     o32     init_module                     sys_init_module\n129     o32     delete_module                   sys_delete_module\n130     o32     get_kernel_syms                 sys_ni_syscall\n131     o32     quotactl                        sys_quotactl\n132     o32     getpgid                         sys_getpgid\n133     o32     fchdir                          sys_fchdir\n134     o32     bdflush                         sys_ni_syscall\n135     o32     sysfs                           sys_sysfs\n136     o32     personality                     sys_personality                 sys_32_personality\n137     o32     afs_syscall                     sys_ni_syscall\n138     o32     setfsuid                        sys_setfsuid\n139     o32     setfsgid                        sys_setfsgid\n140     o32     _llseek                         sys_llseek                      sys_32_llseek\n141     o32     getdents                        sys_getdents                    compat_sys_getdents\n142     o32     _newselect                      sys_select                      compat_sys_select\n143     o32     flock                           sys_flock\n144     o32     msync                           sys_msync\n145     o32     readv                           sys_readv\n146     o32     writev                          sys_writev\n147     o32     cacheflush                      sys_cacheflush\n148     o32     cachectl                        sys_cachectl\n149     o32     sysmips                         __sys_sysmips\n150     o32     unused150                       sys_ni_syscall\n151     o32     getsid                          sys_getsid\n152     o32     fdatasync                       sys_fdatasync\n153     o32     _sysctl                         sys_ni_syscall\n154     o32     mlock                           sys_mlock\n155     o32     munlock                         sys_munlock\n156     o32     mlockall                        sys_mlockall\n157     o32     munlockall                      sys_munlockall\n158     o32     sched_setparam                  sys_sched_setparam\n159     o32     sched_getparam                  sys_sched_getparam\n160     o32     sched_setscheduler              sys_sched_setscheduler\n161     o32     sched_getscheduler              sys_sched_getscheduler\n162     o32     sched_yield                     sys_sched_yield\n163     o32     sched_get_priority_max          sys_sched_get_priority_max\n164     o32     sched_get_priority_min          sys_sched_get_priority_min\n165     o32     sched_rr_get_interval           sys_sched_rr_get_interval_time32\n166     o32     nanosleep                       sys_nanosleep_time32\n167     o32     mremap                          sys_mremap\n168     o32     accept                          sys_accept\n169     o32     bind                            sys_bind\n170     o32     connect                         sys_connect\n171     o32     getpeername                     sys_getpeername\n172     o32     getsockname                     sys_getsockname\n173     o32     getsockopt                      sys_getsockopt                  sys_getsockopt\n174     o32     listen                          sys_listen\n175     o32     recv                            sys_recv                        compat_sys_recv\n176     o32     recvfrom                        sys_recvfrom                    compat_sys_recvfrom\n177     o32     recvmsg                         sys_recvmsg                     compat_sys_recvmsg\n178     o32     send                            sys_send\n179     o32     sendmsg                         sys_sendmsg                     compat_sys_sendmsg\n180     o32     sendto                          sys_sendto\n181     o32     setsockopt                      sys_setsockopt                  sys_setsockopt\n182     o32     shutdown                        sys_shutdown\n183     o32     socket                          sys_socket\n184     o32     socketpair                      sys_socketpair\n185     o32     setresuid                       sys_setresuid\n186     o32     getresuid                       sys_getresuid\n187     o32     query_module                    sys_ni_syscall\n188     o32     poll                            sys_poll\n189     o32     nfsservctl                      sys_ni_syscall\n190     o32     setresgid                       sys_setresgid\n191     o32     getresgid                       sys_getresgid\n192     o32     prctl                           sys_prctl\n193     o32     rt_sigreturn                    sys_rt_sigreturn                sys32_rt_sigreturn\n194     o32     rt_sigaction                    sys_rt_sigaction                compat_sys_rt_sigaction\n195     o32     rt_sigprocmask                  sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n196     o32     rt_sigpending                   sys_rt_sigpending               compat_sys_rt_sigpending\n197     o32     rt_sigtimedwait                 sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n198     o32     rt_sigqueueinfo                 sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n199     o32     rt_sigsuspend                   sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n200     o32     pread64                         sys_pread64                     sys_32_pread\n201     o32     pwrite64                        sys_pwrite64                    sys_32_pwrite\n202     o32     chown                           sys_chown\n203     o32     getcwd                          sys_getcwd\n204     o32     capget                          sys_capget\n205     o32     capset                          sys_capset\n206     o32     sigaltstack                     sys_sigaltstack                 compat_sys_sigaltstack\n207     o32     sendfile                        sys_sendfile                    compat_sys_sendfile\n208     o32     getpmsg                         sys_ni_syscall\n209     o32     putpmsg                         sys_ni_syscall\n210     o32     mmap2                           sys_mips_mmap2\n211     o32     truncate64                      sys_truncate64                  sys_32_truncate64\n212     o32     ftruncate64                     sys_ftruncate64                 sys_32_ftruncate64\n213     o32     stat64                          sys_stat64                      sys_newstat\n214     o32     lstat64                         sys_lstat64                     sys_newlstat\n215     o32     fstat64                         sys_fstat64                     sys_newfstat\n216     o32     pivot_root                      sys_pivot_root\n217     o32     mincore                         sys_mincore\n218     o32     madvise                         sys_madvise\n219     o32     getdents64                      sys_getdents64\n220     o32     fcntl64                         sys_fcntl64                     compat_sys_fcntl64\n221     o32     reserved221                     sys_ni_syscall\n222     o32     gettid                          sys_gettid\n223     o32     readahead                       sys_readahead                   sys32_readahead\n224     o32     setxattr                        sys_setxattr\n225     o32     lsetxattr                       sys_lsetxattr\n226     o32     fsetxattr                       sys_fsetxattr\n227     o32     getxattr                        sys_getxattr\n228     o32     lgetxattr                       sys_lgetxattr\n229     o32     fgetxattr                       sys_fgetxattr\n230     o32     listxattr                       sys_listxattr\n231     o32     llistxattr                      sys_llistxattr\n232     o32     flistxattr                      sys_flistxattr\n233     o32     removexattr                     sys_removexattr\n234     o32     lremovexattr                    sys_lremovexattr\n235     o32     fremovexattr                    sys_fremovexattr\n236     o32     tkill                           sys_tkill\n237     o32     sendfile64                      sys_sendfile64\n238     o32     futex                           sys_futex_time32\n239     o32     sched_setaffinity               sys_sched_setaffinity           compat_sys_sched_setaffinity\n240     o32     sched_getaffinity               sys_sched_getaffinity           compat_sys_sched_getaffinity\n241     o32     io_setup                        sys_io_setup                    compat_sys_io_setup\n242     o32     io_destroy                      sys_io_destroy\n243     o32     io_getevents                    sys_io_getevents_time32\n244     o32     io_submit                       sys_io_submit                   compat_sys_io_submit\n245     o32     io_cancel                       sys_io_cancel\n246     o32     exit_group                      sys_exit_group\n247     o32     lookup_dcookie                  sys_ni_syscall\n248     o32     epoll_create                    sys_epoll_create\n249     o32     epoll_ctl                       sys_epoll_ctl\n250     o32     epoll_wait                      sys_epoll_wait\n251     o32     remap_file_pages                sys_remap_file_pages\n252     o32     set_tid_address                 sys_set_tid_address\n253     o32     restart_syscall                 sys_restart_syscall\n254     o32     fadvise64                       sys_fadvise64_64                sys32_fadvise64_64\n255     o32     statfs64                        sys_statfs64                    compat_sys_statfs64\n256     o32     fstatfs64                       sys_fstatfs64                   compat_sys_fstatfs64\n257     o32     timer_create                    sys_timer_create                compat_sys_timer_create\n258     o32     timer_settime                   sys_timer_settime32\n259     o32     timer_gettime                   sys_timer_gettime32\n260     o32     timer_getoverrun                sys_timer_getoverrun\n261     o32     timer_delete                    sys_timer_delete\n262     o32     clock_settime                   sys_clock_settime32\n263     o32     clock_gettime                   sys_clock_gettime32\n264     o32     clock_getres                    sys_clock_getres_time32\n265     o32     clock_nanosleep                 sys_clock_nanosleep_time32\n266     o32     tgkill                          sys_tgkill\n267     o32     utimes                          sys_utimes_time32\n268     o32     mbind                           sys_mbind\n269     o32     get_mempolicy                   sys_get_mempolicy\n270     o32     set_mempolicy                   sys_set_mempolicy\n271     o32     mq_open                         sys_mq_open                     compat_sys_mq_open\n272     o32     mq_unlink                       sys_mq_unlink\n273     o32     mq_timedsend                    sys_mq_timedsend_time32\n274     o32     mq_timedreceive                 sys_mq_timedreceive_time32\n275     o32     mq_notify                       sys_mq_notify                   compat_sys_mq_notify\n276     o32     mq_getsetattr                   sys_mq_getsetattr               compat_sys_mq_getsetattr\n277     o32     vserver                         sys_ni_syscall\n278     o32     waitid                          sys_waitid                      compat_sys_waitid\n280     o32     add_key                         sys_add_key\n281     o32     request_key                     sys_request_key\n282     o32     keyctl                          sys_keyctl                      compat_sys_keyctl\n283     o32     set_thread_area                 sys_set_thread_area\n284     o32     inotify_init                    sys_inotify_init\n285     o32     inotify_add_watch               sys_inotify_add_watch\n286     o32     inotify_rm_watch                sys_inotify_rm_watch\n287     o32     migrate_pages                   sys_migrate_pages\n288     o32     openat                          sys_openat                      compat_sys_openat\n289     o32     mkdirat                         sys_mkdirat\n290     o32     mknodat                         sys_mknodat\n291     o32     fchownat                        sys_fchownat\n292     o32     futimesat                       sys_futimesat_time32\n293     o32     fstatat64                       sys_fstatat64                   sys_newfstatat\n294     o32     unlinkat                        sys_unlinkat\n295     o32     renameat                        sys_renameat\n296     o32     linkat                          sys_linkat\n297     o32     symlinkat                       sys_symlinkat\n298     o32     readlinkat                      sys_readlinkat\n299     o32     fchmodat                        sys_fchmodat\n300     o32     faccessat                       sys_faccessat\n301     o32     pselect6                        sys_pselect6_time32             compat_sys_pselect6_time32\n302     o32     ppoll                           sys_ppoll_time32                compat_sys_ppoll_time32\n303     o32     unshare                         sys_unshare\n304     o32     splice                          sys_splice\n305     o32     sync_file_range                 sys_sync_file_range             sys32_sync_file_range\n306     o32     tee                             sys_tee\n307     o32     vmsplice                        sys_vmsplice\n308     o32     move_pages                      sys_move_pages\n309     o32     set_robust_list                 sys_set_robust_list             compat_sys_set_robust_list\n310     o32     get_robust_list                 sys_get_robust_list             compat_sys_get_robust_list\n311     o32     kexec_load                      sys_kexec_load                  compat_sys_kexec_load\n312     o32     getcpu                          sys_getcpu\n313     o32     epoll_pwait                     sys_epoll_pwait                 compat_sys_epoll_pwait\n314     o32     ioprio_set                      sys_ioprio_set\n315     o32     ioprio_get                      sys_ioprio_get\n316     o32     utimensat                       sys_utimensat_time32\n317     o32     signalfd                        sys_signalfd                    compat_sys_signalfd\n318     o32     timerfd                         sys_ni_syscall\n319     o32     eventfd                         sys_eventfd\n320     o32     fallocate                       sys_fallocate                   sys32_fallocate\n321     o32     timerfd_create                  sys_timerfd_create\n322     o32     timerfd_gettime                 sys_timerfd_gettime32\n323     o32     timerfd_settime                 sys_timerfd_settime32\n324     o32     signalfd4                       sys_signalfd4                   compat_sys_signalfd4\n325     o32     eventfd2                        sys_eventfd2\n326     o32     epoll_create1                   sys_epoll_create1\n327     o32     dup3                            sys_dup3\n328     o32     pipe2                           sys_pipe2\n329     o32     inotify_init1                   sys_inotify_init1\n330     o32     preadv                          sys_preadv                      compat_sys_preadv\n331     o32     pwritev                         sys_pwritev                     compat_sys_pwritev\n332     o32     rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n333     o32     perf_event_open                 sys_perf_event_open\n334     o32     accept4                         sys_accept4\n335     o32     recvmmsg                        sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n336     o32     fanotify_init                   sys_fanotify_init\n337     o32     fanotify_mark                   sys_fanotify_mark               compat_sys_fanotify_mark\n338     o32     prlimit64                       sys_prlimit64\n339     o32     name_to_handle_at               sys_name_to_handle_at\n340     o32     open_by_handle_at               sys_open_by_handle_at           compat_sys_open_by_handle_at\n341     o32     clock_adjtime                   sys_clock_adjtime32\n342     o32     syncfs                          sys_syncfs\n343     o32     sendmmsg                        sys_sendmmsg                    compat_sys_sendmmsg\n344     o32     setns                           sys_setns\n345     o32     process_vm_readv                sys_process_vm_readv\n346     o32     process_vm_writev               sys_process_vm_writev\n347     o32     kcmp                            sys_kcmp\n348     o32     finit_module                    sys_finit_module\n349     o32     sched_setattr                   sys_sched_setattr\n350     o32     sched_getattr                   sys_sched_getattr\n351     o32     renameat2                       sys_renameat2\n352     o32     seccomp                         sys_seccomp\n353     o32     getrandom                       sys_getrandom\n354     o32     memfd_create                    sys_memfd_create\n355     o32     bpf                             sys_bpf\n356     o32     execveat                        sys_execveat                    compat_sys_execveat\n357     o32     userfaultfd                     sys_userfaultfd\n358     o32     membarrier                      sys_membarrier\n359     o32     mlock2                          sys_mlock2\n360     o32     copy_file_range                 sys_copy_file_range\n361     o32     preadv2                         sys_preadv2                     compat_sys_preadv2\n362     o32     pwritev2                        sys_pwritev2                    compat_sys_pwritev2\n363     o32     pkey_mprotect                   sys_pkey_mprotect\n364     o32     pkey_alloc                      sys_pkey_alloc\n365     o32     pkey_free                       sys_pkey_free\n366     o32     statx                           sys_statx\n367     o32     rseq                            sys_rseq\n368     o32     io_pgetevents                   sys_io_pgetevents_time32        compat_sys_io_pgetevents\n393     o32     semget                          sys_semget\n394     o32     semctl                          sys_semctl                      compat_sys_semctl\n395     o32     shmget                          sys_shmget\n396     o32     shmctl                          sys_shmctl                      compat_sys_shmctl\n397     o32     shmat                           sys_shmat                       compat_sys_shmat\n398     o32     shmdt                           sys_shmdt\n399     o32     msgget                          sys_msgget\n400     o32     msgsnd                          sys_msgsnd                      compat_sys_msgsnd\n401     o32     msgrcv                          sys_msgrcv                      compat_sys_msgrcv\n402     o32     msgctl                          sys_msgctl                      compat_sys_msgctl\n403     o32     clock_gettime64                 sys_clock_gettime               sys_clock_gettime\n404     o32     clock_settime64                 sys_clock_settime               sys_clock_settime\n405     o32     clock_adjtime64                 sys_clock_adjtime               sys_clock_adjtime\n406     o32     clock_getres_time64             sys_clock_getres                sys_clock_getres\n407     o32     clock_nanosleep_time64          sys_clock_nanosleep             sys_clock_nanosleep\n408     o32     timer_gettime64                 sys_timer_gettime               sys_timer_gettime\n409     o32     timer_settime64                 sys_timer_settime               sys_timer_settime\n410     o32     timerfd_gettime64               sys_timerfd_gettime             sys_timerfd_gettime\n411     o32     timerfd_settime64               sys_timerfd_settime             sys_timerfd_settime\n412     o32     utimensat_time64                sys_utimensat                   sys_utimensat\n413     o32     pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     o32     ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     o32     io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     o32     recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     o32     mq_timedsend_time64             sys_mq_timedsend                sys_mq_timedsend\n419     o32     mq_timedreceive_time64          sys_mq_timedreceive             sys_mq_timedreceive\n420     o32     semtimedop_time64               sys_semtimedop                  sys_semtimedop\n421     o32     rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     o32     futex_time64                    sys_futex                       sys_futex\n423     o32     sched_rr_get_interval_time64    sys_sched_rr_get_interval       sys_sched_rr_get_interval\n424     o32     pidfd_send_signal               sys_pidfd_send_signal\n425     o32     io_uring_setup                  sys_io_uring_setup\n426     o32     io_uring_enter                  sys_io_uring_enter\n427     o32     io_uring_register               sys_io_uring_register\n428     o32     open_tree                       sys_open_tree\n429     o32     move_mount                      sys_move_mount\n430     o32     fsopen                          sys_fsopen\n431     o32     fsconfig                        sys_fsconfig\n432     o32     fsmount                         sys_fsmount\n433     o32     fspick                          sys_fspick\n434     o32     pidfd_open                      sys_pidfd_open\n435     o32     clone3                          __sys_clone3\n436     o32     close_range                     sys_close_range\n437     o32     openat2                         sys_openat2\n438     o32     pidfd_getfd                     sys_pidfd_getfd\n439     o32     faccessat2                      sys_faccessat2\n440     o32     process_madvise                 sys_process_madvise\n441     o32     epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     o32     mount_setattr                   sys_mount_setattr\n443     o32     quotactl_fd                     sys_quotactl_fd\n444     o32     landlock_create_ruleset         sys_landlock_create_ruleset\n445     o32     landlock_add_rule               sys_landlock_add_rule\n446     o32     landlock_restrict_self          sys_landlock_restrict_self\n448     o32     process_mrelease                sys_process_mrelease\n449     o32     futex_waitv                     sys_futex_waitv\n450     o32     set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     o32     cachestat                       sys_cachestat\n452     o32     fchmodat2                       sys_fchmodat2\n453     o32     map_shadow_stack                sys_map_shadow_stack\n454     o32     futex_wake                      sys_futex_wake\n455     o32     futex_wait                      sys_futex_wait\n456     o32     futex_requeue                   sys_futex_requeue\n457     o32     statmount                       sys_statmount\n458     o32     listmount                       sys_listmount\n459     o32     lsm_get_self_attr               sys_lsm_get_self_attr\n460     o32     lsm_set_self_attr               sys_lsm_set_self_attr\n461     o32     lsm_list_modules                sys_lsm_list_modules\n462     o32     mseal                           sys_mseal\n463     o32     setxattrat                      sys_setxattrat\n464     o32     getxattrat                      sys_getxattrat\n465     o32     listxattrat                     sys_listxattrat\n466     o32     removexattrat                   sys_removexattrat\n467     o32     open_tree_attr                  sys_open_tree_attr\n468     o32     file_getattr                    sys_file_getattr\n469     o32     file_setattr                    sys_file_setattr\n470     o32     listns                          sys_listns\n\"\"\"\n\n\n# MIPS n32 (default ABI, present in /lib32)\n# - arch/mips/kernel/syscalls/syscall_n32.tbl\nmips_n32_syscall_tbl = \"\"\"\n0       n32     read                            sys_read\n1       n32     write                           sys_write\n2       n32     open                            sys_open\n3       n32     close                           sys_close\n4       n32     stat                            sys_newstat\n5       n32     fstat                           sys_newfstat\n6       n32     lstat                           sys_newlstat\n7       n32     poll                            sys_poll\n8       n32     lseek                           sys_lseek\n9       n32     mmap                            sys_mips_mmap\n10      n32     mprotect                        sys_mprotect\n11      n32     munmap                          sys_munmap\n12      n32     brk                             sys_brk\n13      n32     rt_sigaction                    compat_sys_rt_sigaction\n14      n32     rt_sigprocmask                  compat_sys_rt_sigprocmask\n15      n32     ioctl                           compat_sys_ioctl\n16      n32     pread64                         sys_pread64\n17      n32     pwrite64                        sys_pwrite64\n18      n32     readv                           sys_readv\n19      n32     writev                          sys_writev\n20      n32     access                          sys_access\n21      n32     pipe                            sysm_pipe\n22      n32     _newselect                      compat_sys_select\n23      n32     sched_yield                     sys_sched_yield\n24      n32     mremap                          sys_mremap\n25      n32     msync                           sys_msync\n26      n32     mincore                         sys_mincore\n27      n32     madvise                         sys_madvise\n28      n32     shmget                          sys_shmget\n29      n32     shmat                           sys_shmat\n30      n32     shmctl                          compat_sys_old_shmctl\n31      n32     dup                             sys_dup\n32      n32     dup2                            sys_dup2\n33      n32     pause                           sys_pause\n34      n32     nanosleep                       sys_nanosleep_time32\n35      n32     getitimer                       compat_sys_getitimer\n36      n32     setitimer                       compat_sys_setitimer\n37      n32     alarm                           sys_alarm\n38      n32     getpid                          sys_getpid\n39      n32     sendfile                        compat_sys_sendfile\n40      n32     socket                          sys_socket\n41      n32     connect                         sys_connect\n42      n32     accept                          sys_accept\n43      n32     sendto                          sys_sendto\n44      n32     recvfrom                        compat_sys_recvfrom\n45      n32     sendmsg                         compat_sys_sendmsg\n46      n32     recvmsg                         compat_sys_recvmsg\n47      n32     shutdown                        sys_shutdown\n48      n32     bind                            sys_bind\n49      n32     listen                          sys_listen\n50      n32     getsockname                     sys_getsockname\n51      n32     getpeername                     sys_getpeername\n52      n32     socketpair                      sys_socketpair\n53      n32     setsockopt                      sys_setsockopt\n54      n32     getsockopt                      sys_getsockopt\n55      n32     clone                           __sys_clone\n56      n32     fork                            __sys_fork\n57      n32     execve                          compat_sys_execve\n58      n32     exit                            sys_exit\n59      n32     wait4                           compat_sys_wait4\n60      n32     kill                            sys_kill\n61      n32     uname                           sys_newuname\n62      n32     semget                          sys_semget\n63      n32     semop                           sys_semop\n64      n32     semctl                          compat_sys_old_semctl\n65      n32     shmdt                           sys_shmdt\n66      n32     msgget                          sys_msgget\n67      n32     msgsnd                          compat_sys_msgsnd\n68      n32     msgrcv                          compat_sys_msgrcv\n69      n32     msgctl                          compat_sys_old_msgctl\n70      n32     fcntl                           compat_sys_fcntl\n71      n32     flock                           sys_flock\n72      n32     fsync                           sys_fsync\n73      n32     fdatasync                       sys_fdatasync\n74      n32     truncate                        sys_truncate\n75      n32     ftruncate                       sys_ftruncate\n76      n32     getdents                        compat_sys_getdents\n77      n32     getcwd                          sys_getcwd\n78      n32     chdir                           sys_chdir\n79      n32     fchdir                          sys_fchdir\n80      n32     rename                          sys_rename\n81      n32     mkdir                           sys_mkdir\n82      n32     rmdir                           sys_rmdir\n83      n32     creat                           sys_creat\n84      n32     link                            sys_link\n85      n32     unlink                          sys_unlink\n86      n32     symlink                         sys_symlink\n87      n32     readlink                        sys_readlink\n88      n32     chmod                           sys_chmod\n89      n32     fchmod                          sys_fchmod\n90      n32     chown                           sys_chown\n91      n32     fchown                          sys_fchown\n92      n32     lchown                          sys_lchown\n93      n32     umask                           sys_umask\n94      n32     gettimeofday                    compat_sys_gettimeofday\n95      n32     getrlimit                       compat_sys_getrlimit\n96      n32     getrusage                       compat_sys_getrusage\n97      n32     sysinfo                         compat_sys_sysinfo\n98      n32     times                           compat_sys_times\n99      n32     ptrace                          compat_sys_ptrace\n100     n32     getuid                          sys_getuid\n101     n32     syslog                          sys_syslog\n102     n32     getgid                          sys_getgid\n103     n32     setuid                          sys_setuid\n104     n32     setgid                          sys_setgid\n105     n32     geteuid                         sys_geteuid\n106     n32     getegid                         sys_getegid\n107     n32     setpgid                         sys_setpgid\n108     n32     getppid                         sys_getppid\n109     n32     getpgrp                         sys_getpgrp\n110     n32     setsid                          sys_setsid\n111     n32     setreuid                        sys_setreuid\n112     n32     setregid                        sys_setregid\n113     n32     getgroups                       sys_getgroups\n114     n32     setgroups                       sys_setgroups\n115     n32     setresuid                       sys_setresuid\n116     n32     getresuid                       sys_getresuid\n117     n32     setresgid                       sys_setresgid\n118     n32     getresgid                       sys_getresgid\n119     n32     getpgid                         sys_getpgid\n120     n32     setfsuid                        sys_setfsuid\n121     n32     setfsgid                        sys_setfsgid\n122     n32     getsid                          sys_getsid\n123     n32     capget                          sys_capget\n124     n32     capset                          sys_capset\n125     n32     rt_sigpending                   compat_sys_rt_sigpending\n126     n32     rt_sigtimedwait                 compat_sys_rt_sigtimedwait_time32\n127     n32     rt_sigqueueinfo                 compat_sys_rt_sigqueueinfo\n128     n32     rt_sigsuspend                   compat_sys_rt_sigsuspend\n129     n32     sigaltstack                     compat_sys_sigaltstack\n130     n32     utime                           sys_utime32\n131     n32     mknod                           sys_mknod\n132     n32     personality                     sys_32_personality\n133     n32     ustat                           compat_sys_ustat\n134     n32     statfs                          compat_sys_statfs\n135     n32     fstatfs                         compat_sys_fstatfs\n136     n32     sysfs                           sys_sysfs\n137     n32     getpriority                     sys_getpriority\n138     n32     setpriority                     sys_setpriority\n139     n32     sched_setparam                  sys_sched_setparam\n140     n32     sched_getparam                  sys_sched_getparam\n141     n32     sched_setscheduler              sys_sched_setscheduler\n142     n32     sched_getscheduler              sys_sched_getscheduler\n143     n32     sched_get_priority_max          sys_sched_get_priority_max\n144     n32     sched_get_priority_min          sys_sched_get_priority_min\n145     n32     sched_rr_get_interval           sys_sched_rr_get_interval_time32\n146     n32     mlock                           sys_mlock\n147     n32     munlock                         sys_munlock\n148     n32     mlockall                        sys_mlockall\n149     n32     munlockall                      sys_munlockall\n150     n32     vhangup                         sys_vhangup\n151     n32     pivot_root                      sys_pivot_root\n152     n32     _sysctl                         sys_ni_syscall\n153     n32     prctl                           sys_prctl\n154     n32     adjtimex                        sys_adjtimex_time32\n155     n32     setrlimit                       compat_sys_setrlimit\n156     n32     chroot                          sys_chroot\n157     n32     sync                            sys_sync\n158     n32     acct                            sys_acct\n159     n32     settimeofday                    compat_sys_settimeofday\n160     n32     mount                           sys_mount\n161     n32     umount2                         sys_umount\n162     n32     swapon                          sys_swapon\n163     n32     swapoff                         sys_swapoff\n164     n32     reboot                          sys_reboot\n165     n32     sethostname                     sys_sethostname\n166     n32     setdomainname                   sys_setdomainname\n167     n32     create_module                   sys_ni_syscall\n168     n32     init_module                     sys_init_module\n169     n32     delete_module                   sys_delete_module\n170     n32     get_kernel_syms                 sys_ni_syscall\n171     n32     query_module                    sys_ni_syscall\n172     n32     quotactl                        sys_quotactl\n173     n32     nfsservctl                      sys_ni_syscall\n174     n32     getpmsg                         sys_ni_syscall\n175     n32     putpmsg                         sys_ni_syscall\n176     n32     afs_syscall                     sys_ni_syscall\n177     n32     reserved177                     sys_ni_syscall\n178     n32     gettid                          sys_gettid\n179     n32     readahead                       sys_readahead\n180     n32     setxattr                        sys_setxattr\n181     n32     lsetxattr                       sys_lsetxattr\n182     n32     fsetxattr                       sys_fsetxattr\n183     n32     getxattr                        sys_getxattr\n184     n32     lgetxattr                       sys_lgetxattr\n185     n32     fgetxattr                       sys_fgetxattr\n186     n32     listxattr                       sys_listxattr\n187     n32     llistxattr                      sys_llistxattr\n188     n32     flistxattr                      sys_flistxattr\n189     n32     removexattr                     sys_removexattr\n190     n32     lremovexattr                    sys_lremovexattr\n191     n32     fremovexattr                    sys_fremovexattr\n192     n32     tkill                           sys_tkill\n193     n32     reserved193                     sys_ni_syscall\n194     n32     futex                           sys_futex_time32\n195     n32     sched_setaffinity               compat_sys_sched_setaffinity\n196     n32     sched_getaffinity               compat_sys_sched_getaffinity\n197     n32     cacheflush                      sys_cacheflush\n198     n32     cachectl                        sys_cachectl\n199     n32     sysmips                         __sys_sysmips\n200     n32     io_setup                        compat_sys_io_setup\n201     n32     io_destroy                      sys_io_destroy\n202     n32     io_getevents                    sys_io_getevents_time32\n203     n32     io_submit                       compat_sys_io_submit\n204     n32     io_cancel                       sys_io_cancel\n205     n32     exit_group                      sys_exit_group\n206     n32     lookup_dcookie                  sys_ni_syscall\n207     n32     epoll_create                    sys_epoll_create\n208     n32     epoll_ctl                       sys_epoll_ctl\n209     n32     epoll_wait                      sys_epoll_wait\n210     n32     remap_file_pages                sys_remap_file_pages\n211     n32     rt_sigreturn                    sysn32_rt_sigreturn\n212     n32     fcntl64                         compat_sys_fcntl64\n213     n32     set_tid_address                 sys_set_tid_address\n214     n32     restart_syscall                 sys_restart_syscall\n215     n32     semtimedop                      sys_semtimedop_time32\n216     n32     fadvise64                       sys_fadvise64_64\n217     n32     statfs64                        compat_sys_statfs64\n218     n32     fstatfs64                       compat_sys_fstatfs64\n219     n32     sendfile64                      sys_sendfile64\n220     n32     timer_create                    compat_sys_timer_create\n221     n32     timer_settime                   sys_timer_settime32\n222     n32     timer_gettime                   sys_timer_gettime32\n223     n32     timer_getoverrun                sys_timer_getoverrun\n224     n32     timer_delete                    sys_timer_delete\n225     n32     clock_settime                   sys_clock_settime32\n226     n32     clock_gettime                   sys_clock_gettime32\n227     n32     clock_getres                    sys_clock_getres_time32\n228     n32     clock_nanosleep                 sys_clock_nanosleep_time32\n229     n32     tgkill                          sys_tgkill\n230     n32     utimes                          sys_utimes_time32\n231     n32     mbind                           sys_mbind\n232     n32     get_mempolicy                   sys_get_mempolicy\n233     n32     set_mempolicy                   sys_set_mempolicy\n234     n32     mq_open                         compat_sys_mq_open\n235     n32     mq_unlink                       sys_mq_unlink\n236     n32     mq_timedsend                    sys_mq_timedsend_time32\n237     n32     mq_timedreceive                 sys_mq_timedreceive_time32\n238     n32     mq_notify                       compat_sys_mq_notify\n239     n32     mq_getsetattr                   compat_sys_mq_getsetattr\n240     n32     vserver                         sys_ni_syscall\n241     n32     waitid                          compat_sys_waitid\n243     n32     add_key                         sys_add_key\n244     n32     request_key                     sys_request_key\n245     n32     keyctl                          compat_sys_keyctl\n246     n32     set_thread_area                 sys_set_thread_area\n247     n32     inotify_init                    sys_inotify_init\n248     n32     inotify_add_watch               sys_inotify_add_watch\n249     n32     inotify_rm_watch                sys_inotify_rm_watch\n250     n32     migrate_pages                   sys_migrate_pages\n251     n32     openat                          sys_openat\n252     n32     mkdirat                         sys_mkdirat\n253     n32     mknodat                         sys_mknodat\n254     n32     fchownat                        sys_fchownat\n255     n32     futimesat                       sys_futimesat_time32\n256     n32     newfstatat                      sys_newfstatat\n257     n32     unlinkat                        sys_unlinkat\n258     n32     renameat                        sys_renameat\n259     n32     linkat                          sys_linkat\n260     n32     symlinkat                       sys_symlinkat\n261     n32     readlinkat                      sys_readlinkat\n262     n32     fchmodat                        sys_fchmodat\n263     n32     faccessat                       sys_faccessat\n264     n32     pselect6                        compat_sys_pselect6_time32\n265     n32     ppoll                           compat_sys_ppoll_time32\n266     n32     unshare                         sys_unshare\n267     n32     splice                          sys_splice\n268     n32     sync_file_range                 sys_sync_file_range\n269     n32     tee                             sys_tee\n270     n32     vmsplice                        sys_vmsplice\n271     n32     move_pages                      sys_move_pages\n272     n32     set_robust_list                 compat_sys_set_robust_list\n273     n32     get_robust_list                 compat_sys_get_robust_list\n274     n32     kexec_load                      compat_sys_kexec_load\n275     n32     getcpu                          sys_getcpu\n276     n32     epoll_pwait                     compat_sys_epoll_pwait\n277     n32     ioprio_set                      sys_ioprio_set\n278     n32     ioprio_get                      sys_ioprio_get\n279     n32     utimensat                       sys_utimensat_time32\n280     n32     signalfd                        compat_sys_signalfd\n281     n32     timerfd                         sys_ni_syscall\n282     n32     eventfd                         sys_eventfd\n283     n32     fallocate                       sys_fallocate\n284     n32     timerfd_create                  sys_timerfd_create\n285     n32     timerfd_gettime                 sys_timerfd_gettime32\n286     n32     timerfd_settime                 sys_timerfd_settime32\n287     n32     signalfd4                       compat_sys_signalfd4\n288     n32     eventfd2                        sys_eventfd2\n289     n32     epoll_create1                   sys_epoll_create1\n290     n32     dup3                            sys_dup3\n291     n32     pipe2                           sys_pipe2\n292     n32     inotify_init1                   sys_inotify_init1\n293     n32     preadv                          compat_sys_preadv\n294     n32     pwritev                         compat_sys_pwritev\n295     n32     rt_tgsigqueueinfo               compat_sys_rt_tgsigqueueinfo\n296     n32     perf_event_open                 sys_perf_event_open\n297     n32     accept4                         sys_accept4\n298     n32     recvmmsg                        compat_sys_recvmmsg_time32\n299     n32     getdents64                      sys_getdents64\n300     n32     fanotify_init                   sys_fanotify_init\n301     n32     fanotify_mark                   sys_fanotify_mark\n302     n32     prlimit64                       sys_prlimit64\n303     n32     name_to_handle_at               sys_name_to_handle_at\n304     n32     open_by_handle_at               sys_open_by_handle_at\n305     n32     clock_adjtime                   sys_clock_adjtime32\n306     n32     syncfs                          sys_syncfs\n307     n32     sendmmsg                        compat_sys_sendmmsg\n308     n32     setns                           sys_setns\n309     n32     process_vm_readv                sys_process_vm_readv\n310     n32     process_vm_writev               sys_process_vm_writev\n311     n32     kcmp                            sys_kcmp\n312     n32     finit_module                    sys_finit_module\n313     n32     sched_setattr                   sys_sched_setattr\n314     n32     sched_getattr                   sys_sched_getattr\n315     n32     renameat2                       sys_renameat2\n316     n32     seccomp                         sys_seccomp\n317     n32     getrandom                       sys_getrandom\n318     n32     memfd_create                    sys_memfd_create\n319     n32     bpf                             sys_bpf\n320     n32     execveat                        compat_sys_execveat\n321     n32     userfaultfd                     sys_userfaultfd\n322     n32     membarrier                      sys_membarrier\n323     n32     mlock2                          sys_mlock2\n324     n32     copy_file_range                 sys_copy_file_range\n325     n32     preadv2                         compat_sys_preadv2\n326     n32     pwritev2                        compat_sys_pwritev2\n327     n32     pkey_mprotect                   sys_pkey_mprotect\n328     n32     pkey_alloc                      sys_pkey_alloc\n329     n32     pkey_free                       sys_pkey_free\n330     n32     statx                           sys_statx\n331     n32     rseq                            sys_rseq\n332     n32     io_pgetevents                   compat_sys_io_pgetevents\n403     n32     clock_gettime64                 sys_clock_gettime\n404     n32     clock_settime64                 sys_clock_settime\n405     n32     clock_adjtime64                 sys_clock_adjtime\n406     n32     clock_getres_time64             sys_clock_getres\n407     n32     clock_nanosleep_time64          sys_clock_nanosleep\n408     n32     timer_gettime64                 sys_timer_gettime\n409     n32     timer_settime64                 sys_timer_settime\n410     n32     timerfd_gettime64               sys_timerfd_gettime\n411     n32     timerfd_settime64               sys_timerfd_settime\n412     n32     utimensat_time64                sys_utimensat\n413     n32     pselect6_time64                 compat_sys_pselect6_time64\n414     n32     ppoll_time64                    compat_sys_ppoll_time64\n416     n32     io_pgetevents_time64            compat_sys_io_pgetevents_time64\n417     n32     recvmmsg_time64                 compat_sys_recvmmsg_time64\n418     n32     mq_timedsend_time64             sys_mq_timedsend\n419     n32     mq_timedreceive_time64          sys_mq_timedreceive\n420     n32     semtimedop_time64               sys_semtimedop\n421     n32     rt_sigtimedwait_time64          compat_sys_rt_sigtimedwait_time64\n422     n32     futex_time64                    sys_futex\n423     n32     sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     n32     pidfd_send_signal               sys_pidfd_send_signal\n425     n32     io_uring_setup                  sys_io_uring_setup\n426     n32     io_uring_enter                  sys_io_uring_enter\n427     n32     io_uring_register               sys_io_uring_register\n428     n32     open_tree                       sys_open_tree\n429     n32     move_mount                      sys_move_mount\n430     n32     fsopen                          sys_fsopen\n431     n32     fsconfig                        sys_fsconfig\n432     n32     fsmount                         sys_fsmount\n433     n32     fspick                          sys_fspick\n434     n32     pidfd_open                      sys_pidfd_open\n435     n32     clone3                          __sys_clone3\n436     n32     close_range                     sys_close_range\n437     n32     openat2                         sys_openat2\n438     n32     pidfd_getfd                     sys_pidfd_getfd\n439     n32     faccessat2                      sys_faccessat2\n440     n32     process_madvise                 sys_process_madvise\n441     n32     epoll_pwait2                    compat_sys_epoll_pwait2\n442     n32     mount_setattr                   sys_mount_setattr\n443     n32     quotactl_fd                     sys_quotactl_fd\n444     n32     landlock_create_ruleset         sys_landlock_create_ruleset\n445     n32     landlock_add_rule               sys_landlock_add_rule\n446     n32     landlock_restrict_self          sys_landlock_restrict_self\n448     n32     process_mrelease                sys_process_mrelease\n449     n32     futex_waitv                     sys_futex_waitv\n450     n32     set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     n32     cachestat                       sys_cachestat\n452     n32     fchmodat2                       sys_fchmodat2\n453     n32     map_shadow_stack                sys_map_shadow_stack\n454     n32     futex_wake                      sys_futex_wake\n455     n32     futex_wait                      sys_futex_wait\n456     n32     futex_requeue                   sys_futex_requeue\n457     n32     statmount                       sys_statmount\n458     n32     listmount                       sys_listmount\n459     n32     lsm_get_self_attr               sys_lsm_get_self_attr\n460     n32     lsm_set_self_attr               sys_lsm_set_self_attr\n461     n32     lsm_list_modules                sys_lsm_list_modules\n462     n32     mseal                           sys_mseal\n463     n32     setxattrat                      sys_setxattrat\n464     n32     getxattrat                      sys_getxattrat\n465     n32     listxattrat                     sys_listxattrat\n466     n32     removexattrat                   sys_removexattrat\n467     n32     open_tree_attr                  sys_open_tree_attr\n468     n32     file_getattr                    sys_file_getattr\n469     n32     file_setattr                    sys_file_setattr\n470     n32     listns                          sys_listns\n\"\"\"\n\n\n# MIPS n64 (for 64-bit ABI, present in /lib64)\n# - arch/mips/kernel/syscalls/syscall_n64.tbl\nmips_n64_syscall_tbl = \"\"\"\n0       n64     read                            sys_read\n1       n64     write                           sys_write\n2       n64     open                            sys_open\n3       n64     close                           sys_close\n4       n64     stat                            sys_newstat\n5       n64     fstat                           sys_newfstat\n6       n64     lstat                           sys_newlstat\n7       n64     poll                            sys_poll\n8       n64     lseek                           sys_lseek\n9       n64     mmap                            sys_mips_mmap\n10      n64     mprotect                        sys_mprotect\n11      n64     munmap                          sys_munmap\n12      n64     brk                             sys_brk\n13      n64     rt_sigaction                    sys_rt_sigaction\n14      n64     rt_sigprocmask                  sys_rt_sigprocmask\n15      n64     ioctl                           sys_ioctl\n16      n64     pread64                         sys_pread64\n17      n64     pwrite64                        sys_pwrite64\n18      n64     readv                           sys_readv\n19      n64     writev                          sys_writev\n20      n64     access                          sys_access\n21      n64     pipe                            sysm_pipe\n22      n64     _newselect                      sys_select\n23      n64     sched_yield                     sys_sched_yield\n24      n64     mremap                          sys_mremap\n25      n64     msync                           sys_msync\n26      n64     mincore                         sys_mincore\n27      n64     madvise                         sys_madvise\n28      n64     shmget                          sys_shmget\n29      n64     shmat                           sys_shmat\n30      n64     shmctl                          sys_old_shmctl\n31      n64     dup                             sys_dup\n32      n64     dup2                            sys_dup2\n33      n64     pause                           sys_pause\n34      n64     nanosleep                       sys_nanosleep\n35      n64     getitimer                       sys_getitimer\n36      n64     setitimer                       sys_setitimer\n37      n64     alarm                           sys_alarm\n38      n64     getpid                          sys_getpid\n39      n64     sendfile                        sys_sendfile64\n40      n64     socket                          sys_socket\n41      n64     connect                         sys_connect\n42      n64     accept                          sys_accept\n43      n64     sendto                          sys_sendto\n44      n64     recvfrom                        sys_recvfrom\n45      n64     sendmsg                         sys_sendmsg\n46      n64     recvmsg                         sys_recvmsg\n47      n64     shutdown                        sys_shutdown\n48      n64     bind                            sys_bind\n49      n64     listen                          sys_listen\n50      n64     getsockname                     sys_getsockname\n51      n64     getpeername                     sys_getpeername\n52      n64     socketpair                      sys_socketpair\n53      n64     setsockopt                      sys_setsockopt\n54      n64     getsockopt                      sys_getsockopt\n55      n64     clone                           __sys_clone\n56      n64     fork                            __sys_fork\n57      n64     execve                          sys_execve\n58      n64     exit                            sys_exit\n59      n64     wait4                           sys_wait4\n60      n64     kill                            sys_kill\n61      n64     uname                           sys_newuname\n62      n64     semget                          sys_semget\n63      n64     semop                           sys_semop\n64      n64     semctl                          sys_old_semctl\n65      n64     shmdt                           sys_shmdt\n66      n64     msgget                          sys_msgget\n67      n64     msgsnd                          sys_msgsnd\n68      n64     msgrcv                          sys_msgrcv\n69      n64     msgctl                          sys_old_msgctl\n70      n64     fcntl                           sys_fcntl\n71      n64     flock                           sys_flock\n72      n64     fsync                           sys_fsync\n73      n64     fdatasync                       sys_fdatasync\n74      n64     truncate                        sys_truncate\n75      n64     ftruncate                       sys_ftruncate\n76      n64     getdents                        sys_getdents\n77      n64     getcwd                          sys_getcwd\n78      n64     chdir                           sys_chdir\n79      n64     fchdir                          sys_fchdir\n80      n64     rename                          sys_rename\n81      n64     mkdir                           sys_mkdir\n82      n64     rmdir                           sys_rmdir\n83      n64     creat                           sys_creat\n84      n64     link                            sys_link\n85      n64     unlink                          sys_unlink\n86      n64     symlink                         sys_symlink\n87      n64     readlink                        sys_readlink\n88      n64     chmod                           sys_chmod\n89      n64     fchmod                          sys_fchmod\n90      n64     chown                           sys_chown\n91      n64     fchown                          sys_fchown\n92      n64     lchown                          sys_lchown\n93      n64     umask                           sys_umask\n94      n64     gettimeofday                    sys_gettimeofday\n95      n64     getrlimit                       sys_getrlimit\n96      n64     getrusage                       sys_getrusage\n97      n64     sysinfo                         sys_sysinfo\n98      n64     times                           sys_times\n99      n64     ptrace                          sys_ptrace\n100     n64     getuid                          sys_getuid\n101     n64     syslog                          sys_syslog\n102     n64     getgid                          sys_getgid\n103     n64     setuid                          sys_setuid\n104     n64     setgid                          sys_setgid\n105     n64     geteuid                         sys_geteuid\n106     n64     getegid                         sys_getegid\n107     n64     setpgid                         sys_setpgid\n108     n64     getppid                         sys_getppid\n109     n64     getpgrp                         sys_getpgrp\n110     n64     setsid                          sys_setsid\n111     n64     setreuid                        sys_setreuid\n112     n64     setregid                        sys_setregid\n113     n64     getgroups                       sys_getgroups\n114     n64     setgroups                       sys_setgroups\n115     n64     setresuid                       sys_setresuid\n116     n64     getresuid                       sys_getresuid\n117     n64     setresgid                       sys_setresgid\n118     n64     getresgid                       sys_getresgid\n119     n64     getpgid                         sys_getpgid\n120     n64     setfsuid                        sys_setfsuid\n121     n64     setfsgid                        sys_setfsgid\n122     n64     getsid                          sys_getsid\n123     n64     capget                          sys_capget\n124     n64     capset                          sys_capset\n125     n64     rt_sigpending                   sys_rt_sigpending\n126     n64     rt_sigtimedwait                 sys_rt_sigtimedwait\n127     n64     rt_sigqueueinfo                 sys_rt_sigqueueinfo\n128     n64     rt_sigsuspend                   sys_rt_sigsuspend\n129     n64     sigaltstack                     sys_sigaltstack\n130     n64     utime                           sys_utime\n131     n64     mknod                           sys_mknod\n132     n64     personality                     sys_personality\n133     n64     ustat                           sys_ustat\n134     n64     statfs                          sys_statfs\n135     n64     fstatfs                         sys_fstatfs\n136     n64     sysfs                           sys_sysfs\n137     n64     getpriority                     sys_getpriority\n138     n64     setpriority                     sys_setpriority\n139     n64     sched_setparam                  sys_sched_setparam\n140     n64     sched_getparam                  sys_sched_getparam\n141     n64     sched_setscheduler              sys_sched_setscheduler\n142     n64     sched_getscheduler              sys_sched_getscheduler\n143     n64     sched_get_priority_max          sys_sched_get_priority_max\n144     n64     sched_get_priority_min          sys_sched_get_priority_min\n145     n64     sched_rr_get_interval           sys_sched_rr_get_interval\n146     n64     mlock                           sys_mlock\n147     n64     munlock                         sys_munlock\n148     n64     mlockall                        sys_mlockall\n149     n64     munlockall                      sys_munlockall\n150     n64     vhangup                         sys_vhangup\n151     n64     pivot_root                      sys_pivot_root\n152     n64     _sysctl                         sys_ni_syscall\n153     n64     prctl                           sys_prctl\n154     n64     adjtimex                        sys_adjtimex\n155     n64     setrlimit                       sys_setrlimit\n156     n64     chroot                          sys_chroot\n157     n64     sync                            sys_sync\n158     n64     acct                            sys_acct\n159     n64     settimeofday                    sys_settimeofday\n160     n64     mount                           sys_mount\n161     n64     umount2                         sys_umount\n162     n64     swapon                          sys_swapon\n163     n64     swapoff                         sys_swapoff\n164     n64     reboot                          sys_reboot\n165     n64     sethostname                     sys_sethostname\n166     n64     setdomainname                   sys_setdomainname\n167     n64     create_module                   sys_ni_syscall\n168     n64     init_module                     sys_init_module\n169     n64     delete_module                   sys_delete_module\n170     n64     get_kernel_syms                 sys_ni_syscall\n171     n64     query_module                    sys_ni_syscall\n172     n64     quotactl                        sys_quotactl\n173     n64     nfsservctl                      sys_ni_syscall\n174     n64     getpmsg                         sys_ni_syscall\n175     n64     putpmsg                         sys_ni_syscall\n176     n64     afs_syscall                     sys_ni_syscall\n177     n64     reserved177                     sys_ni_syscall\n178     n64     gettid                          sys_gettid\n179     n64     readahead                       sys_readahead\n180     n64     setxattr                        sys_setxattr\n181     n64     lsetxattr                       sys_lsetxattr\n182     n64     fsetxattr                       sys_fsetxattr\n183     n64     getxattr                        sys_getxattr\n184     n64     lgetxattr                       sys_lgetxattr\n185     n64     fgetxattr                       sys_fgetxattr\n186     n64     listxattr                       sys_listxattr\n187     n64     llistxattr                      sys_llistxattr\n188     n64     flistxattr                      sys_flistxattr\n189     n64     removexattr                     sys_removexattr\n190     n64     lremovexattr                    sys_lremovexattr\n191     n64     fremovexattr                    sys_fremovexattr\n192     n64     tkill                           sys_tkill\n193     n64     reserved193                     sys_ni_syscall\n194     n64     futex                           sys_futex\n195     n64     sched_setaffinity               sys_sched_setaffinity\n196     n64     sched_getaffinity               sys_sched_getaffinity\n197     n64     cacheflush                      sys_cacheflush\n198     n64     cachectl                        sys_cachectl\n199     n64     sysmips                         __sys_sysmips\n200     n64     io_setup                        sys_io_setup\n201     n64     io_destroy                      sys_io_destroy\n202     n64     io_getevents                    sys_io_getevents\n203     n64     io_submit                       sys_io_submit\n204     n64     io_cancel                       sys_io_cancel\n205     n64     exit_group                      sys_exit_group\n206     n64     lookup_dcookie                  sys_ni_syscall\n207     n64     epoll_create                    sys_epoll_create\n208     n64     epoll_ctl                       sys_epoll_ctl\n209     n64     epoll_wait                      sys_epoll_wait\n210     n64     remap_file_pages                sys_remap_file_pages\n211     n64     rt_sigreturn                    sys_rt_sigreturn\n212     n64     set_tid_address                 sys_set_tid_address\n213     n64     restart_syscall                 sys_restart_syscall\n214     n64     semtimedop                      sys_semtimedop\n215     n64     fadvise64                       sys_fadvise64_64\n216     n64     timer_create                    sys_timer_create\n217     n64     timer_settime                   sys_timer_settime\n218     n64     timer_gettime                   sys_timer_gettime\n219     n64     timer_getoverrun                sys_timer_getoverrun\n220     n64     timer_delete                    sys_timer_delete\n221     n64     clock_settime                   sys_clock_settime\n222     n64     clock_gettime                   sys_clock_gettime\n223     n64     clock_getres                    sys_clock_getres\n224     n64     clock_nanosleep                 sys_clock_nanosleep\n225     n64     tgkill                          sys_tgkill\n226     n64     utimes                          sys_utimes\n227     n64     mbind                           sys_mbind\n228     n64     get_mempolicy                   sys_get_mempolicy\n229     n64     set_mempolicy                   sys_set_mempolicy\n230     n64     mq_open                         sys_mq_open\n231     n64     mq_unlink                       sys_mq_unlink\n232     n64     mq_timedsend                    sys_mq_timedsend\n233     n64     mq_timedreceive                 sys_mq_timedreceive\n234     n64     mq_notify                       sys_mq_notify\n235     n64     mq_getsetattr                   sys_mq_getsetattr\n236     n64     vserver                         sys_ni_syscall\n237     n64     waitid                          sys_waitid\n239     n64     add_key                         sys_add_key\n240     n64     request_key                     sys_request_key\n241     n64     keyctl                          sys_keyctl\n242     n64     set_thread_area                 sys_set_thread_area\n243     n64     inotify_init                    sys_inotify_init\n244     n64     inotify_add_watch               sys_inotify_add_watch\n245     n64     inotify_rm_watch                sys_inotify_rm_watch\n246     n64     migrate_pages                   sys_migrate_pages\n247     n64     openat                          sys_openat\n248     n64     mkdirat                         sys_mkdirat\n249     n64     mknodat                         sys_mknodat\n250     n64     fchownat                        sys_fchownat\n251     n64     futimesat                       sys_futimesat\n252     n64     newfstatat                      sys_newfstatat\n253     n64     unlinkat                        sys_unlinkat\n254     n64     renameat                        sys_renameat\n255     n64     linkat                          sys_linkat\n256     n64     symlinkat                       sys_symlinkat\n257     n64     readlinkat                      sys_readlinkat\n258     n64     fchmodat                        sys_fchmodat\n259     n64     faccessat                       sys_faccessat\n260     n64     pselect6                        sys_pselect6\n261     n64     ppoll                           sys_ppoll\n262     n64     unshare                         sys_unshare\n263     n64     splice                          sys_splice\n264     n64     sync_file_range                 sys_sync_file_range\n265     n64     tee                             sys_tee\n266     n64     vmsplice                        sys_vmsplice\n267     n64     move_pages                      sys_move_pages\n268     n64     set_robust_list                 sys_set_robust_list\n269     n64     get_robust_list                 sys_get_robust_list\n270     n64     kexec_load                      sys_kexec_load\n271     n64     getcpu                          sys_getcpu\n272     n64     epoll_pwait                     sys_epoll_pwait\n273     n64     ioprio_set                      sys_ioprio_set\n274     n64     ioprio_get                      sys_ioprio_get\n275     n64     utimensat                       sys_utimensat\n276     n64     signalfd                        sys_signalfd\n277     n64     timerfd                         sys_ni_syscall\n278     n64     eventfd                         sys_eventfd\n279     n64     fallocate                       sys_fallocate\n280     n64     timerfd_create                  sys_timerfd_create\n281     n64     timerfd_gettime                 sys_timerfd_gettime\n282     n64     timerfd_settime                 sys_timerfd_settime\n283     n64     signalfd4                       sys_signalfd4\n284     n64     eventfd2                        sys_eventfd2\n285     n64     epoll_create1                   sys_epoll_create1\n286     n64     dup3                            sys_dup3\n287     n64     pipe2                           sys_pipe2\n288     n64     inotify_init1                   sys_inotify_init1\n289     n64     preadv                          sys_preadv\n290     n64     pwritev                         sys_pwritev\n291     n64     rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n292     n64     perf_event_open                 sys_perf_event_open\n293     n64     accept4                         sys_accept4\n294     n64     recvmmsg                        sys_recvmmsg\n295     n64     fanotify_init                   sys_fanotify_init\n296     n64     fanotify_mark                   sys_fanotify_mark\n297     n64     prlimit64                       sys_prlimit64\n298     n64     name_to_handle_at               sys_name_to_handle_at\n299     n64     open_by_handle_at               sys_open_by_handle_at\n300     n64     clock_adjtime                   sys_clock_adjtime\n301     n64     syncfs                          sys_syncfs\n302     n64     sendmmsg                        sys_sendmmsg\n303     n64     setns                           sys_setns\n304     n64     process_vm_readv                sys_process_vm_readv\n305     n64     process_vm_writev               sys_process_vm_writev\n306     n64     kcmp                            sys_kcmp\n307     n64     finit_module                    sys_finit_module\n308     n64     getdents64                      sys_getdents64\n309     n64     sched_setattr                   sys_sched_setattr\n310     n64     sched_getattr                   sys_sched_getattr\n311     n64     renameat2                       sys_renameat2\n312     n64     seccomp                         sys_seccomp\n313     n64     getrandom                       sys_getrandom\n314     n64     memfd_create                    sys_memfd_create\n315     n64     bpf                             sys_bpf\n316     n64     execveat                        sys_execveat\n317     n64     userfaultfd                     sys_userfaultfd\n318     n64     membarrier                      sys_membarrier\n319     n64     mlock2                          sys_mlock2\n320     n64     copy_file_range                 sys_copy_file_range\n321     n64     preadv2                         sys_preadv2\n322     n64     pwritev2                        sys_pwritev2\n323     n64     pkey_mprotect                   sys_pkey_mprotect\n324     n64     pkey_alloc                      sys_pkey_alloc\n325     n64     pkey_free                       sys_pkey_free\n326     n64     statx                           sys_statx\n327     n64     rseq                            sys_rseq\n328     n64     io_pgetevents                   sys_io_pgetevents\n424     n64     pidfd_send_signal               sys_pidfd_send_signal\n425     n64     io_uring_setup                  sys_io_uring_setup\n426     n64     io_uring_enter                  sys_io_uring_enter\n427     n64     io_uring_register               sys_io_uring_register\n428     n64     open_tree                       sys_open_tree\n429     n64     move_mount                      sys_move_mount\n430     n64     fsopen                          sys_fsopen\n431     n64     fsconfig                        sys_fsconfig\n432     n64     fsmount                         sys_fsmount\n433     n64     fspick                          sys_fspick\n434     n64     pidfd_open                      sys_pidfd_open\n435     n64     clone3                          __sys_clone3\n436     n64     close_range                     sys_close_range\n437     n64     openat2                         sys_openat2\n438     n64     pidfd_getfd                     sys_pidfd_getfd\n439     n64     faccessat2                      sys_faccessat2\n440     n64     process_madvise                 sys_process_madvise\n441     n64     epoll_pwait2                    sys_epoll_pwait2\n442     n64     mount_setattr                   sys_mount_setattr\n443     n64     quotactl_fd                     sys_quotactl_fd\n444     n64     landlock_create_ruleset         sys_landlock_create_ruleset\n445     n64     landlock_add_rule               sys_landlock_add_rule\n446     n64     landlock_restrict_self          sys_landlock_restrict_self\n448     n64     process_mrelease                sys_process_mrelease\n449     n64     futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     n64     cachestat                       sys_cachestat\n452     n64     fchmodat2                       sys_fchmodat2\n453     n64     map_shadow_stack                sys_map_shadow_stack\n454     n64     futex_wake                      sys_futex_wake\n455     n64     futex_wait                      sys_futex_wait\n456     n64     futex_requeue                   sys_futex_requeue\n457     n64     statmount                       sys_statmount\n458     n64     listmount                       sys_listmount\n459     n64     lsm_get_self_attr               sys_lsm_get_self_attr\n460     n64     lsm_set_self_attr               sys_lsm_set_self_attr\n461     n64     lsm_list_modules                sys_lsm_list_modules\n462     n64     mseal                           sys_mseal\n463     n64     setxattrat                      sys_setxattrat\n464     n64     getxattrat                      sys_getxattrat\n465     n64     listxattrat                     sys_listxattrat\n466     n64     removexattrat                   sys_removexattrat\n467     n64     open_tree_attr                  sys_open_tree_attr\n468     n64     file_getattr                    sys_file_getattr\n469     n64     file_setattr                    sys_file_setattr\n470     n64     listns                          sys_listns\n\"\"\"\n\n\n# PowerPC\n# - arch/powerpc/kernel/syscalls/syscall.tbl\nppc_syscall_tbl = \"\"\"\n0       nospu   restart_syscall                 sys_restart_syscall\n1       nospu   exit                            sys_exit\n2       nospu   fork                            sys_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  open                            sys_open                        compat_sys_open\n6       common  close                           sys_close\n7       common  waitpid                         sys_waitpid\n8       common  creat                           sys_creat\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      nospu   execve                          sys_execve                      compat_sys_execve\n12      common  chdir                           sys_chdir\n13      32      time                            sys_time32\n13      64      time                            sys_time\n13      spu     time                            sys_time\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n16      common  lchown                          sys_lchown\n17      common  break                           sys_ni_syscall\n18      32      oldstat                         sys_stat                        sys_ni_syscall\n18      64      oldstat                         sys_ni_syscall\n18      spu     oldstat                         sys_ni_syscall\n19      common  lseek                           sys_lseek                       compat_sys_lseek\n20      common  getpid                          sys_getpid\n21      nospu   mount                           sys_mount\n22      32      umount                          sys_oldumount\n22      64      umount                          sys_ni_syscall\n22      spu     umount                          sys_ni_syscall\n23      common  setuid                          sys_setuid\n24      common  getuid                          sys_getuid\n25      32      stime                           sys_stime32\n25      64      stime                           sys_stime\n25      spu     stime                           sys_stime\n26      nospu   ptrace                          sys_ptrace                      compat_sys_ptrace\n27      common  alarm                           sys_alarm\n28      32      oldfstat                        sys_fstat                       sys_ni_syscall\n28      64      oldfstat                        sys_ni_syscall\n28      spu     oldfstat                        sys_ni_syscall\n29      nospu   pause                           sys_pause\n30      32      utime                           sys_utime32\n30      64      utime                           sys_utime\n31      common  stty                            sys_ni_syscall\n32      common  gtty                            sys_ni_syscall\n33      common  access                          sys_access\n34      common  nice                            sys_nice\n35      common  ftime                           sys_ni_syscall\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  rename                          sys_rename\n39      common  mkdir                           sys_mkdir\n40      common  rmdir                           sys_rmdir\n41      common  dup                             sys_dup\n42      common  pipe                            sys_pipe\n43      common  times                           sys_times                       compat_sys_times\n44      common  prof                            sys_ni_syscall\n45      common  brk                             sys_brk\n46      common  setgid                          sys_setgid\n47      common  getgid                          sys_getgid\n48      nospu   signal                          sys_signal\n49      common  geteuid                         sys_geteuid\n50      common  getegid                         sys_getegid\n51      nospu   acct                            sys_acct\n52      nospu   umount2                         sys_umount\n53      common  lock                            sys_ni_syscall\n54      common  ioctl                           sys_ioctl                       compat_sys_ioctl\n55      common  fcntl                           sys_fcntl                       compat_sys_fcntl\n56      common  mpx                             sys_ni_syscall\n57      common  setpgid                         sys_setpgid\n58      common  ulimit                          sys_ni_syscall\n59      32      oldolduname                     sys_olduname\n59      64      oldolduname                     sys_ni_syscall\n59      spu     oldolduname                     sys_ni_syscall\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      nospu   ustat                           sys_ustat                       compat_sys_ustat\n63      common  dup2                            sys_dup2\n64      common  getppid                         sys_getppid\n65      common  getpgrp                         sys_getpgrp\n66      common  setsid                          sys_setsid\n67      32      sigaction                       sys_sigaction                   compat_sys_sigaction\n67      64      sigaction                       sys_ni_syscall\n67      spu     sigaction                       sys_ni_syscall\n68      common  sgetmask                        sys_sgetmask\n69      common  ssetmask                        sys_ssetmask\n70      common  setreuid                        sys_setreuid\n71      common  setregid                        sys_setregid\n72      32      sigsuspend                      sys_sigsuspend\n72      64      sigsuspend                      sys_ni_syscall\n72      spu     sigsuspend                      sys_ni_syscall\n73      32      sigpending                      sys_sigpending                  compat_sys_sigpending\n73      64      sigpending                      sys_ni_syscall\n73      spu     sigpending                      sys_ni_syscall\n74      common  sethostname                     sys_sethostname\n75      common  setrlimit                       sys_setrlimit                   compat_sys_setrlimit\n76      32      getrlimit                       sys_old_getrlimit               compat_sys_old_getrlimit\n76      64      getrlimit                       sys_ni_syscall\n76      spu     getrlimit                       sys_ni_syscall\n77      common  getrusage                       sys_getrusage                   compat_sys_getrusage\n78      common  gettimeofday                    sys_gettimeofday                compat_sys_gettimeofday\n79      common  settimeofday                    sys_settimeofday                compat_sys_settimeofday\n80      common  getgroups                       sys_getgroups\n81      common  setgroups                       sys_setgroups\n82      32      select                          sys_old_select                  compat_sys_old_select\n82      64      select                          sys_ni_syscall\n82      spu     select                          sys_ni_syscall\n83      common  symlink                         sys_symlink\n84      32      oldlstat                        sys_lstat                       sys_ni_syscall\n84      64      oldlstat                        sys_ni_syscall\n84      spu     oldlstat                        sys_ni_syscall\n85      common  readlink                        sys_readlink\n86      nospu   uselib                          sys_uselib\n87      nospu   swapon                          sys_swapon\n88      nospu   reboot                          sys_reboot\n89      32      readdir                         sys_old_readdir                 compat_sys_old_readdir\n89      64      readdir                         sys_ni_syscall\n89      spu     readdir                         sys_ni_syscall\n90      common  mmap                            sys_mmap\n91      common  munmap                          sys_munmap\n92      common  truncate                        sys_truncate                    compat_sys_truncate\n93      common  ftruncate                       sys_ftruncate                   compat_sys_ftruncate\n94      common  fchmod                          sys_fchmod\n95      common  fchown                          sys_fchown\n96      common  getpriority                     sys_getpriority\n97      common  setpriority                     sys_setpriority\n98      common  profil                          sys_ni_syscall\n99      nospu   statfs                          sys_statfs                      compat_sys_statfs\n100     nospu   fstatfs                         sys_fstatfs                     compat_sys_fstatfs\n101     common  ioperm                          sys_ni_syscall\n102     common  socketcall                      sys_socketcall                  compat_sys_socketcall\n103     common  syslog                          sys_syslog\n104     common  setitimer                       sys_setitimer                   compat_sys_setitimer\n105     common  getitimer                       sys_getitimer                   compat_sys_getitimer\n106     common  stat                            sys_newstat                     compat_sys_newstat\n107     common  lstat                           sys_newlstat                    compat_sys_newlstat\n108     common  fstat                           sys_newfstat                    compat_sys_newfstat\n109     32      olduname                        sys_uname\n109     64      olduname                        sys_ni_syscall\n109     spu     olduname                        sys_ni_syscall\n110     common  iopl                            sys_ni_syscall\n111     common  vhangup                         sys_vhangup\n112     common  idle                            sys_ni_syscall\n113     common  vm86                            sys_ni_syscall\n114     common  wait4                           sys_wait4                       compat_sys_wait4\n115     nospu   swapoff                         sys_swapoff\n116     common  sysinfo                         sys_sysinfo                     compat_sys_sysinfo\n117     nospu   ipc                             sys_ipc                         compat_sys_ipc\n118     common  fsync                           sys_fsync\n119     32      sigreturn                       sys_sigreturn                   compat_sys_sigreturn\n119     64      sigreturn                       sys_ni_syscall\n119     spu     sigreturn                       sys_ni_syscall\n120     nospu   clone                           sys_clone\n121     common  setdomainname                   sys_setdomainname\n122     common  uname                           sys_newuname\n123     common  modify_ldt                      sys_ni_syscall\n124     32      adjtimex                        sys_adjtimex_time32\n124     64      adjtimex                        sys_adjtimex\n124     spu     adjtimex                        sys_adjtimex\n125     common  mprotect                        sys_mprotect\n126     32      sigprocmask                     sys_sigprocmask                 compat_sys_sigprocmask\n126     64      sigprocmask                     sys_ni_syscall\n126     spu     sigprocmask                     sys_ni_syscall\n127     common  create_module                   sys_ni_syscall\n128     nospu   init_module                     sys_init_module\n129     nospu   delete_module                   sys_delete_module\n130     common  get_kernel_syms                 sys_ni_syscall\n131     nospu   quotactl                        sys_quotactl\n132     common  getpgid                         sys_getpgid\n133     common  fchdir                          sys_fchdir\n134     common  bdflush                         sys_ni_syscall\n135     common  sysfs                           sys_sysfs\n136     32      personality                     sys_personality                 compat_sys_ppc64_personality\n136     64      personality                     sys_ppc64_personality\n136     spu     personality                     sys_ppc64_personality\n137     common  afs_syscall                     sys_ni_syscall\n138     common  setfsuid                        sys_setfsuid\n139     common  setfsgid                        sys_setfsgid\n140     common  _llseek                         sys_llseek\n141     common  getdents                        sys_getdents                    compat_sys_getdents\n142     common  _newselect                      sys_select                      compat_sys_select\n143     common  flock                           sys_flock\n144     common  msync                           sys_msync\n145     common  readv                           sys_readv\n146     common  writev                          sys_writev\n147     common  getsid                          sys_getsid\n148     common  fdatasync                       sys_fdatasync\n149     nospu   _sysctl                         sys_ni_syscall\n150     common  mlock                           sys_mlock\n151     common  munlock                         sys_munlock\n152     common  mlockall                        sys_mlockall\n153     common  munlockall                      sys_munlockall\n154     common  sched_setparam                  sys_sched_setparam\n155     common  sched_getparam                  sys_sched_getparam\n156     common  sched_setscheduler              sys_sched_setscheduler\n157     common  sched_getscheduler              sys_sched_getscheduler\n158     common  sched_yield                     sys_sched_yield\n159     common  sched_get_priority_max          sys_sched_get_priority_max\n160     common  sched_get_priority_min          sys_sched_get_priority_min\n161     32      sched_rr_get_interval           sys_sched_rr_get_interval_time32\n161     64      sched_rr_get_interval           sys_sched_rr_get_interval\n161     spu     sched_rr_get_interval           sys_sched_rr_get_interval\n162     32      nanosleep                       sys_nanosleep_time32\n162     64      nanosleep                       sys_nanosleep\n162     spu     nanosleep                       sys_nanosleep\n163     common  mremap                          sys_mremap\n164     common  setresuid                       sys_setresuid\n165     common  getresuid                       sys_getresuid\n166     common  query_module                    sys_ni_syscall\n167     common  poll                            sys_poll\n168     common  nfsservctl                      sys_ni_syscall\n169     common  setresgid                       sys_setresgid\n170     common  getresgid                       sys_getresgid\n171     common  prctl                           sys_prctl\n172     nospu   rt_sigreturn                    sys_rt_sigreturn                compat_sys_rt_sigreturn\n173     nospu   rt_sigaction                    sys_rt_sigaction                compat_sys_rt_sigaction\n174     nospu   rt_sigprocmask                  sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n175     nospu   rt_sigpending                   sys_rt_sigpending               compat_sys_rt_sigpending\n176     32      rt_sigtimedwait                 sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n176     64      rt_sigtimedwait                 sys_rt_sigtimedwait\n177     nospu   rt_sigqueueinfo                 sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n178     nospu   rt_sigsuspend                   sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n179     32      pread64                         sys_ppc_pread64                 compat_sys_ppc_pread64\n179     64      pread64                         sys_pread64\n179     spu     pread64                         sys_pread64\n180     32      pwrite64                        sys_ppc_pwrite64                compat_sys_ppc_pwrite64\n180     64      pwrite64                        sys_pwrite64\n180     spu     pwrite64                        sys_pwrite64\n181     common  chown                           sys_chown\n182     common  getcwd                          sys_getcwd\n183     common  capget                          sys_capget\n184     common  capset                          sys_capset\n185     nospu   sigaltstack                     sys_sigaltstack                 compat_sys_sigaltstack\n186     32      sendfile                        sys_sendfile                    compat_sys_sendfile\n186     64      sendfile                        sys_sendfile64\n186     spu     sendfile                        sys_sendfile64\n187     common  getpmsg                         sys_ni_syscall\n188     common  putpmsg                         sys_ni_syscall\n189     nospu   vfork                           sys_vfork\n190     common  ugetrlimit                      sys_getrlimit                   compat_sys_getrlimit\n191     32      readahead                       sys_ppc_readahead               compat_sys_ppc_readahead\n191     64      readahead                       sys_readahead\n191     spu     readahead                       sys_readahead\n192     32      mmap2                           sys_mmap2                       compat_sys_mmap2\n193     32      truncate64                      sys_ppc_truncate64              compat_sys_ppc_truncate64\n194     32      ftruncate64                     sys_ppc_ftruncate64             compat_sys_ppc_ftruncate64\n195     32      stat64                          sys_stat64\n196     32      lstat64                         sys_lstat64\n197     32      fstat64                         sys_fstat64\n198     nospu   pciconfig_read                  sys_pciconfig_read\n199     nospu   pciconfig_write                 sys_pciconfig_write\n200     nospu   pciconfig_iobase                sys_pciconfig_iobase\n201     common  multiplexer                     sys_ni_syscall\n202     common  getdents64                      sys_getdents64\n203     common  pivot_root                      sys_pivot_root\n204     32      fcntl64                         sys_fcntl64                     compat_sys_fcntl64\n205     common  madvise                         sys_madvise\n206     common  mincore                         sys_mincore\n207     common  gettid                          sys_gettid\n208     common  tkill                           sys_tkill\n209     common  setxattr                        sys_setxattr\n210     common  lsetxattr                       sys_lsetxattr\n211     common  fsetxattr                       sys_fsetxattr\n212     common  getxattr                        sys_getxattr\n213     common  lgetxattr                       sys_lgetxattr\n214     common  fgetxattr                       sys_fgetxattr\n215     common  listxattr                       sys_listxattr\n216     common  llistxattr                      sys_llistxattr\n217     common  flistxattr                      sys_flistxattr\n218     common  removexattr                     sys_removexattr\n219     common  lremovexattr                    sys_lremovexattr\n220     common  fremovexattr                    sys_fremovexattr\n221     32      futex                           sys_futex_time32\n221     64      futex                           sys_futex\n221     spu     futex                           sys_futex\n222     common  sched_setaffinity               sys_sched_setaffinity           compat_sys_sched_setaffinity\n223     common  sched_getaffinity               sys_sched_getaffinity           compat_sys_sched_getaffinity\n225     common  tuxcall                         sys_ni_syscall\n226     32      sendfile64                      sys_sendfile64                  compat_sys_sendfile64\n227     common  io_setup                        sys_io_setup                    compat_sys_io_setup\n228     common  io_destroy                      sys_io_destroy\n229     32      io_getevents                    sys_io_getevents_time32\n229     64      io_getevents                    sys_io_getevents\n229     spu     io_getevents                    sys_io_getevents\n230     common  io_submit                       sys_io_submit                   compat_sys_io_submit\n231     common  io_cancel                       sys_io_cancel\n232     nospu   set_tid_address                 sys_set_tid_address\n233     32      fadvise64                       sys_ppc32_fadvise64             compat_sys_ppc32_fadvise64\n233     64      fadvise64                       sys_fadvise64\n233     spu     fadvise64                       sys_fadvise64\n234     nospu   exit_group                      sys_exit_group\n235     nospu   lookup_dcookie                  sys_ni_syscall\n236     common  epoll_create                    sys_epoll_create\n237     common  epoll_ctl                       sys_epoll_ctl\n238     common  epoll_wait                      sys_epoll_wait\n239     common  remap_file_pages                sys_remap_file_pages\n240     common  timer_create                    sys_timer_create                compat_sys_timer_create\n241     32      timer_settime                   sys_timer_settime32\n241     64      timer_settime                   sys_timer_settime\n241     spu     timer_settime                   sys_timer_settime\n242     32      timer_gettime                   sys_timer_gettime32\n242     64      timer_gettime                   sys_timer_gettime\n242     spu     timer_gettime                   sys_timer_gettime\n243     common  timer_getoverrun                sys_timer_getoverrun\n244     common  timer_delete                    sys_timer_delete\n245     32      clock_settime                   sys_clock_settime32\n245     64      clock_settime                   sys_clock_settime\n245     spu     clock_settime                   sys_clock_settime\n246     32      clock_gettime                   sys_clock_gettime32\n246     64      clock_gettime                   sys_clock_gettime\n246     spu     clock_gettime                   sys_clock_gettime\n247     32      clock_getres                    sys_clock_getres_time32\n247     64      clock_getres                    sys_clock_getres\n247     spu     clock_getres                    sys_clock_getres\n248     32      clock_nanosleep                 sys_clock_nanosleep_time32\n248     64      clock_nanosleep                 sys_clock_nanosleep\n248     spu     clock_nanosleep                 sys_clock_nanosleep\n249     nospu   swapcontext                     sys_swapcontext                 compat_sys_swapcontext\n250     common  tgkill                          sys_tgkill\n251     32      utimes                          sys_utimes_time32\n251     64      utimes                          sys_utimes\n251     spu     utimes                          sys_utimes\n252     common  statfs64                        sys_statfs64                    compat_sys_statfs64\n253     common  fstatfs64                       sys_fstatfs64                   compat_sys_fstatfs64\n254     32      fadvise64_64                    sys_ppc_fadvise64_64\n254     spu     fadvise64_64                    sys_ni_syscall\n255     common  rtas                            sys_rtas\n256     32      sys_debug_setcontext            sys_debug_setcontext            sys_ni_syscall\n256     64      sys_debug_setcontext            sys_ni_syscall\n256     spu     sys_debug_setcontext            sys_ni_syscall\n258     nospu   migrate_pages                   sys_migrate_pages\n259     nospu   mbind                           sys_mbind\n260     nospu   get_mempolicy                   sys_get_mempolicy\n261     nospu   set_mempolicy                   sys_set_mempolicy\n262     nospu   mq_open                         sys_mq_open                     compat_sys_mq_open\n263     nospu   mq_unlink                       sys_mq_unlink\n264     32      mq_timedsend                    sys_mq_timedsend_time32\n264     64      mq_timedsend                    sys_mq_timedsend\n265     32      mq_timedreceive                 sys_mq_timedreceive_time32\n265     64      mq_timedreceive                 sys_mq_timedreceive\n266     nospu   mq_notify                       sys_mq_notify                   compat_sys_mq_notify\n267     nospu   mq_getsetattr                   sys_mq_getsetattr               compat_sys_mq_getsetattr\n268     nospu   kexec_load                      sys_kexec_load                  compat_sys_kexec_load\n269     nospu   add_key                         sys_add_key\n270     nospu   request_key                     sys_request_key\n271     nospu   keyctl                          sys_keyctl                      compat_sys_keyctl\n272     nospu   waitid                          sys_waitid                      compat_sys_waitid\n273     nospu   ioprio_set                      sys_ioprio_set\n274     nospu   ioprio_get                      sys_ioprio_get\n275     nospu   inotify_init                    sys_inotify_init\n276     nospu   inotify_add_watch               sys_inotify_add_watch\n277     nospu   inotify_rm_watch                sys_inotify_rm_watch\n278     nospu   spu_run                         sys_spu_run\n279     nospu   spu_create                      sys_spu_create\n280     32      pselect6                        sys_pselect6_time32             compat_sys_pselect6_time32\n280     64      pselect6                        sys_pselect6\n281     32      ppoll                           sys_ppoll_time32                compat_sys_ppoll_time32\n281     64      ppoll                           sys_ppoll\n282     common  unshare                         sys_unshare\n283     common  splice                          sys_splice\n284     common  tee                             sys_tee\n285     common  vmsplice                        sys_vmsplice\n286     common  openat                          sys_openat                      compat_sys_openat\n287     common  mkdirat                         sys_mkdirat\n288     common  mknodat                         sys_mknodat\n289     common  fchownat                        sys_fchownat\n290     32      futimesat                       sys_futimesat_time32\n290     64      futimesat                       sys_futimesat\n290     spu     utimesat                        sys_futimesat\n291     32      fstatat64                       sys_fstatat64\n291     64      newfstatat                      sys_newfstatat\n291     spu     newfstatat                      sys_newfstatat\n292     common  unlinkat                        sys_unlinkat\n293     common  renameat                        sys_renameat\n294     common  linkat                          sys_linkat\n295     common  symlinkat                       sys_symlinkat\n296     common  readlinkat                      sys_readlinkat\n297     common  fchmodat                        sys_fchmodat\n298     common  faccessat                       sys_faccessat\n299     common  get_robust_list                 sys_get_robust_list             compat_sys_get_robust_list\n300     common  set_robust_list                 sys_set_robust_list             compat_sys_set_robust_list\n301     common  move_pages                      sys_move_pages\n302     common  getcpu                          sys_getcpu\n303     nospu   epoll_pwait                     sys_epoll_pwait                 compat_sys_epoll_pwait\n304     32      utimensat                       sys_utimensat_time32\n304     64      utimensat                       sys_utimensat\n304     spu     utimensat                       sys_utimensat\n305     common  signalfd                        sys_signalfd                    compat_sys_signalfd\n306     common  timerfd_create                  sys_timerfd_create\n307     common  eventfd                         sys_eventfd\n308     32      sync_file_range2                sys_ppc_sync_file_range2        compat_sys_ppc_sync_file_range2\n308     64      sync_file_range2                sys_sync_file_range2\n308     spu     sync_file_range2                sys_sync_file_range2\n309     32      fallocate                       sys_ppc_fallocate               compat_sys_fallocate\n309     64      fallocate                       sys_fallocate\n310     nospu   subpage_prot                    sys_subpage_prot\n311     32      timerfd_settime                 sys_timerfd_settime32\n311     64      timerfd_settime                 sys_timerfd_settime\n311     spu     timerfd_settime                 sys_timerfd_settime\n312     32      timerfd_gettime                 sys_timerfd_gettime32\n312     64      timerfd_gettime                 sys_timerfd_gettime\n312     spu     timerfd_gettime                 sys_timerfd_gettime\n313     common  signalfd4                       sys_signalfd4                   compat_sys_signalfd4\n314     common  eventfd2                        sys_eventfd2\n315     common  epoll_create1                   sys_epoll_create1\n316     common  dup3                            sys_dup3\n317     common  pipe2                           sys_pipe2\n318     nospu   inotify_init1                   sys_inotify_init1\n319     common  perf_event_open                 sys_perf_event_open\n320     common  preadv                          sys_preadv                      compat_sys_preadv\n321     common  pwritev                         sys_pwritev                     compat_sys_pwritev\n322     nospu   rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n323     nospu   fanotify_init                   sys_fanotify_init\n324     nospu   fanotify_mark                   sys_fanotify_mark               compat_sys_fanotify_mark\n325     common  prlimit64                       sys_prlimit64\n326     common  socket                          sys_socket\n327     common  bind                            sys_bind\n328     common  connect                         sys_connect\n329     common  listen                          sys_listen\n330     common  accept                          sys_accept\n331     common  getsockname                     sys_getsockname\n332     common  getpeername                     sys_getpeername\n333     common  socketpair                      sys_socketpair\n334     common  send                            sys_send\n335     common  sendto                          sys_sendto\n336     common  recv                            sys_recv                        compat_sys_recv\n337     common  recvfrom                        sys_recvfrom                    compat_sys_recvfrom\n338     common  shutdown                        sys_shutdown\n339     common  setsockopt                      sys_setsockopt                  sys_setsockopt\n340     common  getsockopt                      sys_getsockopt                  sys_getsockopt\n341     common  sendmsg                         sys_sendmsg                     compat_sys_sendmsg\n342     common  recvmsg                         sys_recvmsg                     compat_sys_recvmsg\n343     32      recvmmsg                        sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n343     64      recvmmsg                        sys_recvmmsg\n343     spu     recvmmsg                        sys_recvmmsg\n344     common  accept4                         sys_accept4\n345     common  name_to_handle_at               sys_name_to_handle_at\n346     common  open_by_handle_at               sys_open_by_handle_at           compat_sys_open_by_handle_at\n347     32      clock_adjtime                   sys_clock_adjtime32\n347     64      clock_adjtime                   sys_clock_adjtime\n347     spu     clock_adjtime                   sys_clock_adjtime\n348     common  syncfs                          sys_syncfs\n349     common  sendmmsg                        sys_sendmmsg                    compat_sys_sendmmsg\n350     common  setns                           sys_setns\n351     nospu   process_vm_readv                sys_process_vm_readv\n352     nospu   process_vm_writev               sys_process_vm_writev\n353     nospu   finit_module                    sys_finit_module\n354     nospu   kcmp                            sys_kcmp\n355     common  sched_setattr                   sys_sched_setattr\n356     common  sched_getattr                   sys_sched_getattr\n357     common  renameat2                       sys_renameat2\n358     common  seccomp                         sys_seccomp\n359     common  getrandom                       sys_getrandom\n360     common  memfd_create                    sys_memfd_create\n361     common  bpf                             sys_bpf\n362     nospu   execveat                        sys_execveat                    compat_sys_execveat\n363     32      switch_endian                   sys_ni_syscall\n363     64      switch_endian                   sys_switch_endian\n363     spu     switch_endian                   sys_ni_syscall\n364     common  userfaultfd                     sys_userfaultfd\n365     common  membarrier                      sys_membarrier\n378     nospu   mlock2                          sys_mlock2\n379     nospu   copy_file_range                 sys_copy_file_range\n380     common  preadv2                         sys_preadv2                     compat_sys_preadv2\n381     common  pwritev2                        sys_pwritev2                    compat_sys_pwritev2\n382     nospu   kexec_file_load                 sys_kexec_file_load\n383     nospu   statx                           sys_statx\n384     nospu   pkey_alloc                      sys_pkey_alloc\n385     nospu   pkey_free                       sys_pkey_free\n386     nospu   pkey_mprotect                   sys_pkey_mprotect\n387     nospu   rseq                            sys_rseq\n388     32      io_pgetevents                   sys_io_pgetevents_time32        compat_sys_io_pgetevents\n388     64      io_pgetevents                   sys_io_pgetevents\n392     64      semtimedop                      sys_semtimedop\n393     common  semget                          sys_semget\n394     common  semctl                          sys_semctl                      compat_sys_semctl\n395     common  shmget                          sys_shmget\n396     common  shmctl                          sys_shmctl                      compat_sys_shmctl\n397     common  shmat                           sys_shmat                       compat_sys_shmat\n398     common  shmdt                           sys_shmdt\n399     common  msgget                          sys_msgget\n400     common  msgsnd                          sys_msgsnd                      compat_sys_msgsnd\n401     common  msgrcv                          sys_msgrcv                      compat_sys_msgrcv\n402     common  msgctl                          sys_msgctl                      compat_sys_msgctl\n403     32      clock_gettime64                 sys_clock_gettime               sys_clock_gettime\n404     32      clock_settime64                 sys_clock_settime               sys_clock_settime\n405     32      clock_adjtime64                 sys_clock_adjtime               sys_clock_adjtime\n406     32      clock_getres_time64             sys_clock_getres                sys_clock_getres\n407     32      clock_nanosleep_time64          sys_clock_nanosleep             sys_clock_nanosleep\n408     32      timer_gettime64                 sys_timer_gettime               sys_timer_gettime\n409     32      timer_settime64                 sys_timer_settime               sys_timer_settime\n410     32      timerfd_gettime64               sys_timerfd_gettime             sys_timerfd_gettime\n411     32      timerfd_settime64               sys_timerfd_settime             sys_timerfd_settime\n412     32      utimensat_time64                sys_utimensat                   sys_utimensat\n413     32      pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     32      ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     32      io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     32      recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     32      mq_timedsend_time64             sys_mq_timedsend                sys_mq_timedsend\n419     32      mq_timedreceive_time64          sys_mq_timedreceive             sys_mq_timedreceive\n420     32      semtimedop_time64               sys_semtimedop                  sys_semtimedop\n421     32      rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     32      futex_time64                    sys_futex                       sys_futex\n423     32      sched_rr_get_interval_time64    sys_sched_rr_get_interval       sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     nospu   clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     nospu   set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_ni_syscall\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# SPARC\n# - arch/sparc/kernel/syscalls/syscall.tbl\nsparc_syscall_tbl = \"\"\"\n0       common  restart_syscall         sys_restart_syscall\n1       32      exit                    sys_exit                        sparc_exit\n1       64      exit                    sparc_exit\n2       common  fork                    sys_fork\n3       common  read                    sys_read\n4       common  write                   sys_write\n5       common  open                    sys_open                        compat_sys_open\n6       common  close                   sys_close\n7       common  wait4                   sys_wait4                       compat_sys_wait4\n8       common  creat                   sys_creat\n9       common  link                    sys_link\n10      common  unlink                  sys_unlink\n11      32      execv                   sunos_execv\n11      64      execv                   sys_nis_syscall\n12      common  chdir                   sys_chdir\n13      32      chown                   sys_chown16\n13      64      chown                   sys_chown\n14      common  mknod                   sys_mknod\n15      common  chmod                   sys_chmod\n16      32      lchown                  sys_lchown16\n16      64      lchown                  sys_lchown\n17      common  brk                     sys_brk\n18      common  perfctr                 sys_nis_syscall\n19      common  lseek                   sys_lseek                       compat_sys_lseek\n20      common  getpid                  sys_getpid\n21      common  capget                  sys_capget\n22      common  capset                  sys_capset\n23      32      setuid                  sys_setuid16\n23      64      setuid                  sys_setuid\n24      32      getuid                  sys_getuid16\n24      64      getuid                  sys_getuid\n25      common  vmsplice                sys_vmsplice\n26      common  ptrace                  sys_ptrace                      compat_sys_ptrace\n27      common  alarm                   sys_alarm\n28      common  sigaltstack             sys_sigaltstack                 compat_sys_sigaltstack\n29      32      pause                   sys_pause\n29      64      pause                   sys_nis_syscall\n30      32      utime                   sys_utime32\n30      64      utime                   sys_utime\n31      32      lchown32                sys_lchown\n32      32      fchown32                sys_fchown\n33      common  access                  sys_access\n34      common  nice                    sys_nice\n35      32      chown32                 sys_chown\n36      common  sync                    sys_sync\n37      common  kill                    sys_kill\n38      common  stat                    sys_newstat                     compat_sys_newstat\n39      32      sendfile                sys_sendfile                    compat_sys_sendfile\n39      64      sendfile                sys_sendfile64\n40      common  lstat                   sys_newlstat                    compat_sys_newlstat\n41      common  dup                     sys_dup\n42      common  pipe                    sys_sparc_pipe\n43      common  times                   sys_times                       compat_sys_times\n44      32      getuid32                sys_getuid\n45      common  umount2                 sys_umount\n46      32      setgid                  sys_setgid16\n46      64      setgid                  sys_setgid\n47      32      getgid                  sys_getgid16\n47      64      getgid                  sys_getgid\n48      common  signal                  sys_signal\n49      32      geteuid                 sys_geteuid16\n49      64      geteuid                 sys_geteuid\n50      32      getegid                 sys_getegid16\n50      64      getegid                 sys_getegid\n51      common  acct                    sys_acct\n52      64      memory_ordering         sys_memory_ordering\n53      32      getgid32                sys_getgid\n54      common  ioctl                   sys_ioctl                       compat_sys_ioctl\n55      common  reboot                  sys_reboot\n56      32      mmap2                   sys_mmap2                       sys32_mmap2\n57      common  symlink                 sys_symlink\n58      common  readlink                sys_readlink\n59      32      execve                  sys_execve                      sys32_execve\n59      64      execve                  sys64_execve\n60      common  umask                   sys_umask\n61      common  chroot                  sys_chroot\n62      common  fstat                   sys_newfstat                    compat_sys_newfstat\n63      common  fstat64                 sys_fstat64                     compat_sys_fstat64\n64      common  getpagesize             sys_getpagesize\n65      common  msync                   sys_msync\n66      common  vfork                   sys_vfork\n67      common  pread64                 sys_pread64                     compat_sys_pread64\n68      common  pwrite64                sys_pwrite64                    compat_sys_pwrite64\n69      32      geteuid32               sys_geteuid\n70      32      getegid32               sys_getegid\n71      common  mmap                    sys_mmap\n72      32      setreuid32              sys_setreuid\n73      32      munmap                  sys_munmap\n73      64      munmap                  sys_64_munmap\n74      common  mprotect                sys_mprotect\n75      common  madvise                 sys_madvise\n76      common  vhangup                 sys_vhangup\n77      32      truncate64              sys_truncate64                  compat_sys_truncate64\n78      common  mincore                 sys_mincore\n79      32      getgroups               sys_getgroups16\n79      64      getgroups               sys_getgroups\n80      32      setgroups               sys_setgroups16\n80      64      setgroups               sys_setgroups\n81      common  getpgrp                 sys_getpgrp\n82      32      setgroups32             sys_setgroups\n83      common  setitimer               sys_setitimer                   compat_sys_setitimer\n84      32      ftruncate64             sys_ftruncate64                 compat_sys_ftruncate64\n85      common  swapon                  sys_swapon\n86      common  getitimer               sys_getitimer                   compat_sys_getitimer\n87      32      setuid32                sys_setuid\n88      common  sethostname             sys_sethostname\n89      32      setgid32                sys_setgid\n90      common  dup2                    sys_dup2\n91      32      setfsuid32              sys_setfsuid\n92      common  fcntl                   sys_fcntl                       compat_sys_fcntl\n93      common  select                  sys_select                      compat_sys_select\n94      32      setfsgid32              sys_setfsgid\n95      common  fsync                   sys_fsync\n96      common  setpriority             sys_setpriority\n97      common  socket                  sys_socket\n98      common  connect                 sys_connect\n99      common  accept                  sys_accept\n100     common  getpriority             sys_getpriority\n101     common  rt_sigreturn            sys_rt_sigreturn                sys32_rt_sigreturn\n102     common  rt_sigaction            sys_rt_sigaction                compat_sys_rt_sigaction\n103     common  rt_sigprocmask          sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n104     common  rt_sigpending           sys_rt_sigpending               compat_sys_rt_sigpending\n105     32      rt_sigtimedwait         sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n105     64      rt_sigtimedwait         sys_rt_sigtimedwait\n106     common  rt_sigqueueinfo         sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n107     common  rt_sigsuspend           sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n108     32      setresuid32             sys_setresuid\n108     64      setresuid               sys_setresuid\n109     32      getresuid32             sys_getresuid\n109     64      getresuid               sys_getresuid\n110     32      setresgid32             sys_setresgid\n110     64      setresgid               sys_setresgid\n111     32      getresgid32             sys_getresgid\n111     64      getresgid               sys_getresgid\n112     32      setregid32              sys_setregid\n113     common  recvmsg                 sys_recvmsg                     compat_sys_recvmsg\n114     common  sendmsg                 sys_sendmsg                     compat_sys_sendmsg\n115     32      getgroups32             sys_getgroups\n116     common  gettimeofday            sys_gettimeofday                compat_sys_gettimeofday\n117     common  getrusage               sys_getrusage                   compat_sys_getrusage\n118     common  getsockopt              sys_getsockopt                  sys_getsockopt\n119     common  getcwd                  sys_getcwd\n120     common  readv                   sys_readv\n121     common  writev                  sys_writev\n122     common  settimeofday            sys_settimeofday                compat_sys_settimeofday\n123     32      fchown                  sys_fchown16\n123     64      fchown                  sys_fchown\n124     common  fchmod                  sys_fchmod\n125     common  recvfrom                sys_recvfrom                    compat_sys_recvfrom\n126     32      setreuid                sys_setreuid16\n126     64      setreuid                sys_setreuid\n127     32      setregid                sys_setregid16\n127     64      setregid                sys_setregid\n128     common  rename                  sys_rename\n129     common  truncate                sys_truncate                    compat_sys_truncate\n130     common  ftruncate               sys_ftruncate                   compat_sys_ftruncate\n131     common  flock                   sys_flock\n132     common  lstat64                 sys_lstat64                     compat_sys_lstat64\n133     common  sendto                  sys_sendto\n134     common  shutdown                sys_shutdown\n135     common  socketpair              sys_socketpair\n136     common  mkdir                   sys_mkdir\n137     common  rmdir                   sys_rmdir\n138     32      utimes                  sys_utimes_time32\n138     64      utimes                  sys_utimes\n139     common  stat64                  sys_stat64                      compat_sys_stat64\n140     common  sendfile64              sys_sendfile64\n141     common  getpeername             sys_getpeername\n142     32      futex                   sys_futex_time32\n142     64      futex                   sys_futex\n143     common  gettid                  sys_gettid\n144     common  getrlimit               sys_getrlimit                   compat_sys_getrlimit\n145     common  setrlimit               sys_setrlimit                   compat_sys_setrlimit\n146     common  pivot_root              sys_pivot_root\n147     common  prctl                   sys_prctl\n148     common  pciconfig_read          sys_pciconfig_read\n149     common  pciconfig_write         sys_pciconfig_write\n150     common  getsockname             sys_getsockname\n151     common  inotify_init            sys_inotify_init\n152     common  inotify_add_watch       sys_inotify_add_watch\n153     common  poll                    sys_poll\n154     common  getdents64              sys_getdents64\n155     32      fcntl64                 sys_fcntl64                     compat_sys_fcntl64\n156     common  inotify_rm_watch        sys_inotify_rm_watch\n157     common  statfs                  sys_statfs                      compat_sys_statfs\n158     common  fstatfs                 sys_fstatfs                     compat_sys_fstatfs\n159     common  umount                  sys_oldumount\n160     common  sched_set_affinity      sys_sched_setaffinity           compat_sys_sched_setaffinity\n161     common  sched_get_affinity      sys_sched_getaffinity           compat_sys_sched_getaffinity\n162     common  getdomainname           sys_getdomainname\n163     common  setdomainname           sys_setdomainname\n164     64      utrap_install           sys_utrap_install\n165     common  quotactl                sys_quotactl\n166     common  set_tid_address         sys_set_tid_address\n167     common  mount                   sys_mount\n168     common  ustat                   sys_ustat                       compat_sys_ustat\n169     common  setxattr                sys_setxattr\n170     common  lsetxattr               sys_lsetxattr\n171     common  fsetxattr               sys_fsetxattr\n172     common  getxattr                sys_getxattr\n173     common  lgetxattr               sys_lgetxattr\n174     common  getdents                sys_getdents                    compat_sys_getdents\n175     common  setsid                  sys_setsid\n176     common  fchdir                  sys_fchdir\n177     common  fgetxattr               sys_fgetxattr\n178     common  listxattr               sys_listxattr\n179     common  llistxattr              sys_llistxattr\n180     common  flistxattr              sys_flistxattr\n181     common  removexattr             sys_removexattr\n182     common  lremovexattr            sys_lremovexattr\n183     32      sigpending              sys_sigpending                  compat_sys_sigpending\n183     64      sigpending              sys_nis_syscall\n184     common  query_module            sys_ni_syscall\n185     common  setpgid                 sys_setpgid\n186     common  fremovexattr            sys_fremovexattr\n187     common  tkill                   sys_tkill\n188     32      exit_group              sys_exit_group                  sparc_exit_group\n188     64      exit_group              sparc_exit_group\n189     common  uname                   sys_newuname\n190     common  init_module             sys_init_module\n191     32      personality             sys_personality                 sys_sparc64_personality\n191     64      personality             sys_sparc64_personality\n192     32      remap_file_pages        sys_sparc_remap_file_pages      sys_remap_file_pages\n192     64      remap_file_pages        sys_remap_file_pages\n193     common  epoll_create            sys_epoll_create\n194     common  epoll_ctl               sys_epoll_ctl\n195     common  epoll_wait              sys_epoll_wait\n196     common  ioprio_set              sys_ioprio_set\n197     common  getppid                 sys_getppid\n198     32      sigaction               sys_sparc_sigaction             compat_sys_sparc_sigaction\n198     64      sigaction               sys_nis_syscall\n199     common  sgetmask                sys_sgetmask\n200     common  ssetmask                sys_ssetmask\n201     32      sigsuspend              sys_sigsuspend\n201     64      sigsuspend              sys_nis_syscall\n202     common  oldlstat                sys_newlstat                    compat_sys_newlstat\n203     common  uselib                  sys_uselib\n204     32      readdir                 sys_old_readdir                 compat_sys_old_readdir\n204     64      readdir                 sys_nis_syscall\n205     common  readahead               sys_readahead                   compat_sys_readahead\n206     common  socketcall              sys_socketcall                  compat_sys_socketcall\n207     common  syslog                  sys_syslog\n208     common  lookup_dcookie          sys_ni_syscall\n209     common  fadvise64               sys_fadvise64                   compat_sys_fadvise64\n210     common  fadvise64_64            sys_fadvise64_64                compat_sys_fadvise64_64\n211     common  tgkill                  sys_tgkill\n212     common  waitpid                 sys_waitpid\n213     common  swapoff                 sys_swapoff\n214     common  sysinfo                 sys_sysinfo                     compat_sys_sysinfo\n215     32      ipc                     sys_ipc                         compat_sys_ipc\n215     64      ipc                     sys_sparc_ipc\n216     32      sigreturn               sys_sigreturn                   sys32_sigreturn\n216     64      sigreturn               sys_nis_syscall\n217     common  clone                   sys_clone\n218     common  ioprio_get              sys_ioprio_get\n219     32      adjtimex                sys_adjtimex_time32\n219     64      adjtimex                sys_sparc_adjtimex\n220     32      sigprocmask             sys_sigprocmask                 compat_sys_sigprocmask\n220     64      sigprocmask             sys_nis_syscall\n221     common  create_module           sys_ni_syscall\n222     common  delete_module           sys_delete_module\n223     common  get_kernel_syms         sys_ni_syscall\n224     common  getpgid                 sys_getpgid\n225     common  bdflush                 sys_ni_syscall\n226     common  sysfs                   sys_sysfs\n227     common  afs_syscall             sys_nis_syscall\n228     common  setfsuid                sys_setfsuid16\n229     common  setfsgid                sys_setfsgid16\n230     common  _newselect              sys_select                      compat_sys_select\n231     32      time                    sys_time32\n232     common  splice                  sys_splice\n233     32      stime                   sys_stime32\n233     64      stime                   sys_stime\n234     common  statfs64                sys_statfs64                    compat_sys_statfs64\n235     common  fstatfs64               sys_fstatfs64                   compat_sys_fstatfs64\n236     common  _llseek                 sys_llseek\n237     common  mlock                   sys_mlock\n238     common  munlock                 sys_munlock\n239     common  mlockall                sys_mlockall\n240     common  munlockall              sys_munlockall\n241     common  sched_setparam          sys_sched_setparam\n242     common  sched_getparam          sys_sched_getparam\n243     common  sched_setscheduler      sys_sched_setscheduler\n244     common  sched_getscheduler      sys_sched_getscheduler\n245     common  sched_yield             sys_sched_yield\n246     common  sched_get_priority_max  sys_sched_get_priority_max\n247     common  sched_get_priority_min  sys_sched_get_priority_min\n248     32      sched_rr_get_interval   sys_sched_rr_get_interval_time32\n248     64      sched_rr_get_interval   sys_sched_rr_get_interval\n249     32      nanosleep               sys_nanosleep_time32\n249     64      nanosleep               sys_nanosleep\n250     32      mremap                  sys_mremap\n250     64      mremap                  sys_64_mremap\n251     common  _sysctl                 sys_ni_syscall\n252     common  getsid                  sys_getsid\n253     common  fdatasync               sys_fdatasync\n254     32      nfsservctl              sys_ni_syscall                  sys_nis_syscall\n254     64      nfsservctl              sys_nis_syscall\n255     common  sync_file_range         sys_sync_file_range             compat_sys_sync_file_range\n256     32      clock_settime           sys_clock_settime32\n256     64      clock_settime           sys_clock_settime\n257     32      clock_gettime           sys_clock_gettime32\n257     64      clock_gettime           sys_clock_gettime\n258     32      clock_getres            sys_clock_getres_time32\n258     64      clock_getres            sys_clock_getres\n259     32      clock_nanosleep         sys_clock_nanosleep_time32\n259     64      clock_nanosleep         sys_clock_nanosleep\n260     common  sched_getaffinity       sys_sched_getaffinity           compat_sys_sched_getaffinity\n261     common  sched_setaffinity       sys_sched_setaffinity           compat_sys_sched_setaffinity\n262     32      timer_settime           sys_timer_settime32\n262     64      timer_settime           sys_timer_settime\n263     32      timer_gettime           sys_timer_gettime32\n263     64      timer_gettime           sys_timer_gettime\n264     common  timer_getoverrun        sys_timer_getoverrun\n265     common  timer_delete            sys_timer_delete\n266     common  timer_create            sys_timer_create                compat_sys_timer_create\n267     common  vserver                 sys_nis_syscall\n268     common  io_setup                sys_io_setup                    compat_sys_io_setup\n269     common  io_destroy              sys_io_destroy\n270     common  io_submit               sys_io_submit                   compat_sys_io_submit\n271     common  io_cancel               sys_io_cancel\n272     32      io_getevents            sys_io_getevents_time32\n272     64      io_getevents            sys_io_getevents\n273     common  mq_open                 sys_mq_open                     compat_sys_mq_open\n274     common  mq_unlink               sys_mq_unlink\n275     32      mq_timedsend            sys_mq_timedsend_time32\n275     64      mq_timedsend            sys_mq_timedsend\n276     32      mq_timedreceive         sys_mq_timedreceive_time32\n276     64      mq_timedreceive         sys_mq_timedreceive\n277     common  mq_notify               sys_mq_notify                   compat_sys_mq_notify\n278     common  mq_getsetattr           sys_mq_getsetattr               compat_sys_mq_getsetattr\n279     common  waitid                  sys_waitid                      compat_sys_waitid\n280     common  tee                     sys_tee\n281     common  add_key                 sys_add_key\n282     common  request_key             sys_request_key\n283     common  keyctl                  sys_keyctl                      compat_sys_keyctl\n284     common  openat                  sys_openat                      compat_sys_openat\n285     common  mkdirat                 sys_mkdirat\n286     common  mknodat                 sys_mknodat\n287     common  fchownat                sys_fchownat\n288     32      futimesat               sys_futimesat_time32\n288     64      futimesat               sys_futimesat\n289     common  fstatat64               sys_fstatat64                   compat_sys_fstatat64\n290     common  unlinkat                sys_unlinkat\n291     common  renameat                sys_renameat\n292     common  linkat                  sys_linkat\n293     common  symlinkat               sys_symlinkat\n294     common  readlinkat              sys_readlinkat\n295     common  fchmodat                sys_fchmodat\n296     common  faccessat               sys_faccessat\n297     32      pselect6                sys_pselect6_time32             compat_sys_pselect6_time32\n297     64      pselect6                sys_pselect6\n298     32      ppoll                   sys_ppoll_time32                compat_sys_ppoll_time32\n298     64      ppoll                   sys_ppoll\n299     common  unshare                 sys_unshare\n300     common  set_robust_list         sys_set_robust_list             compat_sys_set_robust_list\n301     common  get_robust_list         sys_get_robust_list             compat_sys_get_robust_list\n302     common  migrate_pages           sys_migrate_pages\n303     common  mbind                   sys_mbind\n304     common  get_mempolicy           sys_get_mempolicy\n305     common  set_mempolicy           sys_set_mempolicy\n306     common  kexec_load              sys_kexec_load                  compat_sys_kexec_load\n307     common  move_pages              sys_move_pages\n308     common  getcpu                  sys_getcpu\n309     common  epoll_pwait             sys_epoll_pwait                 compat_sys_epoll_pwait\n310     32      utimensat               sys_utimensat_time32\n310     64      utimensat               sys_utimensat\n311     common  signalfd                sys_signalfd                    compat_sys_signalfd\n312     common  timerfd_create          sys_timerfd_create\n313     common  eventfd                 sys_eventfd\n314     common  fallocate               sys_fallocate                   compat_sys_fallocate\n315     32      timerfd_settime         sys_timerfd_settime32\n315     64      timerfd_settime         sys_timerfd_settime\n316     32      timerfd_gettime         sys_timerfd_gettime32\n316     64      timerfd_gettime         sys_timerfd_gettime\n317     common  signalfd4               sys_signalfd4                   compat_sys_signalfd4\n318     common  eventfd2                sys_eventfd2\n319     common  epoll_create1           sys_epoll_create1\n320     common  dup3                    sys_dup3\n321     common  pipe2                   sys_pipe2\n322     common  inotify_init1           sys_inotify_init1\n323     common  accept4                 sys_accept4\n324     common  preadv                  sys_preadv                      compat_sys_preadv\n325     common  pwritev                 sys_pwritev                     compat_sys_pwritev\n326     common  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n327     common  perf_event_open         sys_perf_event_open\n328     32      recvmmsg                sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n328     64      recvmmsg                sys_recvmmsg\n329     common  fanotify_init           sys_fanotify_init\n330     common  fanotify_mark           sys_fanotify_mark               compat_sys_fanotify_mark\n331     common  prlimit64               sys_prlimit64\n332     common  name_to_handle_at       sys_name_to_handle_at\n333     common  open_by_handle_at       sys_open_by_handle_at           compat_sys_open_by_handle_at\n334     32      clock_adjtime           sys_clock_adjtime32\n334     64      clock_adjtime           sys_sparc_clock_adjtime\n335     common  syncfs                  sys_syncfs\n336     common  sendmmsg                sys_sendmmsg                    compat_sys_sendmmsg\n337     common  setns                   sys_setns\n338     common  process_vm_readv        sys_process_vm_readv\n339     common  process_vm_writev       sys_process_vm_writev\n340     32      kern_features           sys_ni_syscall                  sys_kern_features\n340     64      kern_features           sys_kern_features\n341     common  kcmp                    sys_kcmp\n342     common  finit_module            sys_finit_module\n343     common  sched_setattr           sys_sched_setattr\n344     common  sched_getattr           sys_sched_getattr\n345     common  renameat2               sys_renameat2\n346     common  seccomp                 sys_seccomp\n347     common  getrandom               sys_getrandom\n348     common  memfd_create            sys_memfd_create\n349     common  bpf                     sys_bpf\n350     32      execveat                sys_execveat                    sys32_execveat\n350     64      execveat                sys64_execveat\n351     common  membarrier              sys_membarrier\n352     common  userfaultfd             sys_userfaultfd\n353     common  bind                    sys_bind\n354     common  listen                  sys_listen\n355     common  setsockopt              sys_setsockopt                  sys_setsockopt\n356     common  mlock2                  sys_mlock2\n357     common  copy_file_range         sys_copy_file_range\n358     common  preadv2                 sys_preadv2                     compat_sys_preadv2\n359     common  pwritev2                sys_pwritev2                    compat_sys_pwritev2\n360     common  statx                   sys_statx\n361     32      io_pgetevents           sys_io_pgetevents_time32        compat_sys_io_pgetevents\n361     64      io_pgetevents           sys_io_pgetevents\n362     common  pkey_mprotect           sys_pkey_mprotect\n363     common  pkey_alloc              sys_pkey_alloc\n364     common  pkey_free               sys_pkey_free\n365     common  rseq                    sys_rseq\n392     64      semtimedop                      sys_semtimedop\n393     common  semget                  sys_semget\n394     common  semctl                  sys_semctl                      compat_sys_semctl\n395     common  shmget                  sys_shmget\n396     common  shmctl                  sys_shmctl                      compat_sys_shmctl\n397     common  shmat                   sys_shmat                       compat_sys_shmat\n398     common  shmdt                   sys_shmdt\n399     common  msgget                  sys_msgget\n400     common  msgsnd                  sys_msgsnd                      compat_sys_msgsnd\n401     common  msgrcv                  sys_msgrcv                      compat_sys_msgrcv\n402     common  msgctl                  sys_msgctl                      compat_sys_msgctl\n403     32      clock_gettime64                 sys_clock_gettime               sys_clock_gettime\n404     32      clock_settime64                 sys_clock_settime               sys_clock_settime\n405     32      clock_adjtime64                 sys_clock_adjtime               sys_clock_adjtime\n406     32      clock_getres_time64             sys_clock_getres                sys_clock_getres\n407     32      clock_nanosleep_time64          sys_clock_nanosleep             sys_clock_nanosleep\n408     32      timer_gettime64                 sys_timer_gettime               sys_timer_gettime\n409     32      timer_settime64                 sys_timer_settime               sys_timer_settime\n410     32      timerfd_gettime64               sys_timerfd_gettime             sys_timerfd_gettime\n411     32      timerfd_settime64               sys_timerfd_settime             sys_timerfd_settime\n412     32      utimensat_time64                sys_utimensat                   sys_utimensat\n413     32      pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     32      ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     32      io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     32      recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     32      mq_timedsend_time64             sys_mq_timedsend                sys_mq_timedsend\n419     32      mq_timedreceive_time64          sys_mq_timedreceive             sys_mq_timedreceive\n420     32      semtimedop_time64               sys_semtimedop                  sys_semtimedop\n421     32      rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     32      futex_time64                    sys_futex                       sys_futex\n423     32      sched_rr_get_interval_time64    sys_sched_rr_get_interval       sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n436     common  close_range                     sys_close_range\n437     common  openat2                 sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# RISCV64\nriscv64_syscall_tbl = arm64_syscall_tbl\n\n\n# RISCV32\nriscv32_syscall_tbl = arm64_syscall_tbl\n\n\n# S390X\n# - arch/s390/kernel/syscalls/syscall.tbl\ns390x_syscall_tbl = \"\"\"\n1       common  exit                            sys_exit\n2       common  fork                            sys_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  open                            sys_open\n6       common  close                           sys_close\n7       common  restart_syscall                 sys_restart_syscall\n8       common  creat                           sys_creat\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      common  execve                          sys_execve\n12      common  chdir                           sys_chdir\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n19      common  lseek                           sys_lseek\n20      common  getpid                          sys_getpid\n21      common  mount                           sys_mount\n22      common  umount                          sys_oldumount\n26      common  ptrace                          sys_ptrace\n27      common  alarm                           sys_alarm\n29      common  pause                           sys_pause\n30      common  utime                           sys_utime\n33      common  access                          sys_access\n34      common  nice                            sys_nice\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  rename                          sys_rename\n39      common  mkdir                           sys_mkdir\n40      common  rmdir                           sys_rmdir\n41      common  dup                             sys_dup\n42      common  pipe                            sys_pipe\n43      common  times                           sys_times\n45      common  brk                             sys_brk\n48      common  signal                          sys_signal\n51      common  acct                            sys_acct\n52      common  umount2                         sys_umount\n54      common  ioctl                           sys_ioctl\n55      common  fcntl                           sys_fcntl\n57      common  setpgid                         sys_setpgid\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      common  ustat                           sys_ustat\n63      common  dup2                            sys_dup2\n64      common  getppid                         sys_getppid\n65      common  getpgrp                         sys_getpgrp\n66      common  setsid                          sys_setsid\n67      common  sigaction                       sys_sigaction\n72      common  sigsuspend                      sys_sigsuspend\n73      common  sigpending                      sys_sigpending\n74      common  sethostname                     sys_sethostname\n75      common  setrlimit                       sys_setrlimit\n77      common  getrusage                       sys_getrusage\n78      common  gettimeofday                    sys_gettimeofday\n79      common  settimeofday                    sys_settimeofday\n83      common  symlink                         sys_symlink\n85      common  readlink                        sys_readlink\n86      common  uselib                          sys_uselib\n87      common  swapon                          sys_swapon\n88      common  reboot                          sys_reboot\n89      common  readdir                         sys_ni_syscall\n90      common  mmap                            sys_old_mmap\n91      common  munmap                          sys_munmap\n92      common  truncate                        sys_truncate\n93      common  ftruncate                       sys_ftruncate\n94      common  fchmod                          sys_fchmod\n96      common  getpriority                     sys_getpriority\n97      common  setpriority                     sys_setpriority\n99      common  statfs                          sys_statfs\n100     common  fstatfs                         sys_fstatfs\n102     common  socketcall                      sys_socketcall\n103     common  syslog                          sys_syslog\n104     common  setitimer                       sys_setitimer\n105     common  getitimer                       sys_getitimer\n106     common  stat                            sys_newstat\n107     common  lstat                           sys_newlstat\n108     common  fstat                           sys_newfstat\n110     common  lookup_dcookie                  sys_ni_syscall\n111     common  vhangup                         sys_vhangup\n112     common  idle                            sys_ni_syscall\n114     common  wait4                           sys_wait4\n115     common  swapoff                         sys_swapoff\n116     common  sysinfo                         sys_sysinfo\n117     common  ipc                             sys_s390_ipc\n118     common  fsync                           sys_fsync\n119     common  sigreturn                       sys_sigreturn\n120     common  clone                           sys_clone\n121     common  setdomainname                   sys_setdomainname\n122     common  uname                           sys_newuname\n124     common  adjtimex                        sys_adjtimex\n125     common  mprotect                        sys_mprotect\n126     common  sigprocmask                     sys_sigprocmask\n127     common  create_module                   sys_ni_syscall\n128     common  init_module                     sys_init_module\n129     common  delete_module                   sys_delete_module\n130     common  get_kernel_syms                 sys_ni_syscall\n131     common  quotactl                        sys_quotactl\n132     common  getpgid                         sys_getpgid\n133     common  fchdir                          sys_fchdir\n134     common  bdflush                         sys_ni_syscall\n135     common  sysfs                           sys_sysfs\n136     common  personality                     sys_s390_personality\n137     common  afs_syscall                     sys_ni_syscall\n141     common  getdents                        sys_getdents\n142     common  select                          sys_select\n143     common  flock                           sys_flock\n144     common  msync                           sys_msync\n145     common  readv                           sys_readv\n146     common  writev                          sys_writev\n147     common  getsid                          sys_getsid\n148     common  fdatasync                       sys_fdatasync\n149     common  _sysctl                         sys_ni_syscall\n150     common  mlock                           sys_mlock\n151     common  munlock                         sys_munlock\n152     common  mlockall                        sys_mlockall\n153     common  munlockall                      sys_munlockall\n154     common  sched_setparam                  sys_sched_setparam\n155     common  sched_getparam                  sys_sched_getparam\n156     common  sched_setscheduler              sys_sched_setscheduler\n157     common  sched_getscheduler              sys_sched_getscheduler\n158     common  sched_yield                     sys_sched_yield\n159     common  sched_get_priority_max          sys_sched_get_priority_max\n160     common  sched_get_priority_min          sys_sched_get_priority_min\n161     common  sched_rr_get_interval           sys_sched_rr_get_interval\n162     common  nanosleep                       sys_nanosleep\n163     common  mremap                          sys_mremap\n167     common  query_module                    sys_ni_syscall\n168     common  poll                            sys_poll\n169     common  nfsservctl                      sys_ni_syscall\n172     common  prctl                           sys_prctl\n173     common  rt_sigreturn                    sys_rt_sigreturn\n174     common  rt_sigaction                    sys_rt_sigaction\n175     common  rt_sigprocmask                  sys_rt_sigprocmask\n176     common  rt_sigpending                   sys_rt_sigpending\n177     common  rt_sigtimedwait                 sys_rt_sigtimedwait\n178     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n179     common  rt_sigsuspend                   sys_rt_sigsuspend\n180     common  pread64                         sys_pread64\n181     common  pwrite64                        sys_pwrite64\n183     common  getcwd                          sys_getcwd\n184     common  capget                          sys_capget\n185     common  capset                          sys_capset\n186     common  sigaltstack                     sys_sigaltstack\n187     common  sendfile                        sys_sendfile64\n188     common  getpmsg                         sys_ni_syscall\n189     common  putpmsg                         sys_ni_syscall\n190     common  vfork                           sys_vfork\n191     common  getrlimit                       sys_getrlimit\n198     common  lchown                          sys_lchown\n199     common  getuid                          sys_getuid\n200     common  getgid                          sys_getgid\n201     common  geteuid                         sys_geteuid\n202     common  getegid                         sys_getegid\n203     common  setreuid                        sys_setreuid\n204     common  setregid                        sys_setregid\n205     common  getgroups                       sys_getgroups\n206     common  setgroups                       sys_setgroups\n207     common  fchown                          sys_fchown\n208     common  setresuid                       sys_setresuid\n209     common  getresuid                       sys_getresuid\n210     common  setresgid                       sys_setresgid\n211     common  getresgid                       sys_getresgid\n212     common  chown                           sys_chown\n213     common  setuid                          sys_setuid\n214     common  setgid                          sys_setgid\n215     common  setfsuid                        sys_setfsuid\n216     common  setfsgid                        sys_setfsgid\n217     common  pivot_root                      sys_pivot_root\n218     common  mincore                         sys_mincore\n219     common  madvise                         sys_madvise\n220     common  getdents64                      sys_getdents64\n222     common  readahead                       sys_readahead\n224     common  setxattr                        sys_setxattr\n225     common  lsetxattr                       sys_lsetxattr\n226     common  fsetxattr                       sys_fsetxattr\n227     common  getxattr                        sys_getxattr\n228     common  lgetxattr                       sys_lgetxattr\n229     common  fgetxattr                       sys_fgetxattr\n230     common  listxattr                       sys_listxattr\n231     common  llistxattr                      sys_llistxattr\n232     common  flistxattr                      sys_flistxattr\n233     common  removexattr                     sys_removexattr\n234     common  lremovexattr                    sys_lremovexattr\n235     common  fremovexattr                    sys_fremovexattr\n236     common  gettid                          sys_gettid\n237     common  tkill                           sys_tkill\n238     common  futex                           sys_futex\n239     common  sched_setaffinity               sys_sched_setaffinity\n240     common  sched_getaffinity               sys_sched_getaffinity\n241     common  tgkill                          sys_tgkill\n243     common  io_setup                        sys_io_setup\n244     common  io_destroy                      sys_io_destroy\n245     common  io_getevents                    sys_io_getevents\n246     common  io_submit                       sys_io_submit\n247     common  io_cancel                       sys_io_cancel\n248     common  exit_group                      sys_exit_group\n249     common  epoll_create                    sys_epoll_create\n250     common  epoll_ctl                       sys_epoll_ctl\n251     common  epoll_wait                      sys_epoll_wait\n252     common  set_tid_address                 sys_set_tid_address\n253     common  fadvise64                       sys_fadvise64_64\n254     common  timer_create                    sys_timer_create\n255     common  timer_settime                   sys_timer_settime\n256     common  timer_gettime                   sys_timer_gettime\n257     common  timer_getoverrun                sys_timer_getoverrun\n258     common  timer_delete                    sys_timer_delete\n259     common  clock_settime                   sys_clock_settime\n260     common  clock_gettime                   sys_clock_gettime\n261     common  clock_getres                    sys_clock_getres\n262     common  clock_nanosleep                 sys_clock_nanosleep\n265     common  statfs64                        sys_statfs64\n266     common  fstatfs64                       sys_fstatfs64\n267     common  remap_file_pages                sys_remap_file_pages\n268     common  mbind                           sys_mbind\n269     common  get_mempolicy                   sys_get_mempolicy\n270     common  set_mempolicy                   sys_set_mempolicy\n271     common  mq_open                         sys_mq_open\n272     common  mq_unlink                       sys_mq_unlink\n273     common  mq_timedsend                    sys_mq_timedsend\n274     common  mq_timedreceive                 sys_mq_timedreceive\n275     common  mq_notify                       sys_mq_notify\n276     common  mq_getsetattr                   sys_mq_getsetattr\n277     common  kexec_load                      sys_kexec_load\n278     common  add_key                         sys_add_key\n279     common  request_key                     sys_request_key\n280     common  keyctl                          sys_keyctl\n281     common  waitid                          sys_waitid\n282     common  ioprio_set                      sys_ioprio_set\n283     common  ioprio_get                      sys_ioprio_get\n284     common  inotify_init                    sys_inotify_init\n285     common  inotify_add_watch               sys_inotify_add_watch\n286     common  inotify_rm_watch                sys_inotify_rm_watch\n287     common  migrate_pages                   sys_migrate_pages\n288     common  openat                          sys_openat\n289     common  mkdirat                         sys_mkdirat\n290     common  mknodat                         sys_mknodat\n291     common  fchownat                        sys_fchownat\n292     common  futimesat                       sys_futimesat\n293     common  newfstatat                      sys_newfstatat\n294     common  unlinkat                        sys_unlinkat\n295     common  renameat                        sys_renameat\n296     common  linkat                          sys_linkat\n297     common  symlinkat                       sys_symlinkat\n298     common  readlinkat                      sys_readlinkat\n299     common  fchmodat                        sys_fchmodat\n300     common  faccessat                       sys_faccessat\n301     common  pselect6                        sys_pselect6\n302     common  ppoll                           sys_ppoll\n303     common  unshare                         sys_unshare\n304     common  set_robust_list                 sys_set_robust_list\n305     common  get_robust_list                 sys_get_robust_list\n306     common  splice                          sys_splice\n307     common  sync_file_range                 sys_sync_file_range\n308     common  tee                             sys_tee\n309     common  vmsplice                        sys_vmsplice\n310     common  move_pages                      sys_move_pages\n311     common  getcpu                          sys_getcpu\n312     common  epoll_pwait                     sys_epoll_pwait\n313     common  utimes                          sys_utimes\n314     common  fallocate                       sys_fallocate\n315     common  utimensat                       sys_utimensat\n316     common  signalfd                        sys_signalfd\n317     common  timerfd                         sys_ni_syscall\n318     common  eventfd                         sys_eventfd\n319     common  timerfd_create                  sys_timerfd_create\n320     common  timerfd_settime                 sys_timerfd_settime\n321     common  timerfd_gettime                 sys_timerfd_gettime\n322     common  signalfd4                       sys_signalfd4\n323     common  eventfd2                        sys_eventfd2\n324     common  inotify_init1                   sys_inotify_init1\n325     common  pipe2                           sys_pipe2\n326     common  dup3                            sys_dup3\n327     common  epoll_create1                   sys_epoll_create1\n328     common  preadv                          sys_preadv\n329     common  pwritev                         sys_pwritev\n330     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n331     common  perf_event_open                 sys_perf_event_open\n332     common  fanotify_init                   sys_fanotify_init\n333     common  fanotify_mark                   sys_fanotify_mark\n334     common  prlimit64                       sys_prlimit64\n335     common  name_to_handle_at               sys_name_to_handle_at\n336     common  open_by_handle_at               sys_open_by_handle_at\n337     common  clock_adjtime                   sys_clock_adjtime\n338     common  syncfs                          sys_syncfs\n339     common  setns                           sys_setns\n340     common  process_vm_readv                sys_process_vm_readv\n341     common  process_vm_writev               sys_process_vm_writev\n342     common  s390_runtime_instr              sys_s390_runtime_instr\n343     common  kcmp                            sys_kcmp\n344     common  finit_module                    sys_finit_module\n345     common  sched_setattr                   sys_sched_setattr\n346     common  sched_getattr                   sys_sched_getattr\n347     common  renameat2                       sys_renameat2\n348     common  seccomp                         sys_seccomp\n349     common  getrandom                       sys_getrandom\n350     common  memfd_create                    sys_memfd_create\n351     common  bpf                             sys_bpf\n352     common  s390_pci_mmio_write             sys_s390_pci_mmio_write\n353     common  s390_pci_mmio_read              sys_s390_pci_mmio_read\n354     common  execveat                        sys_execveat\n355     common  userfaultfd                     sys_userfaultfd\n356     common  membarrier                      sys_membarrier\n357     common  recvmmsg                        sys_recvmmsg\n358     common  sendmmsg                        sys_sendmmsg\n359     common  socket                          sys_socket\n360     common  socketpair                      sys_socketpair\n361     common  bind                            sys_bind\n362     common  connect                         sys_connect\n363     common  listen                          sys_listen\n364     common  accept4                         sys_accept4\n365     common  getsockopt                      sys_getsockopt\n366     common  setsockopt                      sys_setsockopt\n367     common  getsockname                     sys_getsockname\n368     common  getpeername                     sys_getpeername\n369     common  sendto                          sys_sendto\n370     common  sendmsg                         sys_sendmsg\n371     common  recvfrom                        sys_recvfrom\n372     common  recvmsg                         sys_recvmsg\n373     common  shutdown                        sys_shutdown\n374     common  mlock2                          sys_mlock2\n375     common  copy_file_range                 sys_copy_file_range\n376     common  preadv2                         sys_preadv2\n377     common  pwritev2                        sys_pwritev2\n378     common  s390_guarded_storage            sys_s390_guarded_storage\n379     common  statx                           sys_statx\n380     common  s390_sthyi                      sys_s390_sthyi\n381     common  kexec_file_load                 sys_kexec_file_load\n382     common  io_pgetevents                   sys_io_pgetevents\n383     common  rseq                            sys_rseq\n384     common  pkey_mprotect                   sys_pkey_mprotect\n385     common  pkey_alloc                      sys_pkey_alloc\n386     common  pkey_free                       sys_pkey_free\n392     common  semtimedop                      sys_semtimedop\n393     common  semget                          sys_semget\n394     common  semctl                          sys_semctl\n395     common  shmget                          sys_shmget\n396     common  shmctl                          sys_shmctl\n397     common  shmat                           sys_shmat\n398     common  shmdt                           sys_shmdt\n399     common  msgget                          sys_msgget\n400     common  msgsnd                          sys_msgsnd\n401     common  msgrcv                          sys_msgrcv\n402     common  msgctl                          sys_msgctl\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n447     common  memfd_secret                    sys_memfd_secret\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# SH4\n# - arch/sh/kernel/syscalls/syscall.tbl\nsh4_syscall_tbl = \"\"\"\n0       common  restart_syscall                 sys_restart_syscall\n1       common  exit                            sys_exit\n2       common  fork                            sys_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  open                            sys_open\n6       common  close                           sys_close\n7       common  waitpid                         sys_waitpid\n8       common  creat                           sys_creat\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      common  execve                          sys_execve\n12      common  chdir                           sys_chdir\n13      common  time                            sys_time32\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n16      common  lchown                          sys_lchown16\n18      common  oldstat                         sys_stat\n19      common  lseek                           sys_lseek\n20      common  getpid                          sys_getpid\n21      common  mount                           sys_mount\n22      common  umount                          sys_oldumount\n23      common  setuid                          sys_setuid16\n24      common  getuid                          sys_getuid16\n25      common  stime                           sys_stime32\n26      common  ptrace                          sys_ptrace\n27      common  alarm                           sys_alarm\n28      common  oldfstat                        sys_fstat\n29      common  pause                           sys_pause\n30      common  utime                           sys_utime32\n33      common  access                          sys_access\n34      common  nice                            sys_nice\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  rename                          sys_rename\n39      common  mkdir                           sys_mkdir\n40      common  rmdir                           sys_rmdir\n41      common  dup                             sys_dup\n42      common  pipe                            sys_sh_pipe\n43      common  times                           sys_times\n45      common  brk                             sys_brk\n46      common  setgid                          sys_setgid16\n47      common  getgid                          sys_getgid16\n48      common  signal                          sys_signal\n49      common  geteuid                         sys_geteuid16\n50      common  getegid                         sys_getegid16\n51      common  acct                            sys_acct\n52      common  umount2                         sys_umount\n54      common  ioctl                           sys_ioctl\n55      common  fcntl                           sys_fcntl\n57      common  setpgid                         sys_setpgid\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      common  ustat                           sys_ustat\n63      common  dup2                            sys_dup2\n64      common  getppid                         sys_getppid\n65      common  getpgrp                         sys_getpgrp\n66      common  setsid                          sys_setsid\n67      common  sigaction                       sys_sigaction\n68      common  sgetmask                        sys_sgetmask\n69      common  ssetmask                        sys_ssetmask\n70      common  setreuid                        sys_setreuid16\n71      common  setregid                        sys_setregid16\n72      common  sigsuspend                      sys_sigsuspend\n73      common  sigpending                      sys_sigpending\n74      common  sethostname                     sys_sethostname\n75      common  setrlimit                       sys_setrlimit\n76      common  getrlimit                       sys_old_getrlimit\n77      common  getrusage                       sys_getrusage\n78      common  gettimeofday                    sys_gettimeofday\n79      common  settimeofday                    sys_settimeofday\n80      common  getgroups                       sys_getgroups16\n81      common  setgroups                       sys_setgroups16\n83      common  symlink                         sys_symlink\n84      common  oldlstat                        sys_lstat\n85      common  readlink                        sys_readlink\n86      common  uselib                          sys_uselib\n87      common  swapon                          sys_swapon\n88      common  reboot                          sys_reboot\n89      common  readdir                         sys_old_readdir\n90      common  mmap                            old_mmap\n91      common  munmap                          sys_munmap\n92      common  truncate                        sys_truncate\n93      common  ftruncate                       sys_ftruncate\n94      common  fchmod                          sys_fchmod\n95      common  fchown                          sys_fchown16\n96      common  getpriority                     sys_getpriority\n97      common  setpriority                     sys_setpriority\n99      common  statfs                          sys_statfs\n100     common  fstatfs                         sys_fstatfs\n102     common  socketcall                      sys_socketcall\n103     common  syslog                          sys_syslog\n104     common  setitimer                       sys_setitimer\n105     common  getitimer                       sys_getitimer\n106     common  stat                            sys_newstat\n107     common  lstat                           sys_newlstat\n108     common  fstat                           sys_newfstat\n109     common  olduname                        sys_uname\n111     common  vhangup                         sys_vhangup\n114     common  wait4                           sys_wait4\n115     common  swapoff                         sys_swapoff\n116     common  sysinfo                         sys_sysinfo\n117     common  ipc                             sys_ipc\n118     common  fsync                           sys_fsync\n119     common  sigreturn                       sys_sigreturn\n120     common  clone                           sys_clone\n121     common  setdomainname                   sys_setdomainname\n122     common  uname                           sys_newuname\n123     common  cacheflush                      sys_cacheflush\n124     common  adjtimex                        sys_adjtimex_time32\n125     common  mprotect                        sys_mprotect\n126     common  sigprocmask                     sys_sigprocmask\n128     common  init_module                     sys_init_module\n129     common  delete_module                   sys_delete_module\n131     common  quotactl                        sys_quotactl\n132     common  getpgid                         sys_getpgid\n133     common  fchdir                          sys_fchdir\n134     common  bdflush                         sys_ni_syscall\n135     common  sysfs                           sys_sysfs\n136     common  personality                     sys_personality\n138     common  setfsuid                        sys_setfsuid16\n139     common  setfsgid                        sys_setfsgid16\n140     common  _llseek                         sys_llseek\n141     common  getdents                        sys_getdents\n142     common  _newselect                      sys_select\n143     common  flock                           sys_flock\n144     common  msync                           sys_msync\n145     common  readv                           sys_readv\n146     common  writev                          sys_writev\n147     common  getsid                          sys_getsid\n148     common  fdatasync                       sys_fdatasync\n149     common  _sysctl                         sys_ni_syscall\n150     common  mlock                           sys_mlock\n151     common  munlock                         sys_munlock\n152     common  mlockall                        sys_mlockall\n153     common  munlockall                      sys_munlockall\n154     common  sched_setparam                  sys_sched_setparam\n155     common  sched_getparam                  sys_sched_getparam\n156     common  sched_setscheduler              sys_sched_setscheduler\n157     common  sched_getscheduler              sys_sched_getscheduler\n158     common  sched_yield                     sys_sched_yield\n159     common  sched_get_priority_max          sys_sched_get_priority_max\n160     common  sched_get_priority_min          sys_sched_get_priority_min\n161     common  sched_rr_get_interval           sys_sched_rr_get_interval_time32\n162     common  nanosleep                       sys_nanosleep_time32\n163     common  mremap                          sys_mremap\n164     common  setresuid                       sys_setresuid16\n165     common  getresuid                       sys_getresuid16\n168     common  poll                            sys_poll\n169     common  nfsservctl                      sys_ni_syscall\n170     common  setresgid                       sys_setresgid16\n171     common  getresgid                       sys_getresgid16\n172     common  prctl                           sys_prctl\n173     common  rt_sigreturn                    sys_rt_sigreturn\n174     common  rt_sigaction                    sys_rt_sigaction\n175     common  rt_sigprocmask                  sys_rt_sigprocmask\n176     common  rt_sigpending                   sys_rt_sigpending\n177     common  rt_sigtimedwait                 sys_rt_sigtimedwait_time32\n178     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n179     common  rt_sigsuspend                   sys_rt_sigsuspend\n180     common  pread64                         sys_pread_wrapper\n181     common  pwrite64                        sys_pwrite_wrapper\n182     common  chown                           sys_chown16\n183     common  getcwd                          sys_getcwd\n184     common  capget                          sys_capget\n185     common  capset                          sys_capset\n186     common  sigaltstack                     sys_sigaltstack\n187     common  sendfile                        sys_sendfile\n190     common  vfork                           sys_vfork\n191     common  ugetrlimit                      sys_getrlimit\n192     common  mmap2                           sys_mmap2\n193     common  truncate64                      sys_truncate64\n194     common  ftruncate64                     sys_ftruncate64\n195     common  stat64                          sys_stat64\n196     common  lstat64                         sys_lstat64\n197     common  fstat64                         sys_fstat64\n198     common  lchown32                        sys_lchown\n199     common  getuid32                        sys_getuid\n200     common  getgid32                        sys_getgid\n201     common  geteuid32                       sys_geteuid\n202     common  getegid32                       sys_getegid\n203     common  setreuid32                      sys_setreuid\n204     common  setregid32                      sys_setregid\n205     common  getgroups32                     sys_getgroups\n206     common  setgroups32                     sys_setgroups\n207     common  fchown32                        sys_fchown\n208     common  setresuid32                     sys_setresuid\n209     common  getresuid32                     sys_getresuid\n210     common  setresgid32                     sys_setresgid\n211     common  getresgid32                     sys_getresgid\n212     common  chown32                         sys_chown\n213     common  setuid32                        sys_setuid\n214     common  setgid32                        sys_setgid\n215     common  setfsuid32                      sys_setfsuid\n216     common  setfsgid32                      sys_setfsgid\n217     common  pivot_root                      sys_pivot_root\n218     common  mincore                         sys_mincore\n219     common  madvise                         sys_madvise\n220     common  getdents64                      sys_getdents64\n221     common  fcntl64                         sys_fcntl64\n224     common  gettid                          sys_gettid\n225     common  readahead                       sys_readahead\n226     common  setxattr                        sys_setxattr\n227     common  lsetxattr                       sys_lsetxattr\n228     common  fsetxattr                       sys_fsetxattr\n229     common  getxattr                        sys_getxattr\n230     common  lgetxattr                       sys_lgetxattr\n231     common  fgetxattr                       sys_fgetxattr\n232     common  listxattr                       sys_listxattr\n233     common  llistxattr                      sys_llistxattr\n234     common  flistxattr                      sys_flistxattr\n235     common  removexattr                     sys_removexattr\n236     common  lremovexattr                    sys_lremovexattr\n237     common  fremovexattr                    sys_fremovexattr\n238     common  tkill                           sys_tkill\n239     common  sendfile64                      sys_sendfile64\n240     common  futex                           sys_futex_time32\n241     common  sched_setaffinity               sys_sched_setaffinity\n242     common  sched_getaffinity               sys_sched_getaffinity\n245     common  io_setup                        sys_io_setup\n246     common  io_destroy                      sys_io_destroy\n247     common  io_getevents                    sys_io_getevents_time32\n248     common  io_submit                       sys_io_submit\n249     common  io_cancel                       sys_io_cancel\n250     common  fadvise64                       sys_fadvise64\n252     common  exit_group                      sys_exit_group\n253     common  lookup_dcookie                  sys_ni_syscall\n254     common  epoll_create                    sys_epoll_create\n255     common  epoll_ctl                       sys_epoll_ctl\n256     common  epoll_wait                      sys_epoll_wait\n257     common  remap_file_pages                sys_remap_file_pages\n258     common  set_tid_address                 sys_set_tid_address\n259     common  timer_create                    sys_timer_create\n260     common  timer_settime                   sys_timer_settime32\n261     common  timer_gettime                   sys_timer_gettime32\n262     common  timer_getoverrun                sys_timer_getoverrun\n263     common  timer_delete                    sys_timer_delete\n264     common  clock_settime                   sys_clock_settime32\n265     common  clock_gettime                   sys_clock_gettime32\n266     common  clock_getres                    sys_clock_getres_time32\n267     common  clock_nanosleep                 sys_clock_nanosleep_time32\n268     common  statfs64                        sys_statfs64\n269     common  fstatfs64                       sys_fstatfs64\n270     common  tgkill                          sys_tgkill\n271     common  utimes                          sys_utimes_time32\n272     common  fadvise64_64                    sys_fadvise64_64_wrapper\n274     common  mbind                           sys_mbind\n275     common  get_mempolicy                   sys_get_mempolicy\n276     common  set_mempolicy                   sys_set_mempolicy\n277     common  mq_open                         sys_mq_open\n278     common  mq_unlink                       sys_mq_unlink\n279     common  mq_timedsend                    sys_mq_timedsend_time32\n280     common  mq_timedreceive                 sys_mq_timedreceive_time32\n281     common  mq_notify                       sys_mq_notify\n282     common  mq_getsetattr                   sys_mq_getsetattr\n283     common  kexec_load                      sys_kexec_load\n284     common  waitid                          sys_waitid\n285     common  add_key                         sys_add_key\n286     common  request_key                     sys_request_key\n287     common  keyctl                          sys_keyctl\n288     common  ioprio_set                      sys_ioprio_set\n289     common  ioprio_get                      sys_ioprio_get\n290     common  inotify_init                    sys_inotify_init\n291     common  inotify_add_watch               sys_inotify_add_watch\n292     common  inotify_rm_watch                sys_inotify_rm_watch\n294     common  migrate_pages                   sys_migrate_pages\n295     common  openat                          sys_openat\n296     common  mkdirat                         sys_mkdirat\n297     common  mknodat                         sys_mknodat\n298     common  fchownat                        sys_fchownat\n299     common  futimesat                       sys_futimesat_time32\n300     common  fstatat64                       sys_fstatat64\n301     common  unlinkat                        sys_unlinkat\n302     common  renameat                        sys_renameat\n303     common  linkat                          sys_linkat\n304     common  symlinkat                       sys_symlinkat\n305     common  readlinkat                      sys_readlinkat\n306     common  fchmodat                        sys_fchmodat\n307     common  faccessat                       sys_faccessat\n308     common  pselect6                        sys_pselect6_time32\n309     common  ppoll                           sys_ppoll_time32\n310     common  unshare                         sys_unshare\n311     common  set_robust_list                 sys_set_robust_list\n312     common  get_robust_list                 sys_get_robust_list\n313     common  splice                          sys_splice\n314     common  sync_file_range                 sys_sh_sync_file_range6\n315     common  tee                             sys_tee\n316     common  vmsplice                        sys_vmsplice\n317     common  move_pages                      sys_move_pages\n318     common  getcpu                          sys_getcpu\n319     common  epoll_pwait                     sys_epoll_pwait\n320     common  utimensat                       sys_utimensat_time32\n321     common  signalfd                        sys_signalfd\n322     common  timerfd_create                  sys_timerfd_create\n323     common  eventfd                         sys_eventfd\n324     common  fallocate                       sys_fallocate\n325     common  timerfd_settime                 sys_timerfd_settime32\n326     common  timerfd_gettime                 sys_timerfd_gettime32\n327     common  signalfd4                       sys_signalfd4\n328     common  eventfd2                        sys_eventfd2\n329     common  epoll_create1                   sys_epoll_create1\n330     common  dup3                            sys_dup3\n331     common  pipe2                           sys_pipe2\n332     common  inotify_init1                   sys_inotify_init1\n333     common  preadv                          sys_preadv\n334     common  pwritev                         sys_pwritev\n335     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n336     common  perf_event_open                 sys_perf_event_open\n337     common  fanotify_init                   sys_fanotify_init\n338     common  fanotify_mark                   sys_fanotify_mark\n339     common  prlimit64                       sys_prlimit64\n340     common  socket                          sys_socket\n341     common  bind                            sys_bind\n342     common  connect                         sys_connect\n343     common  listen                          sys_listen\n344     common  accept                          sys_accept\n345     common  getsockname                     sys_getsockname\n346     common  getpeername                     sys_getpeername\n347     common  socketpair                      sys_socketpair\n348     common  send                            sys_send\n349     common  sendto                          sys_sendto\n350     common  recv                            sys_recv\n351     common  recvfrom                        sys_recvfrom\n352     common  shutdown                        sys_shutdown\n353     common  setsockopt                      sys_setsockopt\n354     common  getsockopt                      sys_getsockopt\n355     common  sendmsg                         sys_sendmsg\n356     common  recvmsg                         sys_recvmsg\n357     common  recvmmsg                        sys_recvmmsg_time32\n358     common  accept4                         sys_accept4\n359     common  name_to_handle_at               sys_name_to_handle_at\n360     common  open_by_handle_at               sys_open_by_handle_at\n361     common  clock_adjtime                   sys_clock_adjtime32\n362     common  syncfs                          sys_syncfs\n363     common  sendmmsg                        sys_sendmmsg\n364     common  setns                           sys_setns\n365     common  process_vm_readv                sys_process_vm_readv\n366     common  process_vm_writev               sys_process_vm_writev\n367     common  kcmp                            sys_kcmp\n368     common  finit_module                    sys_finit_module\n369     common  sched_getattr                   sys_sched_getattr\n370     common  sched_setattr                   sys_sched_setattr\n371     common  renameat2                       sys_renameat2\n372     common  seccomp                         sys_seccomp\n373     common  getrandom                       sys_getrandom\n374     common  memfd_create                    sys_memfd_create\n375     common  bpf                             sys_bpf\n376     common  execveat                        sys_execveat\n377     common  userfaultfd                     sys_userfaultfd\n378     common  membarrier                      sys_membarrier\n379     common  mlock2                          sys_mlock2\n380     common  copy_file_range                 sys_copy_file_range\n381     common  preadv2                         sys_preadv2\n382     common  pwritev2                        sys_pwritev2\n383     common  statx                           sys_statx\n384     common  pkey_mprotect                   sys_pkey_mprotect\n385     common  pkey_alloc                      sys_pkey_alloc\n386     common  pkey_free                       sys_pkey_free\n387     common  rseq                            sys_rseq\n388     common  sync_file_range2                sys_sync_file_range2\n393     common  semget                          sys_semget\n394     common  semctl                          sys_semctl\n395     common  shmget                          sys_shmget\n396     common  shmctl                          sys_shmctl\n397     common  shmat                           sys_shmat\n398     common  shmdt                           sys_shmdt\n399     common  msgget                          sys_msgget\n400     common  msgsnd                          sys_msgsnd\n401     common  msgrcv                          sys_msgrcv\n402     common  msgctl                          sys_msgctl\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6\n414     common  ppoll_time64                    sys_ppoll\n416     common  io_pgetevents_time64            sys_io_pgetevents\n417     common  recvmmsg_time64                 sys_recvmmsg\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# m68k\n# - arch/m68k/kernel/syscalls/syscall.tbl\nm68k_syscall_tbl = \"\"\"\n0       common  restart_syscall                 sys_restart_syscall\n1       common  exit                            sys_exit\n2       common  fork                            __sys_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  open                            sys_open\n6       common  close                           sys_close\n7       common  waitpid                         sys_waitpid\n8       common  creat                           sys_creat\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      common  execve                          sys_execve\n12      common  chdir                           sys_chdir\n13      common  time                            sys_time32\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n16      common  chown                           sys_chown16\n18      common  oldstat                         sys_stat\n19      common  lseek                           sys_lseek\n20      common  getpid                          sys_getpid\n21      common  mount                           sys_mount\n22      common  umount                          sys_oldumount\n23      common  setuid                          sys_setuid16\n24      common  getuid                          sys_getuid16\n25      common  stime                           sys_stime32\n26      common  ptrace                          sys_ptrace\n27      common  alarm                           sys_alarm\n28      common  oldfstat                        sys_fstat\n29      common  pause                           sys_pause\n30      common  utime                           sys_utime32\n33      common  access                          sys_access\n34      common  nice                            sys_nice\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  rename                          sys_rename\n39      common  mkdir                           sys_mkdir\n40      common  rmdir                           sys_rmdir\n41      common  dup                             sys_dup\n42      common  pipe                            sys_pipe\n43      common  times                           sys_times\n45      common  brk                             sys_brk\n46      common  setgid                          sys_setgid16\n47      common  getgid                          sys_getgid16\n48      common  signal                          sys_signal\n49      common  geteuid                         sys_geteuid16\n50      common  getegid                         sys_getegid16\n51      common  acct                            sys_acct\n52      common  umount2                         sys_umount\n54      common  ioctl                           sys_ioctl\n55      common  fcntl                           sys_fcntl\n57      common  setpgid                         sys_setpgid\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      common  ustat                           sys_ustat\n63      common  dup2                            sys_dup2\n64      common  getppid                         sys_getppid\n65      common  getpgrp                         sys_getpgrp\n66      common  setsid                          sys_setsid\n67      common  sigaction                       sys_sigaction\n68      common  sgetmask                        sys_sgetmask\n69      common  ssetmask                        sys_ssetmask\n70      common  setreuid                        sys_setreuid16\n71      common  setregid                        sys_setregid16\n72      common  sigsuspend                      sys_sigsuspend\n73      common  sigpending                      sys_sigpending\n74      common  sethostname                     sys_sethostname\n75      common  setrlimit                       sys_setrlimit\n76      common  getrlimit                       sys_old_getrlimit\n77      common  getrusage                       sys_getrusage\n78      common  gettimeofday                    sys_gettimeofday\n79      common  settimeofday                    sys_settimeofday\n80      common  getgroups                       sys_getgroups16\n81      common  setgroups                       sys_setgroups16\n82      common  select                          sys_old_select\n83      common  symlink                         sys_symlink\n84      common  oldlstat                        sys_lstat\n85      common  readlink                        sys_readlink\n86      common  uselib                          sys_uselib\n87      common  swapon                          sys_swapon\n88      common  reboot                          sys_reboot\n89      common  readdir                         sys_old_readdir\n90      common  mmap                            sys_old_mmap\n91      common  munmap                          sys_munmap\n92      common  truncate                        sys_truncate\n93      common  ftruncate                       sys_ftruncate\n94      common  fchmod                          sys_fchmod\n95      common  fchown                          sys_fchown16\n96      common  getpriority                     sys_getpriority\n97      common  setpriority                     sys_setpriority\n99      common  statfs                          sys_statfs\n100     common  fstatfs                         sys_fstatfs\n102     common  socketcall                      sys_socketcall\n103     common  syslog                          sys_syslog\n104     common  setitimer                       sys_setitimer\n105     common  getitimer                       sys_getitimer\n106     common  stat                            sys_newstat\n107     common  lstat                           sys_newlstat\n108     common  fstat                           sys_newfstat\n111     common  vhangup                         sys_vhangup\n114     common  wait4                           sys_wait4\n115     common  swapoff                         sys_swapoff\n116     common  sysinfo                         sys_sysinfo\n117     common  ipc                             sys_ipc\n118     common  fsync                           sys_fsync\n119     common  sigreturn                       sys_sigreturn\n120     common  clone                           __sys_clone\n121     common  setdomainname                   sys_setdomainname\n122     common  uname                           sys_newuname\n123     common  cacheflush                      sys_cacheflush\n124     common  adjtimex                        sys_adjtimex_time32\n125     common  mprotect                        sys_mprotect\n126     common  sigprocmask                     sys_sigprocmask\n127     common  create_module                   sys_ni_syscall\n128     common  init_module                     sys_init_module\n129     common  delete_module                   sys_delete_module\n130     common  get_kernel_syms                 sys_ni_syscall\n131     common  quotactl                        sys_quotactl\n132     common  getpgid                         sys_getpgid\n133     common  fchdir                          sys_fchdir\n134     common  bdflush                         sys_ni_syscall\n135     common  sysfs                           sys_sysfs\n136     common  personality                     sys_personality\n138     common  setfsuid                        sys_setfsuid16\n139     common  setfsgid                        sys_setfsgid16\n140     common  _llseek                         sys_llseek\n141     common  getdents                        sys_getdents\n142     common  _newselect                      sys_select\n143     common  flock                           sys_flock\n144     common  msync                           sys_msync\n145     common  readv                           sys_readv\n146     common  writev                          sys_writev\n147     common  getsid                          sys_getsid\n148     common  fdatasync                       sys_fdatasync\n149     common  _sysctl                         sys_ni_syscall\n150     common  mlock                           sys_mlock\n151     common  munlock                         sys_munlock\n152     common  mlockall                        sys_mlockall\n153     common  munlockall                      sys_munlockall\n154     common  sched_setparam                  sys_sched_setparam\n155     common  sched_getparam                  sys_sched_getparam\n156     common  sched_setscheduler              sys_sched_setscheduler\n157     common  sched_getscheduler              sys_sched_getscheduler\n158     common  sched_yield                     sys_sched_yield\n159     common  sched_get_priority_max          sys_sched_get_priority_max\n160     common  sched_get_priority_min          sys_sched_get_priority_min\n161     common  sched_rr_get_interval           sys_sched_rr_get_interval_time32\n162     common  nanosleep                       sys_nanosleep_time32\n163     common  mremap                          sys_mremap\n164     common  setresuid                       sys_setresuid16\n165     common  getresuid                       sys_getresuid16\n166     common  getpagesize                     sys_getpagesize\n167     common  query_module                    sys_ni_syscall\n168     common  poll                            sys_poll\n169     common  nfsservctl                      sys_ni_syscall\n170     common  setresgid                       sys_setresgid16\n171     common  getresgid                       sys_getresgid16\n172     common  prctl                           sys_prctl\n173     common  rt_sigreturn                    sys_rt_sigreturn\n174     common  rt_sigaction                    sys_rt_sigaction\n175     common  rt_sigprocmask                  sys_rt_sigprocmask\n176     common  rt_sigpending                   sys_rt_sigpending\n177     common  rt_sigtimedwait                 sys_rt_sigtimedwait_time32\n178     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n179     common  rt_sigsuspend                   sys_rt_sigsuspend\n180     common  pread64                         sys_pread64\n181     common  pwrite64                        sys_pwrite64\n182     common  lchown                          sys_lchown16\n183     common  getcwd                          sys_getcwd\n184     common  capget                          sys_capget\n185     common  capset                          sys_capset\n186     common  sigaltstack                     sys_sigaltstack\n187     common  sendfile                        sys_sendfile\n188     common  getpmsg                         sys_ni_syscall\n189     common  putpmsg                         sys_ni_syscall\n190     common  vfork                           __sys_vfork\n191     common  ugetrlimit                      sys_getrlimit\n192     common  mmap2                           sys_mmap2\n193     common  truncate64                      sys_truncate64\n194     common  ftruncate64                     sys_ftruncate64\n195     common  stat64                          sys_stat64\n196     common  lstat64                         sys_lstat64\n197     common  fstat64                         sys_fstat64\n198     common  chown32                         sys_chown\n199     common  getuid32                        sys_getuid\n200     common  getgid32                        sys_getgid\n201     common  geteuid32                       sys_geteuid\n202     common  getegid32                       sys_getegid\n203     common  setreuid32                      sys_setreuid\n204     common  setregid32                      sys_setregid\n205     common  getgroups32                     sys_getgroups\n206     common  setgroups32                     sys_setgroups\n207     common  fchown32                        sys_fchown\n208     common  setresuid32                     sys_setresuid\n209     common  getresuid32                     sys_getresuid\n210     common  setresgid32                     sys_setresgid\n211     common  getresgid32                     sys_getresgid\n212     common  lchown32                        sys_lchown\n213     common  setuid32                        sys_setuid\n214     common  setgid32                        sys_setgid\n215     common  setfsuid32                      sys_setfsuid\n216     common  setfsgid32                      sys_setfsgid\n217     common  pivot_root                      sys_pivot_root\n220     common  getdents64                      sys_getdents64\n221     common  gettid                          sys_gettid\n222     common  tkill                           sys_tkill\n223     common  setxattr                        sys_setxattr\n224     common  lsetxattr                       sys_lsetxattr\n225     common  fsetxattr                       sys_fsetxattr\n226     common  getxattr                        sys_getxattr\n227     common  lgetxattr                       sys_lgetxattr\n228     common  fgetxattr                       sys_fgetxattr\n229     common  listxattr                       sys_listxattr\n230     common  llistxattr                      sys_llistxattr\n231     common  flistxattr                      sys_flistxattr\n232     common  removexattr                     sys_removexattr\n233     common  lremovexattr                    sys_lremovexattr\n234     common  fremovexattr                    sys_fremovexattr\n235     common  futex                           sys_futex_time32\n236     common  sendfile64                      sys_sendfile64\n237     common  mincore                         sys_mincore\n238     common  madvise                         sys_madvise\n239     common  fcntl64                         sys_fcntl64\n240     common  readahead                       sys_readahead\n241     common  io_setup                        sys_io_setup\n242     common  io_destroy                      sys_io_destroy\n243     common  io_getevents                    sys_io_getevents_time32\n244     common  io_submit                       sys_io_submit\n245     common  io_cancel                       sys_io_cancel\n246     common  fadvise64                       sys_fadvise64\n247     common  exit_group                      sys_exit_group\n248     common  lookup_dcookie                  sys_ni_syscall\n249     common  epoll_create                    sys_epoll_create\n250     common  epoll_ctl                       sys_epoll_ctl\n251     common  epoll_wait                      sys_epoll_wait\n252     common  remap_file_pages                sys_remap_file_pages\n253     common  set_tid_address                 sys_set_tid_address\n254     common  timer_create                    sys_timer_create\n255     common  timer_settime                   sys_timer_settime32\n256     common  timer_gettime                   sys_timer_gettime32\n257     common  timer_getoverrun                sys_timer_getoverrun\n258     common  timer_delete                    sys_timer_delete\n259     common  clock_settime                   sys_clock_settime32\n260     common  clock_gettime                   sys_clock_gettime32\n261     common  clock_getres                    sys_clock_getres_time32\n262     common  clock_nanosleep                 sys_clock_nanosleep_time32\n263     common  statfs64                        sys_statfs64\n264     common  fstatfs64                       sys_fstatfs64\n265     common  tgkill                          sys_tgkill\n266     common  utimes                          sys_utimes_time32\n267     common  fadvise64_64                    sys_fadvise64_64\n268     common  mbind                           sys_mbind\n269     common  get_mempolicy                   sys_get_mempolicy\n270     common  set_mempolicy                   sys_set_mempolicy\n271     common  mq_open                         sys_mq_open\n272     common  mq_unlink                       sys_mq_unlink\n273     common  mq_timedsend                    sys_mq_timedsend_time32\n274     common  mq_timedreceive                 sys_mq_timedreceive_time32\n275     common  mq_notify                       sys_mq_notify\n276     common  mq_getsetattr                   sys_mq_getsetattr\n277     common  waitid                          sys_waitid\n279     common  add_key                         sys_add_key\n280     common  request_key                     sys_request_key\n281     common  keyctl                          sys_keyctl\n282     common  ioprio_set                      sys_ioprio_set\n283     common  ioprio_get                      sys_ioprio_get\n284     common  inotify_init                    sys_inotify_init\n285     common  inotify_add_watch               sys_inotify_add_watch\n286     common  inotify_rm_watch                sys_inotify_rm_watch\n287     common  migrate_pages                   sys_migrate_pages\n288     common  openat                          sys_openat\n289     common  mkdirat                         sys_mkdirat\n290     common  mknodat                         sys_mknodat\n291     common  fchownat                        sys_fchownat\n292     common  futimesat                       sys_futimesat_time32\n293     common  fstatat64                       sys_fstatat64\n294     common  unlinkat                        sys_unlinkat\n295     common  renameat                        sys_renameat\n296     common  linkat                          sys_linkat\n297     common  symlinkat                       sys_symlinkat\n298     common  readlinkat                      sys_readlinkat\n299     common  fchmodat                        sys_fchmodat\n300     common  faccessat                       sys_faccessat\n301     common  pselect6                        sys_pselect6_time32\n302     common  ppoll                           sys_ppoll_time32\n303     common  unshare                         sys_unshare\n304     common  set_robust_list                 sys_set_robust_list\n305     common  get_robust_list                 sys_get_robust_list\n306     common  splice                          sys_splice\n307     common  sync_file_range                 sys_sync_file_range\n308     common  tee                             sys_tee\n309     common  vmsplice                        sys_vmsplice\n310     common  move_pages                      sys_move_pages\n311     common  sched_setaffinity               sys_sched_setaffinity\n312     common  sched_getaffinity               sys_sched_getaffinity\n313     common  kexec_load                      sys_kexec_load\n314     common  getcpu                          sys_getcpu\n315     common  epoll_pwait                     sys_epoll_pwait\n316     common  utimensat                       sys_utimensat_time32\n317     common  signalfd                        sys_signalfd\n318     common  timerfd_create                  sys_timerfd_create\n319     common  eventfd                         sys_eventfd\n320     common  fallocate                       sys_fallocate\n321     common  timerfd_settime                 sys_timerfd_settime32\n322     common  timerfd_gettime                 sys_timerfd_gettime32\n323     common  signalfd4                       sys_signalfd4\n324     common  eventfd2                        sys_eventfd2\n325     common  epoll_create1                   sys_epoll_create1\n326     common  dup3                            sys_dup3\n327     common  pipe2                           sys_pipe2\n328     common  inotify_init1                   sys_inotify_init1\n329     common  preadv                          sys_preadv\n330     common  pwritev                         sys_pwritev\n331     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n332     common  perf_event_open                 sys_perf_event_open\n333     common  get_thread_area                 sys_get_thread_area\n334     common  set_thread_area                 sys_set_thread_area\n335     common  atomic_cmpxchg_32               sys_atomic_cmpxchg_32\n336     common  atomic_barrier                  sys_atomic_barrier\n337     common  fanotify_init                   sys_fanotify_init\n338     common  fanotify_mark                   sys_fanotify_mark\n339     common  prlimit64                       sys_prlimit64\n340     common  name_to_handle_at               sys_name_to_handle_at\n341     common  open_by_handle_at               sys_open_by_handle_at\n342     common  clock_adjtime                   sys_clock_adjtime32\n343     common  syncfs                          sys_syncfs\n344     common  setns                           sys_setns\n345     common  process_vm_readv                sys_process_vm_readv\n346     common  process_vm_writev               sys_process_vm_writev\n347     common  kcmp                            sys_kcmp\n348     common  finit_module                    sys_finit_module\n349     common  sched_setattr                   sys_sched_setattr\n350     common  sched_getattr                   sys_sched_getattr\n351     common  renameat2                       sys_renameat2\n352     common  getrandom                       sys_getrandom\n353     common  memfd_create                    sys_memfd_create\n354     common  bpf                             sys_bpf\n355     common  execveat                        sys_execveat\n356     common  socket                          sys_socket\n357     common  socketpair                      sys_socketpair\n358     common  bind                            sys_bind\n359     common  connect                         sys_connect\n360     common  listen                          sys_listen\n361     common  accept4                         sys_accept4\n362     common  getsockopt                      sys_getsockopt\n363     common  setsockopt                      sys_setsockopt\n364     common  getsockname                     sys_getsockname\n365     common  getpeername                     sys_getpeername\n366     common  sendto                          sys_sendto\n367     common  sendmsg                         sys_sendmsg\n368     common  recvfrom                        sys_recvfrom\n369     common  recvmsg                         sys_recvmsg\n370     common  shutdown                        sys_shutdown\n371     common  recvmmsg                        sys_recvmmsg_time32\n372     common  sendmmsg                        sys_sendmmsg\n373     common  userfaultfd                     sys_userfaultfd\n374     common  membarrier                      sys_membarrier\n375     common  mlock2                          sys_mlock2\n376     common  copy_file_range                 sys_copy_file_range\n377     common  preadv2                         sys_preadv2\n378     common  pwritev2                        sys_pwritev2\n379     common  statx                           sys_statx\n380     common  seccomp                         sys_seccomp\n381     common  pkey_mprotect                   sys_pkey_mprotect\n382     common  pkey_alloc                      sys_pkey_alloc\n383     common  pkey_free                       sys_pkey_free\n384     common  rseq                            sys_rseq\n393     common  semget                          sys_semget\n394     common  semctl                          sys_semctl\n395     common  shmget                          sys_shmget\n396     common  shmctl                          sys_shmctl\n397     common  shmat                           sys_shmat\n398     common  shmdt                           sys_shmdt\n399     common  msgget                          sys_msgget\n400     common  msgsnd                          sys_msgsnd\n401     common  msgrcv                          sys_msgrcv\n402     common  msgctl                          sys_msgctl\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6\n414     common  ppoll_time64                    sys_ppoll\n416     common  io_pgetevents_time64            sys_io_pgetevents\n417     common  recvmmsg_time64                 sys_recvmmsg\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          __sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# alpha\n# - arch/alpha/kernel/syscalls/syscall.tbl\nalpha_syscall_tbl = \"\"\"\n0       common  osf_syscall                     alpha_syscall_zero\n1       common  exit                            sys_exit\n2       common  fork                            alpha_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  osf_old_open                    sys_ni_syscall\n6       common  close                           sys_close\n7       common  osf_wait4                       sys_osf_wait4\n8       common  osf_old_creat                   sys_ni_syscall\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      common  osf_execve                      sys_ni_syscall\n12      common  chdir                           sys_chdir\n13      common  fchdir                          sys_fchdir\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n16      common  chown                           sys_chown\n17      common  brk                             sys_osf_brk\n18      common  osf_getfsstat                   sys_ni_syscall\n19      common  lseek                           sys_lseek\n20      common  getxpid                         sys_getxpid\n21      common  osf_mount                       sys_osf_mount\n22      common  umount2                         sys_umount\n23      common  setuid                          sys_setuid\n24      common  getxuid                         sys_getxuid\n25      common  exec_with_loader                sys_ni_syscall\n26      common  ptrace                          sys_ptrace\n27      common  osf_nrecvmsg                    sys_ni_syscall\n28      common  osf_nsendmsg                    sys_ni_syscall\n29      common  osf_nrecvfrom                   sys_ni_syscall\n30      common  osf_naccept                     sys_ni_syscall\n31      common  osf_ngetpeername                sys_ni_syscall\n32      common  osf_ngetsockname                sys_ni_syscall\n33      common  access                          sys_access\n34      common  osf_chflags                     sys_ni_syscall\n35      common  osf_fchflags                    sys_ni_syscall\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  osf_old_stat                    sys_ni_syscall\n39      common  setpgid                         sys_setpgid\n40      common  osf_old_lstat                   sys_ni_syscall\n41      common  dup                             sys_dup\n42      common  pipe                            sys_alpha_pipe\n43      common  osf_set_program_attributes      sys_osf_set_program_attributes\n44      common  osf_profil                      sys_ni_syscall\n45      common  open                            sys_open\n46      common  osf_old_sigaction               sys_ni_syscall\n47      common  getxgid                         sys_getxgid\n48      common  osf_sigprocmask                 sys_osf_sigprocmask\n49      common  osf_getlogin                    sys_ni_syscall\n50      common  osf_setlogin                    sys_ni_syscall\n51      common  acct                            sys_acct\n52      common  sigpending                      sys_sigpending\n54      common  ioctl                           sys_ioctl\n55      common  osf_reboot                      sys_ni_syscall\n56      common  osf_revoke                      sys_ni_syscall\n57      common  symlink                         sys_symlink\n58      common  readlink                        sys_readlink\n59      common  execve                          sys_execve\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      common  osf_old_fstat                   sys_ni_syscall\n63      common  getpgrp                         sys_getpgrp\n64      common  getpagesize                     sys_getpagesize\n65      common  osf_mremap                      sys_ni_syscall\n66      common  vfork                           alpha_vfork\n67      common  stat                            sys_newstat\n68      common  lstat                           sys_newlstat\n69      common  osf_sbrk                        sys_ni_syscall\n70      common  osf_sstk                        sys_ni_syscall\n71      common  mmap                            sys_osf_mmap\n72      common  osf_old_vadvise                 sys_ni_syscall\n73      common  munmap                          sys_munmap\n74      common  mprotect                        sys_mprotect\n75      common  madvise                         sys_madvise\n76      common  vhangup                         sys_vhangup\n77      common  osf_kmodcall                    sys_ni_syscall\n78      common  osf_mincore                     sys_ni_syscall\n79      common  getgroups                       sys_getgroups\n80      common  setgroups                       sys_setgroups\n81      common  osf_old_getpgrp                 sys_ni_syscall\n82      common  setpgrp                         sys_setpgid\n83      common  osf_setitimer                   compat_sys_setitimer\n84      common  osf_old_wait                    sys_ni_syscall\n85      common  osf_table                       sys_ni_syscall\n86      common  osf_getitimer                   compat_sys_getitimer\n87      common  gethostname                     sys_gethostname\n88      common  sethostname                     sys_sethostname\n89      common  getdtablesize                   sys_getdtablesize\n90      common  dup2                            sys_dup2\n91      common  fstat                           sys_newfstat\n92      common  fcntl                           sys_fcntl\n93      common  osf_select                      sys_osf_select\n94      common  poll                            sys_poll\n95      common  fsync                           sys_fsync\n96      common  setpriority                     sys_setpriority\n97      common  socket                          sys_socket\n98      common  connect                         sys_connect\n99      common  accept                          sys_accept\n100     common  getpriority                     sys_osf_getpriority\n101     common  send                            sys_send\n102     common  recv                            sys_recv\n103     common  sigreturn                       sys_sigreturn\n104     common  bind                            sys_bind\n105     common  setsockopt                      sys_setsockopt\n106     common  listen                          sys_listen\n107     common  osf_plock                       sys_ni_syscall\n108     common  osf_old_sigvec                  sys_ni_syscall\n109     common  osf_old_sigblock                sys_ni_syscall\n110     common  osf_old_sigsetmask              sys_ni_syscall\n111     common  sigsuspend                      sys_sigsuspend\n112     common  osf_sigstack                    sys_osf_sigstack\n113     common  recvmsg                         sys_recvmsg\n114     common  sendmsg                         sys_sendmsg\n115     common  osf_old_vtrace                  sys_ni_syscall\n116     common  osf_gettimeofday                sys_osf_gettimeofday\n117     common  osf_getrusage                   sys_osf_getrusage\n118     common  getsockopt                      sys_getsockopt\n120     common  readv                           sys_readv\n121     common  writev                          sys_writev\n122     common  osf_settimeofday                sys_osf_settimeofday\n123     common  fchown                          sys_fchown\n124     common  fchmod                          sys_fchmod\n125     common  recvfrom                        sys_recvfrom\n126     common  setreuid                        sys_setreuid\n127     common  setregid                        sys_setregid\n128     common  rename                          sys_rename\n129     common  truncate                        sys_truncate\n130     common  ftruncate                       sys_ftruncate\n131     common  flock                           sys_flock\n132     common  setgid                          sys_setgid\n133     common  sendto                          sys_sendto\n134     common  shutdown                        sys_shutdown\n135     common  socketpair                      sys_socketpair\n136     common  mkdir                           sys_mkdir\n137     common  rmdir                           sys_rmdir\n138     common  osf_utimes                      sys_osf_utimes\n139     common  osf_old_sigreturn               sys_ni_syscall\n140     common  osf_adjtime                     sys_ni_syscall\n141     common  getpeername                     sys_getpeername\n142     common  osf_gethostid                   sys_ni_syscall\n143     common  osf_sethostid                   sys_ni_syscall\n144     common  getrlimit                       sys_getrlimit\n145     common  setrlimit                       sys_setrlimit\n146     common  osf_old_killpg                  sys_ni_syscall\n147     common  setsid                          sys_setsid\n148     common  quotactl                        sys_quotactl\n149     common  osf_oldquota                    sys_ni_syscall\n150     common  getsockname                     sys_getsockname\n153     common  osf_pid_block                   sys_ni_syscall\n154     common  osf_pid_unblock                 sys_ni_syscall\n156     common  sigaction                       sys_osf_sigaction\n157     common  osf_sigwaitprim                 sys_ni_syscall\n158     common  osf_nfssvc                      sys_ni_syscall\n159     common  osf_getdirentries               sys_osf_getdirentries\n160     common  osf_statfs                      sys_osf_statfs\n161     common  osf_fstatfs                     sys_osf_fstatfs\n163     common  osf_asynch_daemon               sys_ni_syscall\n164     common  osf_getfh                       sys_ni_syscall\n165     common  osf_getdomainname               sys_osf_getdomainname\n166     common  setdomainname                   sys_setdomainname\n169     common  osf_exportfs                    sys_ni_syscall\n181     common  osf_alt_plock                   sys_ni_syscall\n184     common  osf_getmnt                      sys_ni_syscall\n187     common  osf_alt_sigpending              sys_ni_syscall\n188     common  osf_alt_setsid                  sys_ni_syscall\n199     common  osf_swapon                      sys_swapon\n200     common  msgctl                          sys_old_msgctl\n201     common  msgget                          sys_msgget\n202     common  msgrcv                          sys_msgrcv\n203     common  msgsnd                          sys_msgsnd\n204     common  semctl                          sys_old_semctl\n205     common  semget                          sys_semget\n206     common  semop                           sys_semop\n207     common  osf_utsname                     sys_osf_utsname\n208     common  lchown                          sys_lchown\n209     common  shmat                           sys_shmat\n210     common  shmctl                          sys_old_shmctl\n211     common  shmdt                           sys_shmdt\n212     common  shmget                          sys_shmget\n213     common  osf_mvalid                      sys_ni_syscall\n214     common  osf_getaddressconf              sys_ni_syscall\n215     common  osf_msleep                      sys_ni_syscall\n216     common  osf_mwakeup                     sys_ni_syscall\n217     common  msync                           sys_msync\n218     common  osf_signal                      sys_ni_syscall\n219     common  osf_utc_gettime                 sys_ni_syscall\n220     common  osf_utc_adjtime                 sys_ni_syscall\n222     common  osf_security                    sys_ni_syscall\n223     common  osf_kloadcall                   sys_ni_syscall\n224     common  osf_stat                        sys_osf_stat\n225     common  osf_lstat                       sys_osf_lstat\n226     common  osf_fstat                       sys_osf_fstat\n227     common  osf_statfs64                    sys_osf_statfs64\n228     common  osf_fstatfs64                   sys_osf_fstatfs64\n233     common  getpgid                         sys_getpgid\n234     common  getsid                          sys_getsid\n235     common  sigaltstack                     sys_sigaltstack\n236     common  osf_waitid                      sys_ni_syscall\n237     common  osf_priocntlset                 sys_ni_syscall\n238     common  osf_sigsendset                  sys_ni_syscall\n239     common  osf_set_speculative             sys_ni_syscall\n240     common  osf_msfs_syscall                sys_ni_syscall\n241     common  osf_sysinfo                     sys_osf_sysinfo\n242     common  osf_uadmin                      sys_ni_syscall\n243     common  osf_fuser                       sys_ni_syscall\n244     common  osf_proplist_syscall            sys_osf_proplist_syscall\n245     common  osf_ntp_adjtime                 sys_ni_syscall\n246     common  osf_ntp_gettime                 sys_ni_syscall\n247     common  osf_pathconf                    sys_ni_syscall\n248     common  osf_fpathconf                   sys_ni_syscall\n250     common  osf_uswitch                     sys_ni_syscall\n251     common  osf_usleep_thread               sys_osf_usleep_thread\n252     common  osf_audcntl                     sys_ni_syscall\n253     common  osf_audgen                      sys_ni_syscall\n254     common  sysfs                           sys_sysfs\n255     common  osf_subsys_info                 sys_ni_syscall\n256     common  osf_getsysinfo                  sys_osf_getsysinfo\n257     common  osf_setsysinfo                  sys_osf_setsysinfo\n258     common  osf_afs_syscall                 sys_ni_syscall\n259     common  osf_swapctl                     sys_ni_syscall\n260     common  osf_memcntl                     sys_ni_syscall\n261     common  osf_fdatasync                   sys_ni_syscall\n300     common  bdflush                         sys_ni_syscall\n301     common  sethae                          sys_sethae\n302     common  mount                           sys_mount\n303     common  old_adjtimex                    sys_old_adjtimex\n304     common  swapoff                         sys_swapoff\n305     common  getdents                        sys_getdents\n306     common  create_module                   sys_ni_syscall\n307     common  init_module                     sys_init_module\n308     common  delete_module                   sys_delete_module\n309     common  get_kernel_syms                 sys_ni_syscall\n310     common  syslog                          sys_syslog\n311     common  reboot                          sys_reboot\n312     common  clone                           alpha_clone\n313     common  uselib                          sys_uselib\n314     common  mlock                           sys_mlock\n315     common  munlock                         sys_munlock\n316     common  mlockall                        sys_mlockall\n317     common  munlockall                      sys_munlockall\n318     common  sysinfo                         sys_sysinfo\n319     common  _sysctl                         sys_ni_syscall\n321     common  oldumount                       sys_oldumount\n322     common  swapon                          sys_swapon\n323     common  times                           sys_times\n324     common  personality                     sys_personality\n325     common  setfsuid                        sys_setfsuid\n326     common  setfsgid                        sys_setfsgid\n327     common  ustat                           sys_ustat\n328     common  statfs                          sys_statfs\n329     common  fstatfs                         sys_fstatfs\n330     common  sched_setparam                  sys_sched_setparam\n331     common  sched_getparam                  sys_sched_getparam\n332     common  sched_setscheduler              sys_sched_setscheduler\n333     common  sched_getscheduler              sys_sched_getscheduler\n334     common  sched_yield                     sys_sched_yield\n335     common  sched_get_priority_max          sys_sched_get_priority_max\n336     common  sched_get_priority_min          sys_sched_get_priority_min\n337     common  sched_rr_get_interval           sys_sched_rr_get_interval\n338     common  afs_syscall                     sys_ni_syscall\n339     common  uname                           sys_newuname\n340     common  nanosleep                       sys_nanosleep\n341     common  mremap                          sys_mremap\n342     common  nfsservctl                      sys_ni_syscall\n343     common  setresuid                       sys_setresuid\n344     common  getresuid                       sys_getresuid\n345     common  pciconfig_read                  sys_pciconfig_read\n346     common  pciconfig_write                 sys_pciconfig_write\n347     common  query_module                    sys_ni_syscall\n348     common  prctl                           sys_prctl\n349     common  pread64                         sys_pread64\n350     common  pwrite64                        sys_pwrite64\n351     common  rt_sigreturn                    sys_rt_sigreturn\n352     common  rt_sigaction                    sys_rt_sigaction\n353     common  rt_sigprocmask                  sys_rt_sigprocmask\n354     common  rt_sigpending                   sys_rt_sigpending\n355     common  rt_sigtimedwait                 sys_rt_sigtimedwait\n356     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n357     common  rt_sigsuspend                   sys_rt_sigsuspend\n358     common  select                          sys_select\n359     common  gettimeofday                    sys_gettimeofday\n360     common  settimeofday                    sys_settimeofday\n361     common  getitimer                       sys_getitimer\n362     common  setitimer                       sys_setitimer\n363     common  utimes                          sys_utimes\n364     common  getrusage                       sys_getrusage\n365     common  wait4                           sys_wait4\n366     common  adjtimex                        sys_adjtimex\n367     common  getcwd                          sys_getcwd\n368     common  capget                          sys_capget\n369     common  capset                          sys_capset\n370     common  sendfile                        sys_sendfile64\n371     common  setresgid                       sys_setresgid\n372     common  getresgid                       sys_getresgid\n373     common  dipc                            sys_ni_syscall\n374     common  pivot_root                      sys_pivot_root\n375     common  mincore                         sys_mincore\n376     common  pciconfig_iobase                sys_pciconfig_iobase\n377     common  getdents64                      sys_getdents64\n378     common  gettid                          sys_gettid\n379     common  readahead                       sys_readahead\n381     common  tkill                           sys_tkill\n382     common  setxattr                        sys_setxattr\n383     common  lsetxattr                       sys_lsetxattr\n384     common  fsetxattr                       sys_fsetxattr\n385     common  getxattr                        sys_getxattr\n386     common  lgetxattr                       sys_lgetxattr\n387     common  fgetxattr                       sys_fgetxattr\n388     common  listxattr                       sys_listxattr\n389     common  llistxattr                      sys_llistxattr\n390     common  flistxattr                      sys_flistxattr\n391     common  removexattr                     sys_removexattr\n392     common  lremovexattr                    sys_lremovexattr\n393     common  fremovexattr                    sys_fremovexattr\n394     common  futex                           sys_futex\n395     common  sched_setaffinity               sys_sched_setaffinity\n396     common  sched_getaffinity               sys_sched_getaffinity\n397     common  tuxcall                         sys_ni_syscall\n398     common  io_setup                        sys_io_setup\n399     common  io_destroy                      sys_io_destroy\n400     common  io_getevents                    sys_io_getevents\n401     common  io_submit                       sys_io_submit\n402     common  io_cancel                       sys_io_cancel\n405     common  exit_group                      sys_exit_group\n406     common  lookup_dcookie                  sys_ni_syscall\n407     common  epoll_create                    sys_epoll_create\n408     common  epoll_ctl                       sys_epoll_ctl\n409     common  epoll_wait                      sys_epoll_wait\n410     common  remap_file_pages                sys_remap_file_pages\n411     common  set_tid_address                 sys_set_tid_address\n412     common  restart_syscall                 sys_restart_syscall\n413     common  fadvise64                       sys_fadvise64\n414     common  timer_create                    sys_timer_create\n415     common  timer_settime                   sys_timer_settime\n416     common  timer_gettime                   sys_timer_gettime\n417     common  timer_getoverrun                sys_timer_getoverrun\n418     common  timer_delete                    sys_timer_delete\n419     common  clock_settime                   sys_clock_settime\n420     common  clock_gettime                   sys_clock_gettime\n421     common  clock_getres                    sys_clock_getres\n422     common  clock_nanosleep                 sys_clock_nanosleep\n423     common  semtimedop                      sys_semtimedop\n424     common  tgkill                          sys_tgkill\n425     common  stat64                          sys_stat64\n426     common  lstat64                         sys_lstat64\n427     common  fstat64                         sys_fstat64\n428     common  vserver                         sys_ni_syscall\n429     common  mbind                           sys_ni_syscall\n430     common  get_mempolicy                   sys_ni_syscall\n431     common  set_mempolicy                   sys_ni_syscall\n432     common  mq_open                         sys_mq_open\n433     common  mq_unlink                       sys_mq_unlink\n434     common  mq_timedsend                    sys_mq_timedsend\n435     common  mq_timedreceive                 sys_mq_timedreceive\n436     common  mq_notify                       sys_mq_notify\n437     common  mq_getsetattr                   sys_mq_getsetattr\n438     common  waitid                          sys_waitid\n439     common  add_key                         sys_add_key\n440     common  request_key                     sys_request_key\n441     common  keyctl                          sys_keyctl\n442     common  ioprio_set                      sys_ioprio_set\n443     common  ioprio_get                      sys_ioprio_get\n444     common  inotify_init                    sys_inotify_init\n445     common  inotify_add_watch               sys_inotify_add_watch\n446     common  inotify_rm_watch                sys_inotify_rm_watch\n447     common  fdatasync                       sys_fdatasync\n448     common  kexec_load                      sys_kexec_load\n449     common  migrate_pages                   sys_migrate_pages\n450     common  openat                          sys_openat\n451     common  mkdirat                         sys_mkdirat\n452     common  mknodat                         sys_mknodat\n453     common  fchownat                        sys_fchownat\n454     common  futimesat                       sys_futimesat\n455     common  fstatat64                       sys_fstatat64\n456     common  unlinkat                        sys_unlinkat\n457     common  renameat                        sys_renameat\n458     common  linkat                          sys_linkat\n459     common  symlinkat                       sys_symlinkat\n460     common  readlinkat                      sys_readlinkat\n461     common  fchmodat                        sys_fchmodat\n462     common  faccessat                       sys_faccessat\n463     common  pselect6                        sys_pselect6\n464     common  ppoll                           sys_ppoll\n465     common  unshare                         sys_unshare\n466     common  set_robust_list                 sys_set_robust_list\n467     common  get_robust_list                 sys_get_robust_list\n468     common  splice                          sys_splice\n469     common  sync_file_range                 sys_sync_file_range\n470     common  tee                             sys_tee\n471     common  vmsplice                        sys_vmsplice\n472     common  move_pages                      sys_move_pages\n473     common  getcpu                          sys_getcpu\n474     common  epoll_pwait                     sys_epoll_pwait\n475     common  utimensat                       sys_utimensat\n476     common  signalfd                        sys_signalfd\n477     common  timerfd                         sys_ni_syscall\n478     common  eventfd                         sys_eventfd\n479     common  recvmmsg                        sys_recvmmsg\n480     common  fallocate                       sys_fallocate\n481     common  timerfd_create                  sys_timerfd_create\n482     common  timerfd_settime                 sys_timerfd_settime\n483     common  timerfd_gettime                 sys_timerfd_gettime\n484     common  signalfd4                       sys_signalfd4\n485     common  eventfd2                        sys_eventfd2\n486     common  epoll_create1                   sys_epoll_create1\n487     common  dup3                            sys_dup3\n488     common  pipe2                           sys_pipe2\n489     common  inotify_init1                   sys_inotify_init1\n490     common  preadv                          sys_preadv\n491     common  pwritev                         sys_pwritev\n492     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n493     common  perf_event_open                 sys_perf_event_open\n494     common  fanotify_init                   sys_fanotify_init\n495     common  fanotify_mark                   sys_fanotify_mark\n496     common  prlimit64                       sys_prlimit64\n497     common  name_to_handle_at               sys_name_to_handle_at\n498     common  open_by_handle_at               sys_open_by_handle_at\n499     common  clock_adjtime                   sys_clock_adjtime\n500     common  syncfs                          sys_syncfs\n501     common  setns                           sys_setns\n502     common  accept4                         sys_accept4\n503     common  sendmmsg                        sys_sendmmsg\n504     common  process_vm_readv                sys_process_vm_readv\n505     common  process_vm_writev               sys_process_vm_writev\n506     common  kcmp                            sys_kcmp\n507     common  finit_module                    sys_finit_module\n508     common  sched_setattr                   sys_sched_setattr\n509     common  sched_getattr                   sys_sched_getattr\n510     common  renameat2                       sys_renameat2\n511     common  getrandom                       sys_getrandom\n512     common  memfd_create                    sys_memfd_create\n513     common  execveat                        sys_execveat\n514     common  seccomp                         sys_seccomp\n515     common  bpf                             sys_bpf\n516     common  userfaultfd                     sys_userfaultfd\n517     common  membarrier                      sys_membarrier\n518     common  mlock2                          sys_mlock2\n519     common  copy_file_range                 sys_copy_file_range\n520     common  preadv2                         sys_preadv2\n521     common  pwritev2                        sys_pwritev2\n522     common  statx                           sys_statx\n523     common  io_pgetevents                   sys_io_pgetevents\n524     common  pkey_mprotect                   sys_pkey_mprotect\n525     common  pkey_alloc                      sys_pkey_alloc\n526     common  pkey_free                       sys_pkey_free\n527     common  rseq                            sys_rseq\n528     common  statfs64                        sys_statfs64\n529     common  fstatfs64                       sys_fstatfs64\n530     common  getegid                         sys_getegid\n531     common  geteuid                         sys_geteuid\n532     common  getppid                         sys_getppid\n534     common  pidfd_send_signal               sys_pidfd_send_signal\n535     common  io_uring_setup                  sys_io_uring_setup\n536     common  io_uring_enter                  sys_io_uring_enter\n537     common  io_uring_register               sys_io_uring_register\n538     common  open_tree                       sys_open_tree\n539     common  move_mount                      sys_move_mount\n540     common  fsopen                          sys_fsopen\n541     common  fsconfig                        sys_fsconfig\n542     common  fsmount                         sys_fsmount\n543     common  fspick                          sys_fspick\n544     common  pidfd_open                      sys_pidfd_open\n545     common  clone3                          alpha_clone3\n546     common  close_range                     sys_close_range\n547     common  openat2                         sys_openat2\n548     common  pidfd_getfd                     sys_pidfd_getfd\n549     common  faccessat2                      sys_faccessat2\n550     common  process_madvise                 sys_process_madvise\n551     common  epoll_pwait2                    sys_epoll_pwait2\n552     common  mount_setattr                   sys_mount_setattr\n553     common  quotactl_fd                     sys_quotactl_fd\n554     common  landlock_create_ruleset         sys_landlock_create_ruleset\n555     common  landlock_add_rule               sys_landlock_add_rule\n556     common  landlock_restrict_self          sys_landlock_restrict_self\n558     common  process_mrelease                sys_process_mrelease\n559     common  futex_waitv                     sys_futex_waitv\n560     common  set_mempolicy_home_node         sys_ni_syscall\n561     common  cachestat                       sys_cachestat\n562     common  fchmodat2                       sys_fchmodat2\n563     common  map_shadow_stack                sys_map_shadow_stack\n564     common  futex_wake                      sys_futex_wake\n565     common  futex_wait                      sys_futex_wait\n566     common  futex_requeue                   sys_futex_requeue\n567     common  statmount                       sys_statmount\n568     common  listmount                       sys_listmount\n569     common  lsm_get_self_attr               sys_lsm_get_self_attr\n570     common  lsm_set_self_attr               sys_lsm_set_self_attr\n571     common  lsm_list_modules                sys_lsm_list_modules\n572     common  mseal                           sys_mseal\n573     common  setxattrat                      sys_setxattrat\n574     common  getxattrat                      sys_getxattrat\n575     common  listxattrat                     sys_listxattrat\n576     common  removexattrat                   sys_removexattrat\n577     common  open_tree_attr                  sys_open_tree_attr\n578     common  file_getattr                    sys_file_getattr\n579     common  file_setattr                    sys_file_setattr\n580     common  listns                          sys_listns\n\"\"\"\n\n\n# HPPA\n# - arch/parisc/kernel/syscalls/syscall.tbl\nhppa_syscall_tbl = \"\"\"\n0       common  restart_syscall         sys_restart_syscall\n1       common  exit                    sys_exit\n2       common  fork                    sys_fork_wrapper\n3       common  read                    sys_read\n4       common  write                   sys_write\n5       common  open                    sys_open                        compat_sys_open\n6       common  close                   sys_close\n7       common  waitpid                 sys_waitpid\n8       common  creat                   sys_creat\n9       common  link                    sys_link\n10      common  unlink                  sys_unlink\n11      common  execve                  sys_execve                      compat_sys_execve\n12      common  chdir                   sys_chdir\n13      32      time                    sys_time32\n13      64      time                    sys_time\n14      common  mknod                   sys_mknod\n15      common  chmod                   sys_chmod\n16      common  lchown                  sys_lchown\n17      common  socket                  sys_socket\n18      common  stat                    sys_newstat                     compat_sys_newstat\n19      common  lseek                   sys_lseek                       compat_sys_lseek\n20      common  getpid                  sys_getpid\n21      common  mount                   sys_mount\n22      common  bind                    sys_bind\n23      common  setuid                  sys_setuid\n24      common  getuid                  sys_getuid\n25      32      stime                   sys_stime32\n25      64      stime                   sys_stime\n26      common  ptrace                  sys_ptrace                      compat_sys_ptrace\n27      common  alarm                   sys_alarm\n28      common  fstat                   sys_newfstat                    compat_sys_newfstat\n29      common  pause                   sys_pause\n30      32      utime                   sys_utime32\n30      64      utime                   sys_utime\n31      common  connect                 sys_connect\n32      common  listen                  sys_listen\n33      common  access                  sys_access\n34      common  nice                    sys_nice\n35      common  accept                  sys_accept\n36      common  sync                    sys_sync\n37      common  kill                    sys_kill\n38      common  rename                  sys_rename\n39      common  mkdir                   sys_mkdir\n40      common  rmdir                   sys_rmdir\n41      common  dup                     sys_dup\n42      common  pipe                    sys_pipe\n43      common  times                   sys_times                       compat_sys_times\n44      common  getsockname             sys_getsockname\n45      common  brk                     sys_brk\n46      common  setgid                  sys_setgid\n47      common  getgid                  sys_getgid\n48      common  signal                  sys_signal\n49      common  geteuid                 sys_geteuid\n50      common  getegid                 sys_getegid\n51      common  acct                    sys_acct\n52      common  umount2                 sys_umount\n53      common  getpeername             sys_getpeername\n54      common  ioctl                   sys_ioctl                       compat_sys_ioctl\n55      common  fcntl                   sys_fcntl                       compat_sys_fcntl\n56      common  socketpair              sys_socketpair\n57      common  setpgid                 sys_setpgid\n58      common  send                    sys_send\n59      common  uname                   sys_newuname\n60      common  umask                   sys_umask\n61      common  chroot                  sys_chroot\n62      common  ustat                   sys_ustat                       compat_sys_ustat\n63      common  dup2                    sys_dup2\n64      common  getppid                 sys_getppid\n65      common  getpgrp                 sys_getpgrp\n66      common  setsid                  sys_setsid\n67      common  pivot_root              sys_pivot_root\n68      common  sgetmask                sys_sgetmask                    sys32_unimplemented\n69      common  ssetmask                sys_ssetmask                    sys32_unimplemented\n70      common  setreuid                sys_setreuid\n71      common  setregid                sys_setregid\n72      common  mincore                 sys_mincore\n73      common  sigpending              sys_sigpending                  compat_sys_sigpending\n74      common  sethostname             sys_sethostname\n75      common  setrlimit               sys_setrlimit                   compat_sys_setrlimit\n76      common  getrlimit               sys_getrlimit                   compat_sys_getrlimit\n77      common  getrusage               sys_getrusage                   compat_sys_getrusage\n78      common  gettimeofday            sys_gettimeofday                compat_sys_gettimeofday\n79      common  settimeofday            sys_settimeofday                compat_sys_settimeofday\n80      common  getgroups               sys_getgroups\n81      common  setgroups               sys_setgroups\n82      common  sendto                  sys_sendto\n83      common  symlink                 sys_symlink\n84      common  lstat                   sys_newlstat                    compat_sys_newlstat\n85      common  readlink                sys_readlink\n86      common  uselib                  sys_ni_syscall\n87      common  swapon                  sys_swapon\n88      common  reboot                  sys_reboot\n89      common  mmap2                   sys_mmap2\n90      common  mmap                    sys_mmap\n91      common  munmap                  sys_munmap\n92      common  truncate                sys_truncate                    compat_sys_truncate\n93      common  ftruncate               sys_ftruncate                   compat_sys_ftruncate\n94      common  fchmod                  sys_fchmod\n95      common  fchown                  sys_fchown\n96      common  getpriority             sys_getpriority\n97      common  setpriority             sys_setpriority\n98      common  recv                    sys_recv                        compat_sys_recv\n99      common  statfs                  sys_statfs                      compat_sys_statfs\n100     common  fstatfs                 sys_fstatfs                     compat_sys_fstatfs\n101     common  stat64                  sys_stat64\n103     common  syslog                  sys_syslog\n104     common  setitimer               sys_setitimer                   compat_sys_setitimer\n105     common  getitimer               sys_getitimer                   compat_sys_getitimer\n106     common  capget                  sys_capget\n107     common  capset                  sys_capset\n108     32      pread64                 parisc_pread64\n108     64      pread64                 sys_pread64\n109     32      pwrite64                parisc_pwrite64\n109     64      pwrite64                sys_pwrite64\n110     common  getcwd                  sys_getcwd\n111     common  vhangup                 sys_vhangup\n112     common  fstat64                 sys_fstat64\n113     common  vfork                   sys_vfork_wrapper\n114     common  wait4                   sys_wait4                       compat_sys_wait4\n115     common  swapoff                 sys_swapoff\n116     common  sysinfo                 sys_sysinfo                     compat_sys_sysinfo\n117     common  shutdown                sys_shutdown\n118     common  fsync                   sys_fsync\n119     common  madvise                 parisc_madvise\n120     common  clone                   sys_clone_wrapper\n121     common  setdomainname           sys_setdomainname\n122     common  sendfile                sys_sendfile                    compat_sys_sendfile\n123     common  recvfrom                sys_recvfrom                    compat_sys_recvfrom\n124     32      adjtimex                sys_adjtimex_time32\n124     64      adjtimex                sys_adjtimex\n125     common  mprotect                sys_mprotect\n126     common  sigprocmask             sys_sigprocmask                 compat_sys_sigprocmask\n128     common  init_module             sys_init_module\n129     common  delete_module           sys_delete_module\n131     common  quotactl                sys_quotactl\n132     common  getpgid                 sys_getpgid\n133     common  fchdir                  sys_fchdir\n134     common  bdflush                 sys_ni_syscall\n135     common  sysfs                   sys_sysfs\n136     32      personality             parisc_personality\n136     64      personality             sys_personality\n138     common  setfsuid                sys_setfsuid\n139     common  setfsgid                sys_setfsgid\n140     common  _llseek                 sys_llseek\n141     common  getdents                sys_getdents                    compat_sys_getdents\n142     common  _newselect              sys_select                      compat_sys_select\n143     common  flock                   sys_flock\n144     common  msync                   sys_msync\n145     common  readv                   sys_readv\n146     common  writev                  sys_writev\n147     common  getsid                  sys_getsid\n148     common  fdatasync               sys_fdatasync\n149     common  _sysctl                 sys_ni_syscall\n150     common  mlock                   sys_mlock\n151     common  munlock                 sys_munlock\n152     common  mlockall                sys_mlockall\n153     common  munlockall              sys_munlockall\n154     common  sched_setparam          sys_sched_setparam\n155     common  sched_getparam          sys_sched_getparam\n156     common  sched_setscheduler      sys_sched_setscheduler\n157     common  sched_getscheduler      sys_sched_getscheduler\n158     common  sched_yield             sys_sched_yield\n159     common  sched_get_priority_max  sys_sched_get_priority_max\n160     common  sched_get_priority_min  sys_sched_get_priority_min\n161     32      sched_rr_get_interval   sys_sched_rr_get_interval_time32\n161     64      sched_rr_get_interval   sys_sched_rr_get_interval\n162     32      nanosleep               sys_nanosleep_time32\n162     64      nanosleep               sys_nanosleep\n163     common  mremap                  sys_mremap\n164     common  setresuid               sys_setresuid\n165     common  getresuid               sys_getresuid\n166     common  sigaltstack             sys_sigaltstack                 compat_sys_sigaltstack\n168     common  poll                    sys_poll\n170     common  setresgid               sys_setresgid\n171     common  getresgid               sys_getresgid\n172     common  prctl                   sys_prctl\n173     common  rt_sigreturn            sys_rt_sigreturn_wrapper\n174     common  rt_sigaction            sys_rt_sigaction                compat_sys_rt_sigaction\n175     common  rt_sigprocmask          sys_rt_sigprocmask              compat_sys_rt_sigprocmask\n176     common  rt_sigpending           sys_rt_sigpending               compat_sys_rt_sigpending\n177     32      rt_sigtimedwait         sys_rt_sigtimedwait_time32      compat_sys_rt_sigtimedwait_time32\n177     64      rt_sigtimedwait         sys_rt_sigtimedwait\n178     common  rt_sigqueueinfo         sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo\n179     common  rt_sigsuspend           sys_rt_sigsuspend               compat_sys_rt_sigsuspend\n180     common  chown                   sys_chown\n181     common  setsockopt              sys_setsockopt                  sys_setsockopt\n182     common  getsockopt              sys_getsockopt                  sys_getsockopt\n183     common  sendmsg                 sys_sendmsg                     compat_sys_sendmsg\n184     common  recvmsg                 sys_recvmsg                     compat_sys_recvmsg\n185     common  semop                   sys_semop\n186     common  semget                  sys_semget\n187     common  semctl                  sys_semctl                      compat_sys_semctl\n188     common  msgsnd                  sys_msgsnd                      compat_sys_msgsnd\n189     common  msgrcv                  sys_msgrcv                      compat_sys_msgrcv\n190     common  msgget                  sys_msgget\n191     common  msgctl                  sys_msgctl                      compat_sys_msgctl\n192     common  shmat                   sys_shmat                       compat_sys_shmat\n193     common  shmdt                   sys_shmdt\n194     common  shmget                  sys_shmget\n195     common  shmctl                  sys_shmctl                      compat_sys_shmctl\n198     common  lstat64                 sys_lstat64\n199     32      truncate64              parisc_truncate64\n199     64      truncate64              sys_truncate64\n200     32      ftruncate64             parisc_ftruncate64\n200     64      ftruncate64             sys_ftruncate64\n201     common  getdents64              sys_getdents64\n202     common  fcntl64                 sys_fcntl64                     compat_sys_fcntl64\n206     common  gettid                  sys_gettid\n207     32      readahead               parisc_readahead\n207     64      readahead               sys_readahead\n208     common  tkill                   sys_tkill\n209     common  sendfile64              sys_sendfile64                  compat_sys_sendfile64\n210     32      futex                   sys_futex_time32\n210     64      futex                   sys_futex\n211     common  sched_setaffinity       sys_sched_setaffinity           compat_sys_sched_setaffinity\n212     common  sched_getaffinity       sys_sched_getaffinity           compat_sys_sched_getaffinity\n215     common  io_setup                sys_io_setup                    compat_sys_io_setup\n216     common  io_destroy              sys_io_destroy\n217     32      io_getevents            sys_io_getevents_time32\n217     64      io_getevents            sys_io_getevents\n218     common  io_submit               sys_io_submit                   compat_sys_io_submit\n219     common  io_cancel               sys_io_cancel\n222     common  exit_group              sys_exit_group\n223     common  lookup_dcookie          sys_ni_syscall\n224     common  epoll_create            sys_epoll_create\n225     common  epoll_ctl               sys_epoll_ctl\n226     common  epoll_wait              sys_epoll_wait\n227     common  remap_file_pages        sys_remap_file_pages\n228     32      semtimedop              sys_semtimedop_time32\n228     64      semtimedop              sys_semtimedop\n229     common  mq_open                 sys_mq_open                     compat_sys_mq_open\n230     common  mq_unlink               sys_mq_unlink\n231     32      mq_timedsend            sys_mq_timedsend_time32\n231     64      mq_timedsend            sys_mq_timedsend\n232     32      mq_timedreceive         sys_mq_timedreceive_time32\n232     64      mq_timedreceive         sys_mq_timedreceive\n233     common  mq_notify               sys_mq_notify                   compat_sys_mq_notify\n234     common  mq_getsetattr           sys_mq_getsetattr               compat_sys_mq_getsetattr\n235     common  waitid                  sys_waitid                      compat_sys_waitid\n236     32      fadvise64_64            parisc_fadvise64_64\n236     64      fadvise64_64            sys_fadvise64_64\n237     common  set_tid_address         sys_set_tid_address\n238     common  setxattr                sys_setxattr\n239     common  lsetxattr               sys_lsetxattr\n240     common  fsetxattr               sys_fsetxattr\n241     common  getxattr                sys_getxattr\n242     common  lgetxattr               sys_lgetxattr\n243     common  fgetxattr               sys_fgetxattr\n244     common  listxattr               sys_listxattr\n245     common  llistxattr              sys_llistxattr\n246     common  flistxattr              sys_flistxattr\n247     common  removexattr             sys_removexattr\n248     common  lremovexattr            sys_lremovexattr\n249     common  fremovexattr            sys_fremovexattr\n250     common  timer_create            sys_timer_create                compat_sys_timer_create\n251     32      timer_settime           sys_timer_settime32\n251     64      timer_settime           sys_timer_settime\n252     32      timer_gettime           sys_timer_gettime32\n252     64      timer_gettime           sys_timer_gettime\n253     common  timer_getoverrun        sys_timer_getoverrun\n254     common  timer_delete            sys_timer_delete\n255     32      clock_settime           sys_clock_settime32\n255     64      clock_settime           sys_clock_settime\n256     32      clock_gettime           sys_clock_gettime32\n256     64      clock_gettime           sys_clock_gettime\n257     32      clock_getres            sys_clock_getres_time32\n257     64      clock_getres            sys_clock_getres\n258     32      clock_nanosleep         sys_clock_nanosleep_time32\n258     64      clock_nanosleep         sys_clock_nanosleep\n259     common  tgkill                  sys_tgkill\n260     common  mbind                   sys_mbind\n261     common  get_mempolicy           sys_get_mempolicy\n262     common  set_mempolicy           sys_set_mempolicy\n264     common  add_key                 sys_add_key\n265     common  request_key             sys_request_key\n266     common  keyctl                  sys_keyctl                      compat_sys_keyctl\n267     common  ioprio_set              sys_ioprio_set\n268     common  ioprio_get              sys_ioprio_get\n269     common  inotify_init            sys_inotify_init\n270     common  inotify_add_watch       sys_inotify_add_watch\n271     common  inotify_rm_watch        sys_inotify_rm_watch\n272     common  migrate_pages           sys_migrate_pages\n273     32      pselect6                sys_pselect6_time32             compat_sys_pselect6_time32\n273     64      pselect6                sys_pselect6\n274     32      ppoll                   sys_ppoll_time32                compat_sys_ppoll_time32\n274     64      ppoll                   sys_ppoll\n275     common  openat                  sys_openat                      compat_sys_openat\n276     common  mkdirat                 sys_mkdirat\n277     common  mknodat                 sys_mknodat\n278     common  fchownat                sys_fchownat\n279     32      futimesat               sys_futimesat_time32\n279     64      futimesat               sys_futimesat\n280     common  fstatat64               sys_fstatat64\n281     common  unlinkat                sys_unlinkat\n282     common  renameat                sys_renameat\n283     common  linkat                  sys_linkat\n284     common  symlinkat               sys_symlinkat\n285     common  readlinkat              sys_readlinkat\n286     common  fchmodat                sys_fchmodat\n287     common  faccessat               sys_faccessat\n288     common  unshare                 sys_unshare\n289     common  set_robust_list         sys_set_robust_list             compat_sys_set_robust_list\n290     common  get_robust_list         sys_get_robust_list             compat_sys_get_robust_list\n291     common  splice                  sys_splice\n292     32      sync_file_range         parisc_sync_file_range\n292     64      sync_file_range         sys_sync_file_range\n293     common  tee                     sys_tee\n294     common  vmsplice                sys_vmsplice\n295     common  move_pages              sys_move_pages\n296     common  getcpu                  sys_getcpu\n297     common  epoll_pwait             sys_epoll_pwait                 compat_sys_epoll_pwait\n298     common  statfs64                sys_statfs64                    compat_sys_statfs64\n299     common  fstatfs64               sys_fstatfs64                   compat_sys_fstatfs64\n300     common  kexec_load              sys_kexec_load                  compat_sys_kexec_load\n301     32      utimensat               sys_utimensat_time32\n301     64      utimensat               sys_utimensat\n302     common  signalfd                sys_signalfd                    compat_sys_signalfd\n304     common  eventfd                 sys_eventfd\n305     32      fallocate               parisc_fallocate\n305     64      fallocate               sys_fallocate\n306     common  timerfd_create          parisc_timerfd_create\n307     32      timerfd_settime         sys_timerfd_settime32\n307     64      timerfd_settime         sys_timerfd_settime\n308     32      timerfd_gettime         sys_timerfd_gettime32\n308     64      timerfd_gettime         sys_timerfd_gettime\n309     common  signalfd4               parisc_signalfd4                parisc_compat_signalfd4\n310     common  eventfd2                parisc_eventfd2\n311     common  epoll_create1           sys_epoll_create1\n312     common  dup3                    sys_dup3\n313     common  pipe2                   parisc_pipe2\n314     common  inotify_init1           parisc_inotify_init1\n315     common  preadv  sys_preadv      compat_sys_preadv\n316     common  pwritev sys_pwritev     compat_sys_pwritev\n317     common  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo\n318     common  perf_event_open         sys_perf_event_open\n319     32      recvmmsg                sys_recvmmsg_time32             compat_sys_recvmmsg_time32\n319     64      recvmmsg                sys_recvmmsg\n320     common  accept4                 sys_accept4\n321     common  prlimit64               sys_prlimit64\n322     common  fanotify_init           sys_fanotify_init\n323     common  fanotify_mark           sys_fanotify_mark               compat_sys_fanotify_mark\n324     32      clock_adjtime           sys_clock_adjtime32\n324     64      clock_adjtime           sys_clock_adjtime\n325     common  name_to_handle_at       sys_name_to_handle_at\n326     common  open_by_handle_at       sys_open_by_handle_at           compat_sys_open_by_handle_at\n327     common  syncfs                  sys_syncfs\n328     common  setns                   sys_setns\n329     common  sendmmsg                sys_sendmmsg                    compat_sys_sendmmsg\n330     common  process_vm_readv        sys_process_vm_readv\n331     common  process_vm_writev       sys_process_vm_writev\n332     common  kcmp                    sys_kcmp\n333     common  finit_module            sys_finit_module\n334     common  sched_setattr           sys_sched_setattr\n335     common  sched_getattr           sys_sched_getattr\n336     32      utimes                  sys_utimes_time32\n336     64      utimes                  sys_utimes\n337     common  renameat2               sys_renameat2\n338     common  seccomp                 sys_seccomp\n339     common  getrandom               sys_getrandom\n340     common  memfd_create            sys_memfd_create\n341     common  bpf                     sys_bpf\n342     common  execveat                sys_execveat                    compat_sys_execveat\n343     common  membarrier              sys_membarrier\n344     common  userfaultfd             parisc_userfaultfd\n345     common  mlock2                  sys_mlock2\n346     common  copy_file_range         sys_copy_file_range\n347     common  preadv2                 sys_preadv2                     compat_sys_preadv2\n348     common  pwritev2                sys_pwritev2                    compat_sys_pwritev2\n349     common  statx                   sys_statx\n350     32      io_pgetevents           sys_io_pgetevents_time32        compat_sys_io_pgetevents\n350     64      io_pgetevents           sys_io_pgetevents\n351     common  pkey_mprotect           sys_pkey_mprotect\n352     common  pkey_alloc              sys_pkey_alloc\n353     common  pkey_free               sys_pkey_free\n354     common  rseq                    sys_rseq\n355     common  kexec_file_load         sys_kexec_file_load             sys_kexec_file_load\n356     common  cacheflush              sys_cacheflush\n403     32      clock_gettime64                 sys_clock_gettime               sys_clock_gettime\n404     32      clock_settime64                 sys_clock_settime               sys_clock_settime\n405     32      clock_adjtime64                 sys_clock_adjtime               sys_clock_adjtime\n406     32      clock_getres_time64             sys_clock_getres                sys_clock_getres\n407     32      clock_nanosleep_time64          sys_clock_nanosleep             sys_clock_nanosleep\n408     32      timer_gettime64                 sys_timer_gettime               sys_timer_gettime\n409     32      timer_settime64                 sys_timer_settime               sys_timer_settime\n410     32      timerfd_gettime64               sys_timerfd_gettime             sys_timerfd_gettime\n411     32      timerfd_settime64               sys_timerfd_settime             sys_timerfd_settime\n412     32      utimensat_time64                sys_utimensat                   sys_utimensat\n413     32      pselect6_time64                 sys_pselect6                    compat_sys_pselect6_time64\n414     32      ppoll_time64                    sys_ppoll                       compat_sys_ppoll_time64\n416     32      io_pgetevents_time64            sys_io_pgetevents               compat_sys_io_pgetevents_time64\n417     32      recvmmsg_time64                 sys_recvmmsg                    compat_sys_recvmmsg_time64\n418     32      mq_timedsend_time64             sys_mq_timedsend                sys_mq_timedsend\n419     32      mq_timedreceive_time64          sys_mq_timedreceive             sys_mq_timedreceive\n420     32      semtimedop_time64               sys_semtimedop                  sys_semtimedop\n421     32      rt_sigtimedwait_time64          sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait_time64\n422     32      futex_time64                    sys_futex                       sys_futex\n423     32      sched_rr_get_interval_time64    sys_sched_rr_get_interval       sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3_wrapper\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# OpenRISC\nor1k_syscall_tbl = arm64_syscall_tbl\n\n\n# Nios II\nnios2_syscall_tbl = arm64_syscall_tbl\n\n\n# MicroBlaze\n# - arch/microblaze/kernel/syscalls/syscall.tbl\nmicroblaze_syscall_tbl = \"\"\"\n0       common  restart_syscall                 sys_restart_syscall\n1       common  exit                            sys_exit\n2       common  fork                            sys_fork\n3       common  read                            sys_read\n4       common  write                           sys_write\n5       common  open                            sys_open\n6       common  close                           sys_close\n7       common  waitpid                         sys_waitpid\n8       common  creat                           sys_creat\n9       common  link                            sys_link\n10      common  unlink                          sys_unlink\n11      common  execve                          sys_execve\n12      common  chdir                           sys_chdir\n13      common  time                            sys_time32\n14      common  mknod                           sys_mknod\n15      common  chmod                           sys_chmod\n16      common  lchown                          sys_lchown\n17      common  break                           sys_ni_syscall\n18      common  oldstat                         sys_ni_syscall\n19      common  lseek                           sys_lseek\n20      common  getpid                          sys_getpid\n21      common  mount                           sys_mount\n22      common  umount                          sys_oldumount\n23      common  setuid                          sys_setuid\n24      common  getuid                          sys_getuid\n25      common  stime                           sys_stime32\n26      common  ptrace                          sys_ptrace\n27      common  alarm                           sys_alarm\n28      common  oldfstat                        sys_ni_syscall\n29      common  pause                           sys_pause\n30      common  utime                           sys_utime32\n31      common  stty                            sys_ni_syscall\n32      common  gtty                            sys_ni_syscall\n33      common  access                          sys_access\n34      common  nice                            sys_nice\n35      common  ftime                           sys_ni_syscall\n36      common  sync                            sys_sync\n37      common  kill                            sys_kill\n38      common  rename                          sys_rename\n39      common  mkdir                           sys_mkdir\n40      common  rmdir                           sys_rmdir\n41      common  dup                             sys_dup\n42      common  pipe                            sys_pipe\n43      common  times                           sys_times\n44      common  prof                            sys_ni_syscall\n45      common  brk                             sys_brk\n46      common  setgid                          sys_setgid\n47      common  getgid                          sys_getgid\n48      common  signal                          sys_signal\n49      common  geteuid                         sys_geteuid\n50      common  getegid                         sys_getegid\n51      common  acct                            sys_acct\n52      common  umount2                         sys_umount\n53      common  lock                            sys_ni_syscall\n54      common  ioctl                           sys_ioctl\n55      common  fcntl                           sys_fcntl\n56      common  mpx                             sys_ni_syscall\n57      common  setpgid                         sys_setpgid\n58      common  ulimit                          sys_ni_syscall\n59      common  oldolduname                     sys_ni_syscall\n60      common  umask                           sys_umask\n61      common  chroot                          sys_chroot\n62      common  ustat                           sys_ustat\n63      common  dup2                            sys_dup2\n64      common  getppid                         sys_getppid\n65      common  getpgrp                         sys_getpgrp\n66      common  setsid                          sys_setsid\n67      common  sigaction                       sys_ni_syscall\n68      common  sgetmask                        sys_sgetmask\n69      common  ssetmask                        sys_ssetmask\n70      common  setreuid                        sys_setreuid\n71      common  setregid                        sys_setregid\n72      common  sigsuspend                      sys_ni_syscall\n73      common  sigpending                      sys_sigpending\n74      common  sethostname                     sys_sethostname\n75      common  setrlimit                       sys_setrlimit\n76      common  getrlimit                       sys_ni_syscall\n77      common  getrusage                       sys_getrusage\n78      common  gettimeofday                    sys_gettimeofday\n79      common  settimeofday                    sys_settimeofday\n80      common  getgroups                       sys_getgroups\n81      common  setgroups                       sys_setgroups\n82      common  select                          sys_ni_syscall\n83      common  symlink                         sys_symlink\n84      common  oldlstat                        sys_ni_syscall\n85      common  readlink                        sys_readlink\n86      common  uselib                          sys_uselib\n87      common  swapon                          sys_swapon\n88      common  reboot                          sys_reboot\n89      common  readdir                         sys_ni_syscall\n90      common  mmap                            sys_mmap\n91      common  munmap                          sys_munmap\n92      common  truncate                        sys_truncate\n93      common  ftruncate                       sys_ftruncate\n94      common  fchmod                          sys_fchmod\n95      common  fchown                          sys_fchown\n96      common  getpriority                     sys_getpriority\n97      common  setpriority                     sys_setpriority\n98      common  profil                          sys_ni_syscall\n99      common  statfs                          sys_statfs\n100     common  fstatfs                         sys_fstatfs\n101     common  ioperm                          sys_ni_syscall\n102     common  socketcall                      sys_socketcall\n103     common  syslog                          sys_syslog\n104     common  setitimer                       sys_setitimer\n105     common  getitimer                       sys_getitimer\n106     common  stat                            sys_newstat\n107     common  lstat                           sys_newlstat\n108     common  fstat                           sys_newfstat\n109     common  olduname                        sys_ni_syscall\n110     common  iopl                            sys_ni_syscall\n111     common  vhangup                         sys_vhangup\n112     common  idle                            sys_ni_syscall\n113     common  vm86old                         sys_ni_syscall\n114     common  wait4                           sys_wait4\n115     common  swapoff                         sys_swapoff\n116     common  sysinfo                         sys_sysinfo\n117     common  ipc                             sys_ni_syscall\n118     common  fsync                           sys_fsync\n119     common  sigreturn                       sys_ni_syscall\n120     common  clone                           sys_clone\n121     common  setdomainname                   sys_setdomainname\n122     common  uname                           sys_newuname\n123     common  modify_ldt                      sys_ni_syscall\n124     common  adjtimex                        sys_adjtimex_time32\n125     common  mprotect                        sys_mprotect\n126     common  sigprocmask                     sys_sigprocmask\n127     common  create_module                   sys_ni_syscall\n128     common  init_module                     sys_init_module\n129     common  delete_module                   sys_delete_module\n130     common  get_kernel_syms                 sys_ni_syscall\n131     common  quotactl                        sys_quotactl\n132     common  getpgid                         sys_getpgid\n133     common  fchdir                          sys_fchdir\n134     common  bdflush                         sys_ni_syscall\n135     common  sysfs                           sys_sysfs\n136     common  personality                     sys_personality\n137     common  afs_syscall                     sys_ni_syscall\n138     common  setfsuid                        sys_setfsuid\n139     common  setfsgid                        sys_setfsgid\n140     common  _llseek                         sys_llseek\n141     common  getdents                        sys_getdents\n142     common  _newselect                      sys_select\n143     common  flock                           sys_flock\n144     common  msync                           sys_msync\n145     common  readv                           sys_readv\n146     common  writev                          sys_writev\n147     common  getsid                          sys_getsid\n148     common  fdatasync                       sys_fdatasync\n149     common  _sysctl                         sys_ni_syscall\n150     common  mlock                           sys_mlock\n151     common  munlock                         sys_munlock\n152     common  mlockall                        sys_mlockall\n153     common  munlockall                      sys_munlockall\n154     common  sched_setparam                  sys_sched_setparam\n155     common  sched_getparam                  sys_sched_getparam\n156     common  sched_setscheduler              sys_sched_setscheduler\n157     common  sched_getscheduler              sys_sched_getscheduler\n158     common  sched_yield                     sys_sched_yield\n159     common  sched_get_priority_max          sys_sched_get_priority_max\n160     common  sched_get_priority_min          sys_sched_get_priority_min\n161     common  sched_rr_get_interval           sys_sched_rr_get_interval_time32\n162     common  nanosleep                       sys_nanosleep_time32\n163     common  mremap                          sys_mremap\n164     common  setresuid                       sys_setresuid\n165     common  getresuid                       sys_getresuid\n166     common  vm86                            sys_ni_syscall\n167     common  query_module                    sys_ni_syscall\n168     common  poll                            sys_poll\n169     common  nfsservctl                      sys_ni_syscall\n170     common  setresgid                       sys_setresgid\n171     common  getresgid                       sys_getresgid\n172     common  prctl                           sys_prctl\n173     common  rt_sigreturn                    sys_rt_sigreturn_wrapper\n174     common  rt_sigaction                    sys_rt_sigaction\n175     common  rt_sigprocmask                  sys_rt_sigprocmask\n176     common  rt_sigpending                   sys_rt_sigpending\n177     common  rt_sigtimedwait                 sys_rt_sigtimedwait_time32\n178     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n179     common  rt_sigsuspend                   sys_rt_sigsuspend\n180     common  pread64                         sys_pread64\n181     common  pwrite64                        sys_pwrite64\n182     common  chown                           sys_chown\n183     common  getcwd                          sys_getcwd\n184     common  capget                          sys_capget\n185     common  capset                          sys_capset\n186     common  sigaltstack                     sys_ni_syscall\n187     common  sendfile                        sys_sendfile\n188     common  getpmsg                         sys_ni_syscall\n189     common  putpmsg                         sys_ni_syscall\n190     common  vfork                           sys_vfork\n191     common  ugetrlimit                      sys_getrlimit\n192     common  mmap2                           sys_mmap2\n193     common  truncate64                      sys_truncate64\n194     common  ftruncate64                     sys_ftruncate64\n195     common  stat64                          sys_stat64\n196     common  lstat64                         sys_lstat64\n197     common  fstat64                         sys_fstat64\n198     common  lchown32                        sys_lchown\n199     common  getuid32                        sys_getuid\n200     common  getgid32                        sys_getgid\n201     common  geteuid32                       sys_geteuid\n202     common  getegid32                       sys_getegid\n203     common  setreuid32                      sys_setreuid\n204     common  setregid32                      sys_setregid\n205     common  getgroups32                     sys_getgroups\n206     common  setgroups32                     sys_setgroups\n207     common  fchown32                        sys_fchown\n208     common  setresuid32                     sys_setresuid\n209     common  getresuid32                     sys_getresuid\n210     common  setresgid32                     sys_setresgid\n211     common  getresgid32                     sys_getresgid\n212     common  chown32                         sys_chown\n213     common  setuid32                        sys_setuid\n214     common  setgid32                        sys_setgid\n215     common  setfsuid32                      sys_setfsuid\n216     common  setfsgid32                      sys_setfsgid\n217     common  pivot_root                      sys_pivot_root\n218     common  mincore                         sys_mincore\n219     common  madvise                         sys_madvise\n220     common  getdents64                      sys_getdents64\n221     common  fcntl64                         sys_fcntl64\n224     common  gettid                          sys_gettid\n225     common  readahead                       sys_readahead\n226     common  setxattr                        sys_setxattr\n227     common  lsetxattr                       sys_lsetxattr\n228     common  fsetxattr                       sys_fsetxattr\n229     common  getxattr                        sys_getxattr\n230     common  lgetxattr                       sys_lgetxattr\n231     common  fgetxattr                       sys_fgetxattr\n232     common  listxattr                       sys_listxattr\n233     common  llistxattr                      sys_llistxattr\n234     common  flistxattr                      sys_flistxattr\n235     common  removexattr                     sys_removexattr\n236     common  lremovexattr                    sys_lremovexattr\n237     common  fremovexattr                    sys_fremovexattr\n238     common  tkill                           sys_tkill\n239     common  sendfile64                      sys_sendfile64\n240     common  futex                           sys_futex_time32\n241     common  sched_setaffinity               sys_sched_setaffinity\n242     common  sched_getaffinity               sys_sched_getaffinity\n243     common  set_thread_area                 sys_ni_syscall\n244     common  get_thread_area                 sys_ni_syscall\n245     common  io_setup                        sys_io_setup\n246     common  io_destroy                      sys_io_destroy\n247     common  io_getevents                    sys_io_getevents_time32\n248     common  io_submit                       sys_io_submit\n249     common  io_cancel                       sys_io_cancel\n250     common  fadvise64                       sys_fadvise64\n252     common  exit_group                      sys_exit_group\n253     common  lookup_dcookie                  sys_ni_syscall\n254     common  epoll_create                    sys_epoll_create\n255     common  epoll_ctl                       sys_epoll_ctl\n256     common  epoll_wait                      sys_epoll_wait\n257     common  remap_file_pages                sys_remap_file_pages\n258     common  set_tid_address                 sys_set_tid_address\n259     common  timer_create                    sys_timer_create\n260     common  timer_settime                   sys_timer_settime32\n261     common  timer_gettime                   sys_timer_gettime32\n262     common  timer_getoverrun                sys_timer_getoverrun\n263     common  timer_delete                    sys_timer_delete\n264     common  clock_settime                   sys_clock_settime32\n265     common  clock_gettime                   sys_clock_gettime32\n266     common  clock_getres                    sys_clock_getres_time32\n267     common  clock_nanosleep                 sys_clock_nanosleep_time32\n268     common  statfs64                        sys_statfs64\n269     common  fstatfs64                       sys_fstatfs64\n270     common  tgkill                          sys_tgkill\n271     common  utimes                          sys_utimes_time32\n272     common  fadvise64_64                    sys_fadvise64_64\n273     common  vserver                         sys_ni_syscall\n274     common  mbind                           sys_mbind\n275     common  get_mempolicy                   sys_get_mempolicy\n276     common  set_mempolicy                   sys_set_mempolicy\n277     common  mq_open                         sys_mq_open\n278     common  mq_unlink                       sys_mq_unlink\n279     common  mq_timedsend                    sys_mq_timedsend_time32\n280     common  mq_timedreceive                 sys_mq_timedreceive_time32\n281     common  mq_notify                       sys_mq_notify\n282     common  mq_getsetattr                   sys_mq_getsetattr\n283     common  kexec_load                      sys_kexec_load\n284     common  waitid                          sys_waitid\n286     common  add_key                         sys_add_key\n287     common  request_key                     sys_request_key\n288     common  keyctl                          sys_keyctl\n289     common  ioprio_set                      sys_ioprio_set\n290     common  ioprio_get                      sys_ioprio_get\n291     common  inotify_init                    sys_inotify_init\n292     common  inotify_add_watch               sys_inotify_add_watch\n293     common  inotify_rm_watch                sys_inotify_rm_watch\n294     common  migrate_pages                   sys_ni_syscall\n295     common  openat                          sys_openat\n296     common  mkdirat                         sys_mkdirat\n297     common  mknodat                         sys_mknodat\n298     common  fchownat                        sys_fchownat\n299     common  futimesat                       sys_futimesat_time32\n300     common  fstatat64                       sys_fstatat64\n301     common  unlinkat                        sys_unlinkat\n302     common  renameat                        sys_renameat\n303     common  linkat                          sys_linkat\n304     common  symlinkat                       sys_symlinkat\n305     common  readlinkat                      sys_readlinkat\n306     common  fchmodat                        sys_fchmodat\n307     common  faccessat                       sys_faccessat\n308     common  pselect6                        sys_pselect6_time32\n309     common  ppoll                           sys_ppoll_time32\n310     common  unshare                         sys_unshare\n311     common  set_robust_list                 sys_set_robust_list\n312     common  get_robust_list                 sys_get_robust_list\n313     common  splice                          sys_splice\n314     common  sync_file_range                 sys_sync_file_range\n315     common  tee                             sys_tee\n316     common  vmsplice                        sys_vmsplice\n317     common  move_pages                      sys_move_pages\n318     common  getcpu                          sys_getcpu\n319     common  epoll_pwait                     sys_epoll_pwait\n320     common  utimensat                       sys_utimensat_time32\n321     common  signalfd                        sys_signalfd\n322     common  timerfd_create                  sys_timerfd_create\n323     common  eventfd                         sys_eventfd\n324     common  fallocate                       sys_fallocate\n325     common  semtimedop                      sys_semtimedop_time32\n326     common  timerfd_settime                 sys_timerfd_settime32\n327     common  timerfd_gettime                 sys_timerfd_gettime32\n328     common  semctl                          sys_old_semctl\n329     common  semget                          sys_semget\n330     common  semop                           sys_semop\n331     common  msgctl                          sys_old_msgctl\n332     common  msgget                          sys_msgget\n333     common  msgrcv                          sys_msgrcv\n334     common  msgsnd                          sys_msgsnd\n335     common  shmat                           sys_shmat\n336     common  shmctl                          sys_old_shmctl\n337     common  shmdt                           sys_shmdt\n338     common  shmget                          sys_shmget\n339     common  signalfd4                       sys_signalfd4\n340     common  eventfd2                        sys_eventfd2\n341     common  epoll_create1                   sys_epoll_create1\n342     common  dup3                            sys_dup3\n343     common  pipe2                           sys_pipe2\n344     common  inotify_init1                   sys_inotify_init1\n345     common  socket                          sys_socket\n346     common  socketpair                      sys_socketpair\n347     common  bind                            sys_bind\n348     common  listen                          sys_listen\n349     common  accept                          sys_accept\n350     common  connect                         sys_connect\n351     common  getsockname                     sys_getsockname\n352     common  getpeername                     sys_getpeername\n353     common  sendto                          sys_sendto\n354     common  send                            sys_send\n355     common  recvfrom                        sys_recvfrom\n356     common  recv                            sys_recv\n357     common  setsockopt                      sys_setsockopt\n358     common  getsockopt                      sys_getsockopt\n359     common  shutdown                        sys_shutdown\n360     common  sendmsg                         sys_sendmsg\n361     common  recvmsg                         sys_recvmsg\n362     common  accept4                         sys_accept4\n363     common  preadv                          sys_preadv\n364     common  pwritev                         sys_pwritev\n365     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n366     common  perf_event_open                 sys_perf_event_open\n367     common  recvmmsg                        sys_recvmmsg_time32\n368     common  fanotify_init                   sys_fanotify_init\n369     common  fanotify_mark                   sys_fanotify_mark\n370     common  prlimit64                       sys_prlimit64\n371     common  name_to_handle_at               sys_name_to_handle_at\n372     common  open_by_handle_at               sys_open_by_handle_at\n373     common  clock_adjtime                   sys_clock_adjtime32\n374     common  syncfs                          sys_syncfs\n375     common  setns                           sys_setns\n376     common  sendmmsg                        sys_sendmmsg\n377     common  process_vm_readv                sys_process_vm_readv\n378     common  process_vm_writev               sys_process_vm_writev\n379     common  kcmp                            sys_kcmp\n380     common  finit_module                    sys_finit_module\n381     common  sched_setattr                   sys_sched_setattr\n382     common  sched_getattr                   sys_sched_getattr\n383     common  renameat2                       sys_renameat2\n384     common  seccomp                         sys_seccomp\n385     common  getrandom                       sys_getrandom\n386     common  memfd_create                    sys_memfd_create\n387     common  bpf                             sys_bpf\n388     common  execveat                        sys_execveat\n389     common  userfaultfd                     sys_userfaultfd\n390     common  membarrier                      sys_membarrier\n391     common  mlock2                          sys_mlock2\n392     common  copy_file_range                 sys_copy_file_range\n393     common  preadv2                         sys_preadv2\n394     common  pwritev2                        sys_pwritev2\n395     common  pkey_mprotect                   sys_pkey_mprotect\n396     common  pkey_alloc                      sys_pkey_alloc\n397     common  pkey_free                       sys_pkey_free\n398     common  statx                           sys_statx\n399     common  io_pgetevents                   sys_io_pgetevents_time32\n400     common  rseq                            sys_rseq\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6\n414     common  ppoll_time64                    sys_ppoll\n416     common  io_pgetevents_time64            sys_io_pgetevents\n417     common  recvmmsg_time64                 sys_recvmmsg\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# Xtensa\n# arch/xtensa/kernel/syscalls/syscall.tbl\nxtensa_syscall_tbl = \"\"\"\n0       common  spill                           sys_ni_syscall\n1       common  xtensa                          sys_ni_syscall\n2       common  available4                      sys_ni_syscall\n3       common  available5                      sys_ni_syscall\n4       common  available6                      sys_ni_syscall\n5       common  available7                      sys_ni_syscall\n6       common  available8                      sys_ni_syscall\n7       common  available9                      sys_ni_syscall\n8       common  open                            sys_open\n9       common  close                           sys_close\n10      common  dup                             sys_dup\n11      common  dup2                            sys_dup2\n12      common  read                            sys_read\n13      common  write                           sys_write\n14      common  select                          sys_select\n15      common  lseek                           sys_lseek\n16      common  poll                            sys_poll\n17      common  _llseek                         sys_llseek\n18      common  epoll_wait                      sys_epoll_wait\n19      common  epoll_ctl                       sys_epoll_ctl\n20      common  epoll_create                    sys_epoll_create\n21      common  creat                           sys_creat\n22      common  truncate                        sys_truncate\n23      common  ftruncate                       sys_ftruncate\n24      common  readv                           sys_readv\n25      common  writev                          sys_writev\n26      common  fsync                           sys_fsync\n27      common  fdatasync                       sys_fdatasync\n28      common  truncate64                      sys_truncate64\n29      common  ftruncate64                     sys_ftruncate64\n30      common  pread64                         sys_pread64\n31      common  pwrite64                        sys_pwrite64\n32      common  link                            sys_link\n33      common  rename                          sys_rename\n34      common  symlink                         sys_symlink\n35      common  readlink                        sys_readlink\n36      common  mknod                           sys_mknod\n37      common  pipe                            sys_pipe\n38      common  unlink                          sys_unlink\n39      common  rmdir                           sys_rmdir\n40      common  mkdir                           sys_mkdir\n41      common  chdir                           sys_chdir\n42      common  fchdir                          sys_fchdir\n43      common  getcwd                          sys_getcwd\n44      common  chmod                           sys_chmod\n45      common  chown                           sys_chown\n46      common  stat                            sys_newstat\n47      common  stat64                          sys_stat64\n48      common  lchown                          sys_lchown\n49      common  lstat                           sys_newlstat\n50      common  lstat64                         sys_lstat64\n51      common  available51                     sys_ni_syscall\n52      common  fchmod                          sys_fchmod\n53      common  fchown                          sys_fchown\n54      common  fstat                           sys_newfstat\n55      common  fstat64                         sys_fstat64\n56      common  flock                           sys_flock\n57      common  access                          sys_access\n58      common  umask                           sys_umask\n59      common  getdents                        sys_getdents\n60      common  getdents64                      sys_getdents64\n61      common  fcntl64                         sys_fcntl64\n62      common  fallocate                       sys_fallocate\n63      common  fadvise64_64                    xtensa_fadvise64_64\n64      common  utime                           sys_utime32\n65      common  utimes                          sys_utimes_time32\n66      common  ioctl                           sys_ioctl\n67      common  fcntl                           sys_fcntl\n68      common  setxattr                        sys_setxattr\n69      common  getxattr                        sys_getxattr\n70      common  listxattr                       sys_listxattr\n71      common  removexattr                     sys_removexattr\n72      common  lsetxattr                       sys_lsetxattr\n73      common  lgetxattr                       sys_lgetxattr\n74      common  llistxattr                      sys_llistxattr\n75      common  lremovexattr                    sys_lremovexattr\n76      common  fsetxattr                       sys_fsetxattr\n77      common  fgetxattr                       sys_fgetxattr\n78      common  flistxattr                      sys_flistxattr\n79      common  fremovexattr                    sys_fremovexattr\n80      common  mmap2                           sys_mmap_pgoff\n81      common  munmap                          sys_munmap\n82      common  mprotect                        sys_mprotect\n83      common  brk                             sys_brk\n84      common  mlock                           sys_mlock\n85      common  munlock                         sys_munlock\n86      common  mlockall                        sys_mlockall\n87      common  munlockall                      sys_munlockall\n88      common  mremap                          sys_mremap\n89      common  msync                           sys_msync\n90      common  mincore                         sys_mincore\n91      common  madvise                         sys_madvise\n92      common  shmget                          sys_shmget\n93      common  shmat                           xtensa_shmat\n94      common  shmctl                          sys_old_shmctl\n95      common  shmdt                           sys_shmdt\n96      common  socket                          sys_socket\n97      common  setsockopt                      sys_setsockopt\n98      common  getsockopt                      sys_getsockopt\n99      common  shutdown                        sys_shutdown\n100     common  bind                            sys_bind\n101     common  connect                         sys_connect\n102     common  listen                          sys_listen\n103     common  accept                          sys_accept\n104     common  getsockname                     sys_getsockname\n105     common  getpeername                     sys_getpeername\n106     common  sendmsg                         sys_sendmsg\n107     common  recvmsg                         sys_recvmsg\n108     common  send                            sys_send\n109     common  recv                            sys_recv\n110     common  sendto                          sys_sendto\n111     common  recvfrom                        sys_recvfrom\n112     common  socketpair                      sys_socketpair\n113     common  sendfile                        sys_sendfile\n114     common  sendfile64                      sys_sendfile64\n115     common  sendmmsg                        sys_sendmmsg\n116     common  clone                           sys_clone\n117     common  execve                          sys_execve\n118     common  exit                            sys_exit\n119     common  exit_group                      sys_exit_group\n120     common  getpid                          sys_getpid\n121     common  wait4                           sys_wait4\n122     common  waitid                          sys_waitid\n123     common  kill                            sys_kill\n124     common  tkill                           sys_tkill\n125     common  tgkill                          sys_tgkill\n126     common  set_tid_address                 sys_set_tid_address\n127     common  gettid                          sys_gettid\n128     common  setsid                          sys_setsid\n129     common  getsid                          sys_getsid\n130     common  prctl                           sys_prctl\n131     common  personality                     sys_personality\n132     common  getpriority                     sys_getpriority\n133     common  setpriority                     sys_setpriority\n134     common  setitimer                       sys_setitimer\n135     common  getitimer                       sys_getitimer\n136     common  setuid                          sys_setuid\n137     common  getuid                          sys_getuid\n138     common  setgid                          sys_setgid\n139     common  getgid                          sys_getgid\n140     common  geteuid                         sys_geteuid\n141     common  getegid                         sys_getegid\n142     common  setreuid                        sys_setreuid\n143     common  setregid                        sys_setregid\n144     common  setresuid                       sys_setresuid\n145     common  getresuid                       sys_getresuid\n146     common  setresgid                       sys_setresgid\n147     common  getresgid                       sys_getresgid\n148     common  setpgid                         sys_setpgid\n149     common  getpgid                         sys_getpgid\n150     common  getppid                         sys_getppid\n151     common  getpgrp                         sys_getpgrp\n152     common  reserved152                     sys_ni_syscall\n153     common  reserved153                     sys_ni_syscall\n154     common  times                           sys_times\n155     common  acct                            sys_acct\n156     common  sched_setaffinity               sys_sched_setaffinity\n157     common  sched_getaffinity               sys_sched_getaffinity\n158     common  capget                          sys_capget\n159     common  capset                          sys_capset\n160     common  ptrace                          sys_ptrace\n161     common  semtimedop                      sys_semtimedop_time32\n162     common  semget                          sys_semget\n163     common  semop                           sys_semop\n164     common  semctl                          sys_old_semctl\n165     common  available165                    sys_ni_syscall\n166     common  msgget                          sys_msgget\n167     common  msgsnd                          sys_msgsnd\n168     common  msgrcv                          sys_msgrcv\n169     common  msgctl                          sys_old_msgctl\n170     common  available170                    sys_ni_syscall\n171     common  umount2                         sys_umount\n172     common  mount                           sys_mount\n173     common  swapon                          sys_swapon\n174     common  chroot                          sys_chroot\n175     common  pivot_root                      sys_pivot_root\n176     common  umount                          sys_oldumount\n177     common  swapoff                         sys_swapoff\n178     common  sync                            sys_sync\n179     common  syncfs                          sys_syncfs\n180     common  setfsuid                        sys_setfsuid\n181     common  setfsgid                        sys_setfsgid\n182     common  sysfs                           sys_sysfs\n183     common  ustat                           sys_ustat\n184     common  statfs                          sys_statfs\n185     common  fstatfs                         sys_fstatfs\n186     common  statfs64                        sys_statfs64\n187     common  fstatfs64                       sys_fstatfs64\n188     common  setrlimit                       sys_setrlimit\n189     common  getrlimit                       sys_getrlimit\n190     common  getrusage                       sys_getrusage\n191     common  futex                           sys_futex_time32\n192     common  gettimeofday                    sys_gettimeofday\n193     common  settimeofday                    sys_settimeofday\n194     common  adjtimex                        sys_adjtimex_time32\n195     common  nanosleep                       sys_nanosleep_time32\n196     common  getgroups                       sys_getgroups\n197     common  setgroups                       sys_setgroups\n198     common  sethostname                     sys_sethostname\n199     common  setdomainname                   sys_setdomainname\n200     common  syslog                          sys_syslog\n201     common  vhangup                         sys_vhangup\n202     common  uselib                          sys_uselib\n203     common  reboot                          sys_reboot\n204     common  quotactl                        sys_quotactl\n205     common  nfsservctl                      sys_ni_syscall\n206     common  _sysctl                         sys_ni_syscall\n207     common  bdflush                         sys_ni_syscall\n208     common  uname                           sys_newuname\n209     common  sysinfo                         sys_sysinfo\n210     common  init_module                     sys_init_module\n211     common  delete_module                   sys_delete_module\n212     common  sched_setparam                  sys_sched_setparam\n213     common  sched_getparam                  sys_sched_getparam\n214     common  sched_setscheduler              sys_sched_setscheduler\n215     common  sched_getscheduler              sys_sched_getscheduler\n216     common  sched_get_priority_max          sys_sched_get_priority_max\n217     common  sched_get_priority_min          sys_sched_get_priority_min\n218     common  sched_rr_get_interval           sys_sched_rr_get_interval_time32\n219     common  sched_yield                     sys_sched_yield\n222     common  available222                    sys_ni_syscall\n223     common  restart_syscall                 sys_restart_syscall\n224     common  sigaltstack                     sys_sigaltstack\n225     common  rt_sigreturn                    xtensa_rt_sigreturn\n226     common  rt_sigaction                    sys_rt_sigaction\n227     common  rt_sigprocmask                  sys_rt_sigprocmask\n228     common  rt_sigpending                   sys_rt_sigpending\n229     common  rt_sigtimedwait                 sys_rt_sigtimedwait_time32\n230     common  rt_sigqueueinfo                 sys_rt_sigqueueinfo\n231     common  rt_sigsuspend                   sys_rt_sigsuspend\n232     common  mq_open                         sys_mq_open\n233     common  mq_unlink                       sys_mq_unlink\n234     common  mq_timedsend                    sys_mq_timedsend_time32\n235     common  mq_timedreceive                 sys_mq_timedreceive_time32\n236     common  mq_notify                       sys_mq_notify\n237     common  mq_getsetattr                   sys_mq_getsetattr\n238     common  available238                    sys_ni_syscall\n239     common  io_setup                        sys_io_setup\n240     common  io_destroy                      sys_io_destroy\n241     common  io_submit                       sys_io_submit\n242     common  io_getevents                    sys_io_getevents_time32\n243     common  io_cancel                       sys_io_cancel\n244     common  clock_settime                   sys_clock_settime32\n245     common  clock_gettime                   sys_clock_gettime32\n246     common  clock_getres                    sys_clock_getres_time32\n247     common  clock_nanosleep                 sys_clock_nanosleep_time32\n248     common  timer_create                    sys_timer_create\n249     common  timer_delete                    sys_timer_delete\n250     common  timer_settime                   sys_timer_settime32\n251     common  timer_gettime                   sys_timer_gettime32\n252     common  timer_getoverrun                sys_timer_getoverrun\n253     common  reserved253                     sys_ni_syscall\n254     common  lookup_dcookie                  sys_ni_syscall\n255     common  available255                    sys_ni_syscall\n256     common  add_key                         sys_add_key\n257     common  request_key                     sys_request_key\n258     common  keyctl                          sys_keyctl\n259     common  available259                    sys_ni_syscall\n260     common  readahead                       sys_readahead\n261     common  remap_file_pages                sys_remap_file_pages\n262     common  migrate_pages                   sys_migrate_pages\n263     common  mbind                           sys_mbind\n264     common  get_mempolicy                   sys_get_mempolicy\n265     common  set_mempolicy                   sys_set_mempolicy\n266     common  unshare                         sys_unshare\n267     common  move_pages                      sys_move_pages\n268     common  splice                          sys_splice\n269     common  tee                             sys_tee\n270     common  vmsplice                        sys_vmsplice\n271     common  available271                    sys_ni_syscall\n272     common  pselect6                        sys_pselect6_time32\n273     common  ppoll                           sys_ppoll_time32\n274     common  epoll_pwait                     sys_epoll_pwait\n275     common  epoll_create1                   sys_epoll_create1\n276     common  inotify_init                    sys_inotify_init\n277     common  inotify_add_watch               sys_inotify_add_watch\n278     common  inotify_rm_watch                sys_inotify_rm_watch\n279     common  inotify_init1                   sys_inotify_init1\n280     common  getcpu                          sys_getcpu\n281     common  kexec_load                      sys_ni_syscall\n282     common  ioprio_set                      sys_ioprio_set\n283     common  ioprio_get                      sys_ioprio_get\n284     common  set_robust_list                 sys_set_robust_list\n285     common  get_robust_list                 sys_get_robust_list\n286     common  available286                    sys_ni_syscall\n287     common  available287                    sys_ni_syscall\n288     common  openat                          sys_openat\n289     common  mkdirat                         sys_mkdirat\n290     common  mknodat                         sys_mknodat\n291     common  unlinkat                        sys_unlinkat\n292     common  renameat                        sys_renameat\n293     common  linkat                          sys_linkat\n294     common  symlinkat                       sys_symlinkat\n295     common  readlinkat                      sys_readlinkat\n296     common  utimensat                       sys_utimensat_time32\n297     common  fchownat                        sys_fchownat\n298     common  futimesat                       sys_futimesat_time32\n299     common  fstatat64                       sys_fstatat64\n300     common  fchmodat                        sys_fchmodat\n301     common  faccessat                       sys_faccessat\n302     common  available302                    sys_ni_syscall\n303     common  available303                    sys_ni_syscall\n304     common  signalfd                        sys_signalfd\n306     common  eventfd                         sys_eventfd\n307     common  recvmmsg                        sys_recvmmsg_time32\n308     common  setns                           sys_setns\n309     common  signalfd4                       sys_signalfd4\n310     common  dup3                            sys_dup3\n311     common  pipe2                           sys_pipe2\n312     common  timerfd_create                  sys_timerfd_create\n313     common  timerfd_settime                 sys_timerfd_settime32\n314     common  timerfd_gettime                 sys_timerfd_gettime32\n315     common  available315                    sys_ni_syscall\n316     common  eventfd2                        sys_eventfd2\n317     common  preadv                          sys_preadv\n318     common  pwritev                         sys_pwritev\n319     common  available319                    sys_ni_syscall\n320     common  fanotify_init                   sys_fanotify_init\n321     common  fanotify_mark                   sys_fanotify_mark\n322     common  process_vm_readv                sys_process_vm_readv\n323     common  process_vm_writev               sys_process_vm_writev\n324     common  name_to_handle_at               sys_name_to_handle_at\n325     common  open_by_handle_at               sys_open_by_handle_at\n326     common  sync_file_range2                sys_sync_file_range2\n327     common  perf_event_open                 sys_perf_event_open\n328     common  rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo\n329     common  clock_adjtime                   sys_clock_adjtime32\n330     common  prlimit64                       sys_prlimit64\n331     common  kcmp                            sys_kcmp\n332     common  finit_module                    sys_finit_module\n333     common  accept4                         sys_accept4\n334     common  sched_setattr                   sys_sched_setattr\n335     common  sched_getattr                   sys_sched_getattr\n336     common  renameat2                       sys_renameat2\n337     common  seccomp                         sys_seccomp\n338     common  getrandom                       sys_getrandom\n339     common  memfd_create                    sys_memfd_create\n340     common  bpf                             sys_bpf\n341     common  execveat                        sys_execveat\n342     common  userfaultfd                     sys_userfaultfd\n343     common  membarrier                      sys_membarrier\n344     common  mlock2                          sys_mlock2\n345     common  copy_file_range                 sys_copy_file_range\n346     common  preadv2                         sys_preadv2\n347     common  pwritev2                        sys_pwritev2\n348     common  pkey_mprotect                   sys_pkey_mprotect\n349     common  pkey_alloc                      sys_pkey_alloc\n350     common  pkey_free                       sys_pkey_free\n351     common  statx                           sys_statx\n352     common  rseq                            sys_rseq\n403     common  clock_gettime64                 sys_clock_gettime\n404     common  clock_settime64                 sys_clock_settime\n405     common  clock_adjtime64                 sys_clock_adjtime\n406     common  clock_getres_time64             sys_clock_getres\n407     common  clock_nanosleep_time64          sys_clock_nanosleep\n408     common  timer_gettime64                 sys_timer_gettime\n409     common  timer_settime64                 sys_timer_settime\n410     common  timerfd_gettime64               sys_timerfd_gettime\n411     common  timerfd_settime64               sys_timerfd_settime\n412     common  utimensat_time64                sys_utimensat\n413     common  pselect6_time64                 sys_pselect6\n414     common  ppoll_time64                    sys_ppoll\n416     common  io_pgetevents_time64            sys_io_pgetevents\n417     common  recvmmsg_time64                 sys_recvmmsg\n418     common  mq_timedsend_time64             sys_mq_timedsend\n419     common  mq_timedreceive_time64          sys_mq_timedreceive\n420     common  semtimedop_time64               sys_semtimedop\n421     common  rt_sigtimedwait_time64          sys_rt_sigtimedwait\n422     common  futex_time64                    sys_futex\n423     common  sched_rr_get_interval_time64    sys_sched_rr_get_interval\n424     common  pidfd_send_signal               sys_pidfd_send_signal\n425     common  io_uring_setup                  sys_io_uring_setup\n426     common  io_uring_enter                  sys_io_uring_enter\n427     common  io_uring_register               sys_io_uring_register\n428     common  open_tree                       sys_open_tree\n429     common  move_mount                      sys_move_mount\n430     common  fsopen                          sys_fsopen\n431     common  fsconfig                        sys_fsconfig\n432     common  fsmount                         sys_fsmount\n433     common  fspick                          sys_fspick\n434     common  pidfd_open                      sys_pidfd_open\n435     common  clone3                          sys_clone3\n436     common  close_range                     sys_close_range\n437     common  openat2                         sys_openat2\n438     common  pidfd_getfd                     sys_pidfd_getfd\n439     common  faccessat2                      sys_faccessat2\n440     common  process_madvise                 sys_process_madvise\n441     common  epoll_pwait2                    sys_epoll_pwait2\n442     common  mount_setattr                   sys_mount_setattr\n443     common  quotactl_fd                     sys_quotactl_fd\n444     common  landlock_create_ruleset         sys_landlock_create_ruleset\n445     common  landlock_add_rule               sys_landlock_add_rule\n446     common  landlock_restrict_self          sys_landlock_restrict_self\n448     common  process_mrelease                sys_process_mrelease\n449     common  futex_waitv                     sys_futex_waitv\n450     common  set_mempolicy_home_node         sys_set_mempolicy_home_node\n451     common  cachestat                       sys_cachestat\n452     common  fchmodat2                       sys_fchmodat2\n453     common  map_shadow_stack                sys_map_shadow_stack\n454     common  futex_wake                      sys_futex_wake\n455     common  futex_wait                      sys_futex_wait\n456     common  futex_requeue                   sys_futex_requeue\n457     common  statmount                       sys_statmount\n458     common  listmount                       sys_listmount\n459     common  lsm_get_self_attr               sys_lsm_get_self_attr\n460     common  lsm_set_self_attr               sys_lsm_set_self_attr\n461     common  lsm_list_modules                sys_lsm_list_modules\n462     common  mseal                           sys_mseal\n463     common  setxattrat                      sys_setxattrat\n464     common  getxattrat                      sys_getxattrat\n465     common  listxattrat                     sys_listxattrat\n466     common  removexattrat                   sys_removexattrat\n467     common  open_tree_attr                  sys_open_tree_attr\n468     common  file_getattr                    sys_file_getattr\n469     common  file_setattr                    sys_file_setattr\n470     common  listns                          sys_listns\n\"\"\"\n\n\n# CRIS\n# [How to make]\n# cd /path/to/linux-4.16.18/\n# awk '/sys_call_table:/,/^$/' arch/cris/arch-v10/kernel/entry.S \\\n# | grep -o \"\\.long \\w*\" | nl -v0 | awk '{print $1\" cris \"substr($3,5)\" \"$3}' |column -t\ncris_syscall_tbl = \"\"\"\n0    cris  restart_syscall         sys_restart_syscall\n1    cris  exit                    sys_exit\n2    cris  fork                    sys_fork\n3    cris  read                    sys_read\n4    cris  write                   sys_write\n5    cris  open                    sys_open\n6    cris  close                   sys_close\n7    cris  waitpid                 sys_waitpid\n8    cris  creat                   sys_creat\n9    cris  link                    sys_link\n10   cris  unlink                  sys_unlink\n11   cris  execve                  sys_execve\n12   cris  chdir                   sys_chdir\n13   cris  time                    sys_time\n14   cris  mknod                   sys_mknod\n15   cris  chmod                   sys_chmod\n16   cris  lchown16                sys_lchown16\n17   cris  ni_syscall              sys_ni_syscall\n18   cris  stat                    sys_stat\n19   cris  lseek                   sys_lseek\n20   cris  getpid                  sys_getpid\n21   cris  mount                   sys_mount\n22   cris  oldumount               sys_oldumount\n23   cris  setuid16                sys_setuid16\n24   cris  getuid16                sys_getuid16\n25   cris  stime                   sys_stime\n26   cris  ptrace                  sys_ptrace\n27   cris  alarm                   sys_alarm\n28   cris  fstat                   sys_fstat\n29   cris  pause                   sys_pause\n30   cris  utime                   sys_utime\n31   cris  ni_syscall              sys_ni_syscall\n32   cris  ni_syscall              sys_ni_syscall\n33   cris  access                  sys_access\n34   cris  nice                    sys_nice\n35   cris  ni_syscall              sys_ni_syscall\n36   cris  sync                    sys_sync\n37   cris  kill                    sys_kill\n38   cris  rename                  sys_rename\n39   cris  mkdir                   sys_mkdir\n40   cris  rmdir                   sys_rmdir\n41   cris  dup                     sys_dup\n42   cris  pipe                    sys_pipe\n43   cris  times                   sys_times\n44   cris  ni_syscall              sys_ni_syscall\n45   cris  brk                     sys_brk\n46   cris  setgid16                sys_setgid16\n47   cris  getgid16                sys_getgid16\n48   cris  signal                  sys_signal\n49   cris  geteuid16               sys_geteuid16\n50   cris  getegid16               sys_getegid16\n51   cris  acct                    sys_acct\n52   cris  umount                  sys_umount\n53   cris  ni_syscall              sys_ni_syscall\n54   cris  ioctl                   sys_ioctl\n55   cris  fcntl                   sys_fcntl\n56   cris  ni_syscall              sys_ni_syscall\n57   cris  setpgid                 sys_setpgid\n58   cris  ni_syscall              sys_ni_syscall\n59   cris  ni_syscall              sys_ni_syscall\n60   cris  umask                   sys_umask\n61   cris  chroot                  sys_chroot\n62   cris  ustat                   sys_ustat\n63   cris  dup2                    sys_dup2\n64   cris  getppid                 sys_getppid\n65   cris  getpgrp                 sys_getpgrp\n66   cris  setsid                  sys_setsid\n67   cris  sigaction               sys_sigaction\n68   cris  sgetmask                sys_sgetmask\n69   cris  ssetmask                sys_ssetmask\n70   cris  setreuid16              sys_setreuid16\n71   cris  setregid16              sys_setregid16\n72   cris  sigsuspend              sys_sigsuspend\n73   cris  sigpending              sys_sigpending\n74   cris  sethostname             sys_sethostname\n75   cris  setrlimit               sys_setrlimit\n76   cris  old_getrlimit           sys_old_getrlimit\n77   cris  getrusage               sys_getrusage\n78   cris  gettimeofday            sys_gettimeofday\n79   cris  settimeofday            sys_settimeofday\n80   cris  getgroups16             sys_getgroups16\n81   cris  setgroups16             sys_setgroups16\n82   cris  select                  sys_select\n83   cris  symlink                 sys_symlink\n84   cris  lstat                   sys_lstat\n85   cris  readlink                sys_readlink\n86   cris  uselib                  sys_uselib\n87   cris  swapon                  sys_swapon\n88   cris  reboot                  sys_reboot\n89   cris  old_readdir             sys_old_readdir\n90   cris  old_mmap                sys_old_mmap\n91   cris  munmap                  sys_munmap\n92   cris  truncate                sys_truncate\n93   cris  ftruncate               sys_ftruncate\n94   cris  fchmod                  sys_fchmod\n95   cris  fchown16                sys_fchown16\n96   cris  getpriority             sys_getpriority\n97   cris  setpriority             sys_setpriority\n98   cris  ni_syscall              sys_ni_syscall\n99   cris  statfs                  sys_statfs\n100  cris  fstatfs                 sys_fstatfs\n101  cris  ni_syscall              sys_ni_syscall\n102  cris  socketcall              sys_socketcall\n103  cris  syslog                  sys_syslog\n104  cris  setitimer               sys_setitimer\n105  cris  getitimer               sys_getitimer\n106  cris  newstat                 sys_newstat\n107  cris  newlstat                sys_newlstat\n108  cris  newfstat                sys_newfstat\n109  cris  ni_syscall              sys_ni_syscall\n110  cris  ni_syscall              sys_ni_syscall\n111  cris  vhangup                 sys_vhangup\n112  cris  ni_syscall              sys_ni_syscall\n113  cris  ni_syscall              sys_ni_syscall\n114  cris  wait4                   sys_wait4\n115  cris  swapoff                 sys_swapoff\n116  cris  sysinfo                 sys_sysinfo\n117  cris  ipc                     sys_ipc\n118  cris  fsync                   sys_fsync\n119  cris  sigreturn               sys_sigreturn\n120  cris  clone                   sys_clone\n121  cris  setdomainname           sys_setdomainname\n122  cris  newuname                sys_newuname\n123  cris  ni_syscall              sys_ni_syscall\n124  cris  adjtimex                sys_adjtimex\n125  cris  mprotect                sys_mprotect\n126  cris  sigprocmask             sys_sigprocmask\n127  cris  ni_syscall              sys_ni_syscall\n128  cris  init_module             sys_init_module\n129  cris  delete_module           sys_delete_module\n130  cris  ni_syscall              sys_ni_syscall\n131  cris  quotactl                sys_quotactl\n132  cris  getpgid                 sys_getpgid\n133  cris  fchdir                  sys_fchdir\n134  cris  bdflush                 sys_bdflush\n135  cris  sysfs                   sys_sysfs\n136  cris  personality             sys_personality\n137  cris  ni_syscall              sys_ni_syscall\n138  cris  setfsuid16              sys_setfsuid16\n139  cris  setfsgid16              sys_setfsgid16\n140  cris  llseek                  sys_llseek\n141  cris  getdents                sys_getdents\n142  cris  select                  sys_select\n143  cris  flock                   sys_flock\n144  cris  msync                   sys_msync\n145  cris  readv                   sys_readv\n146  cris  writev                  sys_writev\n147  cris  getsid                  sys_getsid\n148  cris  fdatasync               sys_fdatasync\n149  cris  sysctl                  sys_sysctl\n150  cris  mlock                   sys_mlock\n151  cris  munlock                 sys_munlock\n152  cris  mlockall                sys_mlockall\n153  cris  munlockall              sys_munlockall\n154  cris  sched_setparam          sys_sched_setparam\n155  cris  sched_getparam          sys_sched_getparam\n156  cris  sched_setscheduler      sys_sched_setscheduler\n157  cris  sched_getscheduler      sys_sched_getscheduler\n158  cris  sched_yield             sys_sched_yield\n159  cris  sched_get_priority_max  sys_sched_get_priority_max\n160  cris  sched_get_priority_min  sys_sched_get_priority_min\n161  cris  sched_rr_get_interval   sys_sched_rr_get_interval\n162  cris  nanosleep               sys_nanosleep\n163  cris  mremap                  sys_mremap\n164  cris  setresuid16             sys_setresuid16\n165  cris  getresuid16             sys_getresuid16\n166  cris  ni_syscall              sys_ni_syscall\n167  cris  ni_syscall              sys_ni_syscall\n168  cris  poll                    sys_poll\n169  cris  ni_syscall              sys_ni_syscall\n170  cris  setresgid16             sys_setresgid16\n171  cris  getresgid16             sys_getresgid16\n172  cris  prctl                   sys_prctl\n173  cris  rt_sigreturn            sys_rt_sigreturn\n174  cris  rt_sigaction            sys_rt_sigaction\n175  cris  rt_sigprocmask          sys_rt_sigprocmask\n176  cris  rt_sigpending           sys_rt_sigpending\n177  cris  rt_sigtimedwait         sys_rt_sigtimedwait\n178  cris  rt_sigqueueinfo         sys_rt_sigqueueinfo\n179  cris  rt_sigsuspend           sys_rt_sigsuspend\n180  cris  pread64                 sys_pread64\n181  cris  pwrite64                sys_pwrite64\n182  cris  chown16                 sys_chown16\n183  cris  getcwd                  sys_getcwd\n184  cris  capget                  sys_capget\n185  cris  capset                  sys_capset\n186  cris  sigaltstack             sys_sigaltstack\n187  cris  sendfile                sys_sendfile\n188  cris  ni_syscall              sys_ni_syscall\n189  cris  ni_syscall              sys_ni_syscall\n190  cris  vfork                   sys_vfork\n191  cris  getrlimit               sys_getrlimit\n192  cris  mmap2                   sys_mmap2\n193  cris  truncate64              sys_truncate64\n194  cris  ftruncate64             sys_ftruncate64\n195  cris  stat64                  sys_stat64\n196  cris  lstat64                 sys_lstat64\n197  cris  fstat64                 sys_fstat64\n198  cris  lchown                  sys_lchown\n199  cris  getuid                  sys_getuid\n200  cris  getgid                  sys_getgid\n201  cris  geteuid                 sys_geteuid\n202  cris  getegid                 sys_getegid\n203  cris  setreuid                sys_setreuid\n204  cris  setregid                sys_setregid\n205  cris  getgroups               sys_getgroups\n206  cris  setgroups               sys_setgroups\n207  cris  fchown                  sys_fchown\n208  cris  setresuid               sys_setresuid\n209  cris  getresuid               sys_getresuid\n210  cris  setresgid               sys_setresgid\n211  cris  getresgid               sys_getresgid\n212  cris  chown                   sys_chown\n213  cris  setuid                  sys_setuid\n214  cris  setgid                  sys_setgid\n215  cris  setfsuid                sys_setfsuid\n216  cris  setfsgid                sys_setfsgid\n217  cris  pivot_root              sys_pivot_root\n218  cris  mincore                 sys_mincore\n219  cris  madvise                 sys_madvise\n220  cris  getdents64              sys_getdents64\n221  cris  fcntl64                 sys_fcntl64\n222  cris  ni_syscall              sys_ni_syscall\n223  cris  ni_syscall              sys_ni_syscall\n224  cris  gettid                  sys_gettid\n225  cris  readahead               sys_readahead\n226  cris  setxattr                sys_setxattr\n227  cris  lsetxattr               sys_lsetxattr\n228  cris  fsetxattr               sys_fsetxattr\n229  cris  getxattr                sys_getxattr\n230  cris  lgetxattr               sys_lgetxattr\n231  cris  fgetxattr               sys_fgetxattr\n232  cris  listxattr               sys_listxattr\n233  cris  llistxattr              sys_llistxattr\n234  cris  flistxattr              sys_flistxattr\n235  cris  removexattr             sys_removexattr\n236  cris  lremovexattr            sys_lremovexattr\n237  cris  fremovexattr            sys_fremovexattr\n238  cris  tkill                   sys_tkill\n239  cris  sendfile64              sys_sendfile64\n240  cris  futex                   sys_futex\n241  cris  sched_setaffinity       sys_sched_setaffinity\n242  cris  sched_getaffinity       sys_sched_getaffinity\n243  cris  ni_syscall              sys_ni_syscall\n244  cris  ni_syscall              sys_ni_syscall\n245  cris  io_setup                sys_io_setup\n246  cris  io_destroy              sys_io_destroy\n247  cris  io_getevents            sys_io_getevents\n248  cris  io_submit               sys_io_submit\n249  cris  io_cancel               sys_io_cancel\n250  cris  fadvise64               sys_fadvise64\n251  cris  ni_syscall              sys_ni_syscall\n252  cris  exit_group              sys_exit_group\n253  cris  lookup_dcookie          sys_lookup_dcookie\n254  cris  epoll_create            sys_epoll_create\n255  cris  epoll_ctl               sys_epoll_ctl\n256  cris  epoll_wait              sys_epoll_wait\n257  cris  remap_file_pages        sys_remap_file_pages\n258  cris  set_tid_address         sys_set_tid_address\n259  cris  timer_create            sys_timer_create\n260  cris  timer_settime           sys_timer_settime\n261  cris  timer_gettime           sys_timer_gettime\n262  cris  timer_getoverrun        sys_timer_getoverrun\n263  cris  timer_delete            sys_timer_delete\n264  cris  clock_settime           sys_clock_settime\n265  cris  clock_gettime           sys_clock_gettime\n266  cris  clock_getres            sys_clock_getres\n267  cris  clock_nanosleep         sys_clock_nanosleep\n268  cris  statfs64                sys_statfs64\n269  cris  fstatfs64               sys_fstatfs64\n270  cris  tgkill                  sys_tgkill\n271  cris  utimes                  sys_utimes\n272  cris  fadvise64_64            sys_fadvise64_64\n273  cris  ni_syscall              sys_ni_syscall\n274  cris  ni_syscall              sys_ni_syscall\n275  cris  ni_syscall              sys_ni_syscall\n276  cris  ni_syscall              sys_ni_syscall\n277  cris  mq_open                 sys_mq_open\n278  cris  mq_unlink               sys_mq_unlink\n279  cris  mq_timedsend            sys_mq_timedsend\n280  cris  mq_timedreceive         sys_mq_timedreceive\n281  cris  mq_notify               sys_mq_notify\n282  cris  mq_getsetattr           sys_mq_getsetattr\n283  cris  ni_syscall              sys_ni_syscall\n284  cris  waitid                  sys_waitid\n285  cris  ni_syscall              sys_ni_syscall\n286  cris  add_key                 sys_add_key\n287  cris  request_key             sys_request_key\n288  cris  keyctl                  sys_keyctl\n289  cris  ioprio_set              sys_ioprio_set\n290  cris  ioprio_get              sys_ioprio_get\n291  cris  inotify_init            sys_inotify_init\n292  cris  inotify_add_watch       sys_inotify_add_watch\n293  cris  inotify_rm_watch        sys_inotify_rm_watch\n294  cris  migrate_pages           sys_migrate_pages\n295  cris  openat                  sys_openat\n296  cris  mkdirat                 sys_mkdirat\n297  cris  mknodat                 sys_mknodat\n298  cris  fchownat                sys_fchownat\n299  cris  futimesat               sys_futimesat\n300  cris  fstatat64               sys_fstatat64\n301  cris  unlinkat                sys_unlinkat\n302  cris  renameat                sys_renameat\n303  cris  linkat                  sys_linkat\n304  cris  symlinkat               sys_symlinkat\n305  cris  readlinkat              sys_readlinkat\n306  cris  fchmodat                sys_fchmodat\n307  cris  faccessat               sys_faccessat\n308  cris  pselect6                sys_pselect6\n309  cris  ppoll                   sys_ppoll\n310  cris  unshare                 sys_unshare\n311  cris  set_robust_list         sys_set_robust_list\n312  cris  get_robust_list         sys_get_robust_list\n313  cris  splice                  sys_splice\n314  cris  sync_file_range         sys_sync_file_range\n315  cris  tee                     sys_tee\n316  cris  vmsplice                sys_vmsplice\n317  cris  move_pages              sys_move_pages\n318  cris  getcpu                  sys_getcpu\n319  cris  epoll_pwait             sys_epoll_pwait\n320  cris  utimensat               sys_utimensat\n321  cris  signalfd                sys_signalfd\n322  cris  timerfd_create          sys_timerfd_create\n323  cris  eventfd                 sys_eventfd\n324  cris  fallocate               sys_fallocate\n325  cris  timerfd_settime         sys_timerfd_settime\n326  cris  timerfd_gettime         sys_timerfd_gettime\n327  cris  signalfd4               sys_signalfd4\n328  cris  eventfd2                sys_eventfd2\n329  cris  epoll_create1           sys_epoll_create1\n330  cris  dup3                    sys_dup3\n331  cris  pipe2                   sys_pipe2\n332  cris  inotify_init1           sys_inotify_init1\n333  cris  preadv                  sys_preadv\n334  cris  pwritev                 sys_pwritev\n335  cris  setns                   sys_setns\n336  cris  name_to_handle_at       sys_name_to_handle_at\n337  cris  open_by_handle_at       sys_open_by_handle_at\n338  cris  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo\n339  cris  perf_event_open         sys_perf_event_open\n340  cris  recvmmsg                sys_recvmmsg\n341  cris  accept4                 sys_accept4\n342  cris  fanotify_init           sys_fanotify_init\n343  cris  fanotify_mark           sys_fanotify_mark\n344  cris  prlimit64               sys_prlimit64\n345  cris  clock_adjtime           sys_clock_adjtime\n346  cris  syncfs                  sys_syncfs\n347  cris  sendmmsg                sys_sendmmsg\n348  cris  process_vm_readv        sys_process_vm_readv\n349  cris  process_vm_writev       sys_process_vm_writev\n350  cris  kcmp                    sys_kcmp\n351  cris  finit_module            sys_finit_module\n352  cris  sched_setattr           sys_sched_setattr\n353  cris  sched_getattr           sys_sched_getattr\n354  cris  renameat2               sys_renameat2\n355  cris  seccomp                 sys_seccomp\n356  cris  getrandom               sys_getrandom\n357  cris  memfd_create            sys_memfd_create\n358  cris  bpf                     sys_bpf\n359  cris  execveat                sys_execveat\n\"\"\"\n\n\n# Loongarch\n#\n# [How to make for 6.10.14]\n# cd /path/to/linux-6.10.14/\n# gcc -I `pwd`/include/uapi/ -E -D__SYSCALL=SYSCALL arch/loongarch/include/uapi/asm/unistd.h | grep ^SYSCALL \\\n# | sed -e 's/SYSCALL(//;s/[,)]//g' > /tmp/a\n# grep -oP \"__NR\\S+\\s+\\d+$\" include/uapi/asm-generic/unistd.h | grep -v __NR_sync_file_range2 > /tmp/b\n# join -2 2 -o 1.1,1.10,2.1,1.2 -e loongarch /tmp/a /tmp/b | sed -e 's/\\(__NR_\\|__NR3264_\\)//g' | column -t\nloongarch_syscall_tbl = \"\"\"\n0    loongarch  io_setup                 sys_io_setup\n1    loongarch  io_destroy               sys_io_destroy\n2    loongarch  io_submit                sys_io_submit\n3    loongarch  io_cancel                sys_io_cancel\n4    loongarch  io_getevents             sys_io_getevents\n5    loongarch  setxattr                 sys_setxattr\n6    loongarch  lsetxattr                sys_lsetxattr\n7    loongarch  fsetxattr                sys_fsetxattr\n8    loongarch  getxattr                 sys_getxattr\n9    loongarch  lgetxattr                sys_lgetxattr\n10   loongarch  fgetxattr                sys_fgetxattr\n11   loongarch  listxattr                sys_listxattr\n12   loongarch  llistxattr               sys_llistxattr\n13   loongarch  flistxattr               sys_flistxattr\n14   loongarch  removexattr              sys_removexattr\n15   loongarch  lremovexattr             sys_lremovexattr\n16   loongarch  fremovexattr             sys_fremovexattr\n17   loongarch  getcwd                   sys_getcwd\n18   loongarch  lookup_dcookie           sys_ni_syscall\n19   loongarch  eventfd2                 sys_eventfd2\n20   loongarch  epoll_create1            sys_epoll_create1\n21   loongarch  epoll_ctl                sys_epoll_ctl\n22   loongarch  epoll_pwait              sys_epoll_pwait\n23   loongarch  dup                      sys_dup\n24   loongarch  dup3                     sys_dup3\n25   loongarch  fcntl                    sys_fcntl\n26   loongarch  inotify_init1            sys_inotify_init1\n27   loongarch  inotify_add_watch        sys_inotify_add_watch\n28   loongarch  inotify_rm_watch         sys_inotify_rm_watch\n29   loongarch  ioctl                    sys_ioctl\n30   loongarch  ioprio_set               sys_ioprio_set\n31   loongarch  ioprio_get               sys_ioprio_get\n32   loongarch  flock                    sys_flock\n33   loongarch  mknodat                  sys_mknodat\n34   loongarch  mkdirat                  sys_mkdirat\n35   loongarch  unlinkat                 sys_unlinkat\n36   loongarch  symlinkat                sys_symlinkat\n37   loongarch  linkat                   sys_linkat\n39   loongarch  umount2                  sys_umount\n40   loongarch  mount                    sys_mount\n41   loongarch  pivot_root               sys_pivot_root\n42   loongarch  nfsservctl               sys_ni_syscall\n43   loongarch  statfs                   sys_statfs\n44   loongarch  fstatfs                  sys_fstatfs\n45   loongarch  truncate                 sys_truncate\n46   loongarch  ftruncate                sys_ftruncate\n47   loongarch  fallocate                sys_fallocate\n48   loongarch  faccessat                sys_faccessat\n49   loongarch  chdir                    sys_chdir\n50   loongarch  fchdir                   sys_fchdir\n51   loongarch  chroot                   sys_chroot\n52   loongarch  fchmod                   sys_fchmod\n53   loongarch  fchmodat                 sys_fchmodat\n54   loongarch  fchownat                 sys_fchownat\n55   loongarch  fchown                   sys_fchown\n56   loongarch  openat                   sys_openat\n57   loongarch  close                    sys_close\n58   loongarch  vhangup                  sys_vhangup\n59   loongarch  pipe2                    sys_pipe2\n60   loongarch  quotactl                 sys_quotactl\n61   loongarch  getdents64               sys_getdents64\n62   loongarch  lseek                    sys_lseek\n63   loongarch  read                     sys_read\n64   loongarch  write                    sys_write\n65   loongarch  readv                    sys_readv\n66   loongarch  writev                   sys_writev\n67   loongarch  pread64                  sys_pread64\n68   loongarch  pwrite64                 sys_pwrite64\n69   loongarch  preadv                   sys_preadv\n70   loongarch  pwritev                  sys_pwritev\n71   loongarch  sendfile                 sys_sendfile64\n72   loongarch  pselect6                 sys_pselect6\n73   loongarch  ppoll                    sys_ppoll\n74   loongarch  signalfd4                sys_signalfd4\n75   loongarch  vmsplice                 sys_vmsplice\n76   loongarch  splice                   sys_splice\n77   loongarch  tee                      sys_tee\n78   loongarch  readlinkat               sys_readlinkat\n81   loongarch  sync                     sys_sync\n82   loongarch  fsync                    sys_fsync\n83   loongarch  fdatasync                sys_fdatasync\n84   loongarch  sync_file_range          sys_sync_file_range\n85   loongarch  timerfd_create           sys_timerfd_create\n86   loongarch  timerfd_settime          sys_timerfd_settime\n87   loongarch  timerfd_gettime          sys_timerfd_gettime\n88   loongarch  utimensat                sys_utimensat\n89   loongarch  acct                     sys_acct\n90   loongarch  capget                   sys_capget\n91   loongarch  capset                   sys_capset\n92   loongarch  personality              sys_personality\n93   loongarch  exit                     sys_exit\n94   loongarch  exit_group               sys_exit_group\n95   loongarch  waitid                   sys_waitid\n96   loongarch  set_tid_address          sys_set_tid_address\n97   loongarch  unshare                  sys_unshare\n98   loongarch  futex                    sys_futex\n99   loongarch  set_robust_list          sys_set_robust_list\n100  loongarch  get_robust_list          sys_get_robust_list\n101  loongarch  nanosleep                sys_nanosleep\n102  loongarch  getitimer                sys_getitimer\n103  loongarch  setitimer                sys_setitimer\n104  loongarch  kexec_load               sys_kexec_load\n105  loongarch  init_module              sys_init_module\n106  loongarch  delete_module            sys_delete_module\n107  loongarch  timer_create             sys_timer_create\n108  loongarch  timer_gettime            sys_timer_gettime\n109  loongarch  timer_getoverrun         sys_timer_getoverrun\n110  loongarch  timer_settime            sys_timer_settime\n111  loongarch  timer_delete             sys_timer_delete\n112  loongarch  clock_settime            sys_clock_settime\n113  loongarch  clock_gettime            sys_clock_gettime\n114  loongarch  clock_getres             sys_clock_getres\n115  loongarch  clock_nanosleep          sys_clock_nanosleep\n116  loongarch  syslog                   sys_syslog\n117  loongarch  ptrace                   sys_ptrace\n118  loongarch  sched_setparam           sys_sched_setparam\n119  loongarch  sched_setscheduler       sys_sched_setscheduler\n120  loongarch  sched_getscheduler       sys_sched_getscheduler\n121  loongarch  sched_getparam           sys_sched_getparam\n122  loongarch  sched_setaffinity        sys_sched_setaffinity\n123  loongarch  sched_getaffinity        sys_sched_getaffinity\n124  loongarch  sched_yield              sys_sched_yield\n125  loongarch  sched_get_priority_max   sys_sched_get_priority_max\n126  loongarch  sched_get_priority_min   sys_sched_get_priority_min\n127  loongarch  sched_rr_get_interval    sys_sched_rr_get_interval\n128  loongarch  restart_syscall          sys_restart_syscall\n129  loongarch  kill                     sys_kill\n130  loongarch  tkill                    sys_tkill\n131  loongarch  tgkill                   sys_tgkill\n132  loongarch  sigaltstack              sys_sigaltstack\n133  loongarch  rt_sigsuspend            sys_rt_sigsuspend\n134  loongarch  rt_sigaction             sys_rt_sigaction\n135  loongarch  rt_sigprocmask           sys_rt_sigprocmask\n136  loongarch  rt_sigpending            sys_rt_sigpending\n137  loongarch  rt_sigtimedwait          sys_rt_sigtimedwait\n138  loongarch  rt_sigqueueinfo          sys_rt_sigqueueinfo\n139  loongarch  rt_sigreturn             sys_rt_sigreturn\n140  loongarch  setpriority              sys_setpriority\n141  loongarch  getpriority              sys_getpriority\n142  loongarch  reboot                   sys_reboot\n143  loongarch  setregid                 sys_setregid\n144  loongarch  setgid                   sys_setgid\n145  loongarch  setreuid                 sys_setreuid\n146  loongarch  setuid                   sys_setuid\n147  loongarch  setresuid                sys_setresuid\n148  loongarch  getresuid                sys_getresuid\n149  loongarch  setresgid                sys_setresgid\n150  loongarch  getresgid                sys_getresgid\n151  loongarch  setfsuid                 sys_setfsuid\n152  loongarch  setfsgid                 sys_setfsgid\n153  loongarch  times                    sys_times\n154  loongarch  setpgid                  sys_setpgid\n155  loongarch  getpgid                  sys_getpgid\n156  loongarch  getsid                   sys_getsid\n157  loongarch  setsid                   sys_setsid\n158  loongarch  getgroups                sys_getgroups\n159  loongarch  setgroups                sys_setgroups\n160  loongarch  uname                    sys_newuname\n161  loongarch  sethostname              sys_sethostname\n162  loongarch  setdomainname            sys_setdomainname\n165  loongarch  getrusage                sys_getrusage\n166  loongarch  umask                    sys_umask\n167  loongarch  prctl                    sys_prctl\n168  loongarch  getcpu                   sys_getcpu\n169  loongarch  gettimeofday             sys_gettimeofday\n170  loongarch  settimeofday             sys_settimeofday\n171  loongarch  adjtimex                 sys_adjtimex\n172  loongarch  getpid                   sys_getpid\n173  loongarch  getppid                  sys_getppid\n174  loongarch  getuid                   sys_getuid\n175  loongarch  geteuid                  sys_geteuid\n176  loongarch  getgid                   sys_getgid\n177  loongarch  getegid                  sys_getegid\n178  loongarch  gettid                   sys_gettid\n179  loongarch  sysinfo                  sys_sysinfo\n180  loongarch  mq_open                  sys_mq_open\n181  loongarch  mq_unlink                sys_mq_unlink\n182  loongarch  mq_timedsend             sys_mq_timedsend\n183  loongarch  mq_timedreceive          sys_mq_timedreceive\n184  loongarch  mq_notify                sys_mq_notify\n185  loongarch  mq_getsetattr            sys_mq_getsetattr\n186  loongarch  msgget                   sys_msgget\n187  loongarch  msgctl                   sys_msgctl\n188  loongarch  msgrcv                   sys_msgrcv\n189  loongarch  msgsnd                   sys_msgsnd\n190  loongarch  semget                   sys_semget\n191  loongarch  semctl                   sys_semctl\n192  loongarch  semtimedop               sys_semtimedop\n193  loongarch  semop                    sys_semop\n194  loongarch  shmget                   sys_shmget\n195  loongarch  shmctl                   sys_shmctl\n196  loongarch  shmat                    sys_shmat\n197  loongarch  shmdt                    sys_shmdt\n198  loongarch  socket                   sys_socket\n199  loongarch  socketpair               sys_socketpair\n200  loongarch  bind                     sys_bind\n201  loongarch  listen                   sys_listen\n202  loongarch  accept                   sys_accept\n203  loongarch  connect                  sys_connect\n204  loongarch  getsockname              sys_getsockname\n205  loongarch  getpeername              sys_getpeername\n206  loongarch  sendto                   sys_sendto\n207  loongarch  recvfrom                 sys_recvfrom\n208  loongarch  setsockopt               sys_setsockopt\n209  loongarch  getsockopt               sys_getsockopt\n210  loongarch  shutdown                 sys_shutdown\n211  loongarch  sendmsg                  sys_sendmsg\n212  loongarch  recvmsg                  sys_recvmsg\n213  loongarch  readahead                sys_readahead\n214  loongarch  brk                      sys_brk\n215  loongarch  munmap                   sys_munmap\n216  loongarch  mremap                   sys_mremap\n217  loongarch  add_key                  sys_add_key\n218  loongarch  request_key              sys_request_key\n219  loongarch  keyctl                   sys_keyctl\n220  loongarch  clone                    sys_clone\n221  loongarch  execve                   sys_execve\n222  loongarch  mmap                     sys_mmap\n223  loongarch  fadvise64                sys_fadvise64_64\n224  loongarch  swapon                   sys_swapon\n225  loongarch  swapoff                  sys_swapoff\n226  loongarch  mprotect                 sys_mprotect\n227  loongarch  msync                    sys_msync\n228  loongarch  mlock                    sys_mlock\n229  loongarch  munlock                  sys_munlock\n230  loongarch  mlockall                 sys_mlockall\n231  loongarch  munlockall               sys_munlockall\n232  loongarch  mincore                  sys_mincore\n233  loongarch  madvise                  sys_madvise\n234  loongarch  remap_file_pages         sys_remap_file_pages\n235  loongarch  mbind                    sys_mbind\n236  loongarch  get_mempolicy            sys_get_mempolicy\n237  loongarch  set_mempolicy            sys_set_mempolicy\n238  loongarch  migrate_pages            sys_migrate_pages\n239  loongarch  move_pages               sys_move_pages\n240  loongarch  rt_tgsigqueueinfo        sys_rt_tgsigqueueinfo\n241  loongarch  perf_event_open          sys_perf_event_open\n242  loongarch  accept4                  sys_accept4\n243  loongarch  recvmmsg                 sys_recvmmsg\n260  loongarch  wait4                    sys_wait4\n261  loongarch  prlimit64                sys_prlimit64\n262  loongarch  fanotify_init            sys_fanotify_init\n263  loongarch  fanotify_mark            sys_fanotify_mark\n264  loongarch  name_to_handle_at        sys_name_to_handle_at\n265  loongarch  open_by_handle_at        sys_open_by_handle_at\n266  loongarch  clock_adjtime            sys_clock_adjtime\n267  loongarch  syncfs                   sys_syncfs\n268  loongarch  setns                    sys_setns\n269  loongarch  sendmmsg                 sys_sendmmsg\n270  loongarch  process_vm_readv         sys_process_vm_readv\n271  loongarch  process_vm_writev        sys_process_vm_writev\n272  loongarch  kcmp                     sys_kcmp\n273  loongarch  finit_module             sys_finit_module\n274  loongarch  sched_setattr            sys_sched_setattr\n275  loongarch  sched_getattr            sys_sched_getattr\n276  loongarch  renameat2                sys_renameat2\n277  loongarch  seccomp                  sys_seccomp\n278  loongarch  getrandom                sys_getrandom\n279  loongarch  memfd_create             sys_memfd_create\n280  loongarch  bpf                      sys_bpf\n281  loongarch  execveat                 sys_execveat\n282  loongarch  userfaultfd              sys_userfaultfd\n283  loongarch  membarrier               sys_membarrier\n284  loongarch  mlock2                   sys_mlock2\n285  loongarch  copy_file_range          sys_copy_file_range\n286  loongarch  preadv2                  sys_preadv2\n287  loongarch  pwritev2                 sys_pwritev2\n288  loongarch  pkey_mprotect            sys_pkey_mprotect\n289  loongarch  pkey_alloc               sys_pkey_alloc\n290  loongarch  pkey_free                sys_pkey_free\n291  loongarch  statx                    sys_statx\n292  loongarch  io_pgetevents            sys_io_pgetevents\n293  loongarch  rseq                     sys_rseq\n294  loongarch  kexec_file_load          sys_kexec_file_load\n424  loongarch  pidfd_send_signal        sys_pidfd_send_signal\n425  loongarch  io_uring_setup           sys_io_uring_setup\n426  loongarch  io_uring_enter           sys_io_uring_enter\n427  loongarch  io_uring_register        sys_io_uring_register\n428  loongarch  open_tree                sys_open_tree\n429  loongarch  move_mount               sys_move_mount\n430  loongarch  fsopen                   sys_fsopen\n431  loongarch  fsconfig                 sys_fsconfig\n432  loongarch  fsmount                  sys_fsmount\n433  loongarch  fspick                   sys_fspick\n434  loongarch  pidfd_open               sys_pidfd_open\n435  loongarch  clone3                   sys_clone3\n436  loongarch  close_range              sys_close_range\n437  loongarch  openat2                  sys_openat2\n438  loongarch  pidfd_getfd              sys_pidfd_getfd\n439  loongarch  faccessat2               sys_faccessat2\n440  loongarch  process_madvise          sys_process_madvise\n441  loongarch  epoll_pwait2             sys_epoll_pwait2\n442  loongarch  mount_setattr            sys_mount_setattr\n443  loongarch  quotactl_fd              sys_quotactl_fd\n444  loongarch  landlock_create_ruleset  sys_landlock_create_ruleset\n445  loongarch  landlock_add_rule        sys_landlock_add_rule\n446  loongarch  landlock_restrict_self   sys_landlock_restrict_self\n448  loongarch  process_mrelease         sys_process_mrelease\n449  loongarch  futex_waitv              sys_futex_waitv\n450  loongarch  set_mempolicy_home_node  sys_set_mempolicy_home_node\n451  loongarch  cachestat                sys_cachestat\n452  loongarch  fchmodat2                sys_fchmodat2\n453  loongarch  map_shadow_stack         sys_map_shadow_stack\n454  loongarch  futex_wake               sys_futex_wake\n455  loongarch  futex_wait               sys_futex_wait\n456  loongarch  futex_requeue            sys_futex_requeue\n457  loongarch  statmount                sys_statmount\n458  loongarch  listmount                sys_listmount\n459  loongarch  lsm_get_self_attr        sys_lsm_get_self_attr\n460  loongarch  lsm_set_self_attr        sys_lsm_set_self_attr\n461  loongarch  lsm_list_modules         sys_lsm_list_modules\n462  loongarch  mseal                    sys_mseal\n463  loongarch  setxattrat               sys_setxattrat\n464  loongarch  getxattrat               sys_getxattrat\n465  loongarch  listxattrat              sys_listxattrat\n466  loongarch  removexattrat            sys_removexattrat\n467  loongarch  open_tree_attr           sys_open_tree_attr\n\"\"\"\n\n\n# arc\narc_syscall_tbl = arm64_syscall_tbl\n\n\n# csky\ncsky_syscall_tbl = arm64_syscall_tbl\n\n\n# ARM/ARM64 OP-TEE (at secure world)\n# - core/include/tee/tee_svc.h\n# - core/include/tee/tee_svc_cryp.h\n# - core/include/tee/tee_svc_storage.h\n# - core/include/tee/svc_cache.h\narm_OPTEE_syscall_list = [\n    [0x00, \"syscall_sys_return\", [\"unsigned long ret\"]],\n    [0x01, \"syscall_log\", [\"const void *buf\", \"size_t len\"]],\n    [0x02, \"syscall_panic\", [\"unsigned long code\"]],\n    [0x03, \"syscall_get_property\", [\"unsigned long prop_set\", \"unsigned long index\", \"void *name\", \"uint32_t *name_len\", \"void *buf\", \"uint32_t *blen\", \"uint32_t *prop_type\"]],\n    [0x04, \"syscall_get_property_name_to_index\", [\"unsigned long prop_set\", \"void *name\", \"unsigned long name_len\", \"uint32_t *index\"]],\n    [0x05, \"syscall_open_ta_session\", [\"const TEE_UUID *dest\", \"unsigned long cancel_req_to\", \"struct utee_params *params\", \"uint32_t *sess\", \"uint32_t *ret_orig\"]],\n    [0x06, \"syscall_close_ta_session\", [\"unsigned long sess\"]],\n    [0x07, \"syscall_invoke_ta_command\", [\"unsigned long sess\", \"unsigned long cancel_req_to\", \"unsigned long cmd_id\", \"struct utee_params *params\", \"uint32_t *ret_orig\"]],\n    [0x08, \"syscall_check_access_rights\", [\"unsigned long flags\", \"const void *buf\", \"size_t len\"]],\n    [0x09, \"syscall_get_cancellation_flag\", [\"uint32_t *cancel\"]],\n    [0x0a, \"syscall_unmask_cancellation\", [\"uint32_t *old_mask\"]],\n    [0x0b, \"syscall_mask_cancellation\", [\"uint32_t *old_mask\"]],\n    [0x0c, \"syscall_wait\", [\"unsigned long timeout\"]],\n    [0x0d, \"syscall_get_time\", [\"unsigned long cat\", \"TEE_Time *time\"]],\n    [0x0e, \"syscall_set_ta_time\", [\"const TEE_Time *time\"]],\n    [0x0f, \"syscall_cryp_state_alloc\", [\"unsigned long algo\", \"unsigned long op_mode\", \"unsigned long key1\", \"unsigned long key2\", \"uint32_t *state\"]],\n    [0x10, \"syscall_cryp_state_copy\", [\"unsigned long dst\", \"unsigned long src\"]],\n    [0x11, \"syscall_cryp_state_free\", [\"unsigned long state\"]],\n    [0x12, \"syscall_hash_init\", [\"unsigned long state\", \"const void *iv\", \"size_t iv_len\"]],\n    [0x13, \"syscall_hash_update\", [\"unsigned long state\", \"const void *chunk\", \"size_t chunk_size\"]],\n    [0x14, \"syscall_hash_final\", [\"unsigned long state\", \"const void *chunk\", \"size_t chunk_size\", \"void *hash\", \"uint64_t *hash_len\"]],\n    [0x15, \"syscall_cipher_init\", [\"unsigned long state\", \"const void *iv\", \"size_t iv_len\"]],\n    [0x16, \"syscall_cipher_update\", [\"unsigned long state\", \"const void *src\", \"size_t src_len\", \"void *dest\", \"uint64_t *dest_len\"]],\n    [0x17, \"syscall_cipher_final\", [\"unsigned long state\", \"const void *src\", \"size_t src_len\", \"void *dest\", \"uint64_t *dest_len\"]],\n    [0x18, \"syscall_cryp_obj_get_info\", [\"unsigned long obj\", \"TEE_ObjectInfo *info\"]],\n    [0x19, \"syscall_cryp_obj_restrict_usage\", [\"unsigned long obj\", \"unsigned long usage\"]],\n    [0x1a, \"syscall_cryp_obj_get_attr\", [\"unsigned long obj\", \"unsigned long attr_id\", \"void *buffer\", \"uint64_t *size\"]],\n    [0x1b, \"syscall_cryp_obj_alloc\", [\"unsigned long obj_type\", \"unsigned long max_key_size\", \"uint32_t *obj\"]],\n    [0x1c, \"syscall_cryp_obj_close\", [\"unsigned long obj\"]],\n    [0x1d, \"syscall_cryp_obj_reset\", [\"unsigned long obj\"]],\n    [0x1e, \"syscall_cryp_obj_populate\", [\"unsigned long obj\", \"struct utee_attribute *attrs\", \"unsigned long attr_count\"]],\n    [0x1f, \"syscall_cryp_obj_copy\", [\"unsigned long dst_obj\", \"unsigned long src_obj\"]],\n    [0x20, \"syscall_cryp_derive_key\", [\"unsigned long state\", \"const struct utee_attribute *params\", \"unsigned long param_count\", \"unsigned long derived_key\"]],\n    [0x21, \"syscall_cryp_random_number_generate\", [\"void *buf\", \"size_t blen\"]],\n    [0x22, \"syscall_authenc_init\", [\"unsigned long state\", \"const void *nonce\", \"size_t nonce_len\", \"size_t tag_len\", \"size_t aad_len\", \"size_t payload_len\"]],\n    [0x23, \"syscall_authenc_update_aad\", [\"unsigned long state\", \"const void *aad_data\", \"size_t aad_data_len\"]],\n    [0x24, \"syscall_authenc_update_payload\", [\"unsigned long state\", \"const void *src_data\", \"size_t src_len\", \"void *dest_data\", \"uint64_t *dest_len\"]],\n    [0x25, \"syscall_authenc_enc_final\", [\"unsigned long state\", \"const void *src_data\", \"size_t src_len\", \"void *dest_data\", \"uint64_t *dest_len\", \"void *tag\", \"uint64_t *tag_len\"]],\n    [0x26, \"syscall_authenc_dec_final\", [\"unsigned long state\", \"const void *src_data\", \"size_t src_len\", \"void *dest_data\", \"uint64_t *dest_len\", \"const void *tag\", \"uint64_t *tag_len\"]],\n    [0x27, \"syscall_asymm_operate\", [\"unsigned long state\", \"const struct utee_attribute *usr_params\", \"size_t num_params\", \"const void *src_data\", \"size_t src_len\", \"void *dest_data\", \"uint64_t *dest_len\"]],\n    [0x28, \"syscall_asymm_verify\", [\"unsigned long state\", \"const struct utee_attribute *usr_params\", \"size_t num_params\", \"const void *data\", \"size_t data_len\", \"const void *sig\", \"size_t sig_len\"]],\n    [0x29, \"syscall_storage_obj_open\", [\"unsigned long storage_id\", \"void *object_id\", \"size_t object_id_len\", \"unsigned long flags\", \"uint32_t *obj\"]],\n    [0x2a, \"syscall_storage_obj_create\", [\"unsigned long storage_id\", \"void *object_id\", \"size_t object_id_len\", \"unsigned long flags\", \"unsigned long attr\", \"void *data\", \"size_t len\", \"uint32_t *obj\"]],\n    [0x2b, \"syscall_storage_obj_del\", [\"unsigned long obj\"]],\n    [0x2c, \"syscall_storage_obj_rename\", [\"unsigned long obj\", \"void *object_id\", \"size_t object_id_len\"]],\n    [0x2d, \"syscall_storage_alloc_enum\", [\"uint32_t *obj_enum\"]],\n    [0x2e, \"syscall_storage_free_enum\", [\"nsigned long obj_enum\"]],\n    [0x2f, \"syscall_storage_reset_enum\", [\"unsigned long obj_enum\"]],\n    [0x30, \"syscall_storage_start_enum\", [\"unsigned long obj_enum\", \"unsigned long storage_id\"]],\n    [0x31, \"syscall_storage_next_enum\", [\"unsigned long obj_enum\", \"TEE_ObjectInfo *info\", \"void *obj_id\", \"uint64_t *len\"]],\n    [0x32, \"syscall_storage_obj_read\", [\"unsigned long obj\", \"void *data\", \"size_t len\", \"uint64_t *count\"]],\n    [0x33, \"syscall_storage_obj_write\", [\"unsigned long obj\", \"void *data\", \"size_t len\"]],\n    [0x34, \"syscall_storage_obj_trunc\", [\"unsigned long obj, size_t len\"]],\n    [0x35, \"syscall_storage_obj_seek\", [\"unsigned long obj\", \"int32_t offset\", \"unsigned long whence\"]],\n    [0x36, \"syscall_obj_generate_key\", [\"unsigned long obj\", \"unsigned long key_size\", \"const struct utee_attribute *params\", \"unsigned long param_count\"]],\n    [0x37, \"syscall_not_supported\", []],\n    [0x38, \"syscall_not_supported\", []],\n    [0x39, \"syscall_not_supported\", []],\n    [0x3a, \"syscall_not_supported\", []],\n    [0x3b, \"syscall_not_supported\", []],\n    [0x3c, \"syscall_not_supported\", []],\n    [0x3d, \"syscall_not_supported\", []],\n    [0x3e, \"syscall_not_supported\", []],\n    [0x3f, \"syscall_not_supported\", []],\n    [0x40, \"syscall_not_supported\", []],\n    [0x41, \"syscall_not_supported\", []],\n    [0x42, \"syscall_not_supported\", []],\n    [0x43, \"syscall_not_supported\", []],\n    [0x44, \"syscall_not_supported\", []],\n    [0x45, \"syscall_not_supported\", []],\n    [0x46, \"syscall_cache_operation\", [\"void *va, size_t len\", \"unsigned long op\"]],\n]\n\n\n# ARM/ARM64 OP-TEE ldelf (at secure world)\n# - core/include/tee/tee_svc.h\n# - core/include/kernel/ldelf_syscalls.h\narm_ldelf_syscall_list = [ # noqa: F841\n    [0x00, \"syscall_sys_return\", [\"unsigned long ret\"]],\n    [0x01, \"syscall_log\", [\"const void *buf\", \"size_t len\"]],\n    [0x02, \"syscall_panic\", [\"unsigned long code\"]],\n    [0x03, \"ldelf_syscall_map_zi\", [\"vaddr_t *va\", \"size_t num_bytes\", \"size_t pad_begin\", \"size_t pad_end\", \"unsigned long flags\"]],\n    [0x04, \"ldelf_syscall_unmap\", [\"vaddr_t va\", \"size_t num_bytes\"]],\n    [0x05, \"ldelf_syscall_open_bin\", [\"const TEE_UUID *uuid\", \"size_t uuid_size\", \"uint32_t *handle\"]],\n    [0x06, \"ldelf_syscall_close_bin\", [\"unsigned long handle\"]],\n    [0x07, \"ldelf_syscall_map_bin\", [\"vaddr_t *va\", \"size_t num_bytes\", \"unsigned long handle\", \"size_t offs_bytes\", \"size_t pad_begin\", \"size_t pad_end\", \"unsigned long flags\"]],\n    [0x08, \"ldelf_syscall_copy_from_bin\", [\"void *dst\", \"size_t offs\", \"size_t num_bytes\", \"unsigned long handle\"]],\n    [0x09, \"ldelf_syscall_set_prot\", [\"unsigned long va\", \"size_t num_bytes\", \"unsigned long flags\"]],\n    [0x0a, \"ldelf_syscall_remap\", [\"unsigned long old_va\", \"addr_t *new_va\", \"size_t num_bytes\", \"size_t pad_begin\", \"size_t pad_end\"]],\n    [0x0b, \"ldelf_syscall_gen_rnd_num\", [\"void *buf\", \"size_t num_bytes\"]],\n]\n\n\n# x86_16 FreeDOS int 0x21\n# https://en.wikipedia.org/wiki/DOS_API\n# https://stanislavs.org/helppc/int_21.html\n# http://www2.ift.ulaval.ca/~marchand/ift17583/dosints.pdf\nx86_16_dos_syscall_list = [\n    # nr, syscall name, return registers, args, arg registers\n    # 1.0+\n    [0x00, \"ProgramTerminate\", [], [], []],\n    [0x01, \"CharacterInput\", [\"$al\"], [], []],\n    [0x02, \"CharacterOutput\", [], [\"character\"], [\"$dl\"]],\n    [0x03, \"AuxiliaryInput\", [\"$al\"], [], []],\n    [0x04, \"AuxiliaryOutput\", [], [\"character\"], [\"$dl\"]],\n    [0x05, \"PrinterOutput\", [], [\"character\"], [\"$dl\"]],\n    [0x06, \"DirectConsoleIo\", [\"$al\", \"$eflags.zf\"], [\"character\"], [\"$dl\"]],\n    [0x07, \"DirectStdinInputNoEcho\", [\"$al\"], [], []],\n    [0x08, \"ConsoleInputNoEcho\", [\"$al\"], [], []],\n    [0x09, \"DisplayString\", [], [\"string\"], [\"$ds:$dx\"]],\n    [0x0a, \"BufferedKeyboardInput\", [], [\"buffer\"], [\"$ds:$dx\"]],\n    [0x0b, \"GetInputStatus\", [\"$al\"], [], []],\n    [0x0c, \"FlushInputBufferAndInput\", [\"$al\"], [\"function\"], [\"$al\"]],\n    [0x0d, \"DiskReset\", [], [], []],\n    [0x0e, \"SetDefaultDrive\", [\"$al\"], [\"drive_number\"], [\"$dl\"]],\n    [0x0f, \"OpenFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x10, \"CloseFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x11, \"FindFirstFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x12, \"FindNextFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x13, \"DeleteFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x14, \"SequentialRead\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x15, \"SequentialWrite\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x16, \"CreateFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x17, \"RenameFile\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    # 0x18: reserved\n    [0x19, \"GetDefaultDrive\", [\"$al\"], [], []],\n    [0x1a, \"SetDiskTransferAddress\", [], [\"DTA\"], [\"$ds:$dx\"]],\n    [0x1b, \"GetAllocationInfoForDefaultDrive\", [\"$al\", \"$cx\", \"$dx\", \"$ds:$bx\"], [], []],\n    [0x1c, \"GetAllocationInfoForSpecifiedDrive\", [\"$al\", \"$cx\", \"$dx\", \"$ds:$bx\"], [\"drive_number\"], [\"$dl\"]],\n    # 0x1d: reserved\n    # 0x1e: reserved\n    [0x1f, \"GetDiskParameterBlockForDefaultDrive\", [\"$al\"], [\"drive_number\"], [\"$dl\"]],\n    # 0x20: reserved\n    [0x21, \"RandomRead\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x22, \"RandomWrite\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x23, \"GetFileSizeInRecords\", [\"$al\"], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x24, \"SetRandomRecordNumber\", [], [\"FCB\"], [\"$ds:$dx\"]],\n    [0x25, \"SetInterruptVector\", [], [\"interrupt_number\", \"handler\"], [\"$al\", \"$ds:$dx\"]],\n    [0x26, \"CreatePSP\", [], [\"segment_number\"], [\"$dx\"]],\n    [0x27, \"RandomBlockRead\", [\"$al\", \"$cx\"], [\"FCB\", \"record_count\"], [\"$ds:$dx\", \"$cx\"]],\n    [0x28, \"RandomBlockWrite\", [\"$al\", \"$cx\"], [\"FCB\", \"record_count\"], [\"$ds:$dx\", \"$cx\"]],\n    [0x29, \"ParseFilename\", [\"$al\", \"$ds:$si\", \"$es:$di\"], [\"control\", \"string\", \"buffer\"], [\"$al\", \"$ds:$si\", \"$es:$di\"]],\n    [0x2a, \"GetDate\", [\"$al\", \"$cx\", \"$dh\", \"$dl\"], [], []],\n    [0x2b, \"SetDate\", [\"$al\"], [\"year\", \"month\", \"day\"], [\"$cx\", \"$dh\", \"$dl\"]],\n    [0x2c, \"GetTime\", [\"$ch\", \"$cl\", \"$dh\", \"$dl\"], [], []],\n    [0x2d, \"SetTime\", [\"$al\"], [\"hour\", \"minutes\", \"seconds\", \"hundredths\"], [\"$ch\", \"$cl\", \"$dh\", \"$dl\"]],\n    [0x2e, \"SetVerifyFlag\", [], [\"verify_flag\", \"0\"], [\"$al\", \"$dl\"]],\n    # 2.0+\n    [0x2f, \"GetDiskTransferAddress\", [\"$es:$bx\"], [], []],\n    [0x30, \"GetDosVersion\", [\"$al\", \"$ah\", \"$bh\", \"$bl\", \"$cx\"], [], []],\n    [0x31, \"TerminateAndStayResident\", [], [\"exit_code\", \"program_size\"], [\"$al\", \"$dx\"]],\n    [0x32, \"GetDiskParameterBlock\", [\"$al\", \"$ds:$bx\"], [\"drive\"], [\"$dl\"]],\n    [0x33, \"GetOrSetCtrlBreak\", [\"$al\", \"$dl\"], [\"subfunction\", \"value\"], [\"$al\", \"$dl\"]],\n    [0x34, \"GetDosCriticalFlagPointer\", [\"$es:$bx\"], [], []],\n    [0x35, \"GetInterruptVector\", [\"$es:$bx\"], [\"interrupt_number\"], [\"$al\"]],\n    [0x36, \"GetFreeDiskSpace\", [\"$ax\", \"$bx\", \"$cx\", \"$dx\"], [\"drive_number\"], [\"$dl\"]],\n    [0x37, \"GetOrSetSwitchCharacter\", [\"$al\", \"$dl\"], [\"subfunction\", \"value\"], [\"$al\", \"$dl\"]],\n    [0x38, \"GetOrSetCountryInfo\", [\"$ax\", \"$bx\", \"$ds:$dx\"], [\"subfunction\", \"country_code\", \"buffer\"], [\"$al\", \"$bx\", \"$ds:dx\"]],\n    [0x39, \"CreateSubDirectory\", [\"$ax\"], [\"pathname\"], [\"$ds:$dx\"]],\n    [0x3a, \"RemoveSubDirectory\", [\"$ax\"], [\"pathname\"], [\"$ds:$dx\"]],\n    [0x3b, \"ChangeCurrentDirectory\", [\"$ax\"], [\"pathname\"], [\"$ds:$dx\"]],\n    [0x3c, \"CreateFile\", [\"$ax\"], [\"pathname\", \"attribute\"], [\"$ds:$dx\", \"$cx\"]],\n    [0x3d, \"OpenFile\", [\"$ax\"], [\"mode\", \"pathname\"], [\"$al\", \"$ds:$dx\"]],\n    [0x3e, \"CloseFile\", [\"$ax\"], [\"handle\"], [\"$bx\"]],\n    [0x3f, \"ReadFileOrDevice\", [\"$ax\"], [\"handle\", \"size\"], [\"$bx\", \"$cx\", \"$ds:$dx\"]],\n    [0x40, \"WriteFileOrDevice\", [\"$ax\"], [\"handle\", \"size\", \"buffer\"], [\"$bx\", \"$cx\", \"$ds:$dx\"]],\n    [0x41, \"DeleteFile\", [\"$ax\"], [\"pathname\"], [\"$ds:$dx\"]],\n    [0x42, \"SeekFile\", [\"$dx\", \"$ax\"], [\"origin\", \"handle\", \"move_size_high\", \"move_size_low\"], [\"$al\", \"$bx\", \"$cx\", \"$dx\"]],\n    [0x43, \"GetOrSetFileAttributes\", [\"$ax\", \"$cx\"], [\"subfunction\", \"pathname\", \"attribute\"], [\"$al\", \"$ds:$dx\", \"$cx\"]],\n    [0x44, \"IoControlForDevices\", [\"$ax\", \"$dx\"], [\"subfunction\", \"arg1\", \"arg2\", \"arg3\"], [\"$al\", \"$bx\", \"$cx\", \"$ds:$dx\"]],\n    [0x45, \"DuplicateHandle\", [\"$ax\"], [\"handle\"], [\"$bx\"]],\n    [0x46, \"RedirectHandle\", [\"$ax\"], [\"old_handle\", \"new_handle\"], [\"$bx\", \"$cx\"]],\n    [0x47, \"GetCurrentDirectory\", [\"$ds:$si\", \"$ax\"], [\"drive_number\", \"buffer\"], [\"$dl\", \"$ds:$si\"]],\n    [0x48, \"AllocateMemory\", [\"$ax\", \"$bx\"], [\"block_size\"], [\"$bx\"]],\n    [0x49, \"ReleaseMemory\", [\"$ax\"], [\"segment\"], [\"$es\"]],\n    [0x4a, \"ReallocateMemory\", [\"$ax\", \"$bx\"], [\"new_block_size\", \"segment\"], [\"$bx\", \"$es\"]],\n    [0x4b, \"ExecuteProgram\", [\"$ax\", \"$es:$bx\"], [\"subfunction\", \"pathname\", \"parameter\"], [\"$al\", \"$ds:$dx\", \"$es:$bx\"]],\n    [0x4c, \"TerminateWithReturnCode\", [], [\"return_code\"], [\"$al\"]],\n    [0x4d, \"GetProgramReturnCode\", [\"$ah\", \"$al\"], [], []],\n    [0x4e, \"FindFirstFile\", [\"$ax\"], [\"pathname\", \"attribute\"], [\"$ds:$dx\", \"$cx\"]], # DTA omitted\n    [0x4f, \"FindNextFile\", [\"$ax\"], [\"pathname\"], [\"$ds:$dx\"]], # DTA omitted\n    [0x50, \"SetCurrentPSP\", [], [\"segment\"], [\"$bx\"]],\n    [0x51, \"GetCurrentPSP\", [\"$bx\"], [], []],\n    [0x52, \"GetListOfLists\", [\"$es:$bx\"], [], []],\n    [0x53, \"CreateDiskParameterBlock\", [\"$es:$bp\"], [\"bios_parameter\", \"buffer\"], [\"$ds:si\", \"$es:$bp\"]],\n    [0x54, \"GetVerifyFlag\", [\"$al\"], [], []],\n    [0x55, \"CreateProgramPSP\", [], [\"segment\", \"size\"], [\"$dx\", \"$si\"]],\n    [0x56, \"RenameFile\", [\"$ax\"], [\"old_pathname\", \"new_pathname\"], [\"$ds:$dx\", \"$es:$di\"]],\n    [0x57, \"GetOrSetFileDateAndTime\", [\"$ax\", \"$cx\", \"$dx\"], [\"subfunction\", \"handle\", \"time\", \"date\", \"buffer\"], [\"$al\", \"$bx\", \"$cx\", \"$dx\", \"$es:$di\"]],\n    # 2.11+\n    [0x58, \"GetOrSetAllocationStrategy\", [\"$ax\"], [\"subfunction\", \"strategy\"], [\"$al\", \"$bx\"]],\n    # 3.0+\n    [0x59, \"GetExtendedErrorInfo\", [\"$ax\", \"$bh\", \"$bl\", \"$ch\"], [\"0\"], [\"$bx\"]],\n    [0x5a, \"CreateTempFile\", [\"$ax\", \"$ds:$dx\"], [\"pathname\", \"attribute\"], [\"$ds:$dx\", \"$cx\"]],\n    [0x5b, \"CreateNewFile\", [\"$ax\"], [\"pathname\", \"attribute\"], [\"$ds:$dx\", \"$cx\"]],\n    [0x5c, \"LockOrUnlockFile\", [\"$ax\"], [\"subfunction\", \"handle\", \"offset_high\", \"offset_low\", \"length_high\", \"length_low\"], [\"$al\", \"$bx\", \"$cx\", \"$dx\", \"$si\", \"$di\"]],\n    [0x5d, \"FileSharingFunctions\", [\"$ds:$si\"], [\"subfunction\", \"arg1\"], [\"$al\", \"$ds:$dx\"]],\n    [0x5e, \"NetworkFunctions\", [\"$ax\"], [\"subfunction\"], [\"$al\"]], # too complicated\n    [0x5f, \"NetworkRedirectionFunctions\", [\"$ax\"], [\"subfunction\"], [\"$al\"]], # too complicated\n    [0x60, \"QualifyFilename\", [\"$es:$di\", \"$ah\"], [\"pathname\", \"buffer\"], [\"$ds:$si\", \"$es:$di\"]],\n    # 0x61: reserved\n    [0x62, \"GetCurrentPSP\", [\"$bx\"], [], []],\n    [0x63, \"GetLeadByteTable\", [\"$ax\", \"$ds:$si\", \"$dl\"], [\"subfunction\", \"flag\"], [\"$al\", \"$dl\"]],\n    # 3.2+\n    [0x64, \"SetDeviceDriverLookAhead\", [\"$dl\"], [\"subfunction\", \"arg1\"], [\"$al\", \"$dl\"]],\n    # 3.3+\n    [0x65, \"GetExtendedCountryInfo\", [\"$ax\"], [\"subfunction\"], [\"$al\"]], # too complicated\n    [0x66, \"GetOrSetGlobalCodePage\", [\"$ax\", \"$bx\", \"$cx\"], [\"subfunction\", \"active_codepage\", \"system_codepage\"], [\"$al\", \"$bx\", \"$dx\"]],\n    [0x67, \"SetHandleCount\", [\"$ax\"], [\"max_handle_count\"], [\"$bx\"]],\n    [0x68, \"CommitFile\", [\"$ax\"], [\"handle\"], [\"$bx\"]],\n    # 4.0+\n    [0x69, \"GetOrSetMediaId\", [\"$ax\", \"$ds:$dx\"], [\"subfunction\", \"drive_number\", \"buffer\"], [\"$al\", \"$bl\", \"$ds:$dx\"]],\n    # 0x6a: reserved\n    # 0x6b: reserved\n    [0x6c, \"ExtendedOpenCreateFile\", [\"$ax\", \"$cx\"], [\"0\", \"mode\", \"attribute\", \"control\", \"spec\"], [\"$al\", \"$bx\", \"$cx\", \"$dx\", \"$ds:$si\"]],\n]\n\n\nclass Syscall:\n    \"\"\"A collection of utility functions that are related to syscall tables.\"\"\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def parse_common_syscall_defs():\n        \"\"\"Parse and return a common definition of a syscall, common to all architectures.\"\"\"\n        sc_defs = [\n            syscall_defs,\n            syscall_defs_compat,\n        ]\n        dic = {}\n        for defs in sc_defs:\n            for line in defs.splitlines():\n                if line == \"\":\n                    continue\n                if line.startswith(\"#\"):\n                    continue\n                # ignore `!`\n                m = re.search(r\"asmlinkage\\s+(?:long|ssize_t)\\s+(\\S+)\\((.+?)\\);\", line)\n                if not m:\n                    continue\n                name, args = m.group(1), m.group(2)\n                args = [x.strip() for x in args.split(\",\")]\n                if name in dic:\n                    err(\"Duplicate: {:s}\".format(name))\n                    raise\n                if len(args) == 1 and args[0] == \"void\":\n                    dic[name] = []\n                else:\n                    dic[name] = args\n        return dic\n\n    @staticmethod\n    def parse_syscall_table_defs(table_defs):\n        \"\"\"Parse and return syscall table defines for a specified architecture.\"\"\"\n        table = []\n        for line in table_defs.splitlines():\n            if line == \"\":\n                continue\n            if line.startswith(\"#\"):\n                continue\n            entry = line.split()\n            if len(entry) == 3: # it is unimplemented\n                continue\n            entry[0] = int(entry[0])\n            table.append(entry)\n        return table\n\n    @staticmethod\n    def make_syscall_list_x86_64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(x64_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_modify_ldt\": [\n                \"int func\", \"void __user *ptr\", \"unsigned long bytecount\",\n            ], # arch/x86/kernel/ldt.c\n            \"sys_arch_prctl\": [\n                \"int option\", \"unsigned long arg2\",\n            ], # arch/x86/kernel/process_64.c\n            \"sys_iopl\": [\n                \"unsigned int level\",\n            ], # arch/x86/kernel/ioport.c\n            \"compat_sys_x32_rt_sigreturn\": [], # arch/x86/kernel/signal.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\",\n            ], # arch/x86/kernel/sys_x86_64.c\n            \"sys_rt_sigreturn\": [], # arch/x86/kernel/signal.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # include/linux/syscalls.h\n        }\n\n        syscall_list = []\n        __X32_SYSCALL_BIT = 0x4000_0000\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            if abi not in [\"common\", \"64\", \"x32\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                if abi in [\"common\", \"64\"]:\n                    syscall_list.append([nr, name, arch_specific_dic[func]])\n                if abi in [\"common\", \"x32\"]:\n                    syscall_list.append([nr + __X32_SYSCALL_BIT, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            if abi in [\"common\", \"64\"]:\n                syscall_list.append([nr, name, sc_def[func]])\n            if abi in [\"common\", \"x32\"]:\n                syscall_list.append([nr + __X32_SYSCALL_BIT, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_x86_32_emulated():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(x86_syscall_tbl)\n        arch_specific_dic = {\n            \"compat_sys_sigreturn\": [], # arch/x86/ia32/ia32_signal.c\n            \"compat_sys_rt_sigreturn\": [], # arch/x86/ia32/ia32_signal.c\n            \"compat_sys_old_getrlimit\": [\n                \"unsigned int resource\", \"struct compat_rlimit *rlim\",\n            ], # kernel/sys.c\n            \"compat_sys_ia32_mmap\": [\n                \"struct mmap_arg_struct32 __user *arg\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_iopl\": [\n                \"unsigned int level\",\n            ], # arch/x86/kernel/ioport.c\n            \"compat_sys_ia32_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls_val\", \"int __user *child_tidptr\",\n            ], # arch/x86/kernel/sys_ia32.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_modify_ldt\": [\n                \"int func\", \"void __user *ptr\", \"unsigned long bytecount\",\n            ], # arch/x86/kernel/ldt.c\n            \"sys_ia32_pread64\": [\n                \"unsigned int fd\", \"char __user *ubuf\", \"u32 count\", \"u32 poslo\", \"u32 poshi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_pwrite64\": [\n                \"unsigned int fd\", \"const char __user *ubuf\", \"u32 count\", \"u32 poslo\", \"u32 poshi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_truncate64\": [\n                \"const char __user *filename\", \"unsigned long offset_low\", \"unsigned long offset_high\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_ftruncate64\": [\n                \"unsigned int fd\", \"unsigned long offset_low\", \"unsigned long offset_high\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"compat_sys_ia32_stat64\": [\n                \"const char __user *filename\", \"struct stat64 __user *statbuf\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"compat_sys_ia32_lstat64\": [\n                \"const char __user *filename\", \"struct stat64 __user *statbuf\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"compat_sys_ia32_fstat64\": [\n                \"unsigned long fd\", \"struct stat64 __user *statbuf\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_readahead\": [\n                \"int fd\", \"unsigned int off_lo\", \"unsigned int off_high\", \"size_t count\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_set_thread_area\": [\n                \"struct user_desc __user *u_info\",\n            ], # arch/x86/kernel/tls.c\n            \"sys_get_thread_area\": [\n                \"struct user_desc __user *u_info\",\n            ], # arch/x86/kernel/tls.c\n            \"sys_ia32_fadvise64\": [\n                \"int fd\", \"unsigned int offset_lo\", \"unsigned int offset_hi\", \"size_t len\", \"int advice\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_fadvise64_64\": [\n                \"int fd\", \"__u32 offset_low\", \"__u32 offset_high\", \"__u32 len_low\", \"__u32 len_high\", \"int advice\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"compat_sys_ia32_fstatat64\": [\n                \"unsigned int dfd\", \"const char __user *filename\", \"struct stat64 __user *statbuf\", \"int flag\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_sync_file_range\": [\n                \"int fd\", \"unsigned int off_low\", \"unsigned int off_hi\", \"unsigned int n_low\",\n                \"unsigned int n_hi\", \"unsigned int flags\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_fallocate\": [\n                \"int fd\", \"int mode\", \"unsigned int offset_lo\", \"unsigned int offset_hi\",\n                \"unsigned int len_lo\", \"unsigned int len_hi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_arch_prctl\": [\n                \"int option\", \"unsigned long arg2\",\n            ], # arch/x86/kernel/process_64.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            if len(entry) == 5:\n                nr, abi, name, _, func = entry # use compat\n            else:\n                nr, abi, name, func = entry[:4]\n            if abi != \"i386\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_x86_32_native():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(x86_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_iopl\": [\n                \"unsigned int level\",\n            ], # arch/x86/kernel/ioport.c\n            \"sys_vm86old\": [\n                \"struct vm86_struct __user *user_vm86\",\n            ], # arch/x86/kernel/vm86_32.c\n            \"sys_sigreturn\": [], # arch/x86/kernel/signal.c\n            \"sys_rt_sigreturn\": [], # arch/x86/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_modify_ldt\": [\n                \"int func\", \"void __user *ptr\", \"unsigned long bytecount\",\n            ], # arch/x86/kernel/ldt.c\n            \"sys_vm86\": [\n                \"unsigned long cmd\", \"unsigned long arg\",\n            ], # arch/x86/kernel/vm86_32.c\n            \"sys_ia32_pread64\": [\n                \"unsigned int fd\", \"char __user *ubuf\", \"u32 count\", \"u32 poslo\", \"u32 poshi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_pwrite64\": [\n                \"unsigned int fd\", \"const char __user *ubuf\", \"u32 count\", \"u32 poslo\", \"u32 poshi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_truncate64\": [\n                \"const char __user *filename\", \"unsigned long offset_low\", \"unsigned long offset_high\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_ftruncate64\": [\n                \"unsigned int fd\", \"unsigned long offset_low\", \"unsigned long offset_high\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_readahead\": [\n                \"int fd\", \"unsigned int off_lo\", \"unsigned int off_high\", \"size_t count\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_set_thread_area\": [\n                \"struct user_desc __user *u_info\",\n            ], # arch/x86/kernel/tls.c\n            \"sys_get_thread_area\": [\n                \"struct user_desc __user *u_info\",\n            ], # arch/x86/kernel/tls.c\n            \"sys_ia32_fadvise64\": [\n                \"int fd\", \"unsigned int offset_lo\", \"unsigned int offset_hi\", \"size_t len\", \"int advice\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_fadvise64_64\": [\n                \"int fd\", \"__u32 offset_low\", \"__u32 offset_high\", \"__u32 len_low\", \"__u32 len_high\", \"int advice\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_sync_file_range\": [\n                \"int fd\", \"unsigned int off_low\", \"unsigned int off_hi\", \"unsigned int n_low\",\n                \"unsigned int n_hi\", \"unsigned int flags\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_ia32_fallocate\": [\n                \"int fd\", \"int mode\", \"unsigned int offset_lo\", \"unsigned int offset_hi\",\n                \"unsigned int len_lo\", \"unsigned int len_hi\",\n            ], # arch/x86/kernel/sys_ia32.c\n            \"sys_arch_prctl\": [\n                \"int option\", \"unsigned long arg2\",\n            ], # arch/x86/kernel/process_32.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"unsigned int mask_1\",\n                \"unsigned int mask_2\", \"int dfd\", \"const char __user *pathname\",\n            ], # include/linux/syscalls.h\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi != \"i386\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_arm64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(arm64_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_rt_sigreturn\": [], # arch/arm64/kernel/signal.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\",\n            ], # arch/arm64/kernel/sys.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # include/linux/syscalls.h\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/arm64/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"64\", \"renameat\", \"rlimit\", \"memfd_secret\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_arm32_emulated():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(arm_compat_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"compat_sys_aarch32_pread64\": [\n                \"unsigned int fd\", \"char *buf\", \"size_t count\", \"u32 __pad\", \"arg_u32p(pos)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_pwrite64\": [\n                \"unsigned int fd\", \"const char *buf\", \"size_t count\", \"u32 __pad\", \"arg_u32p(pos)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off_4k\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_truncate64\": [\n                \"const char *path\", \"u32 __pad\", \"arg_u32p(length)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_ftruncate64\": [\n                \"unsigned int fd\", \"u32 __pad\", \"arg_u32p(length)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_readahead\": [\n                \"int fd\", \"u32 __pad\", \"arg_u32(offset)\", \"size_t count\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_statfs64\": [\n                \"const char *pathname\", \"compat_size_t sz\", \"struct compat_statfs64 *buf\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_fstatfs64\": [\n                \"unsigned int fd\", \"compat_size_t sz\", \"struct compat_statfs64 *buf\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"arg_u32p(offset)\", \"arg_u32p(len)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_sync_file_range2\": [\n                \"int fd\", \"unsigned int flags\", \"arg_u32p(offset)\", \"arg_u32p(nbytes)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_aarch32_fallocate\": [\n                \"int fd\", \"int mode\", \"arg_u32p(offset)\", \"arg_u32p(len)\",\n            ], # arch/arm64/kernel/sys32.c\n            \"compat_sys_old_semctl\": [\n                \"int semid\", \"int semnum\", \"int cmd\", \"int arg\",\n            ], # ipc/sem.c\n            \"compat_sys_old_msgctl\": [\n                \"int msqid\", \"int cmd\", \"void *uptr\",\n            ], # ipc/msg.c\n            \"compat_sys_old_shmctl\": [\n                \"int shmid\", \"int cmd\", \"void *uptr\",\n            ], # ipc/shm.c\n            \"compat_sys_sigreturn\": [], # arch/arm64/kernel/signal32.c\n            \"compat_sys_rt_sigreturn\": [], # arch/arm64/kernel/signal32.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            if len(entry) == 5:\n                nr, abi, name, _, func = entry # use compat\n            else:\n                nr, abi, name, func = entry[:4]\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n\n        arch_specific_extra = [\n            [0xf0002, \"cacheflush\", [\n                \"unsigned long start\", \"unsigned long end\", \"int flags\",\n            ]], # arch/arm64/kernel/sys_compat.c\n            [0xf0005, \"set_tls\", [\n                \"unsigned long val\",\n            ]], # arch/arm64/kernel/sys_compat.c\n        ]\n        syscall_list += arch_specific_extra\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_arm32_native():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(arm_native_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # include/asm-generic/syscalls.h\n            \"sys_sigreturn_wrapper\": [], # arch/arm/kernel/entry-common.S\n            \"sys_rt_sigreturn_wrapper\": [], # arch/arm/kernel/entry-common.S\n            \"sys_statfs64_wrapper\": [\n                \"const char __user *path\", \"size_t sz\", \"struct statfs64 __user *buf\",\n            ], # arch/arm/kernel/entry-common.S\n            \"sys_fstatfs64_wrapper\": [\n                \"unsigned int fd\", \"size_t sz\", \"struct statfs64 __user *buf\",\n            ], # arch/arm/kernel/entry-common.S\n            \"sys_arm_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"loff_t offset\", \"loff_t len\",\n            ], # arch/arm/kernel/sys_arm.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use OABI\n            if abi not in [\"common\", \"eabi\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n\n        arch_specific_extra = [\n            [0xf0001, \"breakpoint\", []], # arch/arm/kernel/traps.c\n            [0xf0002, \"cacheflush\", [\n                \"unsigned long start\", \"unsigned long end\", \"int flags\",\n            ]], # arch/arm/kernel/traps.c\n            [0xf0003, \"usr26\", []], # arch/arm/kernel/traps.c\n            [0xf0004, \"usr32\", []], # arch/arm/kernel/traps.c\n            [0xf0005, \"set_tls\", [\n                \"unsigned long val\",\n            ]], # arch/arm/kernel/traps.c\n            [0xf0006, \"get_tls\", []], # arch/arm/kernel/traps.c\n        ]\n        syscall_list += arch_specific_extra\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_mips32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(mips_o32_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_syscall\": [\"...\"], #\n            \"__sys_fork\": [], #\n            \"sys_rt_sigreturn\": [], # arch/mips/kernel/signal.c\n            \"sysm_pipe\": [], # arch/mips/kernel/syscall.c\n            \"sys_mips_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/mips/kernel/syscall.c\n            \"sys_sigreturn\": [], #\n            \"__sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long bytes\", \"unsigned int cache\",\n            ], # arch/mips/mm/cache.c\n            \"sys_cachectl\": [\n                \"char *addr\", \"int nbytes\", \"int op\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_sysmips\": [\n                \"long cmd\", \"long arg1\", \"long arg2\",\n            ], # arch/mips/kernel/syscall.c\n            \"sys_mips_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/mips/kernel/syscall.c\n            \"sys_set_thread_area\": [\n                \"unsigned long addr\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], #\n            \"sys_sigsuspend\": [\n                \"sigset_t __user *uset\",\n            ], # arch/mips/kernel/signal.c\n            \"sys_sigaction\": [\n                \"int sig2\", \"const struct sigaction __user *act\", \"struct sigaction __user *oact\",\n            ], # arch/mips/kernel/signal.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi != \"o32\":\n                continue\n            nr += 4000 # arch/mips/include/asm/unistd.h\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_mipsn32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(mips_n32_syscall_tbl)\n        arch_specific_dic = {\n            \"__sys_fork\": [], #\n            \"sysm_pipe\": [], # arch/mips/kernel/syscall.c\n            \"sys_mips_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long bytes\", \"unsigned int cache\",\n            ], # arch/mips/mm/cache.c\n            \"sys_cachectl\": [\n                \"char *addr\", \"int nbytes\", \"int op\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_sysmips\": [\n                \"long cmd\", \"long arg1\", \"long arg2\",\n            ], # arch/mips/kernel/syscall.c\n            \"sys_set_thread_area\": [\n                \"unsigned long addr\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], #\n            \"compat_sys_old_shmctl\": [\n                \"int shmid\", \"int cmd\", \"void *uptr\",\n            ], # ipc/shm.c\n            \"compat_sys_old_semctl\": [\n                \"int semid\", \"int semnum\", \"int cmd\", \"int arg\",\n            ], # ipc/sem.c\n            \"compat_sys_old_msgctl\": [\n                \"int msqid\", \"int cmd\", \"void *uptr\",\n            ], # ipc/msg.c\n            \"sys_32_personality\": [\n                \"unsigned long personality\",\n            ], # arch/mips/kernel/linux32.c\n            \"sysn32_rt_sigreturn\": [], # arch/mips/kernel/signal_n32.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi != \"n32\":\n                continue\n            nr += 6000 # arch/mips/include/asm/unistd.h\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_mips64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(mips_n64_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_mips_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/mips/kernel/syscall.c\n            \"sysm_pipe\": [], # arch/mips/kernel/syscall.c\n            \"__sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"__sys_fork\": [], #\n            \"sys_rt_sigreturn\": [], # arch/mips/kernel/signal.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long bytes\", \"unsigned int cache\",\n            ], # arch/mips/mm/cache.c\n            \"sys_cachectl\": [\n                \"char *addr\", \"int nbytes\", \"int op\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_sysmips\": [\n                \"long cmd\", \"long arg1\", \"long arg2\",\n            ], # arch/mips/kernel/syscall.c\n            \"sys_set_thread_area\": [\n                \"unsigned long addr\",\n            ], # arch/mips/kernel/syscall.c\n            \"__sys_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], #\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi != \"n64\":\n                continue\n            nr += 5000 # arch/mips/include/asm/unistd.h\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_ppc32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(ppc_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_sigreturn\": [], # arch/powerpc/kernel/signal_32.c\n            \"sys_rt_sigreturn\": [], # arch/powerpc/kernel/signal_32.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"size_t len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"size_t len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_swapcontext\": [\n                \"struct ucontext __user *old_ctx\", \"struct ucontext __user *new_ctx\", \"long ctx_size\",\n            ], # arch/powerpc/kernel/signal_32.c\n            \"ppc_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"u32 offset_high\", \"u32 offset_low\", \"u32 len_high\", \"u32 len_low\",\n            ], # arch/poerpc/kernel/syscalls.c\n            \"sys_rtas\": [\n                \"struct rtas_args __user *uargs\",\n            ], # arch/powerpc/include/asm/syscalls.h\n            \"sys_debug_setcontext\": [\n                \"struct ucontext __user *ctx\", \"int ndbg\", \"struct sig_dbg_op __user *dbg\",\n            ], # arch/powerpc/kernel/signal_32.c\n            \"sys_subpage_prot\": [\n                \"unsigned long addr\", \"unsigned long len\", \"u32 __user *map\",\n            ], # arch/powerpc/mm/book3s64/subpage_prot.c\n            \"sys_ppc_pread64\": [\n                \"unsigned int fd\", \"char __user *ubuf\", \"compat_size_t count\", \"u32 reg6\", \"u32 pos1\", \"u32 pos2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_pwrite64\": [\n                \"unsigned int fd\", \"const char __user *ubuf\", \"compat_size_t count\", \"u32 reg6\", \"u32 pos1\", \"u32 pos2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_readahead\": [\n                \"int fd\", \"u32 r4\", \"u32 offset1\", \"u32 offset2\", \"u32 count\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_truncate64\": [\n                \"const char __user *path\", \"u32 reg4\", \"unsigned long len1\", \"unsigned long len2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_ftruncate64\": [\n                \"unsigned int fd\", \"u32 reg4\", \"unsigned long len1\", \"unsigned long len2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc32_fadvise64\": [\n                \"int fd\", \"u32 unused\", \"u32 offset1\", \"u32 offset2\", \"size_t len\", \"int advice\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"u32 offset_high\", \"u32 offset_low\", \"u32 len_high\", \"u32 len_low\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_ppc_sync_file_range2\": [\n                \"int fd\", \"unsigned int flags\", \"unsigned int offset1\", \"unsigned int offset2\",\n                \"unsigned int nbytes1\", \"unsigned int nbytes2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_ppc_fallocate\": [\n                \"int fd\", \"int mode\", \"u32 offset1\", \"u32 offset2\", \"u32 len1\", \"u32 len2\",\n            ], # arch/powerpc/kernel/sys_ppc32.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"unsigned int mask_1\",\n                \"unsigned int mask_2\", \"int dfd\", \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"32\", \"nospu\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_ppc64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(ppc_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int __user *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_rt_sigreturn\": [], # arch/powerpc/kernel/signal_64.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"size_t len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"size_t len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_ppc64_personality\": [\n                \"unsigned long personality\",\n            ], # arch/powerpc/kernel/syscalls.c\n            \"sys_swapcontext\": [\n                \"struct ucontext __user *old_ctx\", \"struct ucontext __user *new_ctx\", \"long ctx_size\",\n            ], # arch/powerpc/kernel/signal_64.c\n            \"sys_rtas\": [\n                \"struct rtas_args __user *uargs\",\n            ], # arch/powerpc/include/asm/syscalls.h\n            \"sys_subpage_prot\": [\n                \"unsigned long addr\", \"unsigned long len\", \"u32 __user *map\",\n            ], # arch/powerpc/mm/book3s64/subpage_prot.c\n            \"sys_switch_endian\": [], # arch/powerpc/kernel/syscalls.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"64\", \"nospu\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_sparc32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(sparc_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\"\n            ], # arch/sparc/kernel/sys_sparc_32.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\"\n            ], # arch/sparc/kernel/sys_sparc_32.c\n            \"sunos_execv\": [\n                \"const char __user *filename\", \"const char __user *const __user *argv\",\n                \"const char __user *const __user *envp\",\n            ], # arch/sparc/kernel/entry.S\n            \"sys_sparc_pipe\": [], # arch/sparc/kernel/sys_sparc_32.c\n            \"sys_getpagesize\": [], # arch/sparc/kernel/sys_sparc_32.c\n            \"sys_getdomainname\": [\n                \"char __user *name\", \"int len\"\n            ], # arch/sparc/kernel/sys_sparc_32.c\n            \"sys_sparc_remap_file_pages\": [\n                \"unsigned long start\", \"unsigned long size\", \"unsigned long prot\",\n                \"unsigned long pgoff\", \"unsigned long flags\",\n            ], # kernel/sys_sparc_32.c\n            \"sys_sparc_sigaction\": [\n                \"int, sig\", \"struct old_sigaction __user *act\", \"struct old_sigaction __user *oact\",\n            ], # arch/sparc/kernel/sys_sparc_32.c\n            \"sys_sigreturn\": [], # arch/sparc/kernel/syscalls.S\n            \"sys_rt_sigreturn\": [], # arch/sparc/kernel/syscalls.S\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"32\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func in [\"sys_ni_syscall\", \"sys_nis_syscall\"]:\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_sparc64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(sparc_syscall_tbl)\n        arch_specific_dic = {\n            \"sparc_exit\": [\n                \"int error_code\",\n            ], # arch/sparc/kernel/syscalls.S\n            \"sys_sparc_pipe\": [], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_memory_ordering\": [\n                \"unsigned long model\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys64_execve\": [\n                \"const char __user *filename\", \"const char __user *const __user *argv\",\n                \"const char __user *const __user *envp\",\n            ], # arch/sparc/kernel/syscalls.S\n            \"sys_getpagesize\": [], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_64_munmap\": [\n                \"unsigned long addr\", \"size_t len\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_getdomainname\": [\n                \"char __user *name\", \"int len\"\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_utrap_install\": [\n                \"utrap_entry_t type\", \"utrap_handler_t new_p\", \"utrap_handler_t new_d\",\n                \"utrap_handler_t __user * old_p\", \"utrap_handler_t __user *old_d\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sparc_exit_group\": [\n                \"int error_code\",\n            ], # arch/sparc/kernel/syscalls.S\n            \"sys_sparc64_personality\": [\n                \"unsigned long personality\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_sparc_ipc\": [\n                \"unsigned int call\", \"int first\", \"unsigned long second\",\n                \"unsigned long third\", \"void __user *ptr\", \"long fifth\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_sparc_adjtimex\": [\n                \"struct __kernel_timex __user *txc_p\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\"\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_64_mremap\": [\n                \"unsigned long addr\", \"unsigned long old_len\", \"unsigned long new_len\",\n                \"unsigned long flags\", \"unsigned long new_addr\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_sparc_clock_adjtime\": [\n                \"const clockid_t which_clock\", \"struct __kernel_timex __user *txc_p\",\n            ], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys_kern_features\": [], # arch/sparc/kernel/sys_sparc_64.c\n            \"sys64_execveat\": [\n                \"int dfd\", \"const char __user *filename\", \"const char __user *const __user *argv\",\n                \"const char __user *const __user *envp\", \"int flags\",\n            ] ,# arch/sparc/kernel/syscalls.S\n            \"sys_rt_sigreturn\": [\n                \"struct pt_regs *regs\",\n            ], # arch/sparc/kernel/signal_64.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"64\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func in [\"sys_ni_syscall\", \"sys_nis_syscall\"]:\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_riscv32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(riscv32_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_rt_sigreturn\": [], # arch/riscv/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/riscv/kernel/sys_riscv.c\"\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_riscv_flush_icache\": [\n                \"uintptr_t start\", \"uintptr_t end\", \"uintptr_t flags\",\n            ], # arch/riscv/kernel/sys_riscv.c\n            \"sys_riscv_hwprobe\": [\n                \"struct riscv_hwprobe __user *pairs\", \"size_t pair_count\", \"size_t cpusetsize\",\n                \"unsigned long __user *cpus\", \"unsigned int flags\",\n            ], # arch/riscv/kernel/sys_hwprobe.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/riscv/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"32\", \"riscv\", \"memfd_secret\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_riscv64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(riscv64_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_rt_sigreturn\": [], # arch/riscv/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"off_t offset\",\n            ], # arch/riscv/kernel/sys_riscv.c\"\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_riscv_flush_icache\": [\n                \"uintptr_t start\", \"uintptr_t end\", \"uintptr_t flags\",\n            ], # arch/riscv/kernel/sys_riscv.c\n            \"sys_riscv_hwprobe\": [\n                \"struct riscv_hwprobe __user *pairs\", \"size_t pair_count\", \"size_t cpusetsize\",\n                \"unsigned long __user *cpus\", \"unsigned int flags\",\n            ], # arch/riscv/kernel/sys_hwprobe.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/riscv/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"64\", \"riscv\", \"rlimit\", \"memfd_secret\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_s390x():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(s390x_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_s390_ipc\": [\n                \"uint, call\", \"int first\", \"unsigned long second\",\n                \"unsigned long third\", \"void __user *ptr\",\n            ], # arch/s390/kernel/syscall.c\n            \"sys_sigreturn\": [], # arch/s390/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int stack_size\",\n                \"int __user *parent_tidptr\", \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS2)\n            \"sys_s390_personality\": [\n                \"unsigned int personality\",\n            ], # arch/s390/kernel/syscall.c\n            \"sys_rt_sigreturn\": [], # arch/s390/kernel/signal.c\n            \"sys_s390_runtime_instr\": [\n                \"int, command\", \"int signum\",\n            ], # arch/s390/kernel/runtime_instr.c\n            \"sys_s390_pci_mmio_write\": [\n                \"unsigned long mmio_addr\", \"const void __user *user_buffer\", \"size_t length\",\n            ], # arch/s390/pci/pci_mmio.c\n            \"sys_s390_pci_mmio_read\": [\n                \"unsigned long mmio_addr\", \"void __user *user_buffer\", \"size_t length\",\n            ], # arch/s390/pci/pci_mmio.c\n            \"sys_s390_guarded_storage\": [\n                \"int command\", \"struct gs_cb __user *gs_cb\",\n            ], # arch/s390/kernel/guarded_storage.c\n            \"sys_s390_sthyi\": [\n                \"unsigned long function_code\", \"void __user *buffer\", \"u64 __user *return_code\",\n                \"unsigned long flags\",\n            ], # arch/s390/kernel/sthyi.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"64\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func in [\"sys_ni_syscall\", \"-\"]:\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_sh4():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(sh4_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_sh_pipe\": [], # arch/sh/kernel/sys_sh32.c\n            \"old_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"int fd\", \"unsigned long off\",\n            ], # arch/sh/kernel/sys_sh.c\n            \"sys_sigreturn\": [], # arch/sh/kernel/signal_32.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long len\", \"int op\",\n            ], # arch/sh/kernel/sys_sh.c\n            \"sys_rt_sigreturn\": [], # arch/sh/kernel/signal_32.c\n            \"sys_pread_wrapper\": [\n                \"unsigned int fd\", \"char __user *buf\", \"size_t count\", \"long dummy\", \"loff_t pos\",\n            ], # arch/sh/kernel/sys_sh32.c\n            \"sys_pwrite_wrapper\": [\n                \"unsigned int fd\", \"const char __user *buf\", \"size_t count\", \"long dummy\", \"loff_t pos\",\n            ], # arch/sh/kernel/sys_sh32.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/sh/kernel/sys_sh.c\n            \"sys_fadvise64_64_wrapper\": [\n                \"int fd\", \"u32 offset0\", \"u32 offset1\", \"u32 len0\", \"u32 len1\", \"int advice\",\n            ], # arch/sh/kernel/sys_sh32.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_sh_sync_file_range6\": [\n                \"int fd\", \"u64 offset\", \"u64 nbytes\", \"unsigned int flags\",\n            ], # sh/kernel/sys_sh32.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_m68k():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(m68k_syscall_tbl)\n        arch_specific_dic = {\n            \"__sys_fork\": [], # kernel/fork.c\n            \"sys_sigreturn\": [], # arch/m68k/kernel/entry.S\n            \"__sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"int scope\", \"int cache\", \"unsigned long len\",\n            ], #\n            \"sys_getpagesize\": [], # arch/m68k/kernel/sys_m68k.c\n            \"sys_rt_sigreturn\": [], # arch/m68k/kernel/entry.S\n            \"__sys_vfork\": [], # kernel/fork.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/m68k/kernel/sys_m68k.c\n            \"sys_get_thread_area\": [], # arch/m68k/kernel/sys_m68k.c\n            \"sys_set_thread_area\": [\n                \"unsigned long tp\",\n            ], # arch/m68k/kernel/sys_m68k.c\n            \"sys_atomic_cmpxchg_32\": [\n                \"unsigned long newval\", \"int oldval\", \"int d3\", \"int d4\", \"int d5\",\n                \"unsigned long __user *mem\",\n            ], # arch/m68k/kernel/sys_m68k.c\n            \"sys_atomic_barrier\": [], # arch/m68k/kernel/sys_m68k.c\n            \"__sys_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], #\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_alpha():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(alpha_syscall_tbl)\n        arch_specific_dic = {\n            \"alpha_syscall_zero\": [], # arch/alpha/kernel/entry.S\n            \"alpha_fork\": [], # arch/alpha/kernel/entry.S (fork_like macro)\n            \"sys_osf_wait4\": [\n                \"pid_t pid\", \"int __user *ustatus\", \"int options\", \"struct rusage32 __user *ur\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_brk\": [\n                \"unsigned long brk\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_getxpid\": [], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_mount\": [\n                \"unsigned long typenr\", \"const char __user *path\", \"int flag\", \"void __user *data\"\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_getxuid\": [], # arch/alpha/kernel/osf_sys.c\n            \"sys_alpha_pipe\": [], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_set_program_attributes\": [\n                \"unsigned long text_start\", \"unsigned long text_len\",\n                \"unsigned long bss_start\", \"unsigned long bss_len\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_getxgid\": [], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_sigprocmask\": [\n                \"int how\", \"unsigned long newmask\",\n            ], # arch/alpha/kernel/signal.c\n            \"sys_getpagesize\": [], # arch/alpha/kernel/osf_sys.c\n            \"alpha_vfork\": [], # arch/alpha/kernel/entry.S (fork_like macro)\n            \"sys_osf_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_getdtablesize\": [], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_select\": [\n                \"int, n, fd_set __user *inp\", \"fd_set __user *outp\",\n                \"fd_set __user *exp\", \"struct timeval32 __user *tvp\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_getpriority\": [\n                \"int which\", \"int who\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_sigreturn\": [], # arch/alpha/kernel/entry.S (sigreturn_like macro)\n            \"sys_osf_sigstack\": [\n                \"struct sigstack __user *uss\", \"struct sigstack __user *uoss\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_gettimeofday\": [\n                \"struct timeval32 __user *tv\", \"struct timezone __user *tz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_getrusage\": [\n                \"int who\", \"struct rusage32 __user *ru\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_settimeofday\": [\n                \"struct timeval32 __user *tv\", \"struct timezone __user *tz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_utimes\": [\n                \"const char __user *filename\", \"struct timeval32 __user *tvs\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_sigaction\": [\n                \"int, sig\", \"const struct osf_sigaction __user *act\", \"struct osf_sigaction __user *oact\",\n            ], # arch/alpha/kernel/signal.c\n            \"sys_osf_getdirentries\": [\n                \"unsigned int fd\", \"struct osf_dirent __user *dirent\",\n                \"unsigned int count\", \"long __user *basep\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_statfs\": [\n                \"const char __user *pathname\", \"struct osf_statfs __user *buffer\", \"unsigned long bufsiz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_fstatfs\": [\n                \"unsigned long fd\", \"struct osf_statfs __user *buffer\", \"unsigned long bufsiz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_getdomainname\": [\n                \"char __user *name\", \"int namelen\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_utsname\": [\n                \"char __user *name\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_stat\": [\n                \"char __user *name\", \"struct osf_stat __user *buf\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_lstat\": [\n                \"char __user *name\", \"struct osf_stat __user *buf\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_fstat\": [\n                \"int fd\", \"struct osf_stat __user *buf\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_statfs64\": [\n                \"char __user *pathname\", \"struct osf_statfs64 __user *buffer\", \"unsigned long bufsiz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_fstatfs64\": [\n                \"unsigned long fd\", \"struct osf_statfs64 __user *buffer\", \"unsigned long bufsiz\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_sysinfo\": [\n                \"int command\", \"char __user *buf\", \"long count\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_proplist_syscall\": [\n                \"enum pl_code code\", \"union pl_args __user *args\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_usleep_thread\": [\n                \"struct timeval32 __user *sleep\", \"struct timeval32 __user *remain\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_getsysinfo\": [\n                \"unsigned long op\", \"void __user *buffer\", \"unsigned long nbytes\",\n                \"int __user *start\", \"void __user *arg\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_osf_setsysinfo\": [\n                \"unsigned long op\", \"void __user *buffer\", \"unsigned long nbytes\",\n                \"int __user *start\", \"void __user *arg\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_sethae\": [\n                \"unsigned long val\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"sys_old_adjtimex\": [\n                \"struct timex32 __user *txc_p\",\n            ], # arch/alpha/kernel/osf_sys.c\n            \"alpha_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # arch/alpha/kernel/entry.S (fork_like macro)\n            \"alpha_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], # arch/alpha/kernel/entry.S (fork_like macro)\n            \"sys_rt_sigreturn\": [], # arch/alpha/kernel/entry.S (sigreturn_like macro)\n            \"sys_rt_sigaction\": [\n                \"int sig\", \"const struct sigaction __user *act\", \"struct sigaction __user *oact\",\n                \"size_t sigsetsize\", \"void __user *restorer\",\n            ], # arch/alpha/kernel/signal.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_hppa32():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(hppa_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_fork_wrapper\": [], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long offset\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_pread64\": [\n                \"unsigned int fd\", \"char __user *buf\", \"size_t count\",\n                \"unsigned int high\", \"unsigned int low\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_pwrite64\": [\n                \"unsigned int fd\", \"const char __user *buf\", \"size_t count\",\n                \"unsigned int high\", \"unsigned int low\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_vfork_wrapper\": [], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"sys_clone_wrapper\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # arch/parisc/kernel/entry.S (fork_like macro, CONFIG_CLONE_BACKWARDS)\n            \"parisc_personality\": [\n                \"unsigned long personality\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_rt_sigreturn_wrapper\": [], # arch/parisc/kernel/entry.S\n            \"parisc_truncate64\": [\n                \"const char __user * path\", \"unsigned int high\", \"unsigned int low\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_ftruncate64\": [\n                \"unsigned int fd\", \"unsigned int high\", \"unsigned int low\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_readahead\": [\n                \"int fd\", \"unsigned int high\", \"unsigned int low\", \"size_t count\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_fadvise64_64\": [\n                \"int fd\", \"unsigned int high_off\", \"unsigned int low_off\",\n                \"unsigned int high_len\", \"unsigned int low_len\", \"int advice\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_sync_file_range\": [\n                \"int fd\", \"u32 hi_off\", \"u32 lo_off\", \"u32 hi_nbytes\", \"u32 lo_nbytes\",\n                \"unsigned int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_fallocate\": [\n                \"int fd\", \"int mode\", \"u32 offhi\", \"u32 offlo\", \"u32 lenhi\", \"u32 lenlo\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_timerfd_create\": [\n                \"int clockid\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_signalfd4\": [\n                \"int ufd\", \"sigset_t __user *user_mask\", \"size_t sizemask\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_eventfd2\": [\n                \"unsigned int count\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_pipe2\": [\n                \"int __user *fildes\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_inotify_init1\": [\n                \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_userfaultfd\": [\n                \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_clone3_wrapper\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"parisc_madvise\": [\n                \"unsigned long start\", \"size_t len_in\", \"int behavior\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long bytes\", \"unsigned int cache\",\n            ], # arch/parisc/kernel/cache.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"unsigned int mask_1\",\n                \"unsigned int mask_2\", \"int dfd\", \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"32\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_hppa64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(hppa_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_fork_wrapper\": [], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long offset\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_vfork_wrapper\": [], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"sys_clone_wrapper\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # arch/parisc/kernel/entry.S (fork_like macro, CONFIG_CLONE_BACKWARDS)\n            \"sys_rt_sigreturn_wrapper\": [], # arch/parisc/kernel/entry.S\n            \"parisc_timerfd_create\": [\n                \"int clockid\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_signalfd4\": [\n                \"int ufd\", \"sigset_t __user *user_mask\", \"size_t sizemask\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_eventfd2\": [\n                \"unsigned int count\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_pipe2\": [\n                \"int __user *fildes\", \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_inotify_init1\": [\n                \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"parisc_userfaultfd\": [\n                \"int flags\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_clone3_wrapper\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], # arch/parisc/kernel/entry.S (fork_like macro)\n            \"parisc_madvise\": [\n                \"unsigned long start\", \"size_t len_in\", \"int behavior\",\n            ], # arch/parisc/kernel/sys_parisc.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long bytes\", \"unsigned int cache\",\n            ], # arch/parisc/kernel/cache.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n\n        }\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4] # don't use compat\n            if abi not in [\"common\", \"64\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_or1k():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(or1k_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_rt_sigreturn\": [], # arch/openrisc/kernel/entry.S\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\",\n                \"void __user *parent_tid\", \"void __user *child_tid\", \"int tls\",\n            ], # arch/openrisc/include/syscalls.h\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # include/asm-generic/syscalls.h\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_or1k_atomic\": [\n                \"unsigned long type\", \"unsigned long *v1\", \"unsigned long *v2\",\n            ], # arch/openrisc/include/asm/syscalls.h\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/openrisc/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"32\", \"or1k\", \"time32\", \"stat64\", \"rlimit\", \"renameat\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_nios2():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(nios2_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_rt_sigreturn\": [], # arch/nios2/kernel/entry.S\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\",\n                \"int __user *parent_tidptr\", \"int __user *child_tidptr\", \"int tls_val\",\n            ], # arch/nios2/kernel/entry.S\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # include/asm-generic/syscalls.h\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_cacheflush\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned int op\",\n            ], # arch/nios2/include/asm/syscalls.h\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/nios2/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"32\", \"nios2\", \"time32\", \"stat64\", \"renameat\", \"rlimit\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func in [\"sys_clone3\"]: # __ARCH_BROKEN_SYS_CLONE3\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_microblaze():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(microblaze_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/microblaze/kernel/sys_microblaze.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int stack_size\",\n                \"int __user *parent_tidptr\", \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS3)\n            \"sys_rt_sigreturn_wrapper\": [], # arch/microblaze/kernel/entry.S\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/microblaze/kernel/sys_microblaze.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_xtensa():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(xtensa_syscall_tbl)\n        arch_specific_dic = {\n            \"xtensa_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"unsigned long long offset\", \"unsigned long long len\",\n            ], # arch/xtensa/kernel/syscall.c\n            \"xtensa_shmat\": [\n                \"int shmid\", \"char __user *shmaddr\", \"int shmflg\",\n            ], # arch/xtensa/kernel/syscall.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS)\n            \"xtensa_rt_sigreturn\": [], # arch/xtensa/kernel/signal.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"common\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_cris():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(cris_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_sigreturn\": [], # arch/cris/arch-v10/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int stack_size\",\n                \"int __user *parent_tidptr\", \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c (CONFIG_CLONE_BACKWARDS2)\n            \"sys_bdflush\": [\n                \"int func\", \"long data\",\n            ], # include/linux/syscalls.h\n            \"sys_sysctl\": [\n                \"struct __sysctl_args __user *args\",\n            ], # include/linux/syscalls.h\n            \"sys_rt_sigreturn\": [], # arch/cris/arch-v10/kernel/signal.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/cris/kernel/sys_cris.c\n            \"sys_lookup_dcookie\": [\n                \"u64 cookie64\", \"char __user *buf\", \"size_t, len\",\n            ], # fs/dcookies.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"cris\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_loongarch64():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(loongarch_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_rt_sigreturn\": [], # arch/loongarch/kernel/signal.c\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long offset\",\n            ], # arch/loongarch/kernel/syscall.c\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry\n            if abi != \"loongarch\":\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_arc(bit_str):\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(arc_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_rt_sigreturn\": [], # arch/arc/kernel/signal.c\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"unsigned long tls\", \"int *child_tidptr\",\n            ], # arch/arc/kernel/entry.S (sys_clone_wrapper, CONFIG_CLONE_BACKWARDS)\n            \"sys_clone3\": [\n                \"struct clone_args __user *uargs\", \"size_t size\",\n            ], # arch/arc/kernel/entry.S (sys_clone3_wrapper)\n            \"sys_mmap\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long off\",\n            ], # include/uapi/asm/unistd.h\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long pgoff\",\n            ], # arch/arc/kernel/sys.c (sys_mmap_pgoff)\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_cacheflush\": [\n                \"uint32_t start\", \"uint32_t sz\", \"uint32_t flags\",\n            ], # arch/arc/mm/cache.c\n            \"sys_arc_settls\": [\n                \"void* user_tls_data_ptr\",\n            ], # arch/arc/kernel/process.c\n            \"sys_arc_gettls\": [], # arch/arc/kernel/process.c\n            \"sys_sysfs\": [\n                \"int option\", \"unsigned long arg1\", \"unsigned long arg2\",\n            ], # fs/filesystems.c\n            \"sys_arc_usr_cmpxchg\": [\n                \"int __user *uaddr\", \"int expected\", \"int new\",\n            ], # arch/arc/kernel/process.c\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/arc/kernel/Makefile.syscalls\n            if abi not in [\"common\", bit_str, \"arc\", \"time32\", \"renameat\", \"stat64\", \"rlimit\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    def make_syscall_list_csky():\n        sc_def = Syscall.parse_common_syscall_defs()\n        tbl = Syscall.parse_syscall_table_defs(csky_syscall_tbl)\n        arch_specific_dic = {\n            \"sys_clone\": [\n                \"unsigned long clone_flags\", \"unsigned long newsp\", \"int __user *parent_tidptr\",\n                \"int __user *child_tidptr\", \"unsigned long tls\",\n            ], # kernel/fork.c\n            \"sys_rt_sigreturn\": [], # arch/csky/kernel/signal.c\n            \"sys_mmap2\": [\n                \"unsigned long addr\", \"unsigned long len\", \"unsigned long prot\",\n                \"unsigned long flags\", \"unsigned long fd\", \"unsigned long offset\",\n            ], # arch/csky/kernel/syscall.c\n            \"sys_fadvise64_64\": [\n                \"int fd\", \"int advice\", \"loff_t offset\", \"loff_t len\",\n            ], # arch/csky/include/asm/syscalls.h\n            \"sys_fanotify_mark\": [\n                \"int fanotify_fd\", \"unsigned int flags\", \"u64 mask\", \"int fd\",\n                \"const char __user *pathname\",\n            ], # fs/notify/fanotify/fanotify_user.c\n            \"sys_set_thread_area\": [\n                \"unsigned long addr\",\n            ], # arch/csky/kernel/signal.c\n            \"sys_cacheflush\": [\n                \"void __user *addr\", \"unsigned long len\", \"int op\",\n            ], # arch/csky/include/asm/syscalls.h\n        }\n\n        syscall_list = []\n        for entry in tbl:\n            nr, abi, name, func = entry[:4]\n            # arch/csky/kernel/Makefile.syscalls\n            if abi not in [\"common\", \"32\", \"csky\", \"time32\", \"stat64\", \"rlimit\"]:\n                continue\n            # special case\n            if func in arch_specific_dic:\n                syscall_list.append([nr, name, arch_specific_dic[func]])\n                continue\n            # common case\n            if func == \"sys_ni_syscall\":\n                continue\n            if func not in sc_def:\n                err(\"Not found: {:s}\".format(func))\n                raise\n            syscall_list.append([nr, name, sc_def[func]])\n        return syscall_list\n\n    @staticmethod\n    @Cache.cache_this_session\n    def make_syscall_table(arch, mode):\n        if arch == \"X86\" and mode == \"64\":\n            return_register = X86_64.return_register\n            args_register = X86_64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_x86_64()\n\n        elif arch == \"X86\" and mode == \"Emulated-32\":\n            return_register = X86.return_register\n            args_register = X86.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_x86_32_emulated()\n\n        elif arch == \"X86\" and mode == \"Native-32\":\n            return_register = X86.return_register\n            args_register = X86.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_x86_32_native()\n\n        elif arch == \"X86\" and mode == \"16\":\n            syscall_list = []\n            return_register = {}\n            args_register = {}\n            for nr, name, ret_regs, args, arg_regs in x86_16_dos_syscall_list:\n                syscall_list.append([nr, name, args])\n                return_register[nr] = ret_regs\n                args_register[nr] = arg_regs\n\n        elif arch == \"ARM64\" and mode == \"ARM\":\n            return_register = AARCH64.return_register\n            args_register = AARCH64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arm64()\n\n        elif arch == \"ARM\" and mode == \"Emulated-32\":\n            return_register = ARM.return_register\n            args_register = ARM.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arm32_emulated() # only support EABI\n\n        elif arch == \"ARM\" and mode == \"Native-32\":\n            return_register = ARM.return_register\n            args_register = ARM.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arm32_native() # only support EABI\n\n        elif arch == \"ARM64\" and mode == \"Secure-World\":\n            return_register = AARCH64.return_register\n            args_register = AARCH64.syscall_parameters + [\"$x6\"] # OPTEE uses 7 args\n            syscall_list = arm_OPTEE_syscall_list.copy()\n\n        elif arch == \"ARM\" and mode == \"Secure-World\":\n            return_register = ARM.return_register\n            args_register = ARM.syscall_parameters\n            syscall_list = arm_OPTEE_syscall_list.copy()\n\n        elif arch == \"MIPS\" and mode == \"32\":\n            return_register = MIPS.return_register\n            args_register = MIPS.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_mips32()\n\n        elif arch == \"MIPS\" and mode == \"n32\":\n            return_register = MIPSN32.return_register\n            args_register = MIPSN32.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_mipsn32()\n\n        elif arch == \"MIPS\" and mode == \"64\":\n            return_register = MIPS64.return_register\n            args_register = MIPS64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_mips64()\n\n        elif arch == \"PPC\" and mode == \"32\":\n            return_register = PPC.return_register\n            args_register = PPC.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_ppc32()\n\n        elif arch == \"PPC\" and mode == \"64\":\n            return_register = PPC64.return_register\n            args_register = PPC64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_ppc64()\n\n        elif arch == \"SPARC\" and mode == \"32\":\n            return_register = SPARC.return_register\n            args_register = SPARC.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_sparc32()\n\n        elif arch == \"SPARC\" and mode == \"32PLUS\":\n            return_register = SPARC32PLUS.return_register\n            args_register = SPARC32PLUS.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_sparc32() # same sparc32\n\n        elif arch == \"SPARC\" and mode == \"64\":\n            return_register = SPARC64.return_register\n            args_register = SPARC64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_sparc64()\n\n        elif arch == \"RISCV\" and mode == \"32\":\n            return_register = RISCV.return_register\n            args_register = RISCV.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_riscv32()\n\n        elif arch == \"RISCV\" and mode == \"64\":\n            return_register = RISCV64.return_register\n            args_register = RISCV64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_riscv64()\n\n        elif arch == \"S390X\" and mode == \"64\":\n            return_register = S390X.return_register\n            args_register = S390X.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_s390x()\n\n        elif arch == \"SH4\" and mode == \"SH4\":\n            return_register = SH4.return_register\n            args_register = SH4.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_sh4()\n\n        elif arch == \"M68K\" and mode == \"32\":\n            return_register = M68K.return_register\n            args_register = M68K.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_m68k()\n\n        elif arch == \"ALPHA\" and mode == \"ALPHA\":\n            return_register = ALPHA.return_register\n            args_register = ALPHA.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_alpha()\n\n        elif arch == \"HPPA\" and mode == \"32\":\n            return_register = HPPA.return_register\n            args_register = HPPA.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_hppa32()\n\n        elif arch == \"HPPA\" and mode == \"64\":\n            return_register = HPPA64.return_register\n            args_register = HPPA64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_hppa64()\n\n        elif arch == \"OR1K\" and mode == \"OR1K\":\n            return_register = OR1K.return_register\n            args_register = OR1K.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_or1k()\n\n        elif arch == \"NIOS2\" and mode == \"NIOS2\":\n            return_register = NIOS2.return_register\n            args_register = NIOS2.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_nios2()\n\n        elif arch == \"MICROBLAZE\" and mode == \"MICROBLAZE\":\n            return_register = MICROBLAZE.return_register\n            args_register = MICROBLAZE.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_microblaze()\n\n        elif arch == \"XTENSA\" and mode == \"XTENSA\":\n            return_register = XTENSA.return_register\n            args_register = XTENSA.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_xtensa()\n\n        elif arch == \"CRIS\" and mode == \"CRIS\":\n            return_register = CRIS.return_register\n            args_register = CRIS.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_cris()\n\n        elif arch == \"LOONGARCH\" and mode == \"64\":\n            return_register = LOONGARCH64.return_register\n            args_register = LOONGARCH64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_loongarch64()\n\n        elif arch == \"ARC\" and mode in [\"32v2\", \"32\"]:\n            return_register = ARC.return_register\n            args_register = ARC.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arc(\"32\")\n\n        elif arch == \"ARC\" and mode in [\"32v3\"]:\n            return_register = ARCv3.return_register\n            args_register = ARCv3.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arc(\"32\")\n\n        elif arch == \"ARC\" and mode in [\"64v3\", \"64\"]:\n            return_register = ARC64.return_register\n            args_register = ARC64.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_arc(\"64\")\n\n        elif arch == \"CSKY\" and mode == \"CSKY\":\n            return_register = CSKY.return_register\n            args_register = CSKY.syscall_parameters\n            syscall_list = Syscall.make_syscall_list_csky()\n\n        else:\n            return None\n\n        Table = collections.namedtuple(\"Table\", \"arch mode nr_table name_table\")\n        syscall_table = Table(arch, mode, {}, {})\n\n        # example:\n        #   syscall_table.arch: 'X86'\n        #   syscall_table.mode: '64'\n        #   syscall_table.nr_table[0].nr: 0\n        #   syscall_table.nr_table[0].name: 'read'\n        #   syscall_table.nr_table[0].ret_regs: ['$rax']\n        #   syscall_table.nr_table[0].arg_regs: ['$rdi', '$rsi', ...]\n        #   syscall_table.nr_table[0].args_full: ['unsigned int fd', ...]\n        #   syscall_table.nr_table[0].args: ['fd', ...]\n        #   syscall_table.nr_table[1] ...\n        #   syscall_table.name_table[\"read\"].nr: 0\n        #   syscall_table.name_table[\"read\"].name: 'read'\n        #   syscall_table.name_table[\"read\"].ret_regs: ['$rax']\n        #   syscall_table.name_table[\"read\"].arg_regs: ['$rdi', '$rsi', ...]\n        #   syscall_table.name_table[\"read\"].args_full: ['unsigned int fd', ...]\n        #   syscall_table.name_table[\"read\"].args: ['fd', ...]\n        #   syscall_table.name_table[\"write\"] ...\n        Entry = collections.namedtuple(\"Entry\", \"nr name ret_regs arg_regs args_full args\")\n        for nr, name, args_full in sorted(syscall_list, key=lambda x: x[0]):\n            # make entry\n            args = [re.split(r\" |\\*\", p)[-1] for p in args_full]\n            if (arch, mode) == (\"X86\", \"16\"):\n                entry = Entry(nr, name, return_register[nr], args_register[nr], args_full, args)\n            else:\n                entry = Entry(nr, name, [return_register], args_register[:len(args)], args_full, args)\n            # nr_table\n            syscall_table.nr_table[nr] = entry\n            # name_table\n            if name not in syscall_table.name_table:\n                syscall_table.name_table[name] = entry\n        return syscall_table\n\n\ndef get_syscall_table(arch=None, mode=None):\n\n    if arch is None and mode is None :\n        if is_x86_64():\n            arch, mode = \"X86\", \"64\"\n        elif is_x86_32():\n            if is_emulated32():\n                arch, mode = \"X86\", \"Emulated-32\"\n            else:\n                arch, mode = \"X86\", \"Native-32\"\n        elif is_arm64():\n            if is_in_secure():\n                arch, mode = \"ARM64\", \"Secure-World\"\n            else:\n                arch, mode = \"ARM64\", \"ARM\"\n        elif is_arm32():\n            if is_in_secure():\n                arch, mode = \"ARM\", \"Secure-World\"\n            elif is_emulated32():\n                arch, mode = \"ARM\", \"Emulated-32\"\n            else:\n                arch, mode = \"ARM\", \"Native-32\"\n        elif current_arch:\n            arch = current_arch.arch\n            mode = current_arch.mode\n        else:\n            arch, mode = None, None\n\n    if arch in [\"ARM\", \"ARM64\"] and mode == \"S\":\n        mode = \"Secure-World\"\n    if arch in [\"X86\", \"ARM\"] and mode == \"32\":\n        mode = \"Emulated-32\"\n    elif arch in [\"X86\", \"ARM\"] and mode == \"N32\":\n        mode = \"Native-32\"\n\n    return Syscall.make_syscall_table(arch, mode)\n\n\n@register_command\nclass SyscallArgsCommand(GenericCommand):\n    \"\"\"Get the syscall name and arguments based on the register values in the current state.\"\"\"\n\n    _cmdline_ = \"syscall-args\"\n    _category_ = \"01-a. Debugging Support - Context\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"nr\", metavar=\"SYSCALL_NUM\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"syscall number to search.\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def get_nr():\n        # str or list\n        syscall_register = current_arch.syscall_register\n\n        # hppa specific. hppa syscall instruction has a delay slot and _NR may be set there.\n        if is_hppa32() or is_hppa64():\n            next_insn = Disasm.gef_instruction_n(current_arch.pc, 1)\n            if next_insn.mnemonic == \"ldi\" and next_insn.operands[1] == \"r20\":\n                nr = int(next_insn.operands[0], 16)\n            else:\n                # already set\n                nr = get_register(syscall_register)\n\n        # s390x specific. s390x syscall number may be embedded in the instruction.\n        elif is_s390x():\n            insn = get_insn()\n            r = re.search(syscall_register[0], str(insn))\n            nr = int(r.group(1), 0)\n            if nr == 0:\n                syscall_register = syscall_register[1] # use $r1\n                nr = get_register(syscall_register)\n            else:\n                syscall_register = syscall_register[0]\n\n        # normal pattern\n        else:\n            nr = get_register(syscall_register)\n\n        return syscall_register, nr\n\n    def get_values(self, registers):\n        values = []\n        for reg in registers:\n            if \"+\" in reg: # `$sp + 0x10`\n                reg_n, off_n = reg.split(\"+\")\n                values.append(read_int_from_memory(get_register(reg_n) + int(off_n, 0)))\n            elif is_x86_16() and \":\" in reg: # $ds:$dx\n                seg, reg = reg.split(\":\")\n                values.append(current_arch.real2phys(seg, reg))\n            else:\n                values.append(get_register(reg))\n        return values\n\n    def print_syscall(self, syscall_table, syscall_register, nr):\n        if syscall_table:\n            entry = syscall_table.nr_table[nr]\n            syscall_name = entry.name\n            ret_regs = entry.ret_regs\n            arg_regs = entry.arg_regs\n            args_full = entry.args_full\n            args = entry.args\n            arch = syscall_table.arch\n            mode = syscall_table.mode\n        else:\n            syscall_name = None\n            ret_regs = [current_arch.return_register]\n            arg_regs = current_arch.syscall_parameters\n            args_full = None\n            args = [\"?\"] * len(arg_regs)\n            arch = current_arch.arch\n            mode = current_arch.mode\n\n        # header\n        info(\"Detected syscall (arch:{:s}, mode:{:s})\".format(arch, mode))\n        if syscall_name and args_full is not None:\n            gef_print(\"    \" + Color.colorify(\"{}({})\".format(syscall_name, \", \".join(args_full)), \"bold yellow\"))\n        fmt = \"{:<20} {:<20} {}\"\n        legend = [\"Parameter\", \"Register\", \"Value\"]\n        info(GefUtil.make_legend(fmt.format(*legend)))\n\n        # ret\n        for ret in ret_regs:\n            gef_print(\"    {:<20} {:<20} {:<20}\".format(\"RET\", ret, \"-\"))\n\n        # syscall number\n        gef_print(\"    {:<20} {:<20} {:#x}\".format(\"NR\", syscall_register, nr))\n\n        # syscall args\n        values = self.get_values(arg_regs)\n        for name, register, value in zip(args, arg_regs, values):\n            line = \"    {:<20} {:<20} \".format(name, register)\n            if value is not None:\n                line += AddressUtil.recursive_dereference_to_string(value)\n            gef_print(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.nr is not None:\n            syscall_register, nr = \"-\", args.nr\n        else:\n            syscall_register, nr = SyscallArgsCommand.get_nr()\n\n        syscall_table = get_syscall_table()\n        if syscall_table and nr not in syscall_table.nr_table:\n            warn(\"There is no system call for {:#x}\".format(nr))\n            return\n\n        self.print_syscall(syscall_table, syscall_register, nr)\n        return\n\n\n@register_command\nclass CodebaseCommand(GenericCommand):\n    \"\"\"Display various base addresses.\"\"\"\n\n    _cmdline_ = \"codebase\"\n    _category_ = \"02-b. Process Information - Base Address\"\n    _aliases_ = [\"base\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    def define_section_variable(self, elf, bin_base, section_name):\n        sec = elf.get_shdr(section_name)\n        if not sec:\n            return\n\n        if elf.is_pie():\n            addr = sec.sh_addr + bin_base\n        else:\n            addr = sec.sh_addr\n\n        self.quiet_print(titlify(section_name))\n        var_name = section_name.lstrip(\".\")\n        self.quiet_print(\"${:s} = {:#x}\".format(var_name, addr))\n        gdb.execute(\"set ${:s} = {:#x}\".format(var_name, addr))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        # The codebase may be heuristically determined from the memory map.\n        bin_base = ProcessMap.get_codebase()\n        if bin_base is None:\n            self.quiet_err(\"Could not find the binary base\")\n            return\n        self.quiet_print(titlify(\"code base\"))\n        gdb.execute(f\"set $codebase = {bin_base:#x}\")\n        self.quiet_print(f\"$codebase = {bin_base:#x}\")\n        gdb.execute(f\"set $binbase = {bin_base:#x}\")\n        self.quiet_print(f\"$binbase = {bin_base:#x}\")\n\n        # Any other area should use a section header.\n        elf = Elf.get_elf()\n        if elf is None or not elf.is_valid():\n            self.quiet_err(\"Failed to load an ELF\")\n            return\n\n        self.define_section_variable(elf, bin_base, \".text\")\n        self.define_section_variable(elf, bin_base, \".rodata\")\n        self.define_section_variable(elf, bin_base, \".data\")\n        self.define_section_variable(elf, bin_base, \".bss\")\n        return\n\n\n@register_command\nclass HeapbaseCommand(GenericCommand):\n    \"\"\"Display heap base address.\"\"\"\n\n    _cmdline_ = \"heapbase\"\n    _category_ = \"02-b. Process Information - Base Address\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def heap_base_from_symbol(force_heuristic):\n        # The value of mp_->sbrk_base is correct in x86 or x64.\n        # However, for architectures that have TLS in the bss area (such as ARM or ARM64),\n        # the start position of the heap seems to shift by the amount of the area used as the TLS variable.\n        # This method should not be used on ARM or ARM64, as there seems to be no way to predetermine the TLS size.\n        if not is_x86():\n            return None\n        if force_heuristic:\n            return None\n        try:\n            # symbol and type are defined\n            return AddressUtil.parse_address(\"mp_->sbrk_base\")\n        except gdb.error:\n            return None\n\n    @staticmethod\n    def heap_base_from_info_proc_map(force_heuristic):\n        # For non-static binaries, this is mostly sufficient.\n        if force_heuristic:\n            return None\n\n        try:\n            codebase = ProcessMap.get_codebase()\n            elf = Elf(codebase)\n        except Exception:\n            return None\n\n        if elf.is_static():\n            return None\n\n        return ProcessMap.get_section_base_address(\"[heap]\")\n\n    @staticmethod\n    def heap_base_from_tcache():\n        # If glibc has tcache, there is tcache_perthread_struct* in TLS.\n        # This structure is always allocated in the first chunk,\n        # and can be used to find the starting address of the heap.\n        # This path is useful for old qemu-user emulation, etc.\n\n        if get_libc_version() < (2, 26):\n            return None\n\n        # In 2.42 and later, tcache_perthread_struct is not necessarily the first chunk,\n        # so this detection method does not work.\n        # However, glibc 2.42 is used in an Ubuntu 25.10 environment, and in this environment qemu-user is 10.1.\n        # This version of qemu-user can obtain the exact heap base address via `info proc map`,\n        # so the heuristic method should not be necessary.\n        if get_libc_version() >= (2, 42):\n            return None\n\n        if not current_arch.tls_supported:\n            return None\n\n        main_arena_addr = GlibcHeap.search_for_main_arena()\n        if main_arena_addr is None:\n            return None\n\n        tcache_perthread_struct = GlibcHeap.search_for_tcache_from_tls(main_arena_addr)\n        if tcache_perthread_struct is None:\n            return None\n\n        if is_x86_32() or is_riscv32() or is_ppc32():\n            chunk_offset = 0x10\n        else:\n            chunk_offset = current_arch.ptrsize * 2\n        heap_base = tcache_perthread_struct - chunk_offset\n        return heap_base\n\n    @staticmethod\n    def heap_base_from_mp():\n        # However, in the case of qemu-user runs static binary, the heapbase cannot be obtained even with\n        # `info proc map`, and this way may be necessary.\n        main_arena_addr = GlibcHeap.search_for_main_arena()\n        if main_arena_addr is None:\n            return None\n\n        try:\n            codebase = ProcessMap.get_codebase()\n            elf = Elf(codebase)\n        except Exception:\n            return None\n\n        if not elf.is_static():\n            return None\n\n        \"\"\"\n        0x0000004dd160|+0x0000|+000: trim_threshold         : 0x0000000000020000\n        0x0000004dd168|+0x0008|+001: top_pad                : 0x0000000000020000\n        0x0000004dd170|+0x0010|+002: mmap_threshold         : 0x0000000000020000\n        0x0000004dd178|+0x0018|+003: arena_test             : 0x0000000000000008\n        0x0000004dd180|+0x0020|+004: arena_max              : 0x0000000000000000\n        0x0000004dd188|+0x0028|+005: thp_pagesize           : 0x0000000000000000\n        0x0000004dd190|+0x0030|+006: hp_pagesize            : 0x0000000000000000\n        0x0000004dd198|+0x0038|+007: n_mmaps+hp_flags       : 0x0000000000000000\n        0x0000004dd1a0|+0x0040|+008: max_n_mmaps+n_mmaps_max: 0x0000000000010000\n        0x0000004dd1a8|+0x0048|+009: no_dyn_threshold       : 0x0000000000000000\n        0x0000004dd1b0|+0x0050|+010: mmaped_mem             : 0x0000000000000000\n        0x0000004dd1b8|+0x0058|+011: max_mmaped_mem         : 0x0000000000000000\n        0x0000004dd1c0|+0x0060|+012: sbrk_base              : 0x00000000004e5d40 <----- here\n        0x0000004dd1c8|+0x0068|+013: tcache_small_bins      : 0x0000000000000040\n        0x0000004dd1d0|+0x0070|+014: tcache_max_bytes       : 0x0000000000000411\n        0x0000004dd1d8|+0x0078|+015: tcache_count           : 0x0000000000000007\n        0x0000004dd1e0|+0x0080|+016: tcache_unsorted_limit  : 0x0000000000000000\n        0x0000004dd1e8|+0x0088|+017:                        : 0x0000000000000000\n        0x0000004dd1f0|+0x0090|+018:                        : 0x0000000000000000\n        0x0000004dd1f8|+0x0098|+019:                        : 0x0000000000000000\n        0x0000004dd200|+0x00a0|+020: main_arena             : 0x0000000000000000\n        0x0000004dd208|+0x00a8|+021:                        : 0x0000000000000001\n        0x0000004dd210|+0x00b0|+022:                        : 0x00000000005165e0\n        0x0000004dd218|+0x00b8|+023:                        : 0x0000000000000000\n        0x0000004dd220|+0x00c0|+024:                        : 0x0000000000000000\n        0x0000004dd228|+0x00c8|+025:                        : 0x0000000000000000\n        \"\"\"\n        for i in range(1, 20):\n            x = main_arena_addr - current_arch.ptrsize * i\n            if not is_valid_addr(x):\n                break\n            y = read_int_from_memory(x)\n            if is_valid_addr(y):\n                return y\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session_skip_None_cache\n    def heap_base(force_heuristic=False):\n        heap_base = HeapbaseCommand.heap_base_from_symbol(force_heuristic)\n        if is_valid_addr(heap_base):\n            return heap_base\n\n        heap_base = HeapbaseCommand.heap_base_from_info_proc_map(force_heuristic)\n        if is_valid_addr(heap_base):\n            return heap_base\n\n        heap_base = HeapbaseCommand.heap_base_from_tcache()\n        if is_valid_addr(heap_base):\n            return heap_base\n\n        heap_base = HeapbaseCommand.heap_base_from_mp()\n        if is_valid_addr(heap_base):\n            return heap_base\n\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        heap = HeapbaseCommand.heap_base()\n        if heap is None:\n            err(\"Could not find the heap\")\n            return\n\n        self.quiet_print(titlify(\"Heap base\"))\n        gdb.execute(f\"set $heapbase = {heap:#x}\")\n        self.quiet_print(f\"$heapbase = {heap:#x}\")\n        return\n\n\n@register_command\nclass LibcCommand(GenericCommand):\n    \"\"\"Display libc base address.\"\"\"\n\n    _cmdline_ = \"libc\"\n    _category_ = \"02-b. Process Information - Base Address\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        super().__init__()\n        self.add_setting(\"assume_version\", \"()\", \"The default libc version\")\n        return\n\n    @staticmethod\n    def is_same_filename(a, b):\n        # If the file names match, they are considered to be the same file.\n        if os.path.basename(a) == os.path.basename(b):\n            return True\n\n        # If `a` is the destination of a symbolic link, compare whether resolving `b` results in `a`.\n        a_dir = os.path.join(os.path.dirname(a))\n        b_file = os.path.basename(b)\n        ab_path = os.path.join(a_dir, b_file)\n        while os.path.islink(ab_path):\n            ab_path = os.path.normpath(os.path.join(os.path.dirname(ab_path), os.readlink(ab_path)))\n        return os.path.basename(a) == os.path.basename(ab_path)\n\n    def libc_calc_hash(self, libc_targets):\n        libc = ProcessMap.process_lookup_path(libc_targets)\n        real_libc_path = None\n\n        if is_container_attach():\n            real_libc_path = Path.append_proc_root(libc.path)\n            if not os.path.exists(real_libc_path):\n                return\n            data = open(real_libc_path, \"rb\").read()\n\n        elif is_remote_debug():\n            if is_qemu_user():\n                data = None\n                for maps in ProcessMap.get_process_maps(outer=True):\n                    if not LibcCommand.is_same_filename(maps.path, libc.path):\n                        continue\n                    real_libc_path = maps.path\n                    data = open(real_libc_path, \"rb\").read()\n                    break\n            else:\n                data = Path.read_remote_file(libc.path)\n            if not data:\n                return\n        else:\n            if not os.path.exists(libc.path):\n                return\n            data = open(libc.path, \"rb\").read()\n\n        gef_print(\"path:\\t{:s}{:s}\".format(libc.path, \" (remote)\" if is_remote_debug() else \"\"))\n        if real_libc_path:\n            gef_print(\"path:\\t{:s} (real)\".format(real_libc_path))\n        gef_print(\"sha512:\\t{:s}\".format(hashlib.sha512(data).hexdigest()))\n        gef_print(\"sha256:\\t{:s}\".format(hashlib.sha256(data).hexdigest()))\n        gef_print(\"sha1:\\t{:s}\".format(hashlib.sha1(data).hexdigest()))\n        gef_print(\"md5:\\t{:s}\".format(hashlib.md5(data).hexdigest()))\n\n        pos = re.search(b\"(GNU C Library|uClibc-ng release) [\\x20-\\x7e]*\", data)\n        if pos:\n            gef_print(\"ver:\\t{:s}\".format(String.bytes2str(pos.group(0))))\n        return\n\n    def show_libc_assume_version(self):\n        self.quiet_print(titlify(\"GEF libc info\"))\n        try:\n            v = get_libc_version(verbose=True)\n            gef_print(\"GEF recognized: {}\".format(v))\n        except Exception:\n            gef_print(\"GEF recognized: None\")\n        info(\"If version detection is failing, you can fix it with: `gef config libc.assume_version (2,39)`\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        Cache.reset_gef_caches(all=True) # get_process_maps may be caching old information\n\n        libc_targets = (\n            \"libc-2.\", \"libc.so.6\", # glibc\n            \"libuClibc-\", \"/libc.so.0\", # uClibc\n        )\n\n        libc = ProcessMap.get_section_base_address_by_list(libc_targets)\n        if libc is None:\n            err(\"Could not find the libc\")\n            if not args.quiet:\n                self.show_libc_assume_version()\n            return\n\n        self.quiet_print(titlify(\"libc info\"))\n        gdb.execute(f\"set $libc = {libc:#x}\")\n        self.quiet_print(f\"$libc = {libc:#x}\")\n\n        if not args.quiet:\n            self.libc_calc_hash(libc_targets)\n            self.show_libc_assume_version()\n        return\n\n\n@register_command\nclass LdCommand(GenericCommand):\n    \"\"\"Display ld base address.\"\"\"\n\n    _cmdline_ = \"ld\"\n    _category_ = \"02-b. Process Information - Base Address\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    def ld_calc_hash(self, ld_targets):\n        ld = ProcessMap.process_lookup_path(ld_targets)\n        real_ld_path = None\n\n        if is_container_attach():\n            real_ld_path = Path.append_proc_root(ld.path)\n            if not os.path.exists(real_ld_path):\n                return\n            data = open(real_ld_path, \"rb\").read()\n\n        elif is_remote_debug():\n            if is_qemu_user():\n                data = None\n                for maps in ProcessMap.get_process_maps(outer=True):\n                    if not LibcCommand.is_same_filename(maps.path, ld.path):\n                        continue\n                    real_ld_path = maps.path\n                    data = open(real_ld_path, \"rb\").read()\n                    break\n            else:\n                data = Path.read_remote_file(ld.path)\n            if not data:\n                return\n        else:\n            if not os.path.exists(ld.path):\n                return\n            data = open(ld.path, \"rb\").read()\n\n        gef_print(\"path:\\t{:s}{:s}\".format(ld.path, \" (remote)\" if is_remote_debug() else \"\"))\n        if real_ld_path:\n            gef_print(\"path:\\t{:s} (real)\".format(real_ld_path))\n        gef_print(\"sha512:\\t{:s}\".format(hashlib.sha512(data).hexdigest()))\n        gef_print(\"sha256:\\t{:s}\".format(hashlib.sha256(data).hexdigest()))\n        gef_print(\"sha1:\\t{:s}\".format(hashlib.sha1(data).hexdigest()))\n        gef_print(\"md5:\\t{:s}\".format(hashlib.md5(data).hexdigest()))\n\n        pos = re.search(b\"ld.so [\\x20-\\x7e]+ version [\\x20-\\x7e]*\", data)\n        if pos:\n            gef_print(\"ver:\\t{:s}\".format(String.bytes2str(pos.group(0))))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        Cache.reset_gef_caches(all=True) # get_process_maps may be caching old information\n\n        ld_targets = (\n            \"ld-2.\", \"ld-linux-\", \"ld-linux.\", # glibc\n            \"ld64-uClibc-\", \"ld-uClibc-\", \"ld64-uClibc.\", \"ld-uClibc.\", # uClibc\n        )\n\n        ld = ProcessMap.get_section_base_address_by_list(ld_targets)\n        if ld is None:\n            err(\"Could not find the ld\")\n            return\n\n        self.quiet_print(titlify(\"ld info\"))\n        gdb.execute(f\"set $ld = {ld:#x}\")\n        self.quiet_print(f\"$ld = {ld:#x}\")\n\n        if not args.quiet:\n            self.ld_calc_hash(ld_targets)\n        return\n\n\n@register_command\nclass MagicCommand(GenericCommand):\n    \"\"\"Display useful userland addresses and offsets.\"\"\"\n\n    _cmdline_ = \"magic\"\n    _category_ = \"02-g. Process Information - Symbol\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\", help=\"show only the most frequently used items.\")\n    parser.add_argument(\"-j\", \"--print-file-jumps\", action=\"store_true\", help=\"print _IO_xxx_jumps functions.\")\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", help=\"filter string.\")\n    _syntax_ = parser.format_help()\n\n    def should_be_print(self, sym):\n        if not self.args.filter:\n            return True\n\n        for filt in self.args.filter:\n            if filt in sym:\n                return True\n        return False\n\n    def resolve_and_print(self, sym, base):\n        if not self.should_be_print(sym):\n            return\n\n        width = AddressUtil.get_format_address_width()\n        try:\n            addr = int(gdb.parse_and_eval(f\"&{sym}\"))\n        except gdb.error:\n            gef_print(\"{:45s} {:>{:d}s}\".format(sym, \"Not found\", width))\n            return\n\n        addr = ProcessMap.lookup_address(addr)\n        perm = addr.section.permission\n        if is_ascii_string(addr.value):\n            val = read_cstring_from_memory(addr.value)\n            gef_print(\"{:45s} {!s} [{!s}] (+{:#010x}) -> {:s}\".format(\n                sym, addr, perm, addr.value - base, val,\n            ))\n        else:\n            val = ProcessMap.lookup_address(read_int_from_memory(addr.value))\n            val_sym = Symbol.get_symbol_string(val.value)\n            gef_print(\"{:45s} {!s} [{!s}] (+{:#010x}) -> {:s}{:s}\".format(\n                sym, addr, perm, addr.value - base, val.long_fmt(), val_sym,\n            ))\n        return\n\n    def resolve_and_print_fj(self, sym, base):\n        self.resolve_and_print(sym, base)\n\n        if not self.should_be_print(sym):\n            return\n\n        if not self.args.print_file_jumps:\n            return\n\n        try:\n            vtable = int(gdb.parse_and_eval(f\"&{sym}\"))\n        except Exception:\n            return\n\n        gdb.execute(\"dereference {:#x} 22 --no-pager\".format(vtable))\n        return\n\n    def magic(self):\n        codebase = ProcessMap.get_codebase()\n        libc = ProcessMap.get_section_base_address_by_list((\"libc-2.\", \"libc.so.6\"))\n        ld = ProcessMap.get_section_base_address_by_list((\"ld-2.\", \"ld-linux-\", \"ld-linux.so.2\"))\n        if libc is None or ld is None:\n            gef_print(\"libc/ld not found\")\n            return\n\n        gef_print(titlify(\"Legend\"))\n        fmt = \"{:45s} {:{:d}s} {:5s} (+{:10s}) -> {:{:d}s}\"\n        width = AddressUtil.get_format_address_width()\n        legend = [\"Symbol\", \"Addr\", width, \"Perm\", \"Offset\", \"Value\", width]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        gef_print(titlify(\"Heap\"))\n        if not self.args.smart:\n            self.resolve_and_print(\"main_arena\", libc)\n            self.resolve_and_print(\"mp_\", libc)\n        self.resolve_and_print(\"__malloc_hook\", libc)\n        self.resolve_and_print(\"__free_hook\", libc)\n        self.resolve_and_print(\"__realloc_hook\", libc)\n        if not self.args.smart:\n            self.resolve_and_print(\"__memalign_hook\", libc)\n            self.resolve_and_print(\"__after_morecore_hook\", libc)\n            self.resolve_and_print(\"_dl_open_hook\", libc)\n            self.resolve_and_print(\"global_max_fast\", libc)\n            self.resolve_and_print(\"malloc\", libc)\n            self.resolve_and_print(\"free\", libc)\n            self.resolve_and_print(\"calloc\", libc)\n            self.resolve_and_print(\"realloc\", libc)\n\n        gef_print(titlify(\"I/O\"))\n        self.resolve_and_print(\"*stdin\", libc)\n        self.resolve_and_print(\"*stdout\", libc)\n        self.resolve_and_print(\"*stderr\", libc)\n        self.resolve_and_print(\"_IO_list_all\", libc)\n\n        if not self.args.smart:\n            if get_libc_version() < (2, 38):\n                self.resolve_and_print_fj(\"_IO_file_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_file_jumps_mmap\", libc)\n                self.resolve_and_print_fj(\"_IO_file_jumps_maybe_mmap\", libc)\n                self.resolve_and_print_fj(\"_IO_wfile_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_wfile_jumps_mmap\", libc)\n                self.resolve_and_print_fj(\"_IO_wfile_jumps_maybe_mmap\", libc)\n                self.resolve_and_print_fj(\"_IO_old_file_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_mem_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_wmem_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_str_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_strn_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_str_chk_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_wstr_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_wstrn_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_streambuf_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_proc_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_old_proc_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_helper_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_cookie_jumps\", libc)\n                self.resolve_and_print_fj(\"_IO_obstack_jumps\", libc)\n            else:\n                self.resolve_and_print_fj(\"__io_vtables[IO_STR_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WSTR_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_FILE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_FILE_JUMPS_MMAP]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_FILE_JUMPS_MAYBE_MMAP]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WFILE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WFILE_JUMPS_MMAP]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WFILE_JUMPS_MAYBE_MMAP]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_COOKIE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_PROC_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_MEM_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WMEM_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_PRINTF_BUFFER_AS_FILE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_WPRINTF_BUFFER_AS_FILE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_OLD_FILE_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_OLD_PROC_JUMPS]\", libc)\n                self.resolve_and_print_fj(\"__io_vtables[IO_OLD_COOKIED_JUMPS]\", libc)\n\n        self.resolve_and_print(\"open\", libc)\n        self.resolve_and_print(\"read\", libc)\n        self.resolve_and_print(\"write\", libc)\n        if not self.args.smart:\n            self.resolve_and_print(\"dup\", libc)\n            self.resolve_and_print(\"dup2\", libc)\n            self.resolve_and_print(\"dup3\", libc)\n            self.resolve_and_print(\"puts\", libc)\n            self.resolve_and_print(\"gets\", libc)\n            self.resolve_and_print(\"fputs\", libc)\n            self.resolve_and_print(\"fgets\", libc)\n            self.resolve_and_print(\"printf\", libc)\n            self.resolve_and_print(\"fprintf\", libc)\n            self.resolve_and_print(\"dprintf\", libc)\n            self.resolve_and_print(\"sprintf\", libc)\n            self.resolve_and_print(\"snprintf\", libc)\n            self.resolve_and_print(\"__printf_chk\", libc)\n            self.resolve_and_print(\"__fprintf_chk\", libc)\n            self.resolve_and_print(\"__dprintf_chk\", libc)\n            self.resolve_and_print(\"__sprintf_chk\", libc)\n            self.resolve_and_print(\"__snprintf_chk\", libc)\n            self.resolve_and_print(\"__printf_function_table\", libc)\n            self.resolve_and_print(\"__printf_arginfo_table\", libc)\n            self.resolve_and_print(\"scanf\", libc)\n            self.resolve_and_print(\"fscanf\", libc)\n            self.resolve_and_print(\"sscanf\", libc)\n\n        gef_print(titlify(\"Process\"))\n        self.resolve_and_print(\"system\", libc)\n        if not self.args.smart:\n            self.resolve_and_print(\"do_system\", libc)\n        self.resolve_and_print(\"execve\", libc)\n        self.resolve_and_print(\"setcontext\", libc)\n        if not self.args.smart:\n            self.resolve_and_print(\"__libc_start_main\", libc)\n            self.resolve_and_print(\"syscall\", libc)\n            self.resolve_and_print(\"ptrace\", libc)\n            self.resolve_and_print(\"prctl\", libc)\n\n        if not self.args.smart:\n            gef_print(titlify(\"Memory\"))\n            self.resolve_and_print(\"mmap\", libc)\n            self.resolve_and_print(\"munmap\", libc)\n            self.resolve_and_print(\"mremap\", libc)\n            self.resolve_and_print(\"mprotect\", libc)\n            gef_print(titlify(\"Stack\"))\n            self.resolve_and_print(\"__libc_argv\", libc)\n            self.resolve_and_print(\"__environ\", libc)\n            gef_print(titlify(\"Destructor\"))\n            self.resolve_and_print(\"_rtld_global->_dl_rtld_lock_recursive\", ld)\n            self.resolve_and_print(\"_rtld_global->_dl_rtld_unlock_recursive\", ld)\n            self.resolve_and_print(\"error_print_progname\", libc)\n            gef_print(titlify(\"Unwind\"))\n            self.resolve_and_print(\"'DW.ref.__gxx_personality_v0'\", codebase)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"wine\", \"kgdb\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if is_qemu_system() or is_vmware():\n            info(\"Redirect to kmagic\")\n            gdb.execute(\"kmagic {:s}\".format(\" \".join(args.filter)))\n            return\n\n        self.magic()\n        return\n\n\n@register_command\nclass KernelMagicCommand(GenericCommand):\n    \"\"\"Display useful kernel addresses and offsets.\"\"\"\n\n    _cmdline_ = \"kmagic\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", help=\"filter string.\")\n    _syntax_ = parser.format_help()\n\n    def should_be_print(self, sym):\n        if not self.args.filter:\n            return True\n\n        for filt in self.args.filter:\n            if filt in sym:\n                return True\n        return False\n\n    def resolve_and_print_kernel(self, sym, base, maps, external_func=None, to_string=False):\n\n        def get_permission(addr, maps):\n            if maps is None:\n                return \"???\"\n            for vaddr, size, perm in maps:\n                if vaddr <= addr and addr < vaddr + size:\n                    return perm\n            return \"???\"\n\n        if not self.should_be_print(sym):\n            return\n\n        width = AddressUtil.get_format_address_width()\n        if external_func:\n            try:\n                addr = external_func()\n            except Exception:\n                gef_print(\"{:42s} {:>{:d}s}\".format(sym, \"Not found\", width))\n                return\n            if addr is None:\n                gef_print(\"{:42s} {:>{:d}s}\".format(sym, \"Not found\", width))\n                return\n        else:\n            if isinstance(sym, str):\n                addr = Symbol.get_ksymaddr(sym)\n                if addr is None:\n                    gef_print(\"{:42s} {:>{:d}s}\".format(sym, \"Not found\", width))\n                    return\n            elif isinstance(sym, list):\n                for s in sym:\n                    addr = Symbol.get_ksymaddr(s)\n                    if addr:\n                        sym = s\n                        break\n                else:\n                    sym = sym[0]\n                    gef_print(\"{:42s} {:>{:d}s}\".format(sym, \"Not found\", width))\n                    return\n\n        if not is_valid_addr(addr):\n            gef_print(\"{:42s} {:#0{:d}x} [---]               -> Inaccessible\".format(\n                sym, addr, width,\n            ))\n            return\n\n        perm = get_permission(addr, maps)\n        if base is None:\n            val = read_int_from_memory(addr)\n            gef_print(\"{:42s} {:#0{:d}x} [{:3s}]               -> {:#0{:d}x}\".format(\n                sym, addr, width, perm, val, width,\n            ))\n        elif to_string:\n            val = read_cstring_from_memory(addr) or \"???\"\n            gef_print(\"{:42s} {:#0{:d}x} [{:3s}] (+{:#010x}) -> {:s}\".format(\n                sym, addr, width, perm, addr - base, val,\n            ))\n        else:\n            val = read_int_from_memory(addr)\n            gef_print(\"{:42s} {:#0{:d}x} [{:3s}] (+{:#010x}) -> {:#0{:d}x}\".format(\n                sym, addr, width, perm, addr - base, val, width,\n            ))\n        return\n\n    def magic_kernel(self):\n        info(\"Wait for memory scan\")\n        kversion = Kernel.kernel_version()\n\n        kinfo = Kernel.get_kernel_layout()\n        maps = kinfo.maps\n        text_base = kinfo.text_base\n        text_size = kinfo.text_size\n        if text_base is None or text_size is None:\n            return\n        gef_print(\"{:42s} {:#x} ({:#x} bytes)\".format(\"kernel_base\", text_base, text_size))\n\n        gef_print(titlify(\"Legend\"))\n        fmt = \"{:42s} {:{:d}s} {:5s} (+{:10s}) -> {:{:d}s}\"\n        width = AddressUtil.get_format_address_width()\n        legend = [\"Symbol\", \"Addr\", width, \"Perm\", \"Offset\", \"Value\", width]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        gef_print(titlify(\"Credential\"))\n        self.resolve_and_print_kernel(\"commit_creds\", text_base, maps)\n        self.resolve_and_print_kernel(\"prepare_kernel_cred\", text_base, maps)\n        self.resolve_and_print_kernel(\n            \"init_cred\", text_base, maps, KernelAddressHeuristicFinder.get_init_cred,\n        )\n        self.resolve_and_print_kernel([\"sys_setuid\", \"__sys_setuid\"], text_base, maps)\n        self.resolve_and_print_kernel(\n            \"init_task\", text_base, maps, KernelAddressHeuristicFinder.get_init_task,\n        )\n        gef_print(titlify(\"Usermode helper\"))\n        self.resolve_and_print_kernel(\"call_usermodehelper\", text_base, maps)\n        self.resolve_and_print_kernel(\"run_cmd\", text_base, maps)\n        self.resolve_and_print_kernel(\n            \"modprobe_path\", text_base, maps, KernelAddressHeuristicFinder.get_modprobe_path, to_string=True,\n        )\n        self.resolve_and_print_kernel(\"orderly_poweroff\", text_base, maps)\n        self.resolve_and_print_kernel(\n            \"poweroff_cmd\", text_base, maps, KernelAddressHeuristicFinder.get_poweroff_cmd, to_string=True,\n        )\n        self.resolve_and_print_kernel(\n            \"core_pattern\", text_base, maps, KernelAddressHeuristicFinder.get_core_pattern, to_string=True,\n        )\n        gef_print(titlify(\"ROP finalizer\"))\n        if is_x86_64():\n            self.resolve_and_print_kernel(\n                \"swapgs_restore_regs_and_return_to_usermode\", text_base, maps,\n            )\n        self.resolve_and_print_kernel(\"msleep\", text_base, maps)\n        gef_print(titlify(\"Memory protection modifier\"))\n        if is_x86():\n            self.resolve_and_print_kernel(\"native_write_cr0\", text_base, maps)\n            self.resolve_and_print_kernel(\"native_write_cr4\", text_base, maps)\n        self.resolve_and_print_kernel(\"set_memory_rw\", text_base, maps)\n        self.resolve_and_print_kernel(\"set_memory_x\", text_base, maps)\n        gef_print(titlify(\"Memory patcher\"))\n        if is_x86():\n            self.resolve_and_print_kernel(\"text_poke\", text_base, maps)\n        self.resolve_and_print_kernel(\"memcpy\", text_base, maps)\n        if is_x86():\n            self.resolve_and_print_kernel([\"_copy_to_user\", \"copy_to_user\"], text_base, maps)\n            self.resolve_and_print_kernel([\"_copy_from_user\", \"copy_from_user\"], text_base, maps)\n        elif is_arm32():\n            self.resolve_and_print_kernel([\"arm_copy_to_user\", \"__copy_to_user\"], text_base, maps)\n            self.resolve_and_print_kernel([\"arm_copy_from_user\", \"__copy_from_user\"], text_base, maps)\n        elif is_arm64():\n            self.resolve_and_print_kernel(\"__arch_copy_to_user\", text_base, maps)\n            self.resolve_and_print_kernel(\"__arch_copy_from_user\", text_base, maps)\n        gef_print(titlify(\"Memory remapper\"))\n        self.resolve_and_print_kernel([\"ioremap\", \"__ioremap\", \"ioremap_cache\"], text_base, maps)\n        self.resolve_and_print_kernel([\"iounmap\", \"__iounmap\"], text_base, maps)\n        if is_x86():\n            gef_print(titlify(\"Automatically called function pointer\"))\n            self.resolve_and_print_kernel(\"kvm_clock\", text_base, maps)\n            self.resolve_and_print_kernel(\n                \"clocksource_tsc\", text_base, maps, KernelAddressHeuristicFinder.get_clocksource_tsc,\n            )\n        gef_print(titlify(\"Function pointer table\"))\n        self.resolve_and_print_kernel(\n                \"capability_hooks\", text_base, maps, KernelAddressHeuristicFinder.get_capability_hooks,\n            )\n        self.resolve_and_print_kernel(\n            \"n_tty_ops\", text_base, maps, KernelAddressHeuristicFinder.get_n_tty_ops,\n        )\n        gef_print(titlify(\"Function pointer table array\"))\n        self.resolve_and_print_kernel(\n            \"tty_ldiscs\", text_base, maps, KernelAddressHeuristicFinder.get_tty_ldiscs,\n        )\n        gef_print(titlify(\"Allocator\"))\n        self.resolve_and_print_kernel(\"__kmalloc\", text_base, maps)\n        self.resolve_and_print_kernel([\"kzalloc\", \"kzalloc.constprop.0\"], text_base, maps)\n        self.resolve_and_print_kernel(\"kfree\", text_base, maps)\n        self.resolve_and_print_kernel([\"kzfree\", \"kfree_sensitive\"], text_base, maps)\n        self.resolve_and_print_kernel(\n            \"slab_caches\", text_base, maps, KernelAddressHeuristicFinder.get_slab_caches,\n        )\n        gef_print(titlify(\"Dynamic resolver\"))\n        self.resolve_and_print_kernel(\"kallsyms_lookup_name\", text_base, maps)\n        if is_x86_64():\n            if kversion and \"3.16\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_image_64\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_image_64,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso_image_32\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_image_32,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso_image_x32\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_image_x32,\n                )\n        elif is_x86_32():\n            if kversion and \"3.16\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_image_32\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_image_32,\n                )\n        elif is_arm64():\n            if kversion and \"5.8\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_info\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_info,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_start,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso32_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso32_start,\n                )\n            elif kversion and \"5.3\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_lookup\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_lookup,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_start,\n                )\n                self.resolve_and_print_kernel(\n                    \"vdso32_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso32_start,\n                )\n            elif kversion and \"3.7\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_start,\n                )\n        elif is_arm32():\n            if kversion and \"4.1\" <= kversion:\n                gef_print(titlify(\"vDSO\"))\n                self.resolve_and_print_kernel(\n                    \"vdso_start\", text_base, maps, KernelAddressHeuristicFinder.get_vdso_start,\n                )\n        gef_print(titlify(\"Others\"))\n        self.resolve_and_print_kernel([\"do_fchmodat\", \"sys_fchmodat\"], text_base, maps)\n        self.resolve_and_print_kernel(\n            \"mmap_min_addr\", text_base, maps, KernelAddressHeuristicFinder.get_mmap_min_addr,\n        )\n        self.resolve_and_print_kernel(\n            \"__per_cpu_offset\", text_base, maps, KernelAddressHeuristicFinder.get_per_cpu_offset,\n        )\n        if is_x86():\n            gef_print(titlify(\"Descriptor Table\"))\n            self.resolve_and_print_kernel(\n                \"IDT base (fixed address?)\", None, maps, KernelAddressHeuristicFinder.get_idt_base,\n            )\n            self.resolve_and_print_kernel(\n                \"GDT base (fixed address?)\", None, maps, KernelAddressHeuristicFinder.get_gdt_base,\n            )\n            self.resolve_and_print_kernel(\n                \"LDT base (fixed address?)\", None, maps, KernelAddressHeuristicFinder.get_ldt_base,\n            )\n            self.resolve_and_print_kernel(\n                \"TSS base (fixed address?)\", None, maps, KernelAddressHeuristicFinder.get_tss_base,\n            )\n        gef_print(titlify(\"Memory base\"))\n        self.resolve_and_print_kernel(\n            \"PAGE_OFFSET (physmem direct map)\", None, maps, KernelAddressHeuristicFinder.get_PAGE_OFFSET,\n        )\n        self.resolve_and_print_kernel(\n            \"PAGE_OFFSET_END\", None, maps, KernelAddressHeuristicFinder.get_PAGE_OFFSET_END,\n        )\n        self.resolve_and_print_kernel(\n            \"VMALLOC_START\", None, maps, KernelAddressHeuristicFinder.get_VMALLOC_START,\n        )\n        self.resolve_and_print_kernel(\n            \"VMALLOC_END\", None, maps, KernelAddressHeuristicFinder.get_VMALLOC_END,\n        )\n        if is_x86_64() or is_arm64():\n            self.resolve_and_print_kernel(\n                \"VMEMMAP_START (struct page[])\", None, maps, KernelAddressHeuristicFinder.get_VMEMMAP_START,\n            )\n            self.resolve_and_print_kernel(\n                \"VMEMMAP_END\", None, maps, KernelAddressHeuristicFinder.get_VMEMMAP_END,\n            )\n        if is_x86_64():\n            self.resolve_and_print_kernel(\n                \"phys_base (kbase@phys)\", text_base, maps, KernelAddressHeuristicFinder.get_phys_base,\n            )\n        if is_x86_32() or is_arm32():\n            self.resolve_and_print_kernel(\n                \"mem_map (struct page[])\", None, maps, KernelAddressHeuristicFinder.get_mem_map,\n            )\n            self.resolve_and_print_kernel(\n                \"mem_section (struct page[][])\", None, maps, KernelAddressHeuristicFinder.get_mem_section,\n            )\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.magic_kernel()\n        return\n\n\n@register_command\nclass OneGadgetCommand(GenericCommand):\n    \"\"\"Invoke `one_gadget`.\"\"\"\n\n    _cmdline_ = \"onegadget\"\n    _category_ = \"01-i. Debugging Support - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-s\", \"--apply-smart-filter\", action=\"store_true\",\n                        help=\"filter valid gadgets for the current register and memory values (x64 only).\")\n    _syntax_ = parser.format_help()\n\n    def parse_exp(self, exp):\n        orig_exp = exp[::] # for debug\n\n        # preparation\n        exp = re.sub(r\"(xmm\\d+)\", \"$\\\\1.uint128\", exp)\n        exp = exp.replace(\"NULL\", \"0\")\n        exp = exp.replace(\"(u16)\", \"(unsigned short)\")\n        exp = exp.replace(\"(s16)\", \"(signed short)\")\n        exp = exp.replace(\"(u32)\", \"(unsigned int)\")\n        exp = exp.replace(\"(s32)\", \"(signed int)\")\n        exp = exp.replace(\"(u64)\", \"(unsigned long long)\")\n        exp = exp.replace(\"(s64)\", \"(signed long long)\")\n\n        # fix register name\n        for regname in current_arch.general_registers:\n            exp = exp.replace(regname[1:], \"((unsigned long)\" + regname + \")\")\n\n        # enclose both sides in parentheses\n        if \"==\" in exp:\n            exp = [\"(\" + e + \")\" for e in exp.split(\"==\")]\n            exp = \"==\".join(exp)\n\n        # fix memory accessing\n        while True:\n            m = re.search(r\"(\\[[^\\[\\]]+\\])\", exp) # find innermost [...]\n            if not m:\n                break\n            prefix = exp[:m.regs[1][0]]\n            target = m.group(1)[1:-1] # skip \"[\", \"]\"\n            suffix = exp[m.regs[1][1]:]\n            target = \"(*(unsigned long*)(\" + target + \"))\"\n            exp = prefix + target + suffix\n\n        # evaluate\n        try:\n            return AddressUtil.parse_address(exp)\n        except (gdb.MemoryError, MemoryError):\n            pass\n        except Exception:\n            err(\"Could not handle\")\n            err(\"before: \" + orig_exp)\n            err(\"after : \" + exp)\n        return None\n\n    def get_filtered_result(self, one_gadget_command, libc_path):\n        res = GefUtil.gef_execute_external([one_gadget_command, libc_path, \"-l\", \"1\"], as_list=True)\n        res_groups = \"\\n\".join(res).split(\"\\n\\n\")\n        gadgets = [line.split(\"\\n\") for line in res_groups]\n\n        valid_lines = []\n        for g in gadgets:\n            valid = True\n\n            for constraints in g[2:]:\n                constraints = constraints.strip()\n\n                # pattern 1: address rsp+0x60 is writable\n                m = re.match(r\"address (\\S+) is writable\", constraints)\n                if m:\n                    ret = self.parse_exp(m.group(1))\n                    if ret is None:\n                        continue\n                    addr = ProcessMap.lookup_address(ret)\n                    if not addr.valid or not addr.section.is_writable():\n                        valid &= False\n                        break\n                    continue\n\n                # pattern 2: A || B\n                sub_valid = False\n                for sub_constraints in constraints.split(\" || \"):\n                    # pattern 2-1: {\"sh\", rax, rip+0x17302e, r12, ...} is a valid argv\n                    if \"is a valid\" in sub_constraints:\n                        # Accurate evaluation is impossible.\n                        # This condition is rarely met, so it is always considered invalid.\n                        sub_valid |= False\n                        continue\n\n                    # pattern 2-2: writable: rdi\n                    if \"writable:\" in sub_constraints:\n                        exp = sub_constraints.split(\": \")[-1]\n                        ret = self.parse_exp(exp)\n                        if ret is None:\n                            continue\n                        addr = ProcessMap.lookup_address(ret)\n                        if addr.valid and addr.section.is_writable():\n                            sub_valid = True\n                            break\n                        continue\n\n                    # pattern 2-3: rsp & 0xf == 0\n                    #              (u64)xmm0 == NULL\n                    #              rdx == NULL\n                    #              (s32)[rdx+0x4] <= 0\n                    exp = sub_constraints\n                    if self.parse_exp(sub_constraints):\n                        sub_valid = True\n                        break\n                    continue\n\n                if sub_valid is False:\n                    valid = False\n                    continue\n\n            if valid:\n                valid_lines.extend(g)\n                valid_lines.append(\"\")\n        return \"\\n\".join(valid_lines)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_gdb_target_local\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        try:\n            one_gadget_command = GefUtil.which(\"one_gadget\")\n        except FileNotFoundError:\n            err(\"Missing `one_gadget`, install with: `gem install one_gadget`\")\n            return\n\n        if args.apply_smart_filter and not is_x86_64():\n            err(\"Unsupported (x64 only)\")\n            return\n\n        libc = ProcessMap.process_lookup_path((\"libc-2.\", \"libc.so.6\"))\n        if libc is None:\n            err(\"Could not find the libc\")\n            return\n\n        gef_print(titlify(\"{!r} {!r} -l 1\".format(one_gadget_command, libc.path)))\n\n        if args.apply_smart_filter:\n            condition = Color.boldify(\"`... is a valid ...`\")\n            false = Color.boldify(\"false\")\n            info(\"The condition {:s} is always assumed to be {:s}\".format(condition, false))\n\n            res = self.get_filtered_result(one_gadget_command, libc.path)\n            gef_print(res)\n        else:\n            os.system(\"{!r} {!r} -l 1\".format(one_gadget_command, libc.path))\n        return\n\n\n@register_command\nclass SeccompCommand(GenericCommand):\n    \"\"\"Invoke `ceccomp` or `seccomp-tools`.\"\"\"\n\n    _cmdline_ = \"seccomp\"\n    _category_ = \"01-i. Debugging Support - Other\"\n    _aliases_ = [\"ceccomp\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=False)\n    group.add_argument(\"-c\", \"--force-ceccomp\", action=\"store_true\", help=\"force use ceccomp.\")\n    group.add_argument(\"-s\", \"--force-seccomp-tools\", action=\"store_true\", help=\"force use seccomp-tools.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Default: Search `ceccomp` -> `seccomp-tools`, and use found one.\",\n        \"With `-c` or `-s`: Forces GEF to use the specified one.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_ceccomp_command(self):\n        try:\n            comm = GefUtil.which(\"ceccomp\")\n            return [f\"{comm!r} trace --quiet \", f\"{comm!r} probe --quiet \"]\n        except FileNotFoundError:\n            err(\"Missing `ceccomp`, install from https://github.com/dbgbgtf1/Ceccomp\")\n            return None\n\n    def get_seccomp_tools_command(self):\n        try:\n            comm = GefUtil.which(\"seccomp-tools\")\n            return [f\"{comm!r} dump \"]\n        except FileNotFoundError:\n            err(\"Missing `seccomp-tools`, install with: `gem install seccomp-tools`\")\n            return None\n\n    def get_either_command(self):\n        try:\n            comm = GefUtil.which(\"ceccomp\")\n            return [f\"{comm!r} trace --quiet \", f\"{comm!r} probe --quiet \"]\n        except FileNotFoundError:\n            try:\n                comm = GefUtil.which(\"seccomp-tools\")\n                return [f\"{comm!r} dump \"]\n            except FileNotFoundError:\n                err(\"Missing both `ceccomp` and `seccomp-tools`\")\n                err(\"install with `gem install seccomp-tools` or build `ceccomp`\")\n                return None\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.force_seccomp_tools:\n            ret = self.get_seccomp_tools_command()\n        elif args.force_ceccomp:\n            ret = self.get_ceccomp_command()\n        else:\n            ret = self.get_either_command()\n        if ret is None:\n            return\n        commands = ret\n\n        path = Path.get_filepath()\n        if path is None:\n            err(\"Could not find the target binary\")\n            return\n\n        for comm in commands:\n            comm += f\"{path!r}\"\n            gef_print(titlify(comm))\n            os.system(comm)\n        return\n\n\n@register_command\nclass SysregCommand(GenericCommand):\n    \"\"\"Pretty-print system registers (not general purpose) from `info register`.\"\"\"\n\n    _cmdline_ = \"sysreg\"\n    _category_ = \"04-a. Register - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filter\", metavar=\"FILTER\", nargs=\"*\", help=\"filter string.\")\n    parser.add_argument(\"--exact\", action=\"store_true\", help=\"use exact match.\")\n    _syntax_ = parser.format_help()\n\n    def get_non_generic_regs(self):\n        if is_riscv64() or is_riscv32():\n            res = gdb.execute(\"info registers system\", to_string=True)\n        else:\n            res = gdb.execute(\"info registers\", to_string=True)\n        res = res.strip()\n        regs = {}\n        for line in res.splitlines():\n            m = re.match(r\"^(\\S+)\\s*(0x\\S+)\", line)\n            if not m:\n                continue\n            regname, regvalue = m.group(1), m.group(2)\n            if self.args.filter:\n                if self.args.exact:\n                    if not any(f.lower() == regname.lower() for f in self.args.filter):\n                        continue\n                else:\n                    if not any(f.lower() in regname.lower() for f in self.args.filter):\n                        continue\n            regs[regname] = int(regvalue, 16)\n        regs = list(filter(lambda x: \"$\" + x[0] not in current_arch.all_registers, sorted(regs.items())))\n        return regs # [[regname, regvalue], ...]\n\n    def print_sysreg_compact(self):\n        regs = self.get_non_generic_regs()\n        if regs:\n            gef_print(titlify(\"System registers\"))\n        else:\n            gef_print(\"Could not find non generic regs\")\n            return\n        COLUMN = 3\n        length = len(regs)\n        length_of_each_bank = (length + COLUMN - 1) // COLUMN\n        for i in range(length_of_each_bank):\n            out = []\n            for j in range(COLUMN):\n                if len(regs) > i + j * length_of_each_bank:\n                    msg = \"{:25s} = {:#18x}\".format(*regs[i + j * length_of_each_bank])\n                    if regs[i + j * length_of_each_bank][1] > 0:\n                        msg = Color.boldify(msg)\n                    out.append(msg)\n                else:\n                    out.append(\"\")\n            gef_print(\"  |  \".join(out))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if is_kgdb() and not kgdb_has_system_registers():\n            err(\"Unsupported in kgdb mode without access to system registers\")\n            return\n        self.print_sysreg_compact()\n        return\n\n\n@register_command\nclass MmxSetCommand(GenericCommand):\n    \"\"\"Simply set the value to mm register.\"\"\"\n\n    _cmdline_ = \"mmxset\"\n    _category_ = \"04-b. Register - Modify\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"reg_and_value\", metavar=\"REG=VALUE\", help=\"MMX register and value to set.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $mm0=0x1122334455667788\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Disable `-enable-kvm` option for qemu-system.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def execute_movq_mm(self, value, reg):\n        REG_CODE = {\n            \"$mm0\": b\"\\x0f\\x6f\\x00\", # movq  mm0, qword ptr [rax]\n            \"$mm1\": b\"\\x0f\\x6f\\x08\", # movq  mm1, qword ptr [rax]\n            \"$mm2\": b\"\\x0f\\x6f\\x10\", # movq  mm2, qword ptr [rax]\n            \"$mm3\": b\"\\x0f\\x6f\\x08\", # movq  mm3, qword ptr [rax]\n            \"$mm4\": b\"\\x0f\\x6f\\x20\", # movq  mm4, qword ptr [rax]\n            \"$mm5\": b\"\\x0f\\x6f\\x28\", # movq  mm5, qword ptr [rax]\n            \"$mm6\": b\"\\x0f\\x6f\\x30\", # movq  mm6, qword ptr [rax]\n            \"$mm7\": b\"\\x0f\\x6f\\x38\", # movq  mm7, qword ptr [rax]\n        }\n        codes = [REG_CODE[reg] + p64(value)] # movq mm0, [rax]; db value\n\n        if is_x86_64():\n            regs = {\"$rax\": current_arch.pc + 5} # points to value\n        else:\n            regs = {\"$eax\": current_arch.pc + 5} # points to value\n\n        ExecAsm(codes, regs=regs).exec_code()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        # arg parse\n        try:\n            reg, value = args.reg_and_value.split(\"=\")\n            value = int(value, 0)\n        except ValueError:\n            self.usage()\n            return\n\n        # check register is valid or not\n        if reg not in [\"$mm{:d}\".format(i) for i in range(8)]:\n            err(\"Invalid register name\")\n            return\n\n        # modify\n        self.execute_movq_mm(value, reg)\n        return\n\n\n@register_command\nclass MmxCommand(GenericCommand):\n    \"\"\"Display MMX registers.\"\"\"\n\n    _cmdline_ = \"mmx\"\n    _category_ = \"04-a. Register - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def print_mmx(self):\n        gef_print(titlify(\"MMX Register (from fpu register)\"))\n        regs = []\n\n        for i in range(8):\n            regname = \"$st{:d}\".format(i)\n            result = gdb.execute(f\"info registers $st{i}\", to_string=True)\n            r = re.findall(r\"\\(raw (0x[0-9a-f]+)\\)\", result)\n            if r:\n                reg = int(r[0], 16) & 0xffff_ffff_ffff_ffff\n                regs.append(reg)\n\n        fstat = get_register(\"$fstat\")\n        top_of_stack = (fstat >> 11) & 0b111\n        regs = regs[-top_of_stack:] + regs[:-top_of_stack] # need rotate. because mmx0 != st(0)\n\n        fmt = \"{:5s}: {:s}\"\n        legend = [\"Name\", \"64-bit hex\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        red = lambda x: Color.colorify(\"{:s}\".format(x), \"bold red\")\n        for i in range(len(regs)):\n            regname = \"$mm{:d}\".format(i)\n            reghex = \"\"\n            for j in range(8):\n                c = (regs[i] >> (8 * j)) & 0xff\n                reghex += chr(c) if 0x20 <= c < 0x7f else \".\"\n            gef_print(\"{:s} : {:#018x}  |  {:s}  |\".format(red(regname), regs[i], reghex))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        self.print_mmx()\n        return\n\n\n@register_command\nclass XmmSetCommand(GenericCommand):\n    \"\"\"Simply set the value to xmm or ymm register.\"\"\"\n\n    _cmdline_ = \"xmmset\"\n    _category_ = \"04-b. Register - Modify\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"reg_and_value\", metavar=\"REG=VALUE\", help=\"XMM/YMM/ZMM register and value to set.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $ymm0=0x11223344556677889900aabbccddeeff9876543210\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        # arg parse\n        try:\n            reg, value = args.reg_and_value.split(\"=\")\n            value = int(value, 0)\n        except Exception:\n            self.usage()\n            return\n\n        # check register is valid or not\n        try:\n            gdb.execute(f\"info registers {reg}\", to_string=True)\n        except gdb.error:\n            err(\"Invalid register name\")\n            return\n\n        # modify\n        if \"$xmm\" in reg:\n            for i in range(2):\n                v = (value >> (64 * i)) & ((1 << 64) - 1)\n                gdb.execute(f\"set {reg}.v2_int64[{i}]={v:#x}\", to_string=True)\n        elif \"$ymm\" in reg:\n            for i in range(4):\n                v = (value >> (64 * i)) & ((1 << 64) - 1)\n                gdb.execute(f\"set {reg}.v4_int64[{i}]={v:#x}\", to_string=True)\n        elif \"$zmm\" in reg:\n            for i in range(8):\n                v = (value >> (64 * i)) & ((1 << 64) - 1)\n                gdb.execute(f\"set {reg}.v8_int64[{i}]={v:#x}\", to_string=True)\n        else:\n            err(\"Unsupported\")\n        return\n\n\n@register_command\nclass SseCommand(GenericCommand):\n    \"\"\"Display SSE registers.\"\"\"\n\n    _cmdline_ = \"sse\"\n    _category_ = \"04-a. Register - View\"\n    _aliases_ = [\"xmm\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"also display bit information of mxcsr registers.\")\n    _syntax_ = parser.format_help()\n\n    def print_sse(self):\n        gef_print(titlify(\"SSE Data Register\"))\n\n        # xmm0-15\n        regs = []\n        for i in range(16 if is_x86_64() else 8):\n            result = gdb.execute(f\"info registers $xmm{i}\", to_string=True)\n            r = re.findall(r\"uint128 = (0x[0-9a-f]+)\", result)\n            if r:\n                reg = int(r[0], 16)\n                regs.append(reg)\n\n        fmt = \"{:7s}: {:s}\"\n        legend = [\"Name\", \"128-bit hex\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        red = lambda x: Color.colorify(\"{:s}\".format(x), \"bold red\")\n        for i in range(len(regs)):\n            if i == 8:\n                gef_print(\"* xmm8-15 are introduced by AVX\")\n            reghex = \"\"\n            for j in range(16):\n                c = (regs[i] >> (8 * j)) & 0xff\n                reghex += chr(c) if 0x20 <= c < 0x7f else \".\"\n            regname = \"$xmm{:<2d}\".format(i)\n            gef_print(\"{:s} : {:#034x}  |  {:s}  |\".format(red(regname), regs[i], reghex))\n        return\n\n    def print_sse_other(self):\n        # mxcsr\n        gef_print(titlify(\"MXCSR (MXCSR Control and Status Register)\"))\n        bit_info = [\n            [15, \"FZ\", \"Flush To Zero\"],\n            [[13, 14], \"RC\", \"Rounding Control\",\n             \"00: Round To Nearest, 01: Round Negative, 10: Round Positive, 11: Round To Zero\"],\n            [12, \"PM\", \"Precision Exception Mask\"],\n            [11, \"UM\", \"Underflow Exception Mask\"],\n            [10, \"OM\", \"Overflow Exception Mask\"],\n            [9, \"ZM\", \"Zero Divide Exception Mask\"],\n            [8, \"DM\", \"Denormalized Opernad Exception Mask\"],\n            [7, \"IM\", \"Invalid Operation Exception Mask\"],\n            [6, \"DAZ\", \"Use as 0.0 if input data is denormalized\"],\n            [5, \"PE\", \"Precision Exception\"],\n            [4, \"UE\", \"Underflow Exception\"], # codespell:ignore\n            [3, \"OE\", \"Overflow Exception\"],\n            [2, \"ZE\", \"Zero Divide Exception\"],\n            [1, \"DE\", \"Denormalized Operand Exception\"],\n            [0, \"IE\", \"Invalid Operation Exception\"],\n        ]\n        reg = int(gdb.execute(\"info registers $mxcsr\", to_string=True).split()[1], 16)\n        BitInfo(\"$mxcsr\", 32, bit_info).print(reg)\n        return\n\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, argv):\n        if \"-h\" in argv:\n            self.usage()\n            return\n\n        self.print_sse()\n        if \"-v\" in argv:\n            self.print_sse_other()\n        else:\n            info(\"for $mxcsr flags description, use `-v`\")\n        return\n\n\n@register_command\nclass AvxCommand(GenericCommand):\n    \"\"\"Display AVX registers.\"\"\"\n\n    _cmdline_ = \"avx\"\n    _category_ = \"04-a. Register - View\"\n    _aliases_ = [\"ymm\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def print_avx(self):\n        regs = []\n        for i in range(16 if is_x86_64() else 8):\n            try:\n                result = gdb.execute(f\"info registers $ymm{i}\", to_string=True)\n            except gdb.error:\n                continue\n            result = result.replace(\"\\n\", \"\")\n            r = re.findall(r\"v2_int128 = \\{\"\n                           r\".*?\\[0x0\\] = (0x[0-9a-f]+),\"\n                           r\".*?\\[0x1\\] = (0x[0-9a-f]+)\"\n                           r\".*?\\}\", result)\n            if r:\n                reg = (int(r[0][1], 16) << 128) + int(r[0][0], 16)\n                regs.append(reg)\n        if regs:\n            gef_print(titlify(\"AVX Register\"))\n\n            fmt = \"{:7s}: {:s}\"\n            legend = [\"Name\", \"256-bit hex\"]\n            gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n            red = lambda x: Color.colorify(\"{:s}\".format(x), \"bold red\")\n            for i in range(len(regs)):\n                regname = \"$ymm{:<2d}\".format(i)\n                reghex = \"\"\n                for j in range(32):\n                    c = (regs[i] >> (8 * j)) & 0xff\n                    reghex += chr(c) if 0x20 <= c < 0x7f else \".\"\n                gef_print(\"{:s} : {:#066x}  |  {:s}  |\".format(red(regname), regs[i], reghex))\n        else:\n            err(\"Could not find avx registers\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        self.print_avx()\n        return\n\n\n@register_command\nclass Avx512Command(GenericCommand):\n    \"\"\"Display AVX512 registers.\"\"\"\n\n    _cmdline_ = \"avx512\"\n    _category_ = \"04-a. Register - View\"\n    _aliases_ = [\"zmm\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def print_avx512(self):\n        regs = []\n        for i in range(32):\n            try:\n                result = gdb.execute(f\"info registers $zmm{i}\", to_string=True)\n            except gdb.error:\n                continue\n            result = result.replace(\"\\n\", \"\")\n            r = re.findall(r\"v4_int128 = \\{\"\n                           r\".*?\\[0x0\\] = (0x[0-9a-f]+),\"\n                           r\".*?\\[0x1\\] = (0x[0-9a-f]+),\"\n                           r\".*?\\[0x2\\] = (0x[0-9a-f]+),\"\n                           r\".*?\\[0x3\\] = (0x[0-9a-f]+)\"\n                           r\".*?\\}\", result)\n            if r:\n                reg = int(r[0][0], 16)\n                reg += (int(r[0][1], 16) << 128)\n                reg += (int(r[0][2], 16) << 256)\n                reg += (int(r[0][3], 16) << 384)\n                regs.append(reg)\n        if regs:\n            gef_print(titlify(\"AVX Register\"))\n\n            fmt = \"{:7s}: {:s}\"\n            legend = [\"Name\", \"512-bit hex\"]\n            gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n            red = lambda x: Color.colorify(\"{:s}\".format(x), \"bold red\")\n            for i in range(len(regs)):\n                regname = \"$zmm{:<2d}\".format(i)\n                reghex = \"\"\n                for j in range(64):\n                    c = (regs[i] >> (8 * j)) & 0xff\n                    reghex += chr(c) if 0x20 <= c < 0x7f else \".\"\n                gef_print(\"{:s} : {:#0130x}  |  {:s}  |\".format(red(regname), regs[i], reghex))\n        else:\n            err(\"Could not find avx512 registers\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        self.print_avx512()\n        return\n\n\n@register_command\nclass FpuCommand(GenericCommand):\n    \"\"\"Display fpu registers (x86/x64:x87-fpu, ARM/ARM64:vfp-d16).\"\"\"\n\n    _cmdline_ = \"fpu\"\n    _category_ = \"04-a. Register - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"also display bit information of fpu control registers.\")\n    _syntax_ = parser.format_help()\n\n    def f2u(self, a):\n        u = lambda a: struct.unpack(\"<I\", a)[0]\n        pf = lambda a: struct.pack(\"<f\", a)\n        return u(pf(a))\n\n    def u2f(self, a):\n        p = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        uf = lambda a: struct.unpack(\"<f\", a)[0]\n        return uf(p(a))\n\n    def d2u(self, a):\n        uQ = lambda a: struct.unpack(\"<Q\", a)[0]\n        pd = lambda a: struct.pack(\"<d\", a)\n        return uQ(pd(a))\n\n    def u2d(self, a):\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        ud = lambda a: struct.unpack(\"<d\", a)[0]\n        return ud(pQ(a))\n\n    def d2u80(self, a):\n        value = ctypes.c_longdouble(a)\n        BYTES = ctypes.POINTER(ctypes.c_byte * 10)\n        ptr = ctypes.cast(ctypes.addressof(value), BYTES)\n        x = [\"{:02x}\".format(int(x) & 0xff) for x in ptr[0][::-1]]\n        return int(\"\".join(x), 16)\n\n    def print_fpu_arm(self):\n        red = lambda x: Color.colorify(\"{:4s}\".format(x), \"bold red\") # need padding\n\n        # s0-s31, d0-d31, q0-q15\n        gef_print(titlify(\"FPU/NEON Data Register\"))\n\n        fmt = \"{:4s}: {:15s} {:10s} | {:4s}: {:28s} {:18s} | {:4s}: {:34s}\"\n        legend = [\n            \"Name\", \"Value\", \"32-bit hex\",\n            \"Name\", \"Value\", \"64-bit hex\",\n            \"Name\", \"128-bit hex\",\n        ]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        for i in range(32):\n            regname1 = \"$s{:d}\".format(i)\n            regname2 = \"$d{:d}\".format(i)\n            regname3 = \"$q{:d}\".format(i)\n            if is_32bit():\n                reg1 = self.f2u(float(gdb.execute(\"p {}\".format(regname1), to_string=True).split()[2]))\n                reg2 = int(gdb.execute(\"p {}.u64\".format(regname2), to_string=True).split()[2], 16)\n                try:\n                    reg3h = int(gdb.execute(\"p {}.u64[0]\".format(regname3), to_string=True).split()[2], 16)\n                    reg3l = int(gdb.execute(\"p {}.u64[1]\".format(regname3), to_string=True).split()[2], 16)\n                    reg3 = (reg3h << 64) + reg3l\n                except Exception:\n                    reg3 = None\n            else:\n                reg1 = int(gdb.execute(\"p {}.u\".format(regname1), to_string=True).split()[2], 16)\n                reg2 = int(gdb.execute(\"p {}.u\".format(regname2), to_string=True).split()[2], 16)\n                try:\n                    reg3 = int(gdb.execute(\"p {}.u\".format(regname3), to_string=True).split()[2], 16)\n                except Exception:\n                    reg3 = None\n\n            fmt1 = \"{:s}: {:15s} {:<#10x}\".format(red(regname1), \"{:<+.8e}\".format(self.u2f(reg1)), reg1)\n            fmt2 = \"{:s}: {:28s} {:<#18x}\".format(red(regname2), \"{:<+.20e}\".format(self.u2d(reg2)), reg2)\n            if reg3 is None:\n                fmt3 = \"{:s}: {:s}\".format(red(regname3), \"Access denied\")\n            else:\n                fmt3 = \"{:s}: {:<#34x}\".format(red(regname3), reg3)\n            gef_print(\"{:s} | {:s} | {:s}\".format(fmt1, fmt2, fmt3))\n        return\n\n    def print_fpu_x86(self):\n        red = lambda x: Color.colorify(\"{:s}\".format(x), \"bold red\")\n\n        # st0-7\n        gef_print(titlify(\"FPU Data Register\"))\n\n        fmt = \"{:9s} : {:27s}\\t{:24s} {:18s} {:10s}\"\n        legend = [\"Name\", \"Value\", \"80-bit hex(TWORD/XWORD)\", \"64-bit hex(QWORD)\", \"32-bit Hex(DWORD)\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        fstat = get_register(\"$fstat\")\n        top_of_stack = (fstat >> 11) & 0b111\n        regs = [\"mm{:d}\".format(i) for i in range(8)]\n        regs = regs[top_of_stack:] + regs[:top_of_stack] # need rotate. because mmx0 != st(0)\n\n        for i in range(8):\n            regname = \"$st{:d}\".format(i)\n            result = gdb.execute(\"info registers {}\".format(regname), to_string=True)\n            if \"invalid\" in result:\n                r = re.findall(r\"\\(raw (0x[0-9a-f]+)\\)\", result)\n                u80 = int(r[0], 16)\n                u64 = 0xfff8_0000_0000_0000 # nan\n                u32 = 0xffc0_0000 # nan\n                gef_print(\"{:4s}({:3s}) : {:<27s}\\t{:<#24x} {:<#18x} {:<#10x}\".format(\n                    red(regname), regs[i], \"<invalid>\", u80, u64, u32,\n                ))\n            else:\n                reg = float(result.split()[1])\n                u80 = self.d2u80(reg)\n                u64 = self.d2u(reg)\n                u32 = self.f2u(reg)\n                gef_print(\"{:4s}({:3s}) : {:<+.20e}\\t{:<#24x} {:<#18x} {:<#10x}\".format(\n                    red(regname), regs[i], reg, u80, u64, u32,\n                ))\n        info('XWORD: Real register value; Used at \"fstp xword ptr [rax]\".')\n        info('QWORD: Used at \"fst/fstp qword ptr [rax]\".')\n        info('DWORD: Used at \"fst/fstp dword ptr [rax]\".')\n        return\n\n    def print_fpu_arm_other(self):\n        # fpscr\n        gef_print(titlify(\"FPSCR (Floating-Point Status and Control Register)\"))\n        bit_info = [\n            [31, \"N\", \"Negative condition flag\"],\n            [30, \"Z\", \"Zero condition flag\"],\n            [29, \"C\", \"Carry condition flag\"],\n            [28, \"V\", \"Overflow condition flag\"],\n            [27, \"QC\", \"Cumulative saturation bit\"],\n            [26, \"AHP\", \"Alternative Half-Precision Control\"],\n            [25, \"DN\", \"Default NaN mode Control\"],\n            [24, \"FZ\", \"Flush-to-zero mode Control\"],\n            [[22, 23], \"RMode\", \"Rounding Control\", \"00: Round To Nearest, 01: Round Positive, 10: Round Negative, 11: Round To Zero\"],\n            [[20, 21], \"Stride\", \"\", \"IMPLEMENTATION DEFINED\"],\n            [19, \"FZ16\", \"Flush-to-zero mode Control\", \"When FEAT_FP16 is implemented\"],\n            [[16, 17, 18], \"Len\", \"\", \"IMPLEMENTATION DEFINED\"],\n            [15, \"IDE\", \"Input Denormal floating-point Exception trap enable\"],\n            [12, \"IXE\", \"Inexact floating-point Exception trap enable\"],\n            [11, \"UFE\", \"Underflow floating-point Exception trap enable\"],\n            [10, \"OFE\", \"Overflow floating-point Exception trap enable\"],\n            [9, \"DZE\", \"Divide by Zero floating-point Exception trap enable\"],\n            [8, \"IOE\", \"Invalid Operation floating-point Exception trap enable\"],\n            [7, \"IDC\", \"Input Denormal Cumulative floating-point exception bit\"],\n            [4, \"IXC\", \"Inexact Cumulative floating-point exception bit\"],\n            [3, \"UFC\", \"Underflow Cumulative floating-point exception bit\"],\n            [2, \"OFC\", \"Overflow Cumulative floating-point exception bit\"],\n            [1, \"DZC\", \"Divide by Zero Cumulative floating-point exception bit\"],\n            [0, \"IOC\", \"Invalid Operation Cumulative floating-point exception bit\"],\n        ]\n        reg = get_register(\"$fpscr\")\n        if reg is not None:\n            BitInfo(\"$fpscr\", 32, bit_info).print(reg)\n        else:\n            warn(\"Failed to get the value\")\n\n        # fpsid\n        gef_print(titlify(\"FPSID (Floating-Point System ID Register)\"))\n        bit_info = [\n            [range(24, 32), \"Implementer\", \"Implementer code\"],\n            [23, \"SW\", \"Software bit\", \"Implementation of floating point instructions, 0:HW, 1:SW\"],\n            [range(16, 23), \"Subarchitecture\", \"Subarchitecture version number\"],\n            [range(8, 16), \"PartNum\", \"Part number\", \"IMPLEMENTATION DEFINED\"],\n            [[4, 5, 6, 7], \"Variant\", \"Variant number\", \"IMPLEMENTATION DEFINED\"],\n            [[0, 1, 2, 3], \"Revision\", \"Revisino number\", \"IMPLEMENTATION DEFINED\"],\n        ]\n        impl = {\n            0x00: \"Reserved for software use\",\n            0xc0: \"Ampere Computing\",\n            0x41: \"Arm Limited\",\n            0x42: \"Broadcom Corporation\",\n            0x43: \"Cavium Inc.\",\n            0x44: \"Digital Equipment Corporation\",\n            0x46: \"Fujitsu Ltd.\",\n            0x49: \"Infineon Technologies AG\",\n            0x4d: \"Motorola or Freescale Semiconductor Inc.\",\n            0x4e: \"NVIDIA Corporation\",\n            0x50: \"Applied Micro Circuits Corporation\",\n            0x51: \"Qualcomm Inc.\",\n            0x56: \"Marvell International Ltd.\",\n            0x69: \"Intel Corporation\",\n        }\n        reg = get_register(\"$fpsid\")\n        if reg is not None:\n            BitInfo(\"$fpsid\", 32, bit_info).print(reg)\n            gef_print(\"Implementer code\")\n            for k, v in impl.items():\n                gef_print(\"  {:#02x}: {:s}\".format(k, v))\n        else:\n            warn(\"Failed to get the value\")\n\n        # fpexc\n        gef_print(titlify(\"FPEXC (Floating-Point Exception Control Register)\"))\n        bit_info = [\n            [31, \"EX\", \"Exception bit\"],\n            [30, \"EN\", \"Enables access to the Advanced SIMD and floating-point functionality from all Exception levels\"],\n            [29, \"DEX\", \"Defined synchronous exception on floating-point execution\"],\n            [28, \"FP2V\", \"FPINST2 instruction valid bit\"],\n            [27, \"VV\", \"VECITR valid bit\"],\n            [26, \"TFV\", \"Trapped Fault Valid bit\"],\n            [[8, 9, 10], \"VECITR\", \"Vector iteration count\"],\n            [7, \"IDF\", \"Input Denormal trapped exception bit\"],\n            [4, \"IXF\", \"Inexact trapped exception bit\"],\n            [3, \"UFF\", \"Underflow trapped exception bit\"],\n            [2, \"OFF\", \"Overflow trapped exception bit\"],\n            [1, \"DZF\", \"Divide by Zero trapped exception bit\"],\n            [0, \"IOF\", \"Invalid Operation trapped exception bit\"],\n        ]\n        reg = get_register(\"$fpexc\")\n        if reg is not None:\n            BitInfo(\"$fpexc\", 32, bit_info).print(reg)\n        else:\n            warn(\"Failed to get the value\")\n        return\n\n    def print_fpu_arm64_other(self):\n        # fpcr\n        gef_print(titlify(\"FPCR (Floating-Point Control Register)\"))\n        bit_info = [\n            [26, \"AHP\", \"Alternative Half-Precision Control\"],\n            [25, \"DN\", \"Default NaN mode Control\"],\n            [24, \"FZ\", \"Flush-to-zero mode Control\"],\n            [[22, 23], \"RMode\", \"Rounding Control\", \"00: Round To Nearest, 01: Round Positive, 10: Round Negative, 11: Round To Zero\"],\n            [[20, 21], \"Stride\", \"\", \"Unused\"],\n            [19, \"FZ16\", \"Flush-to-zero mode Control\", \"When FEAT_FP16 is implemented\"],\n            [[16, 17, 18], \"Len\", \"\", \"Unused\"],\n            [15, \"IDE\", \"Input Denormal floating-point Exception trap enable\"],\n            [12, \"IXE\", \"Inexact floating-point Exception trap enable\"],\n            [11, \"UFE\", \"Underflow floating-point Exception trap enable\"],\n            [10, \"OFE\", \"Overflow floating-point Exception trap enable\"],\n            [9, \"DZE\", \"Divide by Zero floating-point Exception trap enable\"],\n            [8, \"IOE\", \"Invalid Operation floating-point Exception trap enable\"],\n        ]\n        reg = get_register(\"$fpcr\")\n        if reg is not None:\n            BitInfo(\"$fpcr\", 32, bit_info).print(reg)\n\n        # fpsr\n        gef_print(titlify(\"FPCR (Floating-Point Status Register)\"))\n        bit_info = [\n            [31, \"N\", \"\", \"Unused, see $cpsr\"],\n            [30, \"Z\", \"\", \"Unused, see $cpsr\"],\n            [29, \"C\", \"\", \"Unused, see $cpsr\"],\n            [28, \"V\", \"\", \"Unused, see $cpsr\"],\n            [27, \"QC\", \"Cumulative saturation bit\"],\n            [7, \"IDC\", \"Input Denormal Cumulative floating-point exception bit\"],\n            [4, \"IXC\", \"Inexact Cumulative floating-point exception bit\"],\n            [3, \"UFC\", \"Underflow Cumulative floating-point exception bit\"],\n            [2, \"OFC\", \"Overflow Cumulative floating-point exception bit\"],\n            [1, \"DZC\", \"Divide by Zero Cumulative floating-point exception bit\"],\n            [0, \"IOC\", \"Invalid Operation Cumulative floating-point exception bit\"],\n        ]\n        reg = get_register(\"$fpsr\")\n        if reg is not None:\n            BitInfo(\"$fpsr\", 32, bit_info).print(reg)\n        return\n\n    def print_fpu_x86_other(self):\n        # fctrl\n        gef_print(titlify(\"FCTRL (x87 FPU Control Word)\"))\n        bit_info = [\n            [12, \"X\", \"Infinity Control\"],\n            [[10, 11], \"RC\", \"Rounding Control\", \"00: Round To Nearest, 01: Round Negative, 10: Round Positive, 11: Round To Zero\"],\n            [[8, 9], \"PC\", \"Precision Control\", \"00: Single Precision, 01: Reserved, 10: Double Precision, 11: Double-Extended Precision\"],\n            [5, \"PM\", \"Precision Exception Mask\"],\n            [4, \"UM\", \"Underflow Exception Mask\"],\n            [3, \"OM\", \"Overflow Exception Mask\"],\n            [2, \"ZM\", \"Zero Divide Exception Mask\"],\n            [1, \"DM\", \"Denormalized Opernd Exception Mask\"],\n            [0, \"IM\", \"Invalid Operation Exception Mask\"],\n        ]\n        reg = get_register(\"$fctrl\")\n        BitInfo(\"$fctrl\", 16, bit_info).print(reg)\n\n        # fstat\n        gef_print(titlify(\"FSTAT (x87 FPU Status Word)\"))\n        bit_info = [\n            [15, \"B\", \"FPU Busy\"],\n            [14, \"C3\", \"Condition Code\"],\n            [[11, 12, 13], \"TOP\", \"Top of Stack Pointer\"],\n            [10, \"C2\", \"Condition Code\"],\n            [9, \"C1\", \"Condition Code\"],\n            [8, \"C0\", \"Condition Code\"],\n            [7, \"ES\", \"Exception Summary Status\"],\n            [6, \"SF\", \"Stack Fault\"],\n            [5, \"PE\", \"Precision Exception\"],\n            [4, \"UE\", \"Underflow Exception\"], # codespell:ignore\n            [3, \"OE\", \"Overflow Exception\"],\n            [2, \"ZE\", \"Zero Divide Exception\"],\n            [1, \"DE\", \"Denormalized Operand Exception\"],\n            [0, \"IE\", \"Invalid Operation Exception\"],\n        ]\n        reg = get_register(\"$fstat\")\n        BitInfo(\"$fstat\", 16, bit_info).print(reg)\n\n        # ftag\n        gef_print(titlify(\"FTAG (x87 FPU Tag Word)\"))\n        bit_info = [\n            [[14, 15], \"TAG(7)\", \"Reg7 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[12, 13], \"TAG(6)\", \"Reg6 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[10, 11], \"TAG(5)\", \"Reg5 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[8, 9], \"TAG(4)\", \"Reg4 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[6, 7], \"TAG(3)\", \"Reg3 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[4, 5], \"TAG(2)\", \"Reg2 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[2, 3], \"TAG(1)\", \"Reg1 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n            [[0, 1], \"TAG(0)\", \"Reg0 Tag\", \"00: Valid, 01: Zero, 10: Invalid/Nan/Inf/Denormal, 11: Blank\"],\n        ]\n        reg = get_register(\"$ftag\")\n        BitInfo(\"$ftag\", 16, bit_info).print(reg)\n\n        # $fiseg, $fioff\n        gef_print(titlify(\"FCS:FIP (x87 FPU Last Instruction Pointer)\"))\n        reg = get_register(\"$fiseg\")\n        BitInfo(\"$fiseg(FCS)\", 16).print(reg)\n        reg = get_register(\"$fioff\")\n        BitInfo(\"$fioff(FIP)\", 32).print(reg)\n\n        # $foseg, $fooff\n        gef_print(titlify(\"FDS:FDP (x87 FPU Last Data(Operand) Pointer)\"))\n        reg = get_register(\"$foseg\")\n        BitInfo(\"$foseg(FDS)\", 16).print(reg)\n        reg = get_register(\"$fooff\")\n        BitInfo(\"$fooff(FDP)\", 32).print(reg)\n\n        # $fop\n        gef_print(titlify(\"FOP (x87 FPU Last Instruction Opcode)\"))\n        reg = get_register(\"$fop\")\n        BitInfo(\"$fop\", 11).print(reg)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"kgdb\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if is_x86():\n            self.print_fpu_x86()\n        elif is_arm32() or is_arm64():\n            self.print_fpu_arm()\n\n        if args.verbose:\n            if is_x86():\n                self.print_fpu_x86_other()\n            elif is_arm32():\n                self.print_fpu_arm_other()\n            elif is_arm64():\n                self.print_fpu_arm64_other()\n        else:\n            info(\"for fpu other register's flags description, use `-v`\")\n        return\n\n\n@register_command\nclass ErrnoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Convert errno (or argument) to its string representation.\"\"\"\n\n    _cmdline_ = \"errno\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"errno\", metavar=\"ERRNO\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"show specific errno definitions.\")\n    parser.add_argument(\"-a\", \"--all\", action=\"store_true\", help=\"show all errno definitions.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def get_errno_dict():\n        ERRNO_BASE_DICT = {\n            0   : [\"-\",               \"No error\"],\n            # include/uapi/asm-generic/errno-base.h\n            1   : [\"EPERM\",           \"Operation not permitted\"],\n            2   : [\"ENOENT\",          \"No such file or directory\"],\n            3   : [\"ESRCH\",           \"No such process\"],\n            4   : [\"EINTR\",           \"Interrupted system call\"],\n            5   : [\"EIO\",             \"I/O error\"],\n            6   : [\"ENXIO\",           \"No such device or address\"],\n            7   : [\"E2BIG\",           \"Argument list too long\"],\n            8   : [\"ENOEXEC\",         \"Exec format error\"],\n            9   : [\"EBADF\",           \"Bad file number\"],\n            10  : [\"ECHILD\",          \"No child processes\"],\n            11  : [\"EAGAIN\",          \"Try again\"],\n            12  : [\"ENOMEM\",          \"Out of memory\"],\n            13  : [\"EACCES\",          \"Permission denied\"],\n            14  : [\"EFAULT\",          \"Bad address\"],\n            15  : [\"ENOTBLK\",         \"Block device required\"],\n            16  : [\"EBUSY\",           \"Device or resource busy\"],\n            17  : [\"EEXIST\",          \"File exists\"],\n            18  : [\"EXDEV\",           \"Cross-device link\"],\n            19  : [\"ENODEV\",          \"No such device\"],\n            20  : [\"ENOTDIR\",         \"Not a directory\"],\n            21  : [\"EISDIR\",          \"Is a directory\"],\n            22  : [\"EINVAL\",          \"Invalid argument\"],\n            23  : [\"ENFILE\",          \"File table overflow\"],\n            24  : [\"EMFILE\",          \"Too many open files\"],\n            25  : [\"ENOTTY\",          \"Not a typewriter\"],\n            26  : [\"ETXTBSY\",         \"Text file busy\"],\n            27  : [\"EFBIG\",           \"File too large\"],\n            28  : [\"ENOSPC\",          \"No space left on device\"],\n            29  : [\"ESPIPE\",          \"Illegal seek\"],\n            30  : [\"EROFS\",           \"Read-only file system\"],\n            31  : [\"EMLINK\",          \"Too many links\"],\n            32  : [\"EPIPE\",           \"Broken pipe\"],\n            33  : [\"EDOM\",            \"Math argument out of domain of func\"],\n            34  : [\"ERANGE\",          \"Math result not representable\"],\n        }\n\n        ERRNO_DICT = {\n            # include/uapi/asm-generic/errno.h\n            35  : [\"EDEADLK\",         \"Resource deadlock would occur\"],\n            36  : [\"ENAMETOOLONG\",    \"File name too long\"],\n            37  : [\"ENOLCK\",          \"No record locks available\"],\n            38  : [\"ENOSYS\",          \"Invalid system call number\"],\n            39  : [\"ENOTEMPTY\",       \"Directory not empty\"],\n            40  : [\"ELOOP\",           \"Too many symbolic links encountered\"],\n            # 41\n            42  : [\"ENOMSG\",          \"No message of desired type\"],\n            43  : [\"EIDRM\",           \"Identifier removed\"],\n            44  : [\"ECHRNG\",          \"Channel number out of range\"],\n            45  : [\"EL2NSYNC\",        \"Level 2 not synchronized\"],\n            46  : [\"EL3HLT\",          \"Level 3 halted\"],\n            47  : [\"EL3RST\",          \"Level 3 reset\"],\n            48  : [\"ELNRNG\",          \"Link number out of range\"],\n            49  : [\"EUNATCH\",         \"Protocol driver not attached\"],\n            50  : [\"ENOCSI\",          \"No CSI structure available\"],\n            51  : [\"EL2HLT\",          \"Level 2 halted\"],\n            52  : [\"EBADE\",           \"Invalid exchange\"],\n            53  : [\"EBADR\",           \"Invalid request descriptor\"],\n            54  : [\"EXFULL\",          \"Exchange full\"],\n            55  : [\"ENOANO\",          \"No anode\"],\n            56  : [\"EBADRQC\",         \"Invalid request code\"],\n            57  : [\"EBADSLT\",         \"Invalid slot\"],\n            # 58\n            59  : [\"EBFONT\",          \"Bad font file format\"],\n            60  : [\"ENOSTR\",          \"Device not a stream\"],\n            61  : [\"ENODATA\",         \"No data available\"],\n            62  : [\"ETIME\",           \"Timer expired\"],\n            63  : [\"ENOSR\",           \"Out of streams resources\"],\n            64  : [\"ENONET\",          \"Machine is not on the network\"],\n            65  : [\"ENOPKG\",          \"Package not installed\"],\n            66  : [\"EREMOTE\",         \"Object is remote\"],\n            67  : [\"ENOLINK\",         \"Link has been severed\"],\n            68  : [\"EADV\",            \"Advertise error\"],\n            69  : [\"ESRMNT\",          \"Srmount error\"],\n            70  : [\"ECOMM\",           \"Communication error on send\"],\n            71  : [\"EPROTO\",          \"Protocol error\"],\n            72  : [\"EMULTIHOP\",       \"Multihop attempted\"],\n            73  : [\"EDOTDOT\",         \"RFS specific error\"],\n            74  : [\"EBADMSG\",         \"Not a data message\"],\n            75  : [\"EOVERFLOW\",       \"Value too large for defined data type\"],\n            76  : [\"ENOTUNIQ\",        \"Name not unique on network\"],\n            77  : [\"EBADFD\",          \"File descriptor in bad state\"],\n            78  : [\"EREMCHG\",         \"Remote address changed\"],\n            79  : [\"ELIBACC\",         \"Can not access a needed shared library\"],\n            80  : [\"ELIBBAD\",         \"Accessing a corrupted shared library\"],\n            81  : [\"ELIBSCN\",         \".lib section in a.out corrupted\"],\n            82  : [\"ELIBMAX\",         \"Attempting to link in too many shared libraries\"],\n            83  : [\"ELIBEXEC\",        \"Cannot exec a shared library directly\"],\n            84  : [\"EILSEQ\",          \"Illegal byte sequence\"],\n            85  : [\"ERESTART\",        \"Interrupted system call should be restarted\"],\n            86  : [\"ESTRPIPE\",        \"Streams pipe error\"],\n            87  : [\"EUSERS\",          \"Too many users\"],\n            88  : [\"ENOTSOCK\",        \"Socket operation on non-socket\"],\n            89  : [\"EDESTADDRREQ\",    \"Destination address required\"],\n            90  : [\"EMSGSIZE\",        \"Message too long\"],\n            91  : [\"EPROTOTYPE\",      \"Protocol wrong type for socket\"],\n            92  : [\"ENOPROTOOPT\",     \"Protocol not available\"],\n            93  : [\"EPROTONOSUPPORT\", \"Protocol not supported\"],\n            94  : [\"ESOCKTNOSUPPORT\", \"Socket type not supported\"],\n            95  : [\"EOPNOTSUPP\",      \"Operation not supported on transport endpoint\"],\n            96  : [\"EPFNOSUPPORT\",    \"Protocol family not supported\"],\n            97  : [\"EAFNOSUPPORT\",    \"Address family not supported by protocol\"],\n            98  : [\"EADDRINUSE\",      \"Address already in use\"],\n            99  : [\"EADDRNOTAVAIL\",   \"Cannot assign requested address\"],\n            100 : [\"ENETDOWN\",        \"Network is down\"],\n            101 : [\"ENETUNREACH\",     \"Network is unreachable\"],\n            102 : [\"ENETRESET\",       \"Network dropped connection because of reset\"],\n            103 : [\"ECONNABORTED\",    \"Software caused connection abort\"],\n            104 : [\"ECONNRESET\",      \"Connection reset by peer\"],\n            105 : [\"ENOBUFS\",         \"No buffer space available\"],\n            106 : [\"EISCONN\",         \"Transport endpoint is already connected\"],\n            107 : [\"ENOTCONN\",        \"Transport endpoint is not connected\"],\n            108 : [\"ESHUTDOWN\",       \"Cannot send after transport endpoint shutdown\"],\n            109 : [\"ETOOMANYREFS\",    \"Too many references: cannot splice\"],\n            110 : [\"ETIMEDOUT\",       \"Connection timed out\"],\n            111 : [\"ECONNREFUSED\",    \"Connection refused\"],\n            112 : [\"EHOSTDOWN\",       \"Host is down\"],\n            113 : [\"EHOSTUNREACH\",    \"No route to host\"],\n            114 : [\"EALREADY\",        \"Operation already in progress\"],\n            115 : [\"EINPROGRESS\",     \"Operation now in progress\"],\n            116 : [\"ESTALE\",          \"Stale file handle\"],\n            117 : [\"EUCLEAN\",         \"Structure needs cleaning\"],\n            118 : [\"ENOTNAM\",         \"Not a XENIX named type file\"],\n            119 : [\"ENAVAIL\",         \"No XENIX semaphores available\"],\n            120 : [\"EISNAM\",          \"Is a named type file\"],\n            121 : [\"EREMOTEIO\",       \"Remote I/O error\"],\n            122 : [\"EDQUOT\",          \"Quota exceeded\"],\n            123 : [\"ENOMEDIUM\",       \"No medium found\"],\n            124 : [\"EMEDIUMTYPE\",     \"Wrong medium type\"],\n            125 : [\"ECANCELED\",       \"Operation Canceled\"],\n            126 : [\"ENOKEY\",          \"Required key not available\"],\n            127 : [\"EKEYEXPIRED\",     \"Key has expired\"],\n            128 : [\"EKEYREVOKED\",     \"Key has been revoked\"],\n            129 : [\"EKEYREJECTED\",    \"Key was rejected by service\"],\n            130 : [\"EOWNERDEAD\",      \"Owner died\"],\n            131 : [\"ENOTRECOVERABLE\", \"State not recoverable\"],\n            132 : [\"ERFKILL\",         \"Operation not possible due to RF-kill\"],\n            133 : [\"EHWPOISON\",       \"Memory page has hardware error\"],\n        }\n\n        if is_alpha():\n            ERRNO_DICT = {\n                # arch/alpha/include/uapi/asm/errno.h\n                11  : [\"EDEADLK\",         \"Resource deadlock would occur\"], # override\n                #\n                35  : [\"EAGAIN\",          \"Try again\"],\n                36  : [\"EINPROGRESS\",     \"Operation now in progress\"],\n                37  : [\"EALREADY\",        \"Operation already in progress\"],\n                38  : [\"ENOTSOCK\",        \"Socket operation on non-socket\"],\n                39  : [\"EDESTADDRREQ\",    \"Destination address required\"],\n                40  : [\"EMSGSIZE\",        \"Message too long\"],\n                41  : [\"EPROTOTYPE\",      \"Protocol wrong type for socket\"],\n                42  : [\"ENOPROTOOPT\",     \"Protocol not available\"],\n                43  : [\"EPROTONOSUPPORT\", \"Protocol not supported\"],\n                44  : [\"ESOCKTNOSUPPORT\", \"Socket type not supported\"],\n                45  : [\"EOPNOTSUPP\",      \"Operation not supported on transport endpoint\"],\n                46  : [\"EPFNOSUPPORT\",    \"Protocol family not supported\"],\n                47  : [\"EAFNOSUPPORT\",    \"Address family not supported by protocol\"],\n                48  : [\"EADDRINUSE\",      \"Address already in use\"],\n                49  : [\"EADDRNOTAVAIL\",   \"Cannot assign requested address\"],\n                50  : [\"ENETDOWN\",        \"Network is down\"],\n                51  : [\"ENETUNREACH\",     \"Network is unreachable\"],\n                52  : [\"ENETRESET\",       \"Network dropped connection because of reset\"],\n                53  : [\"ECONNABORTED\",    \"Software caused connection abort\"],\n                54  : [\"ECONNRESET\",      \"Connection reset by peer\"],\n                55  : [\"ENOBUFS\",         \"No buffer space available\"],\n                56  : [\"EISCONN\",         \"Transport endpoint is already connected\"],\n                57  : [\"ENOTCONN\",        \"Transport endpoint is not connected\"],\n                58  : [\"ESHUTDOWN\",       \"Cannot send after transport endpoint shutdown\"],\n                59  : [\"ETOOMANYREFS\",    \"Too many references: cannot splice\"],\n                60  : [\"ETIMEDOUT\",       \"Connection timed out\"],\n                61  : [\"ECONNREFUSED\",    \"Connection refused\"],\n                62  : [\"ELOOP\",           \"Too many symbolic links encountered\"],\n                63  : [\"ENAMETOOLONG\",    \"File name too long\"],\n                64  : [\"EHOSTDOWN\",       \"Host is down\"],\n                65  : [\"EHOSTUNREACH\",    \"No route to host\"],\n                66  : [\"ENOTEMPTY\",       \"Directory not empty\"],\n                # 67\n                68  : [\"EUSERS\",          \"Too many users\"],\n                69  : [\"EDQUOT\",          \"Quota exceeded\"],\n                70  : [\"ESTALE\",          \"Stale file handle\"],\n                71  : [\"EREMOTE\",         \"Object is remote\"],\n                # 72-76\n                77  : [\"ENOLCK\",          \"No record locks available\"],\n                78  : [\"ENOSYS\",          \"Function not implemented\"],\n                # 79\n                80  : [\"ENOMSG\",          \"No message of desired type\"],\n                81  : [\"EIDRM\",           \"Identifier removed\"],\n                82  : [\"ENOSR\",           \"Out of streams resources\"],\n                83  : [\"ETIME\",           \"Timer expired\"],\n                84  : [\"EBADMSG\",         \"Not a data message\"],\n                85  : [\"EPROTO\",          \"Protocol error\"],\n                86  : [\"ENODATA\",         \"No data available\"],\n                87  : [\"ENOSTR\",          \"Device not a stream\"],\n                88  : [\"ECHRNG\",          \"Channel number out of range\"],\n                89  : [\"EL2NSYNC\",        \"Level 2 not synchronized\"],\n                90  : [\"EL3HLT\",          \"Level 3 halted\"],\n                91  : [\"EL3RST\",          \"Level 3 reset\"],\n                92  : [\"ENOPKG\",          \"Package not installed\"],\n                93  : [\"ELNRNG\",          \"Link number out of range\"],\n                94  : [\"EUNATCH\",         \"Protocol driver not attached\"],\n                95  : [\"ENOCSI\",          \"No CSI structure available\"],\n                96  : [\"EL2HLT\",          \"Level 2 halted\"],\n                97  : [\"EBADE\",           \"Invalid exchange\"],\n                98  : [\"EBADR\",           \"Invalid request descriptor\"],\n                99  : [\"EXFULL\",          \"Exchange full\"],\n                100 : [\"ENOANO\",          \"No anode\"],\n                101 : [\"EBADRQC\",         \"Invalid request code\"],\n                102 : [\"EBADSLT\",         \"Invalid slot\"],\n                # 103\n                104 : [\"EBFONT\",          \"Bad font file format\"],\n                105 : [\"ENONET\",          \"Machine is not on the network\"],\n                106 : [\"ENOLINK\",         \"Link has been severed\"],\n                107 : [\"EADV\",            \"Advertise error\"],\n                108 : [\"ESRMNT\",          \"Srmount error\"],\n                109 : [\"ECOMM\",           \"Communication error on send\"],\n                110 : [\"EMULTIHOP\",       \"Multihop attempted\"],\n                111 : [\"EDOTDOT\",         \"RFS specific error\"],\n                112 : [\"EOVERFLOW\",       \"Value too large for defined data type\"],\n                113 : [\"ENOTUNIQ\",        \"Name not unique on network\"],\n                114 : [\"EBADFD\",          \"File descriptor in bad state\"],\n                115 : [\"EREMCHG\",         \"Remote address changed\"],\n                116 : [\"EILSEQ\",          \"Illegal byte sequence\"],\n                117 : [\"EUCLEAN\",         \"Structure needs cleaning\"],\n                118 : [\"ENOTNAM\",         \"Not a XENIX named type file\"],\n                119 : [\"ENAVAIL\",         \"No XENIX semaphores available\"],\n                120 : [\"EISNAM\",          \"Is a named type file\"],\n                121 : [\"EREMOTEIO\",       \"Remote I/O error\"],\n                122 : [\"ELIBACC\",         \"Can not access a needed shared library\"],\n                123 : [\"ELIBBAD\",         \"Accessing a corrupted shared library\"],\n                124 : [\"ELIBSCN\",         \".lib section in a.out corrupted\"],\n                125 : [\"ELIBMAX\",         \"Attempting to link in too many shared libraries\"],\n                126 : [\"ELIBEXEC\",        \"Cannot exec a shared library directly\"],\n                127 : [\"ERESTART\",        \"Interrupted system call should be restarted\"],\n                128 : [\"ESTRPIPE\",        \"Streams pipe error\"],\n                129 : [\"ENOMEDIUM\",       \"No medium found\"],\n                130 : [\"EMEDIUMTYPE\",     \"Wrong medium type\"],\n                131 : [\"ECANCELED\",       \"Operation Canceled\"],\n                132 : [\"ENOKEY\",          \"Required key not available\"],\n                133 : [\"EKEYEXPIRED\",     \"Key has expired\"],\n                134 : [\"EKEYREVOKED\",     \"Key has been revoked\"],\n                135 : [\"EKEYREJECTED\",    \"Key was rejected by service\"],\n                136 : [\"EOWNERDEAD\",      \"Owner died\"],\n                137 : [\"ENOTRECOVERABLE\", \"State not recoverable\"],\n                138 : [\"ERFKILL\",         \"Operation not possible due to RF-kill\"],\n                139 : [\"EHWPOISON\",       \"Memory page has hardware error\"],\n            }\n        elif is_mips32() or is_mips64() or is_mipsn32():\n            ERRNO_DICT = {\n                35  : [\"ENOMSG\",          \"No message of desired type\"],\n                36  : [\"EIDRM\",           \"Identifier removed\"],\n                37  : [\"ECHRNG\",          \"Channel number out of range\"],\n                38  : [\"EL2NSYNC\",        \"Level 2 not synchronized\"],\n                39  : [\"EL3HLT\",          \"Level 3 halted\"],\n                40  : [\"EL3RST\",          \"Level 3 reset\"],\n                41  : [\"ELNRNG\",          \"Link number out of range\"],\n                42  : [\"EUNATCH\",         \"Protocol driver not attached\"],\n                43  : [\"ENOCSI\",          \"No CSI structure available\"],\n                44  : [\"EL2HLT\",          \"Level 2 halted\"],\n                45  : [\"EDEADLK\",         \"Resource deadlock would occur\"],\n                46  : [\"ENOLCK\",          \"No record locks available\"],\n                # 47-49\n                50  : [\"EBADE\",           \"Invalid exchange\"],\n                51  : [\"EBADR\",           \"Invalid request descriptor\"],\n                52  : [\"EXFULL\",          \"Exchange full\"],\n                53  : [\"ENOANO\",          \"No anode\"],\n                54  : [\"EBADRQC\",         \"Invalid request code\"],\n                55  : [\"EBADSLT\",         \"Invalid slot\"],\n                56  : [\"EDEADLOCK\",       \"File locking deadlock error\"],\n                # 57-58\n                59  : [\"EBFONT\",          \"Bad font file format\"],\n                60  : [\"ENOSTR\",          \"Device not a stream\"],\n                61  : [\"ENODATA\",         \"No data available\"],\n                62  : [\"ETIME\",           \"Timer expired\"],\n                63  : [\"ENOSR\",           \"Out of streams resources\"],\n                64  : [\"ENONET\",          \"Machine is not on the network\"],\n                65  : [\"ENOPKG\",          \"Package not installed\"],\n                66  : [\"EREMOTE\",         \"Object is remote\"],\n                67  : [\"ENOLINK\",         \"Link has been severed\"],\n                68  : [\"EADV\",            \"Advertise error\"],\n                69  : [\"ESRMNT\",          \"Srmount error\"],\n                70  : [\"ECOMM\",           \"Communication error on send\"],\n                71  : [\"EPROTO\",          \"Protocol error\"],\n                # 72\n                73  : [\"EDOTDOT\",         \"RFS specific error\"],\n                74  : [\"EMULTIHOP\",       \"Multihop attempted\"],\n                # 75-76\n                77  : [\"EBADMSG\",         \"Not a data message\"],\n                78  : [\"ENAMETOOLONG\",    \"File name too long\"],\n                79  : [\"EOVERFLOW\",       \"Value too large for defined data type\"],\n                80  : [\"ENOTUNIQ\",        \"Name not unique on network\"],\n                81  : [\"EBADFD\",          \"File descriptor in bad state\"],\n                82  : [\"EREMCHG\",         \"Remote address changed\"],\n                83  : [\"ELIBACC\",         \"Can not access a needed shared library\"],\n                84  : [\"ELIBBAD\",         \"Accessing a corrupted shared library\"],\n                85  : [\"ELIBSCN\",         \".lib section in a.out corrupted\"],\n                86  : [\"ELIBMAX\",         \"Attempting to link in too many shared libraries\"],\n                87  : [\"ELIBEXEC\",        \"Cannot exec a shared library directly\"],\n                88  : [\"EILSEQ\",          \"Illegal byte sequence\"],\n                89  : [\"ENOSYS\",          \"Function not implemented\"],\n                90  : [\"ELOOP\",           \"Too many symbolic links encountered\"],\n                91  : [\"ERESTART\",        \"Interrupted system call should be restarted\"],\n                92  : [\"ESTRPIPE\",        \"Streams pipe error\"],\n                93  : [\"ENOTEMPTY\",       \"Directory not empty\"],\n                94  : [\"EUSERS\",          \"Too many users\"],\n                95  : [\"ENOTSOCK\",        \"Socket operation on non-socket\"],\n                96  : [\"EDESTADDRREQ\",    \"Destination address required\"],\n                97  : [\"EMSGSIZE\",        \"Message too long\"],\n                98  : [\"EPROTOTYPE\",      \"Protocol wrong type for socket\"],\n                99  : [\"ENOPROTOOPT\",     \"Protocol not available\"],\n                # 100-119\n                120 : [\"EPROTONOSUPPORT\", \"Protocol not supported\"],\n                121 : [\"ESOCKTNOSUPPORT\", \"Socket type not supported\"],\n                122 : [\"EOPNOTSUPP\",      \"Operation not supported on transport endpoint\"],\n                123 : [\"EPFNOSUPPORT\",    \"Protocol family not supported\"],\n                124 : [\"EAFNOSUPPORT\",    \"Address family not supported by protocol\"],\n                125 : [\"EADDRINUSE\",      \"Address already in use\"],\n                126 : [\"EADDRNOTAVAIL\",   \"Cannot assign requested address\"],\n                127 : [\"ENETDOWN\",        \"Network is down\"],\n                128 : [\"ENETUNREACH\",     \"Network is unreachable\"],\n                129 : [\"ENETRESET\",       \"Network dropped connection because of reset\"],\n                130 : [\"ECONNABORTED\",    \"Software caused connection abort\"],\n                131 : [\"ECONNRESET\",      \"Connection reset by peer\"],\n                132 : [\"ENOBUFS\",         \"No buffer space available\"],\n                133 : [\"EISCONN\",         \"Transport endpoint is already connected\"],\n                134 : [\"ENOTCONN\",        \"Transport endpoint is not connected\"],\n                135 : [\"EUCLEAN\",         \"Structure needs cleaning\"],\n                # 136\n                137 : [\"ENOTNAM\",         \"Not a XENIX named type file\"],\n                138 : [\"ENAVAIL\",         \"No XENIX semaphores available\"],\n                139 : [\"EISNAM\",          \"Is a named type file\"],\n                140 : [\"EREMOTEIO\",       \"Remote I/O error\"],\n                141 : [\"EINIT\",           \"Reserved\"],\n                142 : [\"EREMDEV\",         \"Error 142\"],\n                143 : [\"ESHUTDOWN\",       \"Cannot send after transport endpoint shutdown\"],\n                144 : [\"ETOOMANYREFS\",    \"Too many references: cannot splice\"],\n                145 : [\"ETIMEDOUT\",       \"Connection timed out\"],\n                146 : [\"ECONNREFUSED\",    \"Connection refused\"],\n                147 : [\"EHOSTDOWN\",       \"Host is down\"],\n                148 : [\"EHOSTUNREACH\",    \"No route to host\"],\n                149 : [\"EALREADY\",        \"Operation already in progress\"],\n                150 : [\"EINPROGRESS\",     \"Operation now in progress\"],\n                151 : [\"ESTALE\",          \"Stale file handle\"],\n                # 152-157\n                158 : [\"ECANCELED\",       \"AIO operation canceled\"],\n                159 : [\"ENOMEDIUM\",       \"No medium found\"],\n                160 : [\"EMEDIUMTYPE\",     \"Wrong medium type\"],\n                161 : [\"ENOKEY\",          \"Required key not available\"],\n                162 : [\"EKEYEXPIRED\",     \"Key has expired\"],\n                163 : [\"EKEYREVOKED\",     \"Key has been revoked\"],\n                164 : [\"EKEYREJECTED\",    \"Key was rejected by service\"],\n                165 : [\"EOWNERDEAD\",      \"Owner died\"],\n                166 : [\"ENOTRECOVERABLE\", \"State not recoverable\"],\n                167 : [\"ERFKILL\",         \"Operation not possible due to RF-kill\"],\n                168 : [\"EHWPOISON\",       \"Memory page has hardware error\"],\n                #\n                1133: [\"EDQUOT\",          \"Quota exceeded\"],\n            }\n        elif is_hppa32() or is_hppa64():\n            ERRNO_DICT = {\n                35 :  [\"ENOMSG\",          \"No message of desired type\"],\n                36 :  [\"EIDRM\",           \"Identifier removed\"],\n                37 :  [\"ECHRNG\",          \"Channel number out of range\"],\n                38 :  [\"EL2NSYNC\",        \"Level 2 not synchronized\"],\n                39 :  [\"EL3HLT\",          \"Level 3 halted\"],\n                40 :  [\"EL3RST\",          \"Level 3 reset\"],\n                41 :  [\"ELNRNG\",          \"Link number out of range\"],\n                42 :  [\"EUNATCH\",         \"Protocol driver not attached\"],\n                43 :  [\"ENOCSI\",          \"No CSI structure available\"],\n                44 :  [\"EL2HLT\",          \"Level 2 halted\"],\n                45 :  [\"EDEADLK\",         \"Resource deadlock would occur\"],\n                46 :  [\"ENOLCK\",          \"No record locks available\"],\n                47 :  [\"EILSEQ\",          \"Illegal byte sequence\"],\n                # 48-49\n                50 :  [\"ENONET\",          \"Machine is not on the network\"],\n                51 :  [\"ENODATA\",         \"No data available\"],\n                52 :  [\"ETIME\",           \"Timer expired\"],\n                53 :  [\"ENOSR\",           \"Out of streams resources\"],\n                54 :  [\"ENOSTR\",          \"Device not a stream\"],\n                55 :  [\"ENOPKG\",          \"Package not installed\"],\n                # 56\n                57 :  [\"ENOLINK\",         \"Link has been severed\"],\n                58 :  [\"EADV\",            \"Advertise error\"],\n                59 :  [\"ESRMNT\",          \"Srmount error\"],\n                60 :  [\"ECOMM\",           \"Communication error on send\"],\n                61 :  [\"EPROTO\",          \"Protocol error\"],\n                # 62-63\n                64 :  [\"EMULTIHOP\",       \"Multihop attempted\"],\n                # 65\n                66 :  [\"EDOTDOT\",         \"RFS specific error\"],\n                67 :  [\"EBADMSG\",         \"Not a data message\"],\n                68 :  [\"EUSERS\",          \"Too many users\"],\n                69 :  [\"EDQUOT\",          \"Quota exceeded\"],\n                70 :  [\"ESTALE\",          \"Stale file handle\"],\n                71 :  [\"EREMOTE\",         \"Object is remote\"],\n                72 :  [\"EOVERFLOW\",       \"Value too large for defined data type\"],\n                # 73-159\n                160 : [\"EBADE\",           \"Invalid exchange\"],\n                161 : [\"EBADR\",           \"Invalid request descriptor\"],\n                162 : [\"EXFULL\",          \"Exchange full\"],\n                163 : [\"ENOANO\",          \"No anode\"],\n                164 : [\"EBADRQC\",         \"Invalid request code\"],\n                165 : [\"EBADSLT\",         \"Invalid slot\"],\n                166 : [\"EBFONT\",          \"Bad font file format\"],\n                167 : [\"ENOTUNIQ\",        \"Name not unique on network\"],\n                168 : [\"EBADFD\",          \"File descriptor in bad state\"],\n                169 : [\"EREMCHG\",         \"Remote address changed\"],\n                170 : [\"ELIBACC\",         \"Can not access a needed shared library\"],\n                171 : [\"ELIBBAD\",         \"Accessing a corrupted shared library\"],\n                172 : [\"ELIBSCN\",         \".lib section in a.out corrupted\"],\n                173 : [\"ELIBMAX\",         \"Attempting to link in too many shared libraries\"],\n                174 : [\"ELIBEXEC\",        \"Cannot exec a shared library directly\"],\n                175 : [\"ERESTART\",        \"Interrupted system call should be restarted\"],\n                176 : [\"ESTRPIPE\",        \"Streams pipe error\"],\n                177 : [\"EUCLEAN\",         \"Structure needs cleaning\"],\n                178 : [\"ENOTNAM\",         \"Not a XENIX named type file\"],\n                179 : [\"ENAVAIL\",         \"No XENIX semaphores available\"],\n                180 : [\"EISNAM\",          \"Is a named type file\"],\n                181 : [\"EREMOTEIO\",       \"Remote I/O error\"],\n                182 : [\"ENOMEDIUM\",       \"No medium found\"],\n                183 : [\"EMEDIUMTYPE\",     \"Wrong medium type\"],\n                184 : [\"ENOKEY\",          \"Required key not available\"],\n                185 : [\"EKEYEXPIRED\",     \"Key has expired\"],\n                186 : [\"EKEYREVOKED\",     \"Key has been revoked\"],\n                187 : [\"EKEYREJECTED\",    \"Key was rejected by service\"],\n                # 188-215\n                216 : [\"ENOTSOCK\",        \"Socket operation on non-socket\"],\n                217 : [\"EDESTADDRREQ\",    \"Destination address required\"],\n                218 : [\"EMSGSIZE\",        \"Message too long\"],\n                219 : [\"EPROTOTYPE\",      \"Protocol wrong type for socket\"],\n                220 : [\"ENOPROTOOPT\",     \"Protocol not available\"],\n                221 : [\"EPROTONOSUPPORT\", \"Protocol not supported\"],\n                222 : [\"ESOCKTNOSUPPORT\", \"Socket type not supported\"],\n                223 : [\"EOPNOTSUPP\",      \"Operation not supported on transport endpoint\"],\n                224 : [\"EPFNOSUPPORT\",    \"Protocol family not supported\"],\n                225 : [\"EAFNOSUPPORT\",    \"Address family not supported by protocol\"],\n                226 : [\"EADDRINUSE\",      \"Address already in use\"],\n                227 : [\"EADDRNOTAVAIL\",   \"Cannot assign requested address\"],\n                228 : [\"ENETDOWN\",        \"Network is down\"],\n                229 : [\"ENETUNREACH\",     \"Network is unreachable\"],\n                230 : [\"ENETRESET\",       \"Network dropped connection because of reset\"],\n                231 : [\"ECONNABORTED\",    \"Software caused connection abort\"],\n                232 : [\"ECONNRESET\",      \"Connection reset by peer\"],\n                233 : [\"ENOBUFS\",         \"No buffer space available\"],\n                234 : [\"EISCONN\",         \"Transport endpoint is already connected\"],\n                235 : [\"ENOTCONN\",        \"Transport endpoint is not connected\"],\n                236 : [\"ESHUTDOWN\",       \"Cannot send after transport endpoint shutdown\"],\n                237 : [\"ETOOMANYREFS\",    \"Too many references: cannot splice\"],\n                238 : [\"ETIMEDOUT\",       \"Connection timed out\"],\n                239 : [\"ECONNREFUSED\",    \"Connection refused\"],\n                # 240\n                241 : [\"EHOSTDOWN\",       \"Host is down\"],\n                242 : [\"EHOSTUNREACH\",    \"No route to host\"],\n                # 243\n                244 : [\"EALREADY\",        \"Operation already in progress\"],\n                245 : [\"EINPROGRESS\",     \"Operation now in progress\"],\n                # 246\n                247 : [\"ENOTEMPTY\",       \"Directory not empty\"],\n                248 : [\"ENAMETOOLONG\",    \"File name too long\"],\n                249 : [\"ELOOP\",           \"Too many symbolic links encountered\"],\n                # 250\n                251 : [\"ENOSYS\",          \"Function not implemented\"],\n                # 252\n                253 : [\"ECANCELLED\",      \"aio request was canceled before complete (POSIX.4 / HPUX)\"],\n                254 : [\"EOWNERDEAD\",      \"Owner died\"],\n                255 : [\"ENOTRECOVERABLE\", \"State not recoverable\"],\n                256 : [\"ERFKILL\",         \"Operation not possible due to RF-kill\"],\n                257 : [\"EHWPOISON\",       \"Memory page has hardware error\"],\n            }\n        elif is_sparc32() or is_sparc64():\n            ERRNO_DICT = {\n                36  : [\"EINPROGRESS\",     \"Operation now in progress\"],\n                37  : [\"EALREADY\",        \"Operation already in progress\"],\n                38  : [\"ENOTSOCK\",        \"Socket operation on non-socket\"],\n                39  : [\"EDESTADDRREQ\",    \"Destination address required\"],\n                40  : [\"EMSGSIZE\",        \"Message too long\"],\n                41  : [\"EPROTOTYPE\",      \"Protocol wrong type for socket\"],\n                42  : [\"ENOPROTOOPT\",     \"Protocol not available\"],\n                43  : [\"EPROTONOSUPPORT\", \"Protocol not supported\"],\n                44  : [\"ESOCKTNOSUPPORT\", \"Socket type not supported\"],\n                45  : [\"EOPNOTSUPP\",      \"Op not supported on transport endpoint\"],\n                46  : [\"EPFNOSUPPORT\",    \"Protocol family not supported\"],\n                47  : [\"EAFNOSUPPORT\",    \"Address family not supported by protocol\"],\n                48  : [\"EADDRINUSE\",      \"Address already in use\"],\n                49  : [\"EADDRNOTAVAIL\",   \"Cannot assign requested address\"],\n                50  : [\"ENETDOWN\",        \"Network is down\"],\n                51  : [\"ENETUNREACH\",     \"Network is unreachable\"],\n                52  : [\"ENETRESET\",       \"Net dropped connection because of reset\"],\n                53  : [\"ECONNABORTED\",    \"Software caused connection abort\"],\n                54  : [\"ECONNRESET\",      \"Connection reset by peer\"],\n                55  : [\"ENOBUFS\",         \"No buffer space available\"],\n                56  : [\"EISCONN\",         \"Transport endpoint is already connected\"],\n                57  : [\"ENOTCONN\",        \"Transport endpoint is not connected\"],\n                58  : [\"ESHUTDOWN\",       \"No send after transport endpoint shutdown\"],\n                59  : [\"ETOOMANYREFS\",    \"Too many references: cannot splice\"],\n                60  : [\"ETIMEDOUT\",       \"Connection timed out\"],\n                61  : [\"ECONNREFUSED\",    \"Connection refused\"],\n                62  : [\"ELOOP\",           \"Too many symbolic links encountered\"],\n                63  : [\"ENAMETOOLONG\",    \"File name too long\"],\n                64  : [\"EHOSTDOWN\",       \"Host is down\"],\n                65  : [\"EHOSTUNREACH\",    \"No route to host\"],\n                66  : [\"ENOTEMPTY\",       \"Directory not empty\"],\n                67  : [\"EPROCLIM\",        \"SUNOS: Too many processes\"],\n                68  : [\"EUSERS\",          \"Too many users\"],\n                69  : [\"EDQUOT\",          \"Quota exceeded\"],\n                70  : [\"ESTALE\",          \"Stale file handle\"],\n                71  : [\"EREMOTE\",         \"Object is remote\"],\n                72  : [\"ENOSTR\",          \"Device not a stream\"],\n                73  : [\"ETIME\",           \"Timer expired\"],\n                74  : [\"ENOSR\",           \"Out of streams resources\"],\n                75  : [\"ENOMSG\",          \"No message of desired type\"],\n                76  : [\"EBADMSG\",         \"Not a data message\"],\n                77  : [\"EIDRM\",           \"Identifier removed\"],\n                78  : [\"EDEADLK\",         \"Resource deadlock would occur\"],\n                79  : [\"ENOLCK\",          \"No record locks available\"],\n                80  : [\"ENONET\",          \"Machine is not on the network\"],\n                81  : [\"ERREMOTE\",        \"SunOS: Too many lvls of remote in path\"],\n                82  : [\"ENOLINK\",         \"Link has been severed\"],\n                83  : [\"EADV\",            \"Advertise error\"],\n                84  : [\"ESRMNT\",          \"Srmount error\"],\n                85  : [\"ECOMM\",           \"Communication error on send\"],\n                86  : [\"EPROTO\",          \"Protocol error\"],\n                87  : [\"EMULTIHOP\",       \"Multihop attempted\"],\n                88  : [\"EDOTDOT\",         \"RFS specific error\"],\n                89  : [\"EREMCHG\",         \"Remote address changed\"],\n                90  : [\"ENOSYS\",          \"Function not implemented\"],\n                91  : [\"ESTRPIPE\",        \"Streams pipe error\"],\n                92  : [\"EOVERFLOW\",       \"Value too large for defined data type\"],\n                93  : [\"EBADFD\",          \"File descriptor in bad state\"],\n                94  : [\"ECHRNG\",          \"Channel number out of range\"],\n                95  : [\"EL2NSYNC\",        \"Level 2 not synchronized\"],\n                96  : [\"EL3HLT\",          \"Level 3 halted\"],\n                97  : [\"EL3RST\",          \"Level 3 reset\"],\n                98  : [\"ELNRNG\",          \"Link number out of range\"],\n                99  : [\"EUNATCH\",         \"Protocol driver not attached\"],\n                100 : [\"ENOCSI\",          \"No CSI structure available\"],\n                101 : [\"EL2HLT\",          \"Level 2 halted\"],\n                102 : [\"EBADE\",           \"Invalid exchange\"],\n                103 : [\"EBADR\",           \"Invalid request descriptor\"],\n                104 : [\"EXFULL\",          \"Exchange full\"],\n                105 : [\"ENOANO\",          \"No anode\"],\n                106 : [\"EBADRQC\",         \"Invalid request code\"],\n                107 : [\"EBADSLT\",         \"Invalid slot\"],\n                108 : [\"EDEADLOCK\",       \"File locking deadlock error\"],\n                109 : [\"EBFONT\",          \"Bad font file format\"],\n                110 : [\"ELIBEXEC\",        \"Cannot exec a shared library directly\"],\n                111 : [\"ENODATA\",         \"No data available\"],\n                112 : [\"ELIBBAD\",         \"Accessing a corrupted shared library\"],\n                113 : [\"ENOPKG\",          \"Package not installed\"],\n                114 : [\"ELIBACC\",         \"Can not access a needed shared library\"],\n                115 : [\"ENOTUNIQ\",        \"Name not unique on network\"],\n                116 : [\"ERESTART\",        \"Interrupted syscall should be restarted\"],\n                117 : [\"EUCLEAN\",         \"Structure needs cleaning\"],\n                118 : [\"ENOTNAM\",         \"Not a XENIX named type file\"],\n                119 : [\"ENAVAIL\",         \"No XENIX semaphores available\"],\n                120 : [\"EISNAM\",          \"Is a named type file\"],\n                121 : [\"EREMOTEIO\",       \"Remote I/O error\"],\n                122 : [\"EILSEQ\",          \"Illegal byte sequence\"],\n                123 : [\"ELIBMAX\",         \"Atmpt to link in too many shared libs\"],\n                124 : [\"ELIBSCN\",         \".lib section in a.out corrupted\"],\n                125 : [\"ENOMEDIUM\",       \"No medium found\"],\n                126 : [\"EMEDIUMTYPE\",     \"Wrong medium type\"],\n                127 : [\"ECANCELED\",       \"Operation Cancelled\"],\n                128 : [\"ENOKEY\",          \"Required key not available\"],\n                129 : [\"EKEYEXPIRED\",     \"Key has expired\"],\n                130 : [\"EKEYREVOKED\",     \"Key has been revoked\"],\n                131 : [\"EKEYREJECTED\",    \"Key was rejected by service\"],\n                132 : [\"EOWNERDEAD\",      \"Owner died\"],\n                133 : [\"ENOTRECOVERABLE\", \"State not recoverable\"],\n                134 : [\"ERFKILL\",         \"Operation not possible due to RF-kill\"],\n                135 : [\"EHWPOISON\",       \"Memory page has hardware error\"],\n            }\n\n        return ERRNO_BASE_DICT | ERRNO_DICT\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        ERRNO_DICT = ErrnoCommand.get_errno_dict()\n\n        if args.all:\n            self.out = []\n            for val, (sym, desc) in sorted(ERRNO_DICT.items()):\n                self.out.append('{:3d} (={:#4x}): {:<15s}: \"{:s}\"'.format(val, val, sym, desc))\n            self.print_output(check_terminal_size=True)\n            return\n\n        if args.errno is None:\n            if not is_alive():\n                warn(\"No debugging session active\")\n                return\n            try:\n                val = AddressUtil.parse_address(\"*__errno_location()\")\n            except gdb.error:\n                err(\"Failed to get *__errno_location()\")\n                return\n        else:\n            val = args.errno\n\n        if val > 0xffff:\n            if current_arch and current_arch.ptrsize == 4:\n                val = struct.unpack(\"<i\", struct.pack(\"<I\", val))[0]\n            elif current_arch and current_arch.ptrsize == 8:\n                val = struct.unpack(\"<q\", struct.pack(\"<Q\", val))[0]\n            elif current_arch is None:\n                val = struct.unpack(\"<q\", struct.pack(\"<Q\", val))[0]\n            else:\n                err(\"Not supported this pointer size\")\n                return\n\n        if val < 0:\n            val = -val\n\n        if val in ERRNO_DICT:\n            sym, desc = ERRNO_DICT[val]\n            gef_print('{:3d} (={:#4x}): {:<15s}: \"{:s}\"'.format(val, val, sym, desc))\n        else:\n            err(\"Could not find value in ERRNO_DICT\")\n        return\n\n\n@register_command\nclass DistanceCommand(GenericCommand):\n    \"\"\"Calculate the offset from its base address.\"\"\"\n\n    _cmdline_ = \"distance\"\n    _category_ = \"07-e. Misc - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address_a\", metavar=\"ADDRESS_A\", type=AddressUtil.parse_address,\n                        help=\"the address to calculate the offset as (A - base_addr_of(A)).\")\n    parser.add_argument(\"address_b\", metavar=\"ADDRESS_B\", type=AddressUtil.parse_address, nargs=\"?\",\n                        help=\"the address to calculate the offset as abs(A - B).\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        if args.address_b is not None:\n            offset = abs(args.address_a - args.address_b)\n            gef_print(\"Offset:  {:#x}\".format(offset))\n            return\n\n        addr_a = ProcessMap.lookup_address(args.address_a)\n        if addr_a.section is None:\n            err(\"Could not find the base address\")\n            return\n\n        if addr_a.section.path:\n            base_address = ProcessMap.get_section_base_address(addr_a.section.path)\n        else:\n            base_address = addr_a.section.page_start\n\n        offset = args.address_a - base_address\n        gef_print(\"Address: {:#x}\".format(args.address_a))\n        gef_print(\"Base:    {:#x}\".format(base_address))\n        gef_print(\"Offset:  {:#x}\".format(offset))\n        return\n\n\n@register_command\nclass U2dCommand(GenericCommand):\n    \"\"\"Convert type (unsigned long <-> double/float).\"\"\"\n\n    _cmdline_ = \"u2d\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the hex value or double value.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0xdeadbeef\",\n        \"{0:s} 0.12345\",\n        \"{0:s} 1.2345e-1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Only ~64bit supported (Unsupported 80bit, 128bit)\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def f2u(self, x):\n        u = lambda a: struct.unpack(\"<I\", a)[0]\n        pf = lambda a: struct.pack(\"<f\", a)\n        return u(pf(x))\n\n    def u2f(self, x):\n        p = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        uf = lambda a: struct.unpack(\"<f\", a)[0]\n        return uf(p(x))\n\n    def d2u(self, x):\n        uQ = lambda a: struct.unpack(\"<Q\", a)[0]\n        pd = lambda a: struct.pack(\"<d\", a)\n        return uQ(pd(x))\n\n    def u2d(self, x):\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        ud = lambda a: struct.unpack(\"<d\", a)[0]\n        return ud(pQ(x))\n\n    def convert_from_float(self, n):\n        gef_print(titlify(\"double -> unsigned long long\"))\n        gef_print(Color.cyanify(\"double -> ull (reinterpret_cast)\"))\n        gef_print(\"  {:.20e} ---> {:#018x}\".format(n, self.d2u(n)))\n        gef_print(titlify(\"float -> float\"))\n        gef_print(Color.cyanify(\"float -> uint (reinterpret_cast)\"))\n        gef_print(\"  {:.20e} ---> {:#010x}\".format(n, self.f2u(n)))\n        return\n\n    def convert_from_int(self, n):\n        n &= 0xffff_ffff_ffff_ffff\n        gef_print(titlify(\"unsigned long long <-> double\"))\n        gef_print(Color.cyanify(\"ull -> double (reinterpret_cast)\"))\n        gef_print(\"  {:#018x} ---> {:.20e}\".format(n, self.u2d(n)))\n        gef_print(Color.cyanify(\"ull -> double -> ull (static_cast)\"))\n        gef_print(\"  {:#018x} ---> {:#018x} ---> {:#018x}\".format(n, self.d2u(float(n)), int(self.u2d(self.d2u(float(n))))))\n        gef_print(Color.cyanify(\"double -> ull (reinterpret_cast)\"))\n        try:\n            gef_print(\"  {:#018x} ---> {:#018x}\".format(n, int(self.u2d(n))))\n        except ValueError:\n            gef_print(\"  {:18s} ---> ???\".format(\"nan\"))\n\n        n &= 0xffff_ffff\n        gef_print(titlify(\"unsigned int <-> float\"))\n        gef_print(Color.cyanify(\"uint -> float (reinterpret_cast)\"))\n        gef_print(\"  {:#010x} ---> {:.20e}\".format(n, self.u2f(n)))\n        gef_print(Color.cyanify(\"uint -> float -> uint (static_cast)\"))\n        gef_print(\"  {:#010x} ---> {:#010x} ---> {:#010x}\".format(n, self.f2u(float(n)), int(self.u2f(self.f2u(float(n))))))\n        gef_print(Color.cyanify(\"float -> uint (reinterpret_cast)\"))\n        try:\n            gef_print(\"  {:#010x} ---> {:#010x}\".format(n, int(self.u2f(n))))\n        except ValueError:\n            gef_print(\"  {:10s} ---> ???\".format(\"nan\"))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        try:\n            if \".\" in args.value:\n                n = float(args.value)\n                self.convert_from_float(n)\n            else:\n                n = int(args.value, 0)\n                self.convert_from_int(n)\n        except Exception:\n            self.usage()\n        return\n\n\n@register_command\nclass UnsignedCommand(GenericCommand):\n    \"\"\"Convert the negative number to unsigned.\"\"\"\n\n    _cmdline_ = \"unsigned\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", type=AddressUtil.parse_address,\n                        help=\"the value to convert.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -- -0xa0\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    def do_invoke(self, args):\n        gef_print(\"input: {:#x}\".format(args.value))\n\n        for i in range(4):\n            shift = (2 ** i) * 8\n\n            msb_mask = 1 << (shift - 1)\n            if (1 << shift) > args.value and args.value & msb_mask == 0:\n                value = args.value * -1\n            else:\n                value = args.value\n\n            mask = (1 << shift) - 1\n            unsigned = value & mask\n            if i == 0:\n                signed = struct.unpack(\"<b\", struct.pack(\"<B\", unsigned))[0]\n            elif i == 1:\n                signed = struct.unpack(\"<h\", struct.pack(\"<H\", unsigned))[0]\n            elif i == 2:\n                signed = struct.unpack(\"<i\", struct.pack(\"<I\", unsigned))[0]\n            elif i == 3:\n                signed = struct.unpack(\"<q\", struct.pack(\"<Q\", unsigned))[0]\n            gef_print(\"{:d} byte unsigned: {:#x} ({:#x})\".format(2 ** i, unsigned, signed))\n        return\n\n\n@register_command\nclass AddressifyCommand(GenericCommand):\n    \"\"\"Convert reverse-order hex values to address.\"\"\"\n\n    _cmdline_ = \"addressify\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", nargs=\"+\", help=\"the string to convert.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"00 30 e0 f7 ff 7f\"',\n        \"{0:s} 00 30 e0 f7 ff 7f\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    def do_invoke(self, args):\n        hex_value = \"\"\n        for value in args.value:\n            for c in value.lower():\n                if c in \"0123456789abcdef\":\n                    hex_value += c\n        if hex_value == \"\":\n            err(\"No hex digits found in input\")\n            return\n        if len(hex_value) % 2 != 0:\n            err(\"Hex value length is odd\")\n            return\n\n        hex_values = slicer(hex_value, 2)[::-1]\n        hex_values = \"\".join(hex_values)\n\n        address = int(hex_values, 16)\n        address = ProcessMap.lookup_address(address)\n\n        if address.valid and address.section.path:\n            gef_print(\"{!s} @ {:s}\".format(address, address.section.path))\n        elif is_valid_addr(address.value):\n            gef_print(\"{!s} (valid)\".format(address))\n        else:\n            gef_print(\"{!s} (invalid)\".format(address))\n        return\n\n\n@register_command\nclass ConvertCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to convert values to various.\"\"\"\n\n    _cmdline_ = \"convert\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def pack(self, value):\n        try:\n            value = int(value, 0)\n            self.out.append(titlify(\"pack\"))\n            self.out.append(\"pack8:          {!s}\".format(p8(value & 0xff)))\n            self.out.append(\"pack16:         {!s}\".format(p16(value & 0xffff)))\n            self.out.append(\"pack32:         {!s}\".format(p32(value & 0xffff_ffff)))\n            self.out.append(\"pack64:         {!s}\".format(p64(value & 0xffff_ffff_ffff_ffff)))\n            low = value & 0xffff_ffff_ffff_ffff\n            high = (value >> 64) & 0xffff_ffff_ffff_ffff\n            val128 = p64(low) + p64(high)\n            self.out.append(\"pack128:        {!s}\".format(val128))\n        except ValueError:\n            pass\n        return\n\n    def pack_hex(self, value):\n        try:\n            value = int(value, 0)\n            self.out.append(titlify(\"pack-hex\"))\n            self.out.append(\"pack8-hex:      {!s}\".format(p8(value & 0xff).hex()))\n            self.out.append(\"pack16-hex:     {!s}\".format(p16(value & 0xffff).hex()))\n            self.out.append(\"pack32-hex:     {!s}\".format(p32(value & 0xffff_ffff).hex()))\n            self.out.append(\"pack64-hex:     {!s}\".format(p64(value & 0xffff_ffff_ffff_ffff).hex()))\n            low = value & 0xffff_ffff_ffff_ffff\n            high = (value >> 64) & 0xffff_ffff_ffff_ffff\n            val128 = p64(low) + p64(high)\n            self.out.append(\"pack128-hex:    {!s}\".format(val128.hex()))\n        except ValueError:\n            pass\n        return\n\n    def unpack(self, value):\n        try:\n            value = codecs.escape_decode(value)[0] + b\"\\0\" * 16\n            self.out.append(titlify(\"unpack\"))\n            self.out.append(\"unpack8:        {:#04x}\".format(u8(value[:1])))\n            self.out.append(\"unpack16:       {:#06x}\".format(u16(value[:2])))\n            self.out.append(\"unpack32:       {:#010x}\".format(u32(value[:4])))\n            self.out.append(\"unpack64:       {:#018x}\".format(u64(value[:8])))\n            low, high = value[:8], value[8:16]\n            self.out.append(\"unpack128:      {:#034x}\".format((u64(high) << 64) | u64(low)))\n        except binascii.Error:\n            pass\n        return\n\n    def tohex(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"tohex\"))\n            hexed = binascii.hexlify(value)\n            self.out.append(\"tohex:          {!s}\".format(hexed))\n            hexed_null = b\"00\".join(slicer(hexed, 2)) + b\"00\"\n            self.out.append(\"tohex w/NULL:   {!s}\".format(hexed_null))\n        except binascii.Error:\n            pass\n        return\n\n    def unhex(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex\"))\n            self.out.append(\"unhex:          {!s}\".format(value))\n            value_null = b\"\\x00\".join(slicer(value, 1)) + b\"\\x00\"\n            self.out.append(\"unhex w/NULL:   {!s}\".format(value_null))\n        except (binascii.Error, ValueError):\n            pass\n        return\n\n    def byteswap(self, value):\n        try:\n            value = int(value, 0)\n            converted32 = byteswap(value, 4)\n            converted64 = byteswap(value, 8)\n            self.out.append(titlify(\"byteswap\"))\n            self.out.append(\"byteswap-64:    {:#018x}\".format(converted64))\n            self.out.append(\"byteswap-32:    {:#010x}\".format(converted32))\n        except ValueError:\n            pass\n        return\n\n    def bit_reverse(self, value):\n\n        def bit_reverse(x, n):\n            mask = (1 << n) - 1\n            b = \"{:0{:d}b}\".format(x & mask, n)\n            return int(b[::-1], 2)\n\n        try:\n            value = int(value, 0)\n            br8 = bit_reverse(value, 8)\n            br16 = bit_reverse(value, 16)\n            br32 = bit_reverse(value, 32)\n            br64 = bit_reverse(value, 64)\n            self.out.append(titlify(\"bit-reverse\"))\n            self.out.append(\"bit-reverse8:   {:#04x}\".format(br8))\n            self.out.append(\"bit-reverse16:  {:#06x}\".format(br16))\n            self.out.append(\"bit-reverse32:  {:#010x}\".format(br32))\n            self.out.append(\"bit-reverse64:  {:#018x}\".format(br64))\n            bl = (value.bit_length() + 3) // 4 * 4\n            if bl > 64:\n                brN = bit_reverse(value, bl)\n                self.out.append(\"bit-reverse:    {:#0{:d}x}\".format(brN, bl // 4 + 2))\n        except ValueError:\n            pass\n        return\n\n    def integer(self, value):\n        try:\n            value = int(value, 0)\n            self.out.append(titlify(\"integer\"))\n            self.out.append(\"hex:            {:#x}\".format(value))\n            self.out.append(\"dec:            {:d}\".format(value))\n            self.out.append(\"oct:            {:#o}\".format(value))\n            self.out.append(\"bin:            {:#b}\".format(value))\n            out = \"\"\n            x = value\n            while x:\n                if x & 1:\n                    out = \"1\" + out\n                else:\n                    out = \"0\" + out\n                if (len(out) + 1) % 5 == 0:\n                    out = \"_\" + out\n                x >>= 1\n            splitted_value = \"0b\" + out.lstrip(\"_\")\n            self.out.append(\"bin w/sep:      {:s}\".format(splitted_value))\n        except ValueError:\n            pass\n        return\n\n    def signed(self, value):\n        pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n        uq = lambda a: struct.unpack(\"<q\", a)[0]\n        p = lambda a: struct.pack(\"<I\", a & 0xffff_ffff)\n        ui = lambda a: struct.unpack(\"<i\", a)[0]\n        try:\n            value = int(value, 0)\n            self.out.append(titlify(\"signed\"))\n            self.out.append(\"u2i-64:         {:#018x}\".format(uq(pQ(value))))\n            self.out.append(\"u2i-32:         {:#010x}\".format(ui(p(value))))\n        except ValueError:\n            pass\n        return\n\n    def string(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"string\"))\n            self.out.append(\"str:            {!s}\".format(value))\n            value_null = b\"\\x00\".join(slicer(value, 1)) + b\"\\x00\"\n            self.out.append(\"str w/NULL:     {!s}\".format(value_null))\n        except ValueError:\n            pass\n        return\n\n    def url_encode(self, value):\n        try:\n            import urllib.parse\n            s = urllib.parse.quote(value)\n            if s != value:\n                self.out.append(titlify(\"URL-encode\"))\n                self.out.append(\"URL-encode:     {:s}\".format(s))\n        except Exception:\n            pass\n        return\n\n    def url_decode(self, value):\n        try:\n            import urllib.parse\n            s = urllib.parse.unquote(value)\n            if s != value:\n                self.out.append(titlify(\"URL-decode\"))\n                self.out.append(\"URL-decode:     {:s}\".format(s))\n        except Exception:\n            pass\n        return\n\n    def unhex_xor(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex - XOR\"))\n            for i in range(0x100):\n                xored = b\"\".join(bytes([x ^ i]) for x in value)\n                if 0x20 <= i < 0x7f:\n                    self.out.append(\"xor-{:02X}({:s}):      {!s}\".format(i, chr(i), xored))\n                else:\n                    self.out.append(\"xor-{:02X}:         {!s}\".format(i, xored))\n        except (binascii.Error, ValueError):\n            pass\n        return\n\n    def unhex_add(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex - ADD\"))\n            for i in range(0x100):\n                added = b\"\".join(bytes([(x + i) & 0xff]) for x in value)\n                if 0x20 <= i < 0x7f:\n                    self.out.append(\"add-{:02X}({:s}):      {!s}\".format(i, chr(i), added))\n                else:\n                    self.out.append(\"add-{:02X}:         {!s}\".format(i, added))\n        except (binascii.Error, ValueError):\n            pass\n        return\n\n    def unhex_rol_for_each_byte(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex - ROL (for each byte)\"))\n            for i in range(9):\n                rored = b\"\".join(bytes([((x << i) | x >> (8 - i)) & 0xff]) for x in value)\n                self.out.append(\"rol-{:02X}:         {!s}\".format(i, rored))\n        except (binascii.Error, ValueError):\n            pass\n        return\n\n    def unhex_rol_whole(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex - ROL (whole)\"))\n            bits = []\n            for v in value:\n                for i in range(8):\n                    bits.append(str((v >> (7 - i)) & 1))\n            for i in range(9):\n                rored = bits[i:] + bits[:i]\n                rored = [int(\"\".join(x), 2) for x in slicer(rored, 8)]\n                rored = bytes(rored)\n                self.out.append(\"rol-{:02X}:         {!s}\".format(i, rored))\n        except ValueError:\n            pass\n        return\n\n    def unhex_caesar(self, value):\n        try:\n            if value.startswith(\"0x\"):\n                value = binascii.unhexlify(value[2:])\n            else:\n                value = binascii.unhexlify(value)\n            self.out.append(titlify(\"unhex - caesar\"))\n            for i in range(26):\n                slided = []\n                for x in value:\n                    if ord(\"A\") <= x <= ord(\"Z\"):\n                        x += i\n                        if x > ord(\"Z\"):\n                            x -= ord(\"Z\")\n                            x += ord(\"A\") - 1\n                    elif ord(\"a\") <= x <= ord(\"z\"):\n                        x += i\n                        if x > ord(\"z\"):\n                            x -= ord(\"z\")\n                            x += ord(\"a\") - 1\n                    slided.append(x)\n                self.out.append(\"caesar-{:02d}:      {!s}\".format(i, bytes(slided)))\n        except (binascii.Error, ValueError):\n            pass\n        return\n\n    def string_xor(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"str - XOR\"))\n            for i in range(0x100):\n                xored = b\"\".join(bytes([x ^ i]) for x in value)\n                if 0x20 <= i < 0x7f:\n                    self.out.append(\"xor-{:02X}({:s}):      {!s}\".format(i, chr(i), xored))\n                else:\n                    self.out.append(\"xor-{:02X}:         {!s}\".format(i, xored))\n        except ValueError:\n            pass\n        return\n\n    def string_add(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"str - ADD\"))\n            for i in range(0x100):\n                added = b\"\".join(bytes([(x + i) & 0xff]) for x in value)\n                if 0x20 <= i < 0x7f:\n                    self.out.append(\"add-{:02X}({:s}):      {!s}\".format(i, chr(i), added))\n                else:\n                    self.out.append(\"add-{:02X}:         {!s}\".format(i, added))\n        except ValueError:\n            pass\n        return\n\n    def string_rol_for_each_byte(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"str - ROL (for each byte)\"))\n            for i in range(9):\n                rored = b\"\".join(bytes([((x << i) | x >> (8 - i)) & 0xff]) for x in value)\n                self.out.append(\"rol-{:02X}:         {!s}\".format(i, rored))\n        except ValueError:\n            pass\n        return\n\n    def string_rol_whole(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"str - ROL (whole)\"))\n            bits = []\n            for v in value:\n                for i in range(8):\n                    bits.append(str((v >> (7 - i)) & 1))\n            for i in range(9):\n                rored = bits[i:] + bits[:i]\n                rored = [int(\"\".join(x), 2) for x in slicer(rored, 8)]\n                rored = bytes(rored)\n                self.out.append(\"rol-{:02X}:         {!s}\".format(i, rored))\n        except ValueError:\n            pass\n        return\n\n    def string_caesar(self, value):\n        try:\n            value = codecs.escape_decode(value)[0]\n            self.out.append(titlify(\"str - caesar\"))\n            for i in range(26):\n                slided = []\n                for x in value:\n                    if ord(\"A\") <= x <= ord(\"Z\"):\n                        x += i\n                        if x > ord(\"Z\"):\n                            x -= ord(\"Z\")\n                            x += ord(\"A\") - 1\n                    elif ord(\"a\") <= x <= ord(\"z\"):\n                        x += i\n                        if x > ord(\"z\"):\n                            x -= ord(\"z\")\n                            x += ord(\"a\") - 1\n                    slided.append(x)\n                self.out.append(\"caesar-{:02d}:      {!s}\".format(i, bytes(slided)))\n        except ValueError:\n            pass\n        return\n\n    def convert(self, value, args):\n        self.pack(value)\n        self.pack_hex(value)\n        self.unpack(value)\n        self.tohex(value)\n        self.unhex(value)\n        self.byteswap(value)\n        self.bit_reverse(value)\n        self.integer(value)\n        self.signed(value)\n        self.string(value)\n        self.url_encode(value)\n        self.url_decode(value)\n\n        if args.verbose:\n            self.unhex_xor(value)\n            self.unhex_add(value)\n            self.unhex_rol_for_each_byte(value)\n            self.unhex_rol_whole(value)\n            self.unhex_caesar(value)\n            self.string_xor(value)\n            self.string_add(value)\n            self.string_rol_for_each_byte(value)\n            self.string_rol_whole(value)\n            self.string_caesar(value)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass ConvertMemoryCommand(ConvertCommand):\n    \"\"\"Convert memory values to various.\"\"\"\n\n    _cmdline_ = \"convert memory\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for hash calculation.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for hash calculation.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            value = read_memory(args.location, args.size)\n        except (gdb.MemoryError, MemoryError):\n            err(\"Memory read error\")\n            return\n        value = str(value)[2:-1]\n        self.out = []\n        self.convert(value, args)\n        self.print_output()\n        return\n\n\n@register_command\nclass ConvertValueCommand(ConvertCommand):\n    \"\"\"Convert values to various.\"\"\"\n\n    _cmdline_ = \"convert value\"\n    _category_ = \"07-a. Misc - Conversion\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the value or string to convert.\")\n    parser.add_argument(\"--hex\", action=\"store_true\", help=\"interpret VALUE as hex. invalid character is ignored.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0xdeadbeef\",\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x42\\\\\\\\x43\\\\\\\\x44\" -v',\n        '{0:s} --hex \"41 42 43 44\" -v',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.hex: # \"41414141\" -> \"\\x41\\x41\\x41\\x41\"\n            value = GefUtil.fromhex_ignore_invalid(args.value, to_str=True)\n            if not value:\n                return\n        else:\n            value = args.value\n        self.out = []\n        self.convert(value, args)\n        self.print_output()\n        return\n\n\nclass KernelAddressHeuristicFinderUtil:\n    \"\"\"A class that has utility for KernelAddressHeuristicFinder.\"\"\"\n\n    @staticmethod\n    def common_addr_gen(res, regexp, skip, skip_msb_check, read_valid):\n        for line in res.splitlines():\n            m = re.search(regexp, line)\n            if not m:\n                continue\n            v = AddressUtil.align_address(int(m.group(1), 16))\n            if not skip_msb_check and not AddressUtil.is_msb_on(v):\n                continue\n            if read_valid and not is_valid_addr_addr(v): # not is_valid_addr, but is_valid_addr_addr\n                continue\n            if skip > 0:\n                skip -= 1\n                continue\n            yield v\n\n    @staticmethod\n    def x64_x86_any_const(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"(?:# |,)(0x\\w{8,})\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_x86_mov_reg_const(res, reg=r\"\\w+\", skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"mov\\s+\" + reg + r\"\\s*,\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_lea_reg_const(res, reg=r\"\\w+\", skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"lea\\s+\" + reg + r\"\\s*,\\s*\\[.*([+-]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_x86_cmp_const(res, reg=r\"\\w+\", skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"cmp\\s+\" + reg + r\"\\s*,\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_x86_imul_const(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"imul\\s+\\w+\\s*,\\s*\\w+\\s*,\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_x86_dword_ptr_src(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\",\\s*DWORD PTR \\[.*([+-]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_x86_byte_ptr(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"BYTE PTR \\[.*([+-]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_dword_ptr_rip_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"DWORD PTR \\[rip\\+0x\\w+\\].*#\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_qword_ptr_rip_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"QWORD PTR \\[rip\\+0x\\w+\\].*#\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_qword_ptr_gs_rip_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"QWORD PTR gs:\\[rip\\+0x\\w+\\].*#\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_qword_ptr_array_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"QWORD PTR \\[.*\\*8([-+]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_dword_ptr_array4_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"DWORD PTR \\[.*\\*4([+-]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_dword_ptr_array8_base(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"DWORD PTR \\[.*\\*8([+-]0x\\w+)\\]\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_qword_ptr_ds(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"QWORD PTR ds:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x64_qword_ptr_gs(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"QWORD PTR gs:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_dword_ptr_ds(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"DWORD PTR ds:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_dword_ptr_fs(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"DWORD PTR fs:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_noptr_ds(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"ds:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def x86_mov_noptr_ds(res, skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"mov.*ds:\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def aarch64_cmp_const(res, reg=r\"\\w+\", skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"cmp\\s+\" + reg + r\"\\s*,\\s*#(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def aarch64_adrp_ldr(res, skip=0, skip_msb_check=False, read_valid=False):\n        bases = {}\n        for line in res.splitlines():\n            m = re.search(r\"adrp\\s+(\\w+),\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[(\\w+),\\s*#(\\d+)\\]\", line)\n            if m:\n                srcreg = m.group(1)\n                v = int(m.group(2), 0)\n                if srcreg in bases:\n                    w = AddressUtil.align_address(bases[srcreg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def aarch64_adrp_add(res, skip=0, skip_msb_check=False, read_valid=False):\n        bases = {}\n        for line in res.splitlines():\n            m = re.search(r\"adrp\\s+(\\w+),\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            m = re.search(r\"add\\s+(\\w+),\\s*(\\w+),\\s*#(0x\\w+)\", line)\n            if m:\n                srcreg = m.group(2)\n                v = int(m.group(3), 16)\n                if srcreg in bases:\n                    w = AddressUtil.align_address(bases[srcreg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def aarch64_adrp_add_add(res, skip=0, skip_msb_check=False, read_valid=False):\n        bases = {}\n        add1time = {}\n        for line in res.splitlines():\n            m = re.search(r\"adrp\\s+(\\w+),\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                base = int(m.group(2), 16)\n                bases[reg] = base\n                continue\n            m = re.search(r\"add\\s+(\\w+),\\s*(\\w+),\\s*#(0x\\w+)\", line)\n            if m:\n                dstreg = m.group(1)\n                srcreg = m.group(2)\n                v = int(m.group(3), 16)\n                if srcreg in add1time:\n                    w = AddressUtil.align_address(add1time[srcreg] + v)\n                    if not skip_msb_check or AddressUtil.is_msb_on(w):\n                        if not read_valid or is_valid_addr_addr(w):\n                            if skip <= 0:\n                                yield w\n                            skip -= 1\n                if srcreg in bases:\n                    add1time[dstreg] = bases[srcreg] + v\n                    continue\n\n    @staticmethod\n    def aarch64_adrp_add_ldr(res, skip=0, skip_msb_check=False, read_valid=False):\n        bases = {}\n        add1time = {}\n        for line in res.splitlines():\n            m = re.search(r\"adrp\\s+(\\w+),\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            m = re.search(r\"add\\s+(\\w+),\\s*(\\w+),\\s*#(0x\\w+)\", line)\n            if m:\n                dstreg = m.group(1)\n                srcreg = m.group(2)\n                v = int(m.group(3), 16)\n                if srcreg in bases:\n                    add1time[dstreg] = bases[srcreg] + v\n                    continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[(\\w+),\\s*#(\\d+)\\]\", line)\n            if m:\n                srcreg = m.group(1)\n                v = int(m.group(2), 0)\n                if srcreg in add1time:\n                    w = AddressUtil.align_address(add1time[srcreg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def arm32_movw_movt(res, skip=0, skip_msb_check=False, read_valid=False, allow_cc=False):\n        bases = {}\n        for line in res.splitlines():\n            if allow_cc:\n                m = re.search(r\"movw(?:cc)?\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            else:\n                m = re.search(r\"movw\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            if allow_cc:\n                m = re.search(r\"movt(?:cc)?\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            else:\n                m = re.search(r\"movt\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16) << 16\n                if reg in bases:\n                    w = AddressUtil.align_address(bases[reg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def arm32_movw_movt_ldr(res, skip=0, skip_msb_check=False, read_valid=False, allow_cc=False):\n        bases = {}\n        add1time = {}\n        for line in res.splitlines():\n            if allow_cc:\n                m = re.search(r\"movw(?:cc)?\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            else:\n                m = re.search(r\"movw\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            if allow_cc:\n                m = re.search(r\"movt(?:cc)?\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            else:\n                m = re.search(r\"movt\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16) << 16\n                if reg in bases:\n                    add1time[reg] = bases[reg] + v\n                    continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[(\\w+),\\s*#(\\d+)\\]\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 0)\n                if reg in add1time:\n                    w = AddressUtil.align_address(add1time[reg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def arm32_movw_movt_add(res, skip=0, skip_msb_check=False, read_valid=False):\n        bases = {}\n        add1time = {}\n        for line in res.splitlines():\n            m = re.search(r\"movw\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16)\n                bases[reg] = v\n                continue\n            m = re.search(r\"movt\\s+(\\w+),.+[;@]\\s*(0x\\w+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 16) << 16\n                if reg in bases:\n                    add1time[reg] = bases[reg] + v\n                    continue\n            m = re.search(r\"add\\s+\\w+,\\s*(\\w+),\\s*#(\\d+)\", line)\n            if m:\n                reg = m.group(1)\n                v = int(m.group(2), 0)\n                if reg in add1time:\n                    w = AddressUtil.align_address(add1time[reg] + v)\n                    if not skip_msb_check and not AddressUtil.is_msb_on(w):\n                        continue\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip > 0:\n                        skip -= 1\n                        continue\n                    yield w\n\n    @staticmethod\n    def arm32_ldr_reg_const(res, reg=r\"\\w+\", skip=0, skip_msb_check=False, read_valid=False):\n        regexp = r\"ldr\\s+\" + reg + r\",.*[;@]\\s*(0x\\w+)\"\n        return KernelAddressHeuristicFinderUtil.common_addr_gen(res, regexp, skip, skip_msb_check, read_valid)\n\n    @staticmethod\n    def arm32_ldr_pc_relative(res, skip=0, read_valid=False):\n        for line in res.splitlines():\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[pc,\\s*#(\\d+)\\]\", line)\n            if m:\n                ofs = AddressUtil.align_address(int(m.group(1), 0))\n                pos = AddressUtil.align_address(int(line.split()[0].replace(\":\", \"\"), 16))\n                v = read_int_from_memory(pos + 4 * 2 + ofs)\n                if is_valid_addr(v):\n                    if skip <= 0:\n                        yield v\n                    skip -= 1\n                    continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[pc\\]\", line)\n            if m:\n                pos = AddressUtil.align_address(int(line.split()[0].replace(\":\", \"\"), 16))\n                v = read_int_from_memory(pos + 4 * 2)\n                if is_valid_addr(v):\n                    if read_valid and not is_valid_addr_addr(v):\n                        continue\n                    if skip <= 0:\n                        yield v\n                    skip -= 1\n                    continue\n\n    @staticmethod\n    def arm32_ldr_pc_relative_ldr(res, skip=0, read_valid=False):\n        bases = {}\n        for line in res.splitlines():\n            m = re.search(r\"ldr\\s+(\\w+),\\s*\\[pc,\\s*#(\\d+)\\]\", line)\n            if m:\n                reg = m.group(1)\n                ofs = AddressUtil.align_address(int(m.group(2), 0))\n                pos = AddressUtil.align_address(int(line.split()[0].replace(\":\", \"\"), 16))\n                v = read_int_from_memory(pos + 4 * 2 + ofs)\n                bases[reg] = v\n                continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[(\\w+),\\s*#(\\d*)\\]\", line)\n            if m:\n                reg = m.group(1)\n                ofs = AddressUtil.align_address(int(m.group(2), 0))\n                if reg in bases:\n                    w = AddressUtil.align_address(bases[reg] + ofs)\n                    if skip <= 0:\n                        yield w\n                    skip -= 1\n                    continue\n            m = re.search(r\"ldr\\s+\\w+,\\s*\\[(\\w+)\\]\", line)\n            if m:\n                reg = m.group(1)\n                if reg in bases:\n                    w = AddressUtil.align_address(bases[reg])\n                    if read_valid and not is_valid_addr_addr(w):\n                        continue\n                    if skip <= 0:\n                        yield w\n                    skip -= 1\n                    continue\n\n\nclass KernelConstsBase:\n    \"\"\"A class that manages constants by version.\"\"\"\n\n    SZ_64K = 0x0001_0000\n    SZ_256K = 0x0004_0000\n    SZ_2M = 0x0020_0000\n    SZ_4M = 0x0040_0000\n    SZ_8M = 0x0080_0000\n    SZ_16M = 0x0100_0000\n    SZ_32M = 0x0200_0000\n    SZ_64M = 0x0400_0000\n    SZ_128M = 0x0800_0000\n    SZ_256M = 0x1000_0000\n    SZ_1G = 0x4000_0000\n    SZ_2G = 0x8000_0000\n    SZ_1T = 0x0100_0000_0000\n\n    def __init__(self, version=None):\n        if version:\n            vs = version.split(\".\")\n            if len(vs) == 2:\n                vs = [int(vs[0]), int(vs[1]), 0]\n            else:\n                vs = [int(vs[0]), int(vs[1]), int(vs[2])]\n            self.kversion = Kernel.KernelVersion(0, \"\",  *vs)\n        else:\n            self.kversion = Kernel.kernel_version()\n        return\n\n    def order_base_2(self, n):\n        if n > 1:\n            return GefUtil.log2(n)\n        return 0\n\n    def round_up(self, x, y):\n        return ((x - 1) | (y - 1)) + 1\n\n    def ALIGN(self, x, a):\n        mask = a - 1\n        return (x + mask) & ~mask\n\n    def test(self): # noqa\n        if is_32bit():\n            target = [\"PAGE_OFFSET\", \"PAGE_OFFSET_END\", \"VMALLOC_START\", \"VMALLOC_END\"]\n        else:\n            target = [\"PAGE_OFFSET\", \"PAGE_OFFSET_END\", \"VMALLOC_START\", \"VMALLOC_END\", \"VMEMMAP_START\", \"VMEMMAP_END\"]\n        for attr in target:\n            try:\n                v = getattr(self, attr)\n                if v:\n                    info(\"{:16s} = {:#x}\".format(attr, v))\n                else:\n                    err(\"{:16s} = None\".format(attr))\n            except Exception:\n                err(\"{:16s} = {}\".format(attr, Color.colorify(\"ERROR\", \"bold red\")))\n        return\n\n\nclass KernelConstsX86(KernelConstsBase):\n    \"\"\"A class that manages x86 constants by version.\"\"\"\n\n    def __init__(self, version=None, kaslr=None, pae=None):\n        super().__init__(version)\n        self.kaslr = kaslr\n        self.pae = pae\n        return\n\n    PAGE_SHIFT = 12\n    PAGE_SIZE = 1 << PAGE_SHIFT\n\n    @property\n    def CONFIG_HIGHMEM(self):\n        addr = Symbol.get_ksymaddr(\"nr_free_highpages\")\n        return bool(addr)\n\n    @property\n    def CONFIG_X86_PAE(self):\n        if self.pae is not None:\n            return self.pae\n\n        cr4 = get_register(\"cr4\", use_monitor=True)\n        if not cr4:\n            self.pae = False\n        elif (cr4 >> 5) & 1: # PAE check\n            self.pae = True\n        else:\n            self.pae = False\n        return self.pae\n\n    @property\n    def CONFIG_INTEL_TXT(self):\n        addr = Symbol.get_ksymaddr(\"tboot_probe\")\n        return bool(addr)\n\n    @property\n    def CONFIG_PAGE_OFFSET(self):\n        if hasattr(self, \"cached_PAGE_OFFSET\"):\n            return self.cached_PAGE_OFFSET\n        kern_min = Kernel.get_maps()[0][0]\n        if 0xc000_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0xc000_0000 # VMSPLIT_3G\n        elif 0xb000_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0xb000_0000 # VMSPLIT_3G_OPT\n        elif 0x8000_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0x8000_0000 # VMSPLIT_2G\n        elif 0x7800_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0x7800_0000 # VMSPLIT_2G_OPT\n        elif 0x4000_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0x4000_0000 # VMSPLIT_1G\n        return self.cached_PAGE_OFFSET\n\n    @property\n    def __PAGE_OFFSET(self):\n        return self.CONFIG_PAGE_OFFSET\n\n    @property\n    def PAGE_OFFSET(self):\n        return self.__PAGE_OFFSET\n\n    @property\n    def PAGE_OFFSET_END(self):\n        return self.high_memory\n\n    @property\n    def high_memory(self):\n        if hasattr(self, \"cached_high_memory\"):\n            return self.cached_high_memory\n\n        max_hm = AddressUtil.align_address(-128 << 20)\n        vmalloc_start = KernelAddressHeuristicFinder._get_VMALLOC_START()\n        if vmalloc_start is None:\n            self.cached_high_memory = max_hm\n        else:\n            real_hm = vmalloc_start - self.VMALLOC_OFFSET\n            self.cached_high_memory = min(real_hm, max_hm)\n        return self.cached_high_memory\n\n    @property\n    def __FIXADDR_TOP(self):\n        return 0xffff_f000\n\n    @property\n    def FIXADDR_TOP(self):\n        return self.__FIXADDR_TOP\n\n    @property\n    def __end_of_permanent_fixed_addresses(self):\n        end = self.__end_of_fixed_addresses\n        if end is None:\n            return None\n        if \"3.0\" <= self.kversion < \"3.10\":\n            # (FIX_TBOOT_BASE), FIX_WP_TEST, FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - int(self.CONFIG_INTEL_TXT) - 1 - 256\n        elif \"3.10\" <= self.kversion:\n            # (FIX_TBOOT_BASE), FIX_WP_TEST, FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - int(self.CONFIG_INTEL_TXT) - 1 - 512\n        return None\n\n    @property\n    def __end_of_fixed_addresses(self):\n        return KernelAddressHeuristicFinder.get_end_of_fixed_addresses()\n\n    @property\n    def FIXADDR_SIZE(self):\n        if self.__end_of_permanent_fixed_addresses is None:\n            return None\n        return self.__end_of_permanent_fixed_addresses << self.PAGE_SHIFT\n\n    @property\n    def FIXADDR_BOOT_SIZE(self):\n        if \"3.0\" <= self.kversion < \"3.19\":\n            return self.__end_of_fixed_addresses << self.PAGE_SHIFT\n        return None\n\n    @property\n    def FIXADDR_TOT_SIZE(self):\n        if \"4.14\" <= self.kversion:\n            return self.__end_of_fixed_addresses << self.PAGE_SHIFT\n        return None\n\n    @property\n    def FIXADDR_START(self):\n        return self.FIXADDR_TOP - self.FIXADDR_SIZE\n\n    @property\n    def FIXADDR_BOOT_START(self):\n        if \"3.0\" <= self.kversion < \"3.19\":\n            return self.FIXADDR_TOP - self.FIXADDR_BOOT_SIZE\n        return None\n\n    @property\n    def FIXADDR_TOT_START(self):\n        if \"4.14\" <= self.kversion:\n            return self.FIXADDR_TOP - self.FIXADDR_TOT_SIZE\n        return None\n\n    @property\n    def PMD_SHIFT(self):\n        if self.CONFIG_X86_PAE:\n            return 21\n        else:\n            return 22 # == PUD_SHIFT == PGDIR_SHIFT\n\n    @property\n    def PMD_SIZE(self):\n        return 1 << self.PMD_SHIFT\n\n    @property\n    def PMD_MASK(self):\n        return ~(self.PMD_SIZE - 1)\n\n    @property\n    def VMALLOC_OFFSET(self):\n        return 8 * 1024 * 1024\n\n    @property\n    def VMALLOC_START(self):\n        return self.high_memory + self.VMALLOC_OFFSET\n\n    @property\n    def LAST_PKMAP(self):\n        if self.CONFIG_X86_PAE:\n            return 512\n        else:\n            return 1024\n\n    @property\n    def CPU_ENTRY_AREA_SIZE(self):\n        if \"4.14\" <= self.kversion:\n            if hasattr(self, \"cached_CPU_ENTRY_AREA_SIZE\"):\n                return self.cached_CPU_ENTRY_AREA_SIZE\n\n            cpu_entry_area_size = KernelAddressHeuristicFinder.get_sizeof_cpu_entry_area()\n            if cpu_entry_area_size:\n                self.cached_CPU_ENTRY_AREA_SIZE = cpu_entry_area_size\n            return cpu_entry_area_size\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_PAGES(self):\n        if \"4.14\" <= self.kversion:\n            return self.CPU_ENTRY_AREA_SIZE // self.PAGE_SIZE\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_BASE(self):\n        if \"4.14\" <= self.kversion:\n            return (self.FIXADDR_TOT_START - self.PAGE_SIZE * (self.CPU_ENTRY_AREA_PAGES + 1)) & self.PMD_MASK\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_END(self):\n        if \"4.14\" <= self.kversion:\n            return self.CPU_ENTRY_AREA_BASE + self.CPU_ENTRY_AREA_SIZE\n        return None\n\n    @property\n    def LDT_BASE_ADDR(self):\n        if \"4.19\" <= self.kversion:\n            return (self.CPU_ENTRY_AREA_BASE - self.PAGE_SIZE) & self.PMD_MASK\n        return None\n\n    @property\n    def LDT_END_ADDR(self):\n        if \"4.19\" <= self.kversion:\n            return self.LDT_BASE_ADDR + self.PMD_SIZE\n        return None\n\n    @property\n    def PKMAP_BASE(self):\n        if \"3.0\" <= self.kversion < \"3.19\":\n            return (self.FIXADDR_BOOT_START - self.PAGE_SIZE * (self.LAST_PKMAP + 1)) & self.PMD_MASK\n        elif \"3.19\" <= self.kversion < \"4.14\":\n            return (self.FIXADDR_START - self.PAGE_SIZE * (self.LAST_PKMAP + 1)) & self.PMD_MASK\n        elif \"4.14\" <= self.kversion < \"4.19\":\n            return (self.CPU_ENTRY_AREA_BASE - self.PAGE_SIZE) & self.PMD_MASK\n        elif \"4.19\" <= self.kversion:\n            return (self.LDT_BASE_ADDR - self.PAGE_SIZE) & self.PMD_MASK\n        return None\n\n    @property\n    def VMALLOC_END(self):\n        if \"3.0\" <= self.kversion < \"4.14\":\n            if self.CONFIG_HIGHMEM:\n                return self.PKMAP_BASE - 2 * self.PAGE_SIZE\n            else:\n                return self.FIXADDR_START - 2 * self.PAGE_SIZE\n        elif \"4.14\" <= self.kversion < \"4.19\":\n            if self.CONFIG_HIGHMEM:\n                return self.PKMAP_BASE - 2 * self.PAGE_SIZE\n            else:\n                return self.CPU_ENTRY_AREA_BASE - 2 * self.PAGE_SIZE\n        elif \"4.19\" <= self.kversion:\n            if self.CONFIG_HIGHMEM:\n                return self.PKMAP_BASE - 2 * self.PAGE_SIZE\n            else:\n                return self.LDT_BASE_ADDR - 2 * self.PAGE_SIZE\n        return None\n\n    @property\n    def MODULES_VADDR(self):\n        return self.VMALLOC_START\n\n    @property\n    def MODULES_END(self):\n        return self.VMALLOC_END\n\n    @property # noqa\n    def MODULES_LEN(self):\n        return self.MODULES_VADDR - self.MODULES_END\n\n    @property\n    def mem_map(self):\n        if hasattr(self, \"cached_mem_map\"):\n            return self.cached_mem_map\n        self.cached_mem_map = KernelAddressHeuristicFinder.get_mem_map()\n        return self.cached_mem_map\n\n    @property\n    def mem_section(self):\n        if hasattr(self, \"cached_mem_section\"):\n            return self.cached_mem_section\n        self.cached_mem_section = KernelAddressHeuristicFinder.get_mem_section()\n        return self.cached_mem_section\n\n    @property\n    def CONFIG_FLATMEM(self):\n        return bool(self.mem_map)\n\n    @property\n    def CONFIG_SPARSEMEM(self):\n        return bool(self.mem_section)\n\n    @property\n    def MAX_PHYSMEM_BITS(self):\n        if self.CONFIG_SPARSEMEM:\n            if self.CONFIG_X86_PAE:\n                return 36\n            else:\n                return 32\n        return None\n\n    @property\n    def SECTION_SIZE_BITS(self):\n        if self.CONFIG_SPARSEMEM:\n            if self.CONFIG_X86_PAE:\n                return 29\n            else:\n                return 26\n        return None\n\n    @property\n    def SECTIONS_SHIFT(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.MAX_PHYSMEM_BITS - self.SECTION_SIZE_BITS\n        return 0\n\n    @property\n    def SECTIONS_WIDTH(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.SECTIONS_SHIFT\n        return 0\n\n    @property\n    def SECTIONS_PGOFF(self):\n        return 4 * 8 - self.SECTIONS_WIDTH\n\n    @property\n    def SECTIONS_PGSHIFT(self):\n        return self.SECTIONS_PGOFF * int(self.SECTIONS_WIDTH != 0)\n\n    @property\n    def SECTIONS_MASK(self):\n        return (1 << self.SECTIONS_WIDTH) - 1\n\n    @property\n    def SECTION_HAS_MEM_MAP(self):\n        return 1 << 1\n\n    @property\n    def SECTION_MAP_LAST_BIT(self):\n        if self.kversion < \"4.13\":\n            return 1 << 2\n        elif \"4.13\" <= self.kversion < \"5.3\":\n            return 1 << 3\n        elif \"5.3\" <= self.kversion < \"5.12\":\n            return 1 << 4\n        elif \"5.12\" <= self.kversion < \"6.0\":\n            return 1 << 5\n        elif \"6.0\" <= self.kversion:\n            return 1 << 4\n\n    @property\n    def SECTION_MAP_MASK(self):\n        return ~(self.SECTION_MAP_LAST_BIT - 1) & 0xffff_ffff\n\n    @property\n    def NR_MEM_SECTIONS(self):\n        if self.CONFIG_SPARSEMEM:\n            return 1 << self.SECTIONS_SHIFT\n        return None\n\n    @property\n    def PFN_SECTION_SHIFT(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.SECTION_SIZE_BITS - self.PAGE_SHIFT\n        return None\n\n    @property\n    def CONFIG_PAGE_EXTENSION(self):\n        if \"3.19\" <= self.kversion:\n            addr = Symbol.get_ksymaddr(\"page_ext_init\")\n            return bool(addr)\n        return None\n\n    @property\n    def sizeof_mem_section(self):\n        if not self.CONFIG_SPARSEMEM:\n            return None\n\n        if self.CONFIG_PAGE_EXTENSION:\n            return current_arch.ptrsize * 4\n        return current_arch.ptrsize * 2\n\n    @property\n    def sizeof_struct_page(self):\n        if hasattr(self, \"cached_sizeof_struct_page\"):\n            return self.cached_sizeof_struct_page\n\n        if not (self.CONFIG_FLATMEM or self.CONFIG_SPARSEMEM):\n            return None\n\n        if self.PAGE_OFFSET is None:\n            return None\n\n        ret = Kernel.get_page_virt_pair()\n        if not ret:\n            return None\n        page, vaddr = ret\n\n        pfn = (vaddr - self.PAGE_OFFSET) >> self.PAGE_SHIFT\n        if pfn == 0:\n            return None\n\n        if self.CONFIG_FLATMEM:\n            base = self.mem_map\n            if base is None:\n                return None\n\n        else:\n            flags = read_int_from_memory(page)\n            section_id = (flags >> self.SECTIONS_PGSHIFT) & self.SECTIONS_MASK\n\n            ms = self.mem_section + self.sizeof_mem_section * section_id\n            if ms is None:\n                return None\n\n            section_mem_map = read_int_from_memory(ms)\n            if (section_mem_map & self.SECTION_HAS_MEM_MAP) == 0:\n                return None\n\n            base = section_mem_map & self.SECTION_MAP_MASK\n            if base == 0:\n                return None\n\n        delta = page - base\n        if delta <= 0:\n            return None\n        if (delta % pfn) != 0:\n            return None\n\n        size = delta // pfn\n        if size == 0:\n            return None\n\n        self.cached_sizeof_struct_page = size\n        return size\n\n\nclass KernelConstsX64(KernelConstsBase):\n    \"\"\"A class that manages x64 constants by version.\"\"\"\n\n    def __init__(self, version=None, kaslr=None, level5pt=None):\n        super().__init__(version)\n        self.kaslr = kaslr\n        self.level5pt = level5pt\n        return\n\n    PAGE_SHIFT = 12\n    PAGE_SIZE = 1 << PAGE_SHIFT\n\n    def check_kaslr(self):\n        if self.kaslr is not None:\n            return self.kaslr\n\n        kcmdline = Kernel.kernel_cmdline()\n        ksym_ret = gdb.execute(\"ksymaddr-remote --quiet --no-pager kaslr_\", to_string=True)\n        if not ksym_ret:\n            self.kaslr = False\n        elif kcmdline and \"nokaslr\" in kcmdline.cmdline:\n            self.kaslr = False\n        else:\n            self.kaslr = True\n        return self.kaslr\n\n    @property\n    def sizeof_struct_page(self):\n        if hasattr(self, \"cached_sizeof_struct_page\"):\n            return self.cached_sizeof_struct_page\n\n        ret = Kernel.get_page_virt_pair()\n        if not ret:\n            return None\n        page, vaddr = ret\n        pfn = (vaddr - self.PAGE_OFFSET) >> self.PAGE_SHIFT\n        sizeof_struct_page_value = align_to_ptrsize((page - self.VMEMMAP_START) // pfn)\n        if sizeof_struct_page_value != 0:\n            self.cached_sizeof_struct_page = sizeof_struct_page_value\n        return sizeof_struct_page_value\n\n    @property\n    def CONFIG_X86_5LEVEL(self):\n        if self.level5pt is not None:\n            return self.level5pt\n\n        cr4 = get_register(\"cr4\", use_monitor=True)\n        if not cr4:\n            self.level5pt = False\n        elif (cr4 >> 12) & 1: # PML5T check\n            self.level5pt = True\n        else:\n            self.level5pt = False\n        return self.level5pt\n\n    @property\n    def CONFIG_RANDOMIZE_BASE(self):\n        if \"3.14\" <= self.kversion:\n            return self.check_kaslr()\n        return None\n\n    @property\n    def CONFIG_RANDOMIZE_MEMORY(self):\n        if \"4.8\" <= self.kversion:\n            return self.check_kaslr() # change if needed\n        return None\n\n    @property\n    def CONFIG_DYNAMIC_MEMORY_LAYOUT(self):\n        if \"4.17\" <= self.kversion < \"6.16\":\n            return self.check_kaslr() # change if needed\n        return None\n\n    @property\n    def CONFIG_RANDOMIZE_BASE_MAX_OFFSET(self):\n        if \"3.14\" <= self.kversion < \"4.7\":\n            return 0x4000_0000 # change if needed\n        return None\n\n    @property\n    def CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP(self):\n        if \"5.11\" <= self.kversion:\n            return False # change if needed\n        return None\n\n    @property\n    def CONFIG_KMSAN(self):\n        if \"6.1\" <= self.kversion:\n            return False # change if needed\n        return None\n\n    @property\n    def CONFIG_INTEL_TXT(self):\n        addr = Symbol.get_ksymaddr(\"tboot_probe\")\n        return bool(addr)\n\n    @property\n    def KERNEL_IMAGE_SIZE_DEFAULT(self):\n        if \"3.14\" <= self.kversion < \"4.7\":\n            return 512 * 1024 * 1024\n        return None\n\n    @property\n    def KERNEL_IMAGE_SIZE(self):\n        if \"3.0\" <= self.kversion < \"3.14\":\n            return 512 * 1024 * 1024\n        elif \"3.14\" <= self.kversion < \"4.7\":\n            if self.CONFIG_RANDOMIZE_BASE and self.CONFIG_RANDOMIZE_BASE_MAX_OFFSET > self.KERNEL_IMAGE_SIZE_DEFAULT:\n                return self.CONFIG_RANDOMIZE_BASE_MAX_OFFSET\n            else:\n                return self.KERNEL_IMAGE_SIZE_DEFAULT\n        elif \"4.7\" <= self.kversion:\n            if self.CONFIG_RANDOMIZE_BASE:\n                return 1024 * 1024 * 1024\n            else:\n                return 512 * 1024 * 1024\n        return None\n\n    @property\n    def __START_KERNEL_map(self):\n        if \"3.0\" <= self.kversion:\n            return 0xffff_ffff_8000_0000\n        return None\n\n    @property # noqa\n    def START_KERNEL_map(self):\n        return self.__START_KERNEL_map\n\n    @property\n    def __PAGE_OFFSET_BASE(self):\n        if \"4.8\" <= self.kversion < \"4.12\":\n            return 0xffff_8800_0000_0000\n        elif \"4.12\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return 0xff10_0000_0000_0000\n            else:\n                return 0xffff_8800_0000_0000\n        return None\n\n    @property\n    def __PAGE_OFFSET_BASE_L4(self):\n        if \"4.17\" <= self.kversion < \"4.19\":\n            return 0xffff_8800_0000_0000\n        elif \"4.19\" <= self.kversion:\n            return 0xffff_8880_0000_0000\n        return None\n\n    @property # noqa\n    def __PAGE_OFFSET_BASE_L5(self):\n        if \"4.17\" <= self.kversion < \"4.19\":\n            return 0xff10_0000_0000_0000\n        elif \"4.19\" <= self.kversion:\n            return 0xff11_0000_0000_0000\n        return None\n\n    @property\n    def page_offset_base(self):\n        if \"4.8\" <= self.kversion:\n            if hasattr(self, \"cached_page_offset_base\"):\n                return self.cached_page_offset_base\n\n            page_offset = KernelAddressHeuristicFinder._get_PAGE_OFFSET()\n            if page_offset:\n                self.cached_page_offset_base = page_offset\n            return page_offset\n        return None\n\n    @property\n    def __PAGE_OFFSET(self):\n        if \"3.0\" <= self.kversion < \"4.8\":\n            return 0xffff_8800_0000_0000\n        elif \"4.8\" <= self.kversion < \"4.17\":\n            if self.CONFIG_RANDOMIZE_MEMORY:\n                return self.page_offset_base\n            else:\n                return self.__PAGE_OFFSET_BASE\n        elif \"4.17\" <= self.kversion < \"6.16\":\n            if self.CONFIG_DYNAMIC_MEMORY_LAYOUT:\n                return self.page_offset_base\n            else:\n                return self.__PAGE_OFFSET_BASE_L4\n        elif \"6.16\" <= self.kversion:\n                return self.page_offset_base\n        return None\n\n    @property\n    def PAGE_OFFSET(self):\n        if \"3.0\" <= self.kversion:\n            return self.__PAGE_OFFSET\n        return None\n\n    @property\n    def PAGE_OFFSET_END(self):\n        if \"3.0\" <= self.kversion:\n            return self.VMALLOC_START\n        return None\n\n    @property\n    def LDT_PGD_ENTRY_L4(self):\n        if \"4.17\" <= self.kversion < \"4.19\":\n            return -3\n        return None\n\n    @property\n    def LDT_PGD_ENTRY_L5(self):\n        if \"4.17\" <= self.kversion < \"4.19\":\n            return -112\n        return None\n\n    @property\n    def LDT_PGD_ENTRY(self):\n        if \"4.14\" <= self.kversion < \"4.15\":\n            return -240\n        elif \"4.15\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return -112\n            else:\n                return -3\n        elif \"4.17\" <= self.kversion < \"4.19\":\n            if self.CONFIG_X86_5LEVEL:\n                return self.LDT_PGD_ENTRY_L5\n            else:\n                return self.LDT_PGD_ENTRY_L4\n        elif \"4.19\" <= self.kversion:\n            return -240\n        return None\n\n    @property\n    def LDT_BASE_ADDR(self):\n        if \"4.14\" <= self.kversion:\n            ldt_base_addr = self.LDT_PGD_ENTRY << self.PGDIR_SHIFT\n            return AddressUtil.align_address(ldt_base_addr)\n        return None\n\n    @property\n    def LDT_END_ADDR(self):\n        if \"4.19\" <= self.kversion:\n            return self.LDT_BASE_ADDR + self.PGDIR_SIZE\n        return None\n\n    @property\n    def VMALLOC_SIZE_TB_L4(self):\n        if \"4.17\" <= self.kversion:\n            return 32\n        return None\n\n    @property\n    def VMALLOC_SIZE_TB_L5(self):\n        if \"4.17\" <= self.kversion:\n            return 12800\n        return None\n\n    @property\n    def VMALLOC_SIZE_TB(self):\n        if \"4.8\" <= self.kversion < \"4.12\":\n            return 32\n        elif \"4.12\" <= self.kversion < \"4.14\":\n            if self.CONFIG_X86_5LEVEL:\n                return 16384\n            else:\n                return 32\n        elif \"4.14\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return 12800\n            else:\n                return 32\n        elif \"4.17\" <= self.kversion < \"6.16\":\n            if self.CONFIG_DYNAMIC_MEMORY_LAYOUT:\n                if self.CONFIG_X86_5LEVEL:\n                    return self.VMALLOC_SIZE_TB_L5\n                else:\n                    return self.VMALLOC_SIZE_TB_L4\n            else:\n                return self.VMALLOC_SIZE_TB_L4\n        elif \"6.16\" <= self.kversion:\n            if self.CONFIG_X86_5LEVEL:\n                return self.VMALLOC_SIZE_TB_L5\n            else:\n                return self.VMALLOC_SIZE_TB_L4\n        return None\n\n    @property\n    def __VMALLOC_BASE(self):\n        if \"4.8\" <= self.kversion < \"4.12\":\n            return 0xffff_c900_0000_0000\n        elif \"4.12\" <= self.kversion < \"4.14\":\n            if self.CONFIG_X86_5LEVEL:\n                return 0xff92_0000_0000_0000\n            else:\n                return 0xffff_c900_0000_0000\n        elif \"4.14\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return 0xffa0_0000_0000_0000\n            else:\n                return 0xffff_c900_0000_0000\n        return None\n\n    @property\n    def __VMALLOC_BASE_L4(self):\n        if \"4.17\" <= self.kversion:\n            return 0xffff_c900_0000_0000\n        return None\n\n    @property # noqa\n    def __VMALLOC_BASE_L5(self):\n        if \"4.17\" <= self.kversion:\n            return 0xffa0_0000_0000_0000\n        return None\n\n    @property\n    def vmalloc_base(self):\n        if \"4.8\" <= self.kversion:\n            if hasattr(self, \"cached_vmalloc_base\"):\n                return self.cached_vmalloc_base\n\n            vmalloc_start = KernelAddressHeuristicFinder._get_VMALLOC_START()\n            if vmalloc_start:\n                self.cached_vmalloc_base = vmalloc_start\n            return vmalloc_start\n        return None\n\n    @property\n    def VMALLOC_START(self):\n        if \"3.0\" <= self.kversion < \"4.8\":\n            return 0xffff_c900_0000_0000\n        elif \"4.8\" <= self.kversion < \"4.17\":\n            if self.CONFIG_RANDOMIZE_MEMORY:\n                return self.vmalloc_base\n            else:\n                return self.__VMALLOC_BASE\n        elif \"4.17\" <= self.kversion < \"6.16\":\n            if self.CONFIG_DYNAMIC_MEMORY_LAYOUT:\n                return self.vmalloc_base\n            else:\n                return self.__VMALLOC_BASE_L4\n        elif \"6.16\" <= self.kversion:\n            return self.vmalloc_base\n        return None\n\n    @property\n    def VMEMORY_END(self):\n        if \"6.1\" <= self.kversion:\n            return self.VMALLOC_START + (self.VMALLOC_SIZE_TB << 40)\n        return None\n\n    @property\n    def VMALLOC_QUARTER_SIZE(self):\n        if \"6.1\" <= self.kversion:\n            if self.CONFIG_KMSAN:\n                return (self.VMALLOC_SIZE_TB << 40) >> 2\n        return None\n\n    @property\n    def VMALLOC_END(self):\n        if \"3.0\" <= self.kversion < \"4.8\":\n            return 0xffff_e900_0000_0000\n        elif \"4.8\" <= self.kversion < \"6.1\":\n            return self.VMALLOC_START + (self.VMALLOC_SIZE_TB << 40)\n        elif \"6.1\" <= self.kversion:\n            if not self.CONFIG_KMSAN:\n                return self.VMEMORY_END\n            else:\n                return self.VMALLOC_START + self.VMALLOC_QUARTER_SIZE\n        return None\n\n    @property\n    def __VMEMMAP_BASE(self):\n        if \"4.9\" <= self.kversion < \"4.12\":\n            return 0xffff_ea00_0000_0000\n        elif \"4.12\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return 0xffd4_0000_0000_0000\n            else:\n                return 0xffff_ea00_0000_0000\n        return None\n\n    @property\n    def __VMEMMAP_BASE_L4(self):\n        if \"4.17\" <= self.kversion:\n            return 0xffff_ea00_0000_0000\n        return None\n\n    @property # noqa\n    def __VMEMMAP_BASE_L5(self):\n        if \"4.17\" <= self.kversion:\n            return 0xffd4_0000_0000_0000\n        return None\n\n    @property\n    def vmemmap_base(self):\n        if \"4.9\" <= self.kversion:\n            if hasattr(self, \"cached_vmemmap_base\"):\n                return self.cached_vmemmap_base\n\n            vmemmap_start = KernelAddressHeuristicFinder._get_VMEMMAP_START()\n            if vmemmap_start:\n                self.cached_vmemmap_base = vmemmap_start\n            return vmemmap_start\n        return None\n\n    @property\n    def VMEMMAP_START(self):\n        if \"3.0\" <= self.kversion < \"4.9\":\n            return 0xffff_ea00_0000_0000\n        elif \"4.9\" <= self.kversion < \"4.17\":\n            if self.CONFIG_RANDOMIZE_MEMORY:\n                return self.vmemmap_base\n            else:\n                return self.__VMEMMAP_BASE\n        elif \"4.17\" <= self.kversion < \"6.16\":\n            if self.CONFIG_DYNAMIC_MEMORY_LAYOUT:\n                return self.vmemmap_base\n            else:\n                return self.__VMEMMAP_BASE_L4\n        elif \"6.16\" <= self.kversion:\n            return self.vmemmap_base\n        return None\n\n    @property\n    def VMEMMAP_END(self):\n        if \"3.0\" <= self.kversion:\n            return self.VMEMMAP_START + self.SZ_1T\n        return None\n\n    @property\n    def MODULES_VADDR(self):\n        if \"3.0\" <= self.kversion < \"3.14\":\n            return 0xffff_ffff_a000_0000\n        elif \"3.14\" <= self.kversion:\n            return self.__START_KERNEL_map + self.KERNEL_IMAGE_SIZE\n        return None\n\n    @property\n    def VSYSCALL_START(self):\n        if \"3.0\" <= self.kversion < \"3.16\":\n            vsyscall_start = (-10 << 20)\n            return AddressUtil.align_address(vsyscall_start)\n        return None\n\n    @property\n    def VSYSCALL_END(self):\n        if \"3.0\" <= self.kversion < \"3.16\":\n            vsyscall_end = (-2 << 20)\n            return AddressUtil.align_address(vsyscall_end)\n        return None\n\n    @property\n    def VSYSCALL_ADDR(self):\n        if \"3.0\" <= self.kversion < \"3.16\":\n            return self.VSYSCALL_START\n        elif \"3.16\" <= self.kversion:\n            vsyscall_addr = (-10 << 20)\n            return AddressUtil.align_address(vsyscall_addr)\n        return None\n\n    @property\n    def FIXADDR_TOP(self):\n        if \"3.0\" <= self.kversion < \"3.16\":\n            return self.VSYSCALL_END - self.PAGE_SIZE\n        elif \"3.16\" <= self.kversion:\n            return self.round_up(self.VSYSCALL_ADDR + self.PAGE_SIZE, 1 << self.PMD_SHIFT) - self.PAGE_SIZE\n        return None\n\n    def __fix_to_virt(self, x):\n        return self.FIXADDR_TOP - (x << self.PAGE_SHIFT)\n\n    @property\n    def __end_of_permanent_fixed_addresses(self):\n        end = self.__end_of_fixed_addresses\n        if end is None:\n            return None\n        if \"3.0\" <= self.kversion < \"3.10\":\n            # (FIX_TBOOT_BASE), FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - int(self.CONFIG_INTEL_TXT) - 256\n        elif \"3.10\" <= self.kversion:\n            # (FIX_TBOOT_BASE), FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - int(self.CONFIG_INTEL_TXT) - 512\n        return None\n\n    @property\n    def __end_of_fixed_addresses(self):\n        return KernelAddressHeuristicFinder.get_end_of_fixed_addresses()\n\n    @property\n    def FIXADDR_SIZE(self):\n        if self.__end_of_permanent_fixed_addresses is None:\n            return None\n        return self.__end_of_permanent_fixed_addresses << self.PAGE_SHIFT\n\n    @property\n    def FIXADDR_START(self):\n        if self.FIXADDR_TOP is None:\n            return None\n        if self.FIXADDR_SIZE is None:\n            return None\n        return self.FIXADDR_TOP - self.FIXADDR_SIZE\n\n    @property\n    def MODULES_END(self):\n        if \"3.0\" <= self.kversion < \"4.12\":\n            return 0xffff_ffff_ff00_0000\n        elif \"4.12\" <= self.kversion < \"4.14\":\n            return self.__fix_to_virt(self.__end_of_fixed_addresses + 1)\n        elif \"4.14\" <= self.kversion < \"5.11\":\n            return 0xffff_ffff_ff00_0000\n        elif \"5.11\" <= self.kversion:\n            if not self.CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP:\n                return 0xffff_ffff_ff00_0000\n            else:\n                return 0xffff_ffff_fe00_0000\n        return None\n\n    @property # noqa\n    def MODULES_LEN(self):\n        if \"3.0\" <= self.kversion:\n            return self.MODULES_END - self.MODULES_VADDR\n        return None\n\n    @property\n    def P4D_SHIFT(self):\n        if \"4.12\" <= self.kversion:\n            if self.CONFIG_X86_5LEVEL:\n                return 39\n            else:\n                return self.PGDIR_SHIFT\n        return None\n\n    @property\n    def pgdir_shift(self):\n        if \"4.17\" <= self.kversion:\n            return 48\n        return None\n\n    @property\n    def PGDIR_SHIFT(self):\n        if \"3.0\" <= self.kversion < \"4.12\":\n            return 39\n        elif \"4.12\" <= self.kversion < \"4.17\":\n            if self.CONFIG_X86_5LEVEL:\n                return 48\n            else:\n                return 39\n        elif \"4.17\" <= self.kversion:\n            if self.CONFIG_X86_5LEVEL:\n                return self.pgdir_shift\n            else:\n                return 39\n        return None\n\n    @property\n    def PGDIR_SIZE(self):\n        return 1 << self.PGDIR_SHIFT\n\n    @property\n    def PMD_SHIFT(self):\n        return 21\n\n    @property\n    def ESPFIX_PGD_ENTRY(self):\n        if \"3.0\" <= self.kversion:\n            return -2\n        return None\n\n    @property\n    def ESPFIX_BASE_ADDR(self):\n        if \"3.0\" <= self.kversion < \"4.12\":\n            espfix_base_addr = self.ESPFIX_PGD_ENTRY << self.PGDIR_SHIFT\n            return AddressUtil.align_address(espfix_base_addr)\n        elif \"4.12\" <= self.kversion:\n            espfix_base_addr = self.ESPFIX_PGD_ENTRY << self.P4D_SHIFT\n            return AddressUtil.align_address(espfix_base_addr)\n        return None\n\n    @property # noqa\n    def ESPFIX_END(self):\n        if \"3.0\" <= self.kversion:\n            return self.ESPFIX_BASE_ADDR + 0x0000_0080_0000_0000\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_PGD(self):\n        if \"4.14\" <= self.kversion:\n            return -4\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_BASE(self):\n        if \"4.14\" <= self.kversion:\n            cpu_entry_area_base = self.CPU_ENTRY_AREA_PGD << self.P4D_SHIFT\n            return AddressUtil.align_address(cpu_entry_area_base)\n        return None\n\n    @property\n    def CPU_ENTRY_AREA_END(self):\n        if \"4.14\" <= self.kversion:\n            return self.CPU_ENTRY_AREA_BASE + 0x0000_0080_0000_0000\n        return None\n\n    @property # noqa\n    def EFI_VA_START(self):\n        if \"3.19\" <= self.kversion:\n            efi_va_start = -4 * (1 << 30)\n            return AddressUtil.align_address(efi_va_start)\n        return None\n\n    @property # noqa\n    def EFI_VA_END(self):\n        if \"3.19\" <= self.kversion:\n            efi_va_end = -68 * (1 << 30)\n            return AddressUtil.align_address(efi_va_end)\n        return None\n\n\nclass KernelConstsArm32(KernelConstsBase):\n    \"\"\"A class that manages arm32 constants by version.\"\"\"\n\n    PAGE_SHIFT = 12\n    PAGE_SIZE = 1 << PAGE_SHIFT\n\n    def __init__(self, version=None):\n        super().__init__(version)\n        return\n\n    @property\n    def CONFIG_PAGE_OFFSET(self):\n        if hasattr(self, \"cached_PAGE_OFFSET\"):\n            return self.cached_PAGE_OFFSET\n        kern_min = Kernel.get_maps()[0][0]\n        if 0xc000_0000 - 0x0100_0000 <= kern_min:\n            # 0xbf000000-0xc0000000 is kernel module area.\n            # Even if it is VMSPLIT_3G, this is used.\n            self.cached_PAGE_OFFSET = 0xc000_0000 # VMSPLIT_3G\n        elif 0xb000_0000 - 0x0100_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0xb000_0000 # VMSPLIT_3G_OPT\n        elif 0x8000_0000 - 0x0100_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0x8000_0000 # VMSPLIT_2G\n        elif 0x4000_0000 - 0x0100_0000 <= kern_min:\n            self.cached_PAGE_OFFSET = 0x4000_0000 # VMSPLIT_1G\n        return self.cached_PAGE_OFFSET\n\n    @property\n    def CONFIG_HIGHMEM(self):\n        addr = Symbol.get_ksymaddr(\"nr_free_highpages\")\n        return bool(addr)\n\n    @property\n    def CONFIG_THUMB2_KERNEL(self):\n        if hasattr(self, \"cached_CONFIG_THUMB2_KERNEL\"):\n            return self.cached_CONFIG_THUMB2_KERNEL\n        if is_in_kernel():\n            self.cached_CONFIG_THUMB2_KERNEL = current_arch.is_thumb()\n            return self.cached_CONFIG_THUMB2_KERNEL\n        return None\n\n    @property\n    def PMD_SHIFT(self):\n        return 21\n\n    @property\n    def PMD_SIZE(self):\n        return 1 << self.PMD_SHIFT\n\n    @property\n    def PAGE_OFFSET(self):\n        return self.CONFIG_PAGE_OFFSET\n\n    @property\n    def PAGE_OFFSET_END(self):\n        return self.high_memory\n\n    @property\n    def high_memory(self):\n        if hasattr(self, \"cached_high_memory\"):\n            return self.cached_high_memory\n\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --disable-color\")\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n        res = list(filter(lambda line: \"*\" not in line, res))\n\n        maps = []\n        for line in res:\n            line = line.split()\n            vaddr_start = int(line[0].split(\"-\")[0], 16)\n            if vaddr_start < self.PAGE_OFFSET:\n                continue\n            dic = {\n                \"vaddr_start\": vaddr_start,\n                \"vaddr_end\": int(line[0].split(\"-\")[1], 16),\n                \"paddr_start\": int(line[1].split(\"-\")[0], 16),\n                \"paddr_end\": int(line[1].split(\"-\")[1], 16),\n            }\n            Maps = collections.namedtuple(\"Maps\", dic.keys())\n            maps.append(Maps(*dic.values()))\n\n        physmap = maps[0]\n        for m in maps[1:]:\n            if physmap.vaddr_end != m.vaddr_start:\n                break\n            if physmap.paddr_end != m.paddr_start:\n                break\n            physmap = m\n\n        self.cached_high_memory = physmap.vaddr_end\n        return self.cached_high_memory\n\n    @property\n    def MODULES_VADDR(self):\n        if \"3.0\" <= self.kversion < \"3.8\":\n            if self.CONFIG_THUMB2_KERNEL is None:\n                return None\n            elif self.CONFIG_THUMB2_KERNEL is False:\n                return self.PAGE_OFFSET - 16 * 1024 * 1024\n            else:\n                return self.PAGE_OFFSET - 8 * 1024 * 1024\n        elif \"3.8\" <= self.kversion:\n            if self.CONFIG_THUMB2_KERNEL is None:\n                return None\n            elif self.CONFIG_THUMB2_KERNEL is False:\n                return self.PAGE_OFFSET - self.SZ_16M\n            else:\n                return self.PAGE_OFFSET - self.SZ_8M\n        return None\n\n    @property\n    def MODULES_END(self):\n        if self.CONFIG_HIGHMEM:\n            return self.PAGE_OFFSET - self.PMD_SIZE\n        else:\n            return self.PAGE_OFFSET\n\n    @property\n    def VMALLOC_OFFSET(self):\n        return 8 * 1024 * 1024\n\n    @property\n    def VMALLOC_START(self):\n        return (self.high_memory + self.VMALLOC_OFFSET) & ~(self.VMALLOC_OFFSET - 1)\n\n    @property\n    def VMALLOC_END(self):\n        if \"3.0\" <= self.kversion < \"3.3\":\n            return self.FIXADDR_START\n        elif \"3.3\" <= self.kversion < \"4.4\":\n            return 0xff00_0000\n        elif \"4.4\" <= self.kversion:\n            return 0xff80_0000\n        return None\n\n    @property\n    def DTB_START(self):\n        if \"5.10\" <= self.kversion:\n            return 0xff80_0000\n        return None\n\n    @property\n    def DTB_END(self):\n        if \"5.10\" <= self.kversion:\n            return 0xffc0_0000\n        return None\n\n    @property\n    def FIXADDR_START(self):\n        if self.kversion < \"3.16\":\n            return 0xfff0_0000\n        elif self.kversion < \"5.4\":\n            return 0xffc0_0000\n        else:\n            return 0xffc8_0000\n\n    @property\n    def FIXADDR_TOP(self):\n        if self.kversion < \"3.16\":\n            return 0xfffe_0000\n        elif self.kversion < \"3.19\":\n            return 0xffe0_0000\n        else:\n            return 0xfff0_0000\n\n    @property\n    def FIXADDR_SIZE(self):\n        return self.FIXADDR_TOP - self.FIXADDR_START\n\n    @property\n    def RESERVED_START(self):\n        return 0xffff_1000\n\n    @property\n    def RESERVED_END(self):\n        return 0xffff_8000\n\n    @property\n    def PHYS_OFFSET(self):\n        if hasattr(self, \"cached_PHYS_OFFSET\"):\n            return self.cached_PHYS_OFFSET\n\n        # When p2v and v2p are available, memstart_addr can be resolved without relying on symbols.\n        if self.PAGE_OFFSET is None:\n            return None\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo is None:\n            return None\n        phys_kbase = Kernel.v2p(kinfo.text_base)\n        if phys_kbase is None:\n            return None\n        cands = Kernel.p2v(phys_kbase)\n        linear_cands = [x for x in cands if self.PAGE_OFFSET <= x < self.PAGE_OFFSET_END]\n        if len(linear_cands) != 1:\n            return None\n        linear_kbase = linear_cands[0]\n        self.cached_PHYS_OFFSET = AddressUtil.align_address(phys_kbase - (linear_kbase - self.PAGE_OFFSET))\n        return self.cached_PHYS_OFFSET\n\n    @property\n    def mem_map(self):\n        if hasattr(self, \"cached_mem_map\"):\n            return self.cached_mem_map\n        self.cached_mem_map = KernelAddressHeuristicFinder.get_mem_map()\n        return self.cached_mem_map\n\n    @property\n    def mem_section(self):\n        if hasattr(self, \"cached_mem_section\"):\n            return self.cached_mem_section\n        self.cached_mem_section = KernelAddressHeuristicFinder.get_mem_section()\n        return self.cached_mem_section\n\n    @property\n    def CONFIG_FLATMEM(self):\n        return bool(self.mem_map)\n\n    @property\n    def CONFIG_SPARSEMEM(self):\n        return bool(self.mem_section)\n\n    @property\n    def MAX_PHYSMEM_BITS(self):\n        if self.CONFIG_SPARSEMEM:\n            return 36\n        return None\n\n    @property\n    def SECTION_SIZE_BITS(self):\n        if self.CONFIG_SPARSEMEM:\n            return 28\n        return None\n\n    @property\n    def SECTIONS_SHIFT(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.MAX_PHYSMEM_BITS - self.SECTION_SIZE_BITS\n        return 0\n\n    @property\n    def SECTIONS_WIDTH(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.SECTIONS_SHIFT\n        return 0\n\n    @property\n    def SECTIONS_PGOFF(self):\n        return 4 * 8 - self.SECTIONS_WIDTH\n\n    @property\n    def SECTIONS_PGSHIFT(self):\n        return self.SECTIONS_PGOFF * int(self.SECTIONS_WIDTH != 0)\n\n    @property\n    def SECTIONS_MASK(self):\n        return (1 << self.SECTIONS_WIDTH) - 1\n\n    @property\n    def SECTION_HAS_MEM_MAP(self):\n        return 1 << 1\n\n    @property\n    def SECTION_MAP_LAST_BIT(self):\n        if self.kversion < \"4.13\":\n            return 1 << 2\n        elif \"4.13\" <= self.kversion < \"5.3\":\n            return 1 << 3\n        elif \"5.3\" <= self.kversion < \"5.12\":\n            return 1 << 4\n        elif \"5.12\" <= self.kversion < \"6.0\":\n            return 1 << 5\n        elif \"6.0\" <= self.kversion:\n            return 1 << 4\n\n    @property\n    def SECTION_MAP_MASK(self):\n        return ~(self.SECTION_MAP_LAST_BIT - 1) & 0xffff_ffff\n\n    @property\n    def NR_MEM_SECTIONS(self):\n        if self.CONFIG_SPARSEMEM:\n            return 1 << self.SECTIONS_SHIFT\n        return None\n\n    @property\n    def PFN_SECTION_SHIFT(self):\n        if self.CONFIG_SPARSEMEM:\n            return self.SECTION_SIZE_BITS - self.PAGE_SHIFT\n        return None\n\n    @property\n    def PHYS_PFN_OFFSET(self):\n        return self.PHYS_OFFSET >> self.PAGE_SHIFT\n\n    @property\n    def CONFIG_PAGE_EXTENSION(self):\n        if \"3.19\" <= self.kversion:\n            addr = Symbol.get_ksymaddr(\"page_ext_init\")\n            return bool(addr)\n        return None\n\n    @property\n    def sizeof_mem_section(self):\n        if not self.CONFIG_SPARSEMEM:\n            return None\n\n        if self.CONFIG_PAGE_EXTENSION:\n            return current_arch.ptrsize * 4\n        return current_arch.ptrsize * 2\n\n    @property\n    def sizeof_struct_page(self):\n        if hasattr(self, \"cached_sizeof_struct_page\"):\n            return self.cached_sizeof_struct_page\n\n        if not (self.CONFIG_FLATMEM or self.CONFIG_SPARSEMEM):\n            return None\n\n        if self.PAGE_OFFSET is None or self.PHYS_PFN_OFFSET is None:\n            return None\n\n        ret = Kernel.get_page_virt_pair()\n        if not ret:\n            return None\n        page, vaddr = ret\n\n        pfn = ((vaddr - self.PAGE_OFFSET) >> self.PAGE_SHIFT) + self.PHYS_PFN_OFFSET\n\n        if self.CONFIG_FLATMEM:\n            base = self.mem_map\n            index = pfn - self.PHYS_PFN_OFFSET\n\n        else:\n            flags = read_int_from_memory(page)\n            section_id = (flags >> self.SECTIONS_PGSHIFT) & self.SECTIONS_MASK\n\n            ms = self.mem_section + self.sizeof_mem_section * section_id\n\n            section_mem_map = read_int_from_memory(ms)\n            if (section_mem_map & self.SECTION_HAS_MEM_MAP) == 0:\n                return None\n\n            base = section_mem_map & self.SECTION_MAP_MASK\n            if base == 0:\n                return None\n\n            index = pfn\n\n        delta = page - base\n        if delta < 0:\n            return None\n\n        if index <= 0:\n            return None\n\n        if (delta % index) != 0:\n            return None\n\n        size = delta // index\n        if size == 0:\n            return None\n\n        self.cached_sizeof_struct_page = size\n        return size\n\n\nclass KernelConstsArm64(KernelConstsBase):\n    \"\"\"A class that manages arm64 constants by version.\"\"\"\n\n    def __init__(self, version=None, kasan=None):\n        super().__init__(version)\n        self.kasan = kasan\n        assert \"3.7\" <= self.kversion # arm64 support start version\n        return\n\n    @Cache.cache_until_next\n    def TCR_EL1(self):\n        return get_register(\"$TCR_EL1\", use_mbed_exec=True)\n\n    @Cache.cache_until_next\n    def ID_AA64MMFR2_EL1(self):\n        return get_register(\"$ID_AA64MMFR2_EL1\", use_mbed_exec=True)\n\n    @property\n    def PAGE_SHIFT(self):\n        tcr = self.TCR_EL1()\n        if tcr is not None:\n            tg1 = (tcr >> 30) & 0b11\n            if tg1 == 0b01:\n                return 14\n            elif tg1 == 0b10:\n                return 12\n            elif tg1 == 0b11:\n                return 16\n        # fallback\n        return 12\n\n    @property\n    def PAGE_SIZE(self):\n        return 1 << self.PAGE_SHIFT\n\n    @property\n    def FEAT_LVA(self):\n        ID_AA64MMFR2_EL1 = self.ID_AA64MMFR2_EL1()\n        if ID_AA64MMFR2_EL1 is not None:\n            FEAT_LVA = ((ID_AA64MMFR2_EL1 >> 16) & 0b1111) == 0b0001\n        else:\n            FEAT_LVA = False\n        return FEAT_LVA\n\n    @property\n    def CONFIG_KASAN(self):\n        if self.kasan is not None:\n            return bool(self.kasan)\n        res = gdb.execute(\"ksymaddr-remote --quiet kasan_\", to_string=True)\n        self.kasan = bool(res)\n        return self.kasan\n\n    @property\n    def CONFIG_KASAN_SW_TAGS(self):\n        if \"5.4\" <= self.kversion:\n            return False # change if needed\n        return None\n\n    @property\n    def CONFIG_ARM64_16K_PAGES(self):\n        if \"6.9\" <= self.kversion:\n            return False # change if needed\n        return None\n\n    @property\n    def CONFIG_ARM64_64K_PAGES(self):\n        if \"3.7\" <= self.kversion:\n            return False # change if needed\n        return None\n\n    @property\n    def CONFIG_ARM64_VA_BITS(self):\n        tcr = self.TCR_EL1()\n        T1SZ = (tcr >> 16) & 0b111111\n        region_end = 2 ** 64\n        region_start = region_end - (2 ** (64 - T1SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        if self.FEAT_LVA:\n            return min(52, region_bits)\n        return region_bits\n\n    @property\n    def PTDESC_ORDER(self):\n        if \"6.15\" <= self.kversion:\n            return 3\n        return None\n\n    @property\n    def PTDESC_TABLE_SHIFT(self):\n        if \"6.15\" <= self.kversion:\n            return self.PAGE_SHIFT - self.PTDESC_ORDER\n        return None\n\n    def ARM64_HW_PGTABLE_LEVEL_SHIFT(self, n):\n        if \"4.4\" <= self.kversion < \"6.15\":\n            return (self.PAGE_SHIFT - 3) * (4 - n) + 3\n        elif \"6.15\" <= self.kversion:\n            return self.PTDESC_TABLE_SHIFT * (4 - n) + self.PTDESC_ORDER\n        return None\n\n    @property\n    def PMD_SHIFT(self):\n        if \"3.17\" <= self.kversion < \"4.4\":\n            return (self.PAGE_SHIFT - 3) * 2 + 3\n        elif \"4.4\" <= self.kversion:\n            return self.ARM64_HW_PGTABLE_LEVEL_SHIFT(2)\n        return None\n\n    @property\n    def PMD_SIZE(self):\n        if \"3.17\" <= self.kversion:\n            return 1 << self.PMD_SHIFT\n        return None\n\n    @property\n    def PUD_SHIFT(self):\n        if \"3.17\" <= self.kversion < \"4.4\":\n            return (self.PAGE_SHIFT - 3) * 3 + 3\n        elif \"4.4\" <= self.kversion:\n            return self.ARM64_HW_PGTABLE_LEVEL_SHIFT(1)\n        return None\n\n    @property\n    def PUD_SIZE(self):\n        if \"3.17\" <= self.kversion:\n            return 1 << self.PUD_SHIFT\n        return None\n\n    def _PAGE_END(self, va):\n        if \"5.4\" <= self.kversion:\n            _page_end = -(1 << (va - 1))\n            return AddressUtil.align_address(_page_end)\n        return None\n\n    def _PAGE_OFFSET(self, va):\n        if \"5.4\" <= self.kversion:\n            _page_offset = -(1 << va)\n            return AddressUtil.align_address(_page_offset)\n        return None\n\n    @property\n    def KASAN_SHADOW_SCALE_SHIFT(self):\n        if \"4.16\" <= self.kversion < \"5.0\":\n            if self.CONFIG_KASAN:\n                return 3\n        elif \"5.0\" <= self.kversion < \"5.11\":\n            # arch/arm64/Makefile\n            if self.CONFIG_KASAN_SW_TAGS:\n                return 4\n            else:\n                return 3\n        elif \"5.11\" <= self.kversion:\n            # arch/arm64/Makefile\n            if self.CONFIG_KASAN_SW_TAGS:\n                return 4\n            elif self.CONFIG_KASAN:\n                return 3\n            return None\n        return None\n\n    def _KASAN_SHADOW_START(self, va):\n        if \"5.4\" <= self.kversion:\n            return self.KASAN_SHADOW_END - (1 << (va - self.KASAN_SHADOW_SCALE_SHIFT))\n        return None\n\n    @property\n    def KASAN_SHADOW_OFFSET(self):\n        if \"5.4\" <= self.kversion < \"5.11\":\n            if not self.CONFIG_KASAN_SW_TAGS:\n                if self.VA_BITS == 48 or self.VA_BITS == 52:\n                    return 0xdfff_a000_0000_0000\n                elif self.VA_BITS == 47:\n                    return 0xdfff_d000_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xdfff_fe80_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xdfff_ffd0_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xdfff_fffa_0000_0000\n            else:\n                if self.VA_BITS == 48 or self.VA_BITS == 52:\n                    return 0xefff_9000_0000_0000\n                elif self.VA_BITS == 47:\n                    return 0xefff_c800_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xefff_fe40_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xefff_ffc8_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xefff_fff9_0000_0000\n        elif \"5.11\" <= self.kversion < \"6.10\":\n            if not self.CONFIG_KASAN_SW_TAGS:\n                if self.VA_BITS == 48 or self.VA_BITS == 52:\n                    return 0xdfff_8000_0000_0000\n                elif self.VA_BITS == 47:\n                    return 0xdfff_c000_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xdfff_fe00_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xdfff_ffc0_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xdfff_fff8_0000_0000\n            else:\n                if self.VA_BITS == 48 or self.VA_BITS == 52:\n                    return 0xefff_8000_0000_0000\n                elif self.VA_BITS == 47:\n                    return 0xefff_c000_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xefff_fe00_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xefff_ffc0_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xefff_fff8_0000_0000\n        elif \"6.10\" <= self.kversion:\n            if not self.CONFIG_KASAN_SW_TAGS:\n                if self.VA_BITS == 48 or (self.VA_BITS == 52 and not self.CONFIG_ARM64_16K_PAGES):\n                    return 0xdfff_8000_0000_0000\n                elif (self.VA_BITS == 47 or self.VA_BITS == 52) and self.CONFIG_ARM64_16K_PAGES:\n                    return 0xdfff_c000_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xdfff_fe00_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xdfff_ffc0_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xdfff_fff8_0000_0000\n            else:\n                if self.VA_BITS == 48 or (self.VA_BITS == 52 and not self.CONFIG_ARM64_16K_PAGES):\n                    return 0xefff_8000_0000_0000\n                elif (self.VA_BITS == 47 or self.VA_BITS == 52) and self.CONFIG_ARM64_16K_PAGES:\n                    return 0xefff_c000_0000_0000\n                elif self.VA_BITS == 42:\n                    return 0xefff_fe00_0000_0000\n                elif self.VA_BITS == 39:\n                    return 0xefff_ffc0_0000_0000\n                elif self.VA_BITS == 36:\n                    return 0xefff_fff8_0000_0000\n        return None\n\n    @property\n    def vabits_actual(self):\n        if \"5.4\" <= self.kversion < \"6.0\":\n            # stored at arch/arm64/kernel/head.S\n            if self.FEAT_LVA:\n                return 52\n            else:\n                return self.VA_BITS_MIN\n        elif \"6.0\" <= self.kversion < \"6.9\":\n            # stored at arch/arm64/kernel/head.S\n            if self.FEAT_LVA:\n                return self.VA_BITS\n            else:\n                return self.VA_BITS_MIN\n        elif \"6.9\" <= self.kversion:\n            if self.VA_BITS > 48:\n                tcr = self.TCR_EL1()\n                return (64 - ((tcr >> 16) & 63))\n            else:\n                return self.VA_BITS\n        return None\n\n    @property\n    def KASAN_SHADOW_START(self):\n        if \"4.4\" <= self.kversion < \"5.4\":\n            return self.VA_START\n        elif \"5.4\" <= self.kversion:\n            return self._KASAN_SHADOW_START(self.vabits_actual)\n        return None\n\n    @property\n    def KASAN_SHADOW_END(self):\n        if \"4.4\" <= self.kversion < \"4.6\":\n            return self.KASAN_SHADOW_START + (1 << (self.VA_BITS - 3))\n        elif \"4.6\" <= self.kversion < \"5.4\":\n            return self.KASAN_SHADOW_START + self.KASAN_SHADOW_SIZE\n        elif \"5.4\" <= self.kversion < \"5.11\":\n            if self.CONFIG_KASAN:\n                return (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET\n            else:\n                return self._PAGE_END(self.VA_BITS_MIN)\n        elif \"5.11\" <= self.kversion:\n            if self.CONFIG_KASAN or self.CONFIG_KASAN_SW_TAGS:\n                return (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET\n        return None\n\n    @property\n    def KASAN_SHADOW_SIZE(self):\n        if \"4.6\" <= self.kversion < \"4.16\":\n            if self.CONFIG_KASAN:\n                return 1 << (self.VA_BITS - 3)\n            else:\n                return 0\n        elif \"4.16\" <= self.kversion < \"5.4\":\n            if self.CONFIG_KASAN:\n                return 1 << (self.VA_BITS - self.KASAN_SHADOW_SCALE_SHIFT)\n            else:\n                return 0\n        return None\n\n    @property\n    def sizeof_struct_page(self):\n        return 0x40\n\n    @property\n    def STRUCT_PAGE_MAX_SHIFT(self):\n        if \"4.7\" <= self.kversion < \"4.20\":\n            return 6\n        elif \"4.20\" <= self.kversion:\n            return self.order_base_2(self.sizeof_struct_page)\n        return None\n\n    @property\n    def VMEMMAP_UNUSED_NPAGES(self):\n        if \"6.9\" <= self.kversion:\n            return (self._PAGE_OFFSET(self.vabits_actual) - self.PAGE_OFFSET) >> self.PAGE_SHIFT\n        return None\n\n    @property\n    def VMEMMAP_SHIFT(self):\n        if \"5.11\" <= self.kversion < \"6.9\":\n            return self.PAGE_SHIFT - self.STRUCT_PAGE_MAX_SHIFT\n        return None\n\n    @property\n    def VMEMMAP_RANGE(self):\n        if \"6.9\" <= self.kversion:\n            return self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET\n        return None\n\n    @property\n    def VMEMMAP_SIZE(self):\n        if \"3.17\" <= self.kversion < \"4.7\":\n            return self.ALIGN((1 << (self.VA_BITS - self.PAGE_SHIFT)) * self.sizeof_struct_page, self.PUD_SIZE)\n        elif \"4.7\" <= self.kversion < \"5.4\":\n            return 1 << (self.VA_BITS - self.PAGE_SHIFT - 1 + self.STRUCT_PAGE_MAX_SHIFT)\n        elif \"5.4\" <= self.kversion < \"5.11\":\n            return (self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET) >> (self.PAGE_SHIFT - self.STRUCT_PAGE_MAX_SHIFT)\n        elif \"5.11\" <= self.kversion < \"6.9\":\n            return (self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET) >> self.VMEMMAP_SHIFT\n        elif \"6.9\" <= self.kversion:\n            return (self.VMEMMAP_RANGE >> self.PAGE_SHIFT) * self.sizeof_struct_page\n        return None\n\n    @property\n    def VA_BITS(self):\n        if \"3.7\" <= self.kversion < \"3.12\":\n            return 39\n        elif \"3.12\" <= self.kversion < \"3.17\":\n            if self.CONFIG_ARM64_64K_PAGES:\n                return 42\n            else:\n                return 39\n        elif \"3.17\" <= self.kversion:\n            return self.CONFIG_ARM64_VA_BITS\n        return None\n\n    @property\n    def VA_START(self):\n        if \"4.4\" <= self.kversion < \"4.5\":\n            return 0xffff_ffff_ffff_ffff - (1 << self.VA_BITS) + 1\n        elif \"4.5\" <= self.kversion < \"4.9\":\n            va_start = 0xffff_ffff_ffff_ffff << self.VA_BITS\n            return AddressUtil.align_address(va_start)\n        elif \"4.9\" <= self.kversion < \"4.10\":\n            return 0xffff_ffff_ffff_ffff - (1 << self.VA_BITS) + 1\n        elif \"4.10\" <= self.kversion < \"4.13\":\n            va_start = 0xffff_ffff_ffff_ffff << self.VA_BITS\n            return AddressUtil.align_address(va_start)\n        elif \"4.13\" <= self.kversion < \"5.4\":\n            return 0xffff_ffff_ffff_ffff - (1 << self.VA_BITS) + 1\n        return None\n\n    @property\n    def PAGE_OFFSET(self):\n        if \"3.17\" <= self.kversion < \"4.4\":\n            page_offset = 0xffff_ffff_ffff_ffff << (self.VA_BITS - 1)\n            return AddressUtil.align_address(page_offset)\n        elif \"4.4\" <= self.kversion < \"4.5\":\n            return 0xffff_ffff_ffff_ffff - (1 << (self.VA_BITS - 1)) + 1\n        elif \"4.5\" <= self.kversion < \"4.9\":\n            page_offset = 0xffff_ffff_ffff_ffff << (self.VA_BITS - 1)\n            return AddressUtil.align_address(page_offset)\n        elif \"4.9\" <= self.kversion < \"4.10\":\n            return 0xffff_ffff_ffff_ffff - (1 << (self.VA_BITS - 1)) + 1\n        elif \"4.10\" <= self.kversion < \"4.13\":\n            page_offset = 0xffff_ffff_ffff_ffff << (self.VA_BITS - 1)\n            return AddressUtil.align_address(page_offset)\n        elif \"4.13\" <= self.kversion < \"5.4\":\n            return 0xffff_ffff_ffff_ffff - (1 << (self.VA_BITS - 1)) + 1\n        elif \"5.4\" <= self.kversion:\n            return self._PAGE_OFFSET(self.VA_BITS)\n        return None\n\n    @property\n    def PAGE_OFFSET_END(self):\n        if \"3.17\" <= self.kversion:\n            return self.PAGE_OFFSET + 2 ** (self.VA_BITS - 1) # no need to align\n        return None\n\n    @property # noqa\n    def KIMAGE_VADDR(self):\n        if \"4.6\" <= self.kversion:\n            return self.MODULES_END\n        return None\n\n    @property\n    def BPF_JIT_REGION_START(self):\n        if \"5.0\" <= self.kversion < \"5.4\":\n            return self.VA_START + self.KASAN_SHADOW_SIZE\n        elif \"5.4\" <= self.kversion < \"5.11\":\n            return self.KASAN_SHADOW_END\n        elif \"5.11\" <= self.kversion < \"5.15\":\n            return self._PAGE_END(self.VA_BITS_MIN)\n        return None\n\n    @property\n    def BPF_JIT_REGION_SIZE(self):\n        if \"5.0\" <= self.kversion < \"5.15\":\n            return self.SZ_128M\n        return None\n\n    @property\n    def BPF_JIT_REGION_END(self):\n        if \"5.0\" <= self.kversion < \"5.15\":\n            return self.BPF_JIT_REGION_START + self.BPF_JIT_REGION_SIZE\n        return None\n\n    @property\n    def MODULES_END(self):\n        if \"3.7\" <= self.kversion < \"4.6\":\n            return self.PAGE_OFFSET\n        elif \"4.6\" <= self.kversion:\n            return self.MODULES_VADDR + self.MODULES_VSIZE\n        return None\n\n    @property\n    def MODULES_VADDR(self):\n        if \"3.7\" <= self.kversion < \"4.6\":\n            return self.MODULES_END - self.SZ_64M\n        elif \"4.6\" <= self.kversion < \"5.0\":\n            return self.VA_START + self.KASAN_SHADOW_SIZE\n        elif \"5.0\" <= self.kversion < \"5.15\":\n            return self.BPF_JIT_REGION_END\n        elif \"5.15\" <= self.kversion:\n            return self._PAGE_END(self.VA_BITS_MIN)\n        return None\n\n    @property\n    def MODULES_VSIZE(self):\n        if \"4.6\" <= self.kversion < \"6.5\":\n            return self.SZ_128M\n        elif \"6.5\" <= self.kversion:\n            return self.SZ_2G\n        return None\n\n    @property\n    def VMEMMAP_START(self):\n        if \"3.17\" <= self.kversion < \"4.7\":\n            return self.VMALLOC_END + self.SZ_64K\n        elif \"4.7\" <= self.kversion < \"5.4\":\n            return self.PAGE_OFFSET - self.VMEMMAP_SIZE\n        elif \"5.4\" <= self.kversion < \"5.11\":\n            vmemmap_start = -self.VMEMMAP_SIZE - self.SZ_2M\n            return AddressUtil.align_address(vmemmap_start)\n        elif \"5.11\" <= self.kversion < \"6.9\":\n            vmemmap_start = -(1 << (self.VA_BITS - self.VMEMMAP_SHIFT))\n            return AddressUtil.align_address(vmemmap_start)\n        elif \"6.9\" <= self.kversion:\n            return self.VMEMMAP_END - self.VMEMMAP_SIZE\n        return None\n\n    @property\n    def VMEMMAP_END(self):\n        if \"3.17\" <= self.kversion < \"6.9\":\n            return self.VMEMMAP_START + self.VMEMMAP_SIZE\n        elif \"6.9\" <= self.kversion:\n            vmemmap_end = -self.SZ_1G\n            return AddressUtil.align_address(vmemmap_end)\n        return None\n\n    @property\n    def PCI_IO_SIZE(self):\n        if \"4.0\" <= self.kversion:\n            return self.SZ_16M\n        return None\n\n    @property\n    def PCI_IO_START(self):\n        if \"4.0\" <= self.kversion < \"6.9\":\n            return self.PCI_IO_END - self.PCI_IO_SIZE\n        elif \"6.9\" <= self.kversion:\n            return self.VMEMMAP_END + self.SZ_8M\n        return None\n\n    @property\n    def PCI_IO_END(self):\n        if \"4.0\" <= self.kversion < \"4.6\":\n            return self.MODULES_VADDR - self.SZ_2M\n        elif \"4.6\" <= self.kversion < \"4.7\":\n            return self.PAGE_OFFSET - self.SZ_2M\n        elif \"4.7\" <= self.kversion < \"5.10\":\n            return self.VMEMMAP_START - self.SZ_2M\n        elif \"5.10\" <= self.kversion < \"6.9\":\n            return self.VMEMMAP_START - self.SZ_8M\n        elif \"6.9\" <= self.kversion:\n            return self.PCI_IO_START + self.PCI_IO_SIZE\n        return None\n\n    @property # noqa\n    def FIXADDR_TOP(self):\n        if \"3.15\" <= self.kversion < \"4.0\":\n            return self.MODULES_VADDR - self.SZ_2M - self.PAGE_SIZE\n        elif \"4.0\" <= self.kversion < \"5.10\":\n            return self.PCI_IO_START - self.SZ_2M\n        elif \"5.10\" <= self.kversion < \"6.9\":\n            return self.VMEMMAP_START - self.SZ_32M\n        elif \"6.9\" <= self.kversion:\n            fixaddr_top = -self.SZ_8M\n            return AddressUtil.align_address(fixaddr_top)\n        return None\n\n    @property\n    def NR_FIX_BTMAPS(self):\n        if \"3.7\" <= self.kversion < \"4.4\":\n            if self.CONFIG_ARM64_64K_PAGES:\n                return 4\n            else:\n                return 64\n        elif \"4.4\" <= self.kversion:\n            return self.SZ_256K // self.PAGE_SIZE\n        return None\n\n    @property\n    def FIX_BTMAPS_SLOTS(self):\n        return 7\n\n    @property\n    def TOTAL_FIX_BTMAPS(self):\n        return self.NR_FIX_BTMAPS * self.FIX_BTMAPS_SLOTS\n\n    @property\n    def __end_of_permanent_fixed_addresses(self):\n        end = self.__end_of_fixed_addresses\n        if end is None:\n            return None\n        if \"3.14\" <= self.kversion < \"4.0\":\n            # FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - self.TOTAL_FIX_BTMAPS\n        elif \"4.0\" <= self.kversion < \"4.1\":\n            # FIX_BTMAP_BEGIN ~ FIX_BTMAP_END, FIX_TEXT_POKE0\n            return end - self.TOTAL_FIX_BTMAPS - 1\n        elif \"4.1\" <= self.kversion < \"4.6\":\n            # FIX_BTMAP_BEGIN ~ FIX_BTMAP_END\n            return end - self.TOTAL_FIX_BTMAPS\n        elif \"4.6\" <= self.kversion < \"6.9\":\n            # FIX_BTMAP_BEGIN ~ FIX_BTMAP_END, FIX_PTE ~ FIXPGD\n            return end - self.TOTAL_FIX_BTMAPS - 4\n        elif \"6.9\" <= self.kversion:\n            # FIX_BTMAP_BEGIN ~ FIX_BTMAP_END, FIX_PTE ~ FIXPGD\n            return end - self.TOTAL_FIX_BTMAPS - 5\n        return None\n\n    @property\n    def __end_of_fixed_addresses(self):\n        return KernelAddressHeuristicFinder.get_end_of_fixed_addresses()\n\n    @property\n    def FIXADDR_SIZE(self):\n        if self.__end_of_permanent_fixed_addresses is None:\n            return None\n        return self.__end_of_permanent_fixed_addresses << self.PAGE_SHIFT\n\n    @property\n    def FIXADDR_START(self):\n        if self.FIXADDR_TOP is None:\n            return None\n        if self.FIXADDR_SIZE is None:\n            return None\n        return self.FIXADDR_TOP - self.FIXADDR_SIZE\n\n    @property # noqa\n    def EARLYCON_IOBASE(self):\n        if \"3.7\" <= self.kversion < \"3.15\":\n            return self.MODULES_VADDR - self.SZ_4M\n        return None\n\n    @property\n    def VA_BITS_MIN(self):\n        if \"5.4\" <= self.kversion < \"6.9\":\n            if self.VA_BITS > 48:\n                return 48\n            else:\n                return self.VA_BITS\n        elif \"6.9\" <= self.kversion:\n            if self.VA_BITS > 48:\n                if self.CONFIG_ARM64_16K_PAGES:\n                    return 47\n                else:\n                    return 48\n            else:\n                return self.VA_BITS\n        return None\n\n    @property\n    def VMALLOC_START(self):\n        if \"3.17\" <= self.kversion < \"4.4\":\n            vmalloc_start = 0xffff_ffff_ffff_ffff << self.VA_BITS\n            return AddressUtil.align_address(vmalloc_start)\n        elif \"4.4\" <= self.kversion < \"4.6\":\n            if not self.CONFIG_KASAN:\n                return self.VA_START\n            else:\n                return self.KASAN_SHADOW_END + self.SZ_64K\n        elif \"4.6\" <= self.kversion:\n            return self.MODULES_END\n        return None\n\n    @property\n    def VMALLOC_END(self):\n        if \"3.17\" <= self.kversion < \"5.4\":\n            return self.PAGE_OFFSET - self.PUD_SIZE - self.VMEMMAP_SIZE - self.SZ_64K\n        elif \"5.4\" <= self.kversion < \"5.11\":\n            vmalloc_end = -self.PUD_SIZE - self.VMEMMAP_SIZE - self.SZ_64K\n            return AddressUtil.align_address(vmalloc_end)\n        elif \"5.11\" <= self.kversion < \"6.9\":\n            return self.VMEMMAP_START - self.SZ_256M\n        elif \"6.9\" <= self.kversion:\n            if self.VA_BITS == self.VA_BITS_MIN:\n                return self.VMEMMAP_START - self.SZ_8M\n            else:\n                return self.VMEMMAP_START + self.VMEMMAP_UNUSED_NPAGES * self.sizeof_struct_page - self.SZ_8M\n        return None\n\n    @property\n    def PHYS_MASK_SHIFT(self):\n        if \"6.12\" <= self.kversion:\n            return self.VA_BITS\n        return None\n\n    @property\n    def PHYS_MASK(self):\n        if \"6.12\" <= self.kversion:\n            return (1 << self.PHYS_MASK_SHIFT) - 1\n        return None\n\n    @property\n    def physmap_base(self):\n        if hasattr(self, \"cached_physmap_base\"):\n            return self.cached_physmap_base\n\n        if self.PAGE_OFFSET is None:\n            self.cached_physmap_base = None\n            return None\n\n        # physmap_base is used in KGDB mode when pseudo reading physical addresses without page walking.\n        # physmap_base is calculated as PAGE_OFFSET - PHYS_OFFSET, where PHYS_OFFSET is stored in memstart_addr.\n        # However, at this stage, p2v and v2p are not yet available, so they cannot be used to resolve memstart_addr.\n        # Therefore, the address of memstart_addr is obtained directly from the vmlinux symbols.\n\n        # Prevent recursion:\n        #   read_physmem -> kgdb_use_physmap -> get_ksymaddr -> pagewalk -> read_physmem -> ...\n        if not __gef_command_instances__[\"ksymaddr-remote\"].kallsyms:\n            # None does not cache, because kallsyms may be resolved later\n            return None\n\n        memstart_addr = Symbol.get_ksymaddr(\"memstart_addr\")\n        if memstart_addr is None:\n            self.cached_physmap_base = None\n            return None\n\n        PHYS_OFFSET = read_int_from_memory(memstart_addr)\n        if \"6.12\" <= self.kversion:\n            PHYS_OFFSET &= self.PHYS_MASK\n        self.cached_physmap_base = AddressUtil.align_address(self.PAGE_OFFSET - PHYS_OFFSET)\n        return self.cached_physmap_base\n\n    @property\n    def memstart_addr(self):\n        if hasattr(self, \"cached_memstart_addr\"):\n            return self.cached_memstart_addr\n\n        # When p2v and v2p are available, memstart_addr can be resolved without relying on symbols.\n        if self.PAGE_OFFSET is None:\n            return None\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo is None:\n            return None\n        phys_kbase = Kernel.v2p(kinfo.text_base)\n        if phys_kbase is None:\n            return None\n        cands = Kernel.p2v(phys_kbase)\n        linear_cands = [x for x in cands if self.PAGE_OFFSET <= x < self.PAGE_OFFSET_END]\n        if len(linear_cands) != 1:\n            return None\n        linear_kbase = linear_cands[0]\n        self.cached_memstart_addr = AddressUtil.align_address(phys_kbase - (linear_kbase - self.PAGE_OFFSET))\n        return self.cached_memstart_addr\n\n    @property\n    def PHYS_OFFSET(self):\n        return self.memstart_addr\n\n\nclass KernelAddressHeuristicFinder:\n    \"\"\"A class that heuristically finds a specific symbol in the kernel.\"\"\"\n\n    USE_DIRECTLY = True # for debug\n    USE_KSYSCTL = True # for debug\n    CONSTS = None\n\n    @staticmethod\n    def consts():\n        if KernelAddressHeuristicFinder.CONSTS:\n            return KernelAddressHeuristicFinder.CONSTS\n        if is_x86_64():\n            KernelAddressHeuristicFinder.CONSTS = KernelConstsX64()\n        elif is_x86_32():\n            KernelAddressHeuristicFinder.CONSTS = KernelConstsX86()\n        elif is_arm64():\n            KernelAddressHeuristicFinder.CONSTS = KernelConstsArm64()\n        elif is_arm32():\n            KernelAddressHeuristicFinder.CONSTS = KernelConstsArm32()\n        return KernelAddressHeuristicFinder.CONSTS\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_saved_command_line():\n        # Do not use Symbol.get_ksymaddr since this function is used to discover KPTI,\n        # because Symbol.get_ksymaddr uses a cache.\n\n        kversion = Kernel.kernel_version()\n\n        # plan 1 (available v2.6.28 or later)\n        if kversion and \"2.6.28\" <= kversion:\n            # This is OK since we are not looking for `saved_command_line` directly.\n            addr = Symbol.get_ksymaddr(\"cmdline_proc_show\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_current_task():\n        if not is_x86():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"current_task\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.1 or later)\n        if kversion and \"4.1\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"common_cpu_up\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True)\n                for x in g:\n                    if x < 0x100:\n                        continue\n                    if is_x86_64():\n                        if x & 0x7:\n                            continue\n                        if not AddressUtil.is_msb_on(x) and x > 0x10_0000:\n                            continue\n                    elif is_x86_32():\n                        if x & 0x3:\n                            continue\n                    return x\n\n        # plan 3 (available v2.5.33 or later)\n        if kversion and \"2.5.33\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"setup_arg_pages\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_qword_ptr_ds(res),\n                        KernelAddressHeuristicFinderUtil.x64_qword_ptr_gs(res, skip_msb_check=True),\n                        KernelAddressHeuristicFinderUtil.x64_qword_ptr_gs_rip_base(res, skip_msb_check=True),\n                    )\n                elif is_x86_32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res),\n                        KernelAddressHeuristicFinderUtil.x86_dword_ptr_fs(res, skip_msb_check=True),\n                    )\n                for x in g:\n                    if x < 0x100:\n                        continue\n                    if is_x86_64():\n                        if x & 0x7:\n                            continue\n                    elif is_x86_32():\n                        if x & 0x3:\n                            continue\n                    return x\n        return None\n\n    @staticmethod\n    def get_current_task_for_current_thread():\n        if is_arm32():\n            # plan 1 (from special register)\n            r = get_register(\"$TPIDRURO\")\n            if r and is_valid_addr(r):\n                return r\n            r = get_register(\"$TPIDRURO_S\")\n            if r and is_valid_addr(r):\n                return r\n\n            # plan 2 (from stack top)\n            # We need to consider the case where Linux and RTOS are running on different CPUs at the same time.\n            # If the stack is not the address the kernel expects to use, it should not be interpreted as a task.\n\n            # check if valid kernel address or not\n            current_thread_info = current_arch.sp & ~0x1fff\n            if current_thread_info < KernelAddressHeuristicFinder.get_PAGE_OFFSET():\n                return None\n\n            kversion = Kernel.kernel_version()\n            try:\n                \"\"\"\n                struct thread_info {\n                    unsigned long flags;\n                    int preempt_count;\n                    mm_segment_t addr_limit; // ~v5.14\n                    struct task_struct *task; // ~v5.17\n                    ...\n                }\n                \"\"\"\n                if kversion < \"5.15\":\n                    v = read_int_from_memory(current_thread_info + current_arch.ptrsize * 3)\n                    if v and is_valid_addr(v):\n                        return v\n                elif kversion < \"5.18\":\n                    v = read_int_from_memory(current_thread_info + current_arch.ptrsize * 2)\n                    if v and is_valid_addr(v):\n                        return v\n            except gdb.MemoryError:\n                # In some threads, $sp points to an invalid address.\n                return None\n        elif is_arm64():\n            # plan 1 (from special register)\n            return get_register(\"$SP_EL0\")\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_init_task():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"init_task\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # Detecting `init_task` is very difficult.\n        # This is because `init_task` itself is rarely used, while `init_task.tasks` is used in most cases.\n        # On x86/x64, only one case has been found where detection is stable.\n        # However, there appear to be cases where it cannot be detected.\n\n        # plan 2 (available v3.4 or later)\n        if kversion and \"3.4\" <= kversion:\n            if is_x86_64() or is_x86_32():\n                addr = Symbol.get_ksymaddr(\"do_exit\")\n                if addr:\n                    res = gdb.execute(\"x/600i {:#x}\".format(addr), to_string=True)\n                    if is_x86_64():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res)\n                    elif is_x86_32():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res)\n                    for x in g:\n                        # There are cases where init_pid_ns is falsely detected as init_task.\n                        # The initial value of kref is 2, so exclude this.\n                        if read_int_from_memory(x) == 2:\n                            continue\n                        return x\n\n        # On arm32/arm64, that pattern could not be found.\n        # However, there is a method to locate `current_task` with 100% stability on arm32/arm64\n        # using a special register.\n        # In addition, `init_task` is always located in the kernel .data section.\n        # Therefore, the following method is implemented:\n        # 1. Traverse the linked list `current_task.tasks` starting from `current_task`\n        #    and collect all task addresses.\n        # 2. Select the task with the smallest distance from the kernel .data section.\n        # This method can also be applied to x86/x64 as long as `current_task` can be obtained.\n\n        def get_offset_tasks(current_task):\n            # search for init_task->tasks\n            # On CPU1, the task list is doubly linked, but on others it is not.\n            # For example:\n            #   CPU1: cpu1_current_task <-> task1 <-> task2 <-> ... <-> cpu1_current_task\n            #   CPU2: cpu2_current_task  -> task1 <-> task2 <-> ... <-> cpu1_current_task\n            # Therefore, we should read one element at a time and verify the linkage.\n            for i in range(0x200):\n                offset_tasks = current_arch.ptrsize * i\n                current_task_tasks = current_task + offset_tasks\n                if not is_valid_addr(current_task_tasks):\n                    return None\n                task1 = read_int_from_memory(current_task_tasks)\n                if is_double_link_list(task1, min_len=5):\n                    return offset_tasks\n            return None\n\n        def get_task_list(task, offset_tasks):\n            pos = task + offset_tasks\n            task_list = [pos]\n            # validating candidate offset\n            while True:\n                pos = read_int_from_memory(pos)\n                if pos in task_list:\n                    break\n                task_list.append(pos)\n            return [x - offset_tasks for x in task_list]\n\n        # plan 3 (from current)\n        current = None\n        if is_arm64() or is_arm32():\n            current = KernelAddressHeuristicFinder.get_current_task_for_current_thread()\n        elif is_x86_64() or is_x86_32():\n            current_task = KernelAddressHeuristicFinder.get_current_task()\n            if current_task:\n                if AddressUtil.is_msb_on(current_task) and is_valid_addr(current_task):\n                    # no __per_cpu_offset\n                    current = read_int_from_memory(current_task)\n                else:\n                    # use __per_cpu_offset\n                    p = KernelAddressHeuristicFinder.get_per_cpu_offset()\n                    if p and is_valid_addr(p):\n                        cpu_base = read_int_from_memory(p)\n                        current_ptr = AddressUtil.align_address(cpu_base + current_task)\n                        current = read_int_from_memory(current_ptr)\n        if current:\n            offset_tasks = get_offset_tasks(current)\n            if offset_tasks:\n                task_list = get_task_list(current, offset_tasks)\n                kinfo = Kernel.get_kernel_layout()\n                min_distance_task = (None, 0xffff_ffff_ffff_ffff)\n                for task in task_list:\n                    distance = abs((kinfo.rw_base or kinfo.text_base) - task)\n                    if min_distance_task[1] > distance:\n                        min_distance_task = (task, distance)\n                if min_distance_task[0] is not None:\n                    return min_distance_task[0]\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_init_cred():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"init_cred\")\n            if x:\n                return x\n\n        # plan2 (from ktask)\n        res = gdb.execute(\"ktask --filter swapper/0 --no-pager\", to_string=True)\n        m = re.search(r\"offsetof\\(task_struct, cred\\): (0x\\w+)\", res)\n        if m:\n            cred_offset = int(m.group(1), 16)\n            line = res.strip().splitlines()[-1]\n            addr, _, _, name, *_ = line.split()\n            if name == \"swapper/0\":\n                task = int(addr, 16)\n                return read_int_from_memory(task + cred_offset)\n\n        # plan3 (from ktask, not swapper/0, just swapper)\n        res = gdb.execute(\"ktask --filter swapper --no-pager\", to_string=True)\n        m = re.search(r\"offsetof\\(task_struct, cred\\): (0x\\w+)\", res)\n        if m:\n            cred_offset = int(m.group(1), 16)\n            line = res.strip().splitlines()[-1]\n            addr, _, _, name, *_ = line.split()\n            if name == \"swapper\":\n                task = int(addr, 16)\n                return read_int_from_memory(task + cred_offset)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_init_net():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"init_net\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.35 or later)\n        if kversion and \"2.6.35\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"net_initial_ns\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n\n        # plan 3 (available v2.6.24 or later)\n        if kversion and \"2.6.24\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"netdev_boot_base\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    if not is_valid_addr(x):\n                        continue\n                    if read_cstring_from_memory(x) == \"%s%d\":\n                        continue\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_init_user_ns():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"init_user_ns\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.39 or later)\n        if kversion and \"2.6.39\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"has_capability\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_modules():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"modules\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.7.5 or later)\n        if kversion and \"3.7.5\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"find_module_all\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative_ldr(res),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_chrdevs():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"chrdevs\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.16.12 or later)\n        if kversion and \"2.6.17\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"chrdev_show\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_array4_base(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                    )\n                for x in g:\n                    if not is_valid_addr(x):\n                        continue\n                    for i in range(255):\n                        v = read_int_from_memory(x + current_arch.ptrsize * i)\n                        if not is_single_link_list(v):\n                            break\n                    else:\n                        # Case where all 255 entries meet the conditions\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_cdev_map():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"cdev_map\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.5.70 or later)\n        if kversion and \"2.5.70\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"cdev_del\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative_ldr(res),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sys_call_table_x64():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sys_call_table\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and \"6.6.26\" <= kversion:\n            # On x64, each entry is embedded in `x64_sys_call` as call instruction.\n            # So sys_call_table is no longer in use, but it still remains.\n            # We won't return yet because we may be able to detect this in plan 5.\n            pass\n\n        # plan 2 (available v4.6 ~ v6.6.26)\n        if kversion and \"4.6\" <= kversion < \"6.6.26\":\n            addr = Symbol.get_ksymaddr(\"do_syscall_64\")\n            if addr:\n                res = gdb.execute(\"x/40i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n                for x in g:\n                    return x\n\n        # plan 3 (available v4.2 ~ v4.13)\n        if kversion and \"4.2\" <= kversion < \"4.14\":\n            addr = Symbol.get_ksymaddr(\"entry_SYSCALL_64_fastpath\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n                for x in g:\n                    return x\n\n        # plan 4 (available v2.6.27 ~ v4.1)\n        if kversion and \"2.6.27\" <= kversion < \"4.2\":\n            addr = Symbol.get_ksymaddr(\"system_call_fastpath\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n                for x in g:\n                    return x\n\n        # plan 5 (search for the memory)\n        sys_read = Symbol.get_ksymaddr(\"__x64_sys_read\")\n        sys_write = Symbol.get_ksymaddr(\"__x64_sys_write\")\n        sys_open = Symbol.get_ksymaddr(\"__x64_sys_open\")\n        sys_close = Symbol.get_ksymaddr(\"__x64_sys_close\")\n        seq_to_find = p64(sys_read) + p64(sys_write) + p64(sys_open) + p64(sys_close)\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo and kinfo.ro_base:\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n            sys_call_table_offset = ro_data.find(seq_to_find)\n            if sys_call_table_offset >= 0:\n                return kinfo.ro_base + sys_call_table_offset\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sys_call_table_x32():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"x32_sys_call_table\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and kversion < \"5.4\":\n            # Not introduced\n            return None\n\n        if kversion and \"6.6.26\" <= kversion:\n            # On x64, each entry is embedded in `x32_sys_call` as call instruction.\n            # So x32_sys_call_table is no longer in use, and removed from 6.6.26.\n            return None\n\n        # plan 2 (available v5.4 or later)\n        if kversion and \"5.4\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"do_syscall_64\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res, skip=1)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sys_call_table_x86():\n        if not is_x86():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            if is_x86_64():\n                x = Symbol.get_ksymaddr(\"ia32_sys_call_table\")\n            elif is_x86_32():\n                x = Symbol.get_ksymaddr(\"sys_call_table\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and \"6.6.26\" <= kversion:\n            if is_x86_64():\n                # On x64, ia32_sys_call_table is removed from 6.6.26.\n                return None\n            else:\n                # On i386, each entry is embedded in `ia32_sys_call` as call instruction.\n                # So sys_call_table is no longer in use, but it still remains.\n                # We won't return yet because we may be able to detect this in plan 3.\n                pass\n\n        # plan 2 (available v2.6.24 ~ v6.6.26)\n        if kversion and \"6.6.7\" <= kversion < \"6.6.26\":\n            if is_x86_64():\n                # ia32_sys_call_table is still used, but no detection logic.\n                addr = None\n            else:\n                addr = Symbol.get_ksymaddr(\"do_int80_syscall_32\")\n        elif kversion and \"4.6\" <= kversion < \"6.6.7\":\n            addr = Symbol.get_ksymaddr(\"do_int80_syscall_32\")\n        elif kversion and \"4.4\" <= kversion < \"4.6\":\n            if is_x86_64():\n                addr = Symbol.get_ksymaddr(\"do_syscall_32_irqs_off\")\n            else:\n                addr = Symbol.get_ksymaddr(\"do_syscall_32_irqs_on\")\n        elif kversion and \"2.6.24\" <= kversion < \"4.4\":\n            addr = Symbol.get_ksymaddr(\"syscall_call\")\n        else:\n            addr = None\n        if addr:\n            res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n            elif is_x86_32():\n                g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_array4_base(res)\n            for x in g:\n                return x\n\n        # plan 3 (search for the memory)\n        sys_restart_syscall = Symbol.get_ksymaddr(\"sys_restart_syscall\")\n        sys_exit = Symbol.get_ksymaddr(\"sys_exit\")\n        sys_fork = Symbol.get_ksymaddr(\"sys_fork\")\n        sys_read = Symbol.get_ksymaddr(\"sys_read\")\n        if None not in [sys_restart_syscall, sys_exit, sys_fork, sys_read]:\n            if is_x86_64():\n                seq_to_find = p64(sys_restart_syscall) + p64(sys_exit) + p64(sys_fork) + p64(sys_read)\n            else:\n                seq_to_find = p32(sys_restart_syscall) + p32(sys_exit) + p32(sys_fork) + p32(sys_read)\n            kinfo = Kernel.get_kernel_layout()\n            if kinfo and kinfo.ro_base:\n                ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n                sys_call_table_offset = ro_data.find(seq_to_find)\n                if sys_call_table_offset >= 0:\n                    return kinfo.ro_base + sys_call_table_offset\n        return None\n\n    @staticmethod\n    def get_sys_call_table_arm32():\n        if not is_arm32():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sys_call_table\")\n            if x:\n                return x\n\n        # plan 2 (search for the memory)\n        sys_restart_syscall = Symbol.get_ksymaddr(\"sys_restart_syscall\")\n        sys_exit = Symbol.get_ksymaddr(\"sys_exit\")\n        sys_fork = Symbol.get_ksymaddr(\"sys_fork\")\n        sys_read = Symbol.get_ksymaddr(\"sys_read\")\n        if None not in [sys_restart_syscall, sys_exit, sys_fork, sys_read]:\n            seq_to_find = p32(sys_restart_syscall) + p32(sys_exit) + p32(sys_fork) + p32(sys_read)\n            kinfo = Kernel.get_kernel_layout()\n            # `sys_call_table` is embedded in the .text area even if `CONFIG_KALLSYMS_ALL=n`\n            if kinfo and kinfo.text_base:\n                text_data = read_memory(kinfo.text_base, kinfo.text_size)\n                sys_call_table_offset = text_data.find(seq_to_find)\n                if sys_call_table_offset >= 0:\n                    return kinfo.text_base + sys_call_table_offset\n        return None\n\n    @staticmethod\n    def get_sys_call_table_arm64():\n        if not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sys_call_table\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.7 or later)\n        if kversion and \"5.6\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"do_el0_svc\")\n        elif kversion and \"4.18\" <= kversion < \"5.6\":\n            addr = Symbol.get_ksymaddr(\"el0_svc_handler\")\n        elif kversion and \"3.7\" <= kversion < \"4.18\":\n            addr = Symbol.get_ksymaddr(\"el0_svc\")\n        else:\n            addr = None\n        if addr:\n            res = gdb.execute(\"x/100i {:#x}\".format(addr), to_string=True)\n            g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, read_valid=True)\n            for x in g:\n                return x\n\n        # plan 3 (search for the memory)\n        sys_io_setup = Symbol.get_ksymaddr(\"__arm64_sys_io_setup\")\n        sys_io_destroy = Symbol.get_ksymaddr(\"__arm64_sys_io_destroy\")\n        sys_io_submit = Symbol.get_ksymaddr(\"__arm64_sys_io_submit\")\n        sys_io_cancel = Symbol.get_ksymaddr(\"__arm64_sys_io_cancel\")\n        if None not in [sys_io_setup, sys_io_destroy, sys_io_submit, sys_io_cancel]:\n            seq_to_find = p64(sys_io_setup) + p64(sys_io_destroy) + p64(sys_io_submit) + p64(sys_io_cancel)\n            kinfo = Kernel.get_kernel_layout()\n            if kinfo and kinfo.ro_base:\n                ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n                sys_call_table_offset = ro_data.find(seq_to_find)\n                if sys_call_table_offset >= 0:\n                    return kinfo.ro_base + sys_call_table_offset\n        return None\n\n    @staticmethod\n    def get_sys_call_table_arm64_compat():\n        if not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"compat_sys_call_table\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.7 or later)\n        if kversion and \"5.6\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"do_el0_svc_compat\")\n        elif kversion and \"4.18\" <= kversion < \"5.6\":\n            addr = Symbol.get_ksymaddr(\"el0_svc_compat_handler\")\n        elif kversion and \"3.7\" <= kversion < \"4.18\":\n            addr = Symbol.get_ksymaddr(\"el0_svc_compat\")\n        else:\n            addr = None\n        if addr:\n            res = gdb.execute(\"x/100i {:#x}\".format(addr), to_string=True)\n            g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, read_valid=True)\n            for x in g:\n                return x\n\n        # plan 3 (search for the memory)\n        sys_restart_syscall = Symbol.get_ksymaddr(\"__arm64_sys_restart_syscall\")\n        sys_exit = Symbol.get_ksymaddr(\"__arm64_sys_exit\")\n        sys_fork = Symbol.get_ksymaddr(\"__arm64_sys_fork\")\n        sys_read = Symbol.get_ksymaddr(\"__arm64_sys_read\")\n        sys_write = Symbol.get_ksymaddr(\"__arm64_sys_write\")\n        sys_open = Symbol.get_ksymaddr(\"__arm64_compat_sys_open\")\n        if None not in [sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write, sys_open]:\n            seq_to_find = p64(sys_restart_syscall) + p64(sys_exit) + p64(sys_fork) + p64(sys_read) + p64(sys_write) + p64(sys_open)\n            kinfo = Kernel.get_kernel_layout()\n            if kinfo and kinfo.ro_base:\n                ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n                sys_call_table_offset = ro_data.find(seq_to_find)\n                if sys_call_table_offset >= 0:\n                    return kinfo.ro_base + sys_call_table_offset\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_per_cpu_offset():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"__per_cpu_offset\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.3 or later)\n        if kversion and \"3.3\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"nr_iowait_cpu\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res),\n                        KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res),\n                    )\n                elif is_x86_32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x86_dword_ptr_array4_base(res),\n                        KernelAddressHeuristicFinderUtil.x64_x86_dword_ptr_src(res),\n                    )\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    cpu0 = read_int_from_memory(x)\n                    if cpu0 and (cpu0 & 0xfff) == 0:\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_slab_caches():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"slab_caches\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.9 or later)\n        if kversion and \"4.9\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"slub_cpu_dead\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res, skip=1)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res, skip=1)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, skip=1)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n\n        # plan 3 (available v5.9 or later)\n        if kversion and \"5.9\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"find_mergeable\")\n            if addr:\n                res = gdb.execute(\"x/50i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt_add(res)\n                for x in g:\n                    return x\n\n        # plan 4 (available v4.10 or before and CONFIG_MEMCG=y)\n        if kversion and kversion < \"4.11\":\n            addr = Symbol.get_ksymaddr(\"memcg_update_all_caches\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n\n        # plan 5 (available v3.11 ~ v4.10 and CONFIG_SLABINFO=y)\n        if kversion and \"3.11\" <= kversion < \"4.11\":\n            addr = Symbol.get_ksymaddr(\"slab_next\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_any_const(res)\n                elif is_arm64():\n                    # TODO\n                    g = []\n                elif is_arm32():\n                    # TODO\n                    g = []\n                for x in g:\n                    return x\n\n        # plan 6 (available if CONFIG_SLAB=y)\n        addr = Symbol.get_ksymaddr(\"cache_reap\")\n        if addr:\n            res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n            elif is_x86_32():\n                # TODO\n                g = []\n            elif is_arm64():\n                # TODO\n                g = []\n            elif is_arm32():\n                g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res, skip=1)\n            for x in g:\n                return x\n\n        # plan 7 (available v2.6.24 ~ v3.10 and CONFIG_SLABINFO=y)\n        if kversion and \"2.6.24\" <= kversion < \"3.11\":\n            addrs = Symbol.get_ksymaddr_multiple(\"s_next\")\n            if addrs:\n                for s_next in addrs:\n                    res = gdb.execute(\"x/20i {:#x}\".format(s_next), to_string=True)\n                    if is_x86_64():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, read_valid=True)\n                    elif is_x86_32():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, read_valid=True)\n                    elif is_arm64():\n                        # TODO\n                        g = []\n                    elif is_arm32():\n                        # TODO\n                        g = []\n                    for x in g:\n                        v1 = read_int_from_memory(x)\n                        v2 = read_int_from_memory(x + current_arch.ptrsize)\n                        if is_valid_addr(v1) and is_valid_addr(v2):\n                            return x\n\n        # plan 8 (available v4.11 ~ v6.11)\n        if kversion and \"4.11\" <= kversion < \"6.12\":\n            addr = Symbol.get_ksymaddr(\"slab_caches_to_rcu_destroy_workfn\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for slab_mutex in g:\n                    for i in range(16):\n                        x = slab_mutex + current_arch.ptrsize * i\n                        if is_double_link_list(x, min_len=10):\n                            return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_slab_kset():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"slab_kset\")\n            if x:\n                return x\n\n        # plan 2\n        addr = Symbol.get_ksymaddr(\"sysfs_slab_add\")\n        if addr:\n            res = gdb.execute(\"x/100i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n            elif is_x86_32():\n                g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res)\n            elif is_arm64():\n                g = itertools.chain(\n                    KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res),\n                    KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res),\n                )\n            elif is_arm32():\n                g = itertools.chain(\n                    KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                    KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res),\n                    KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                )\n            for x in g:\n                if is_valid_addr(x):\n                    y = read_int_from_memory(x)\n                    if is_double_link_list(y):\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_modprobe_path():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"modprobe_path\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.modprobe\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_poweroff_cmd():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"poweroff_cmd\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.poweroff_cmd\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_core_pattern():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"core_pattern\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.core_pattern\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_phys_base():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"phys_base\")\n            if x:\n                return read_int_from_memory(x)\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.24 or later)\n        if kversion and \"2.6.24\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"secondary_startup_64\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                for x in g:\n                    return read_int_from_memory(x)\n\n        # plan 3 (available v2.6.25 ~ v5.5)\n        if kversion and \"2.6.25\" <= kversion < \"5.5\":\n            addr = Symbol.get_ksymaddr(\"arch_crash_save_vmcoreinfo\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                for x in g:\n                    s = read_cstring_from_memory(x)\n                    if not s:\n                        return read_int_from_memory(x)\n\n        # plan 4 (available v3.9 or later)\n        if kversion and \"3.9\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"__virt_addr_valid\")\n            if addr:\n                res = gdb.execute(\"x/50i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                for x in g:\n                    return read_int_from_memory(x)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_PAGE_OFFSET_base():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"page_offset_base\")\n            if x:\n                return x\n\n        # plan 2 (from pagewalk)\n        kinfo = Kernel.get_kernel_layout()\n        page_offset_base_raw = kinfo.maps[0][0]\n        ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n        ro_data = slice_unpack(ro_data, current_arch.ptrsize)\n        try:\n            index = ro_data.index(page_offset_base_raw)\n            return kinfo.ro_base + index * current_arch.ptrsize\n        except ValueError:\n            pass\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_PAGE_OFFSET():\n        return KernelAddressHeuristicFinder.consts().PAGE_OFFSET\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def _get_PAGE_OFFSET():\n        if is_x86_64():\n            # plan 1 (fixed address)\n            kversion = Kernel.kernel_version()\n            if kversion and kversion < \"4.8\":\n                # kASLR and Level5 pagetable is unsupported, so fixed address\n                return 0xffff_8800_0000_0000\n\n            # plan 2 (from get_PAGE_OFFSET_base)\n            page_offset_base = KernelAddressHeuristicFinder.get_PAGE_OFFSET_base()\n            if page_offset_base:\n                return read_int_from_memory(page_offset_base)\n\n            # plan 3 (from pagewalk)\n            kinfo = Kernel.get_kernel_layout()\n            if kinfo.maps and len(kinfo.maps) > 0:\n                page_offset_base_raw = kinfo.maps[0][0]\n                return page_offset_base_raw\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_PAGE_OFFSET_END():\n        return KernelAddressHeuristicFinder.consts().PAGE_OFFSET_END\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_VMALLOC_START():\n        return KernelAddressHeuristicFinder.consts().VMALLOC_START\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def _get_VMALLOC_START():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            vmalloc_base = Symbol.get_ksymaddr(\"vmalloc_base\")\n            if vmalloc_base:\n                return read_int_from_memory(vmalloc_base)\n\n        kversion = Kernel.kernel_version()\n        if is_x86_64():\n            # plan 2 (fixed address)\n            if kversion and kversion < \"4.8\":\n                # kASLR and Level5 pagetable is unsupported, so fixed address\n                return 0xffff_c900_0000_0000\n\n            # plan 3 (from get_PAGE_OFFSET_base)\n            page_offset_base = KernelAddressHeuristicFinder.get_PAGE_OFFSET_base()\n            if page_offset_base:\n                \"\"\"\n                [v6.13.9]\n                0xffffffff8d1f0198|+0x0018|+003: 0x0000000100000027  // ?\n                0xffffffff8d1f01a0|+0x0020|+004: 0xffff9d9080000000  // page_offset_base\n                0xffffffff8d1f01a8|+0x0028|+005: 0xffffaeed80000000  // vmalloc_base\n                0xffffffff8d1f01b0|+0x0030|+006: 0xffffec7a80000000  // vmemmap_base\n\n                [v6.2.8]\n                0xffffffffa5549a68|+0x0000|+000: 0xffffea0000000000  // vmemmap_base\n                0xffffffffa5549a70|+0x0008|+001: 0xffffc90000000000  // vmalloc_base\n                0xffffffffa5549a78|+0x0010|+002: 0xffff888000000000  // page_offset_base\n                0xffffffffa5549a80|+0x0018|+003: 0x0000002700000001  // ?\n                \"\"\"\n                page_offset_base_b = read_int_from_memory(page_offset_base - current_arch.ptrsize)\n                page_offset_base_0 = read_int_from_memory(page_offset_base)\n                page_offset_base_a = read_int_from_memory(page_offset_base + current_arch.ptrsize)\n                if page_offset_base_0 < page_offset_base_b:\n                    return page_offset_base_b\n                if page_offset_base_0 < page_offset_base_a:\n                    return page_offset_base_a\n\n        # plan 4 (from vmalloc-dump)\n        if kversion and \"5.2\" <= kversion:\n            res = gdb.execute(\"vmalloc-dump --quiet --no-pager --only-freed\", to_string=True)\n            \"\"\"\n            #    state  virtual address                       size               flags\n            0    freed  0x0000000000000001-0xffffc90000000000 0xffffc8ffffffffff\n            \"\"\"\n            if res:\n                res = Color.remove_color(res)\n                lines = res.splitlines()\n                if len(lines) >= 2:\n                    _, _, vrange, _, *_ = lines[1].split()\n                    s, e = vrange.split(\"-\")\n                    s = int(s, 16)\n                    e = int(e, 16)\n                    if s == 1:\n                        return e\n\n        # plan 5 (from vmalloc-dump and pagewalk)\n        if kversion and kversion < \"6.9\":\n            res = gdb.execute(\"vmalloc-dump --quiet --no-pager --only-used\", to_string=True)\n            \"\"\"\n            [vmalloc-dump; x64]\n            #    state  virtual address                       size               flags\n            0    in-use 0xffffa1c040000000-0xffffa1c040002000 0x2000             VM_IOREMAP\n\n            [pagewalk; x64]\n            0xffff9927bfe00000-0xffff9927bffe0000 0x1e0000 0x1000 480 [RW- KERN ACCESSED DIRTY]\n            0xffffa1c040000000-0xffffa1c040001000 0x1000   0x1000 1   [RW- KERN ACCESSED DIRTY]\n\n            [vmalloc-dump; x86]\n            #    state  virtual address                       size               flags\n            0    in-use 0x00000000e07e0000-0x00000000e07e2000 0x2000             VM_IOREMAP\n\n            [pagewalk; x86]\n            0x00000000c1b83000-0x00000000dffe0000 - 0x1e45d000 - - [RWX KERN]\n            0x00000000e07e0000-0x00000000e07e1000 - 0x1000     - - [RWX KERN]\n            \"\"\"\n            if res:\n                res = Color.remove_color(res)\n                lines = res.splitlines()\n                if len(lines) >= 2:\n                    _, _, vrange, _, *_ = lines[1].split()\n                    s, _ = vrange.split(\"-\")\n                    s = int(s, 16)\n\n                    # incontinuity check\n                    kinfo = Kernel.get_kernel_layout()\n                    prev = None\n                    for vstart, _, _ in kinfo.maps:\n                        if vstart == s:\n                            break\n                        prev = vstart\n\n                    if prev is not None:\n                        if is_64bit():\n                            mask = 0xffff_ff00_0000_0000\n                            if (prev & mask) != (s & mask):\n                                if (s & 0x0fff_ffff) == 0:\n                                    return s\n                        else:\n                            mask = 0xff00_0000\n                            if (prev & mask) != (s & mask):\n                                if (s & 0x0fff) == 0:\n                                    return s\n                    else:\n                        return s\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_VMALLOC_END():\n        return KernelAddressHeuristicFinder.consts().VMALLOC_END\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_VMEMMAP_START():\n        if is_x86_64() or is_arm64():\n            return KernelAddressHeuristicFinder.consts().VMEMMAP_START\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def _get_VMEMMAP_START():\n        if is_x86_64():\n            # plan 1 (fixed address)\n            kversion = Kernel.kernel_version()\n            if kversion and kversion < \"4.8\":\n                # kASLR and Level5 pagetable is unsupported, so fixed address\n                return 0xffff_ea00_0000_0000\n\n            # plan 2 (directly)\n            if KernelAddressHeuristicFinder.USE_DIRECTLY:\n                vmemmap_base = Symbol.get_ksymaddr(\"vmemmap_base\")\n                if vmemmap_base:\n                    return read_int_from_memory(vmemmap_base)\n\n            def get_min_page(r):\n                if r is None:\n                    return None\n                min_page = None\n                for x in r:\n                    x = int(x, 16)\n                    if not is_valid_addr(x):\n                        continue\n                    if min_page is None or x < min_page:\n                        min_page = x\n                return min_page\n\n            # plan 3 (from slub-dump / slub-tiny-dump)\n            allocator = Kernel.get_slab_type()\n            if allocator in [\"SLUB\", \"SLUB_TINY\"]:\n                command = {\"SLUB\": \"slub-dump --node --skip-sheaf\", \"SLUB_TINY\": \"slub-tiny-dump\"}[allocator]\n                for n in [8, 16, 32, 64, 128, 192, 256, 512]:\n                    ret = gdb.execute(\n                        \"{:s} --simple --no-pager --quiet kmalloc-{:d}\".format(command, n),\n                        to_string=True,\n                    )\n                    r = re.findall(r\"(?:active|partial|node) page: (0x\\S\\S+)\", Color.remove_color(ret))\n                    min_page = get_min_page(r)\n                    if min_page is not None:\n                        return min_page & 0xffff_ffff_c000_0000 # ~((1 << PUD_SHIFT) - 1)\n\n            # plan 4 (from slab-dump)\n            if allocator == \"SLAB\":\n                ret = gdb.execute(\"slab-dump --simple --no-pager --quiet kmalloc-256\", to_string=True)\n                r = re.findall(r\"node\\[\\d+\\]\\.slabs_(?:partial|full): (0x\\S+)\", Color.remove_color(ret))\n                min_page = get_min_page(r)\n                if min_page is not None:\n                    return min_page & 0xffff_ffff_c000_0000 # ~((1 << PUD_SHIFT) - 1)\n\n            # plan 5 (from slob-dump)\n            if allocator == \"SLOB\":\n                ret = gdb.execute(\"slob-dump --simple --large --no-pager --quiet\", to_string=True)\n                r = re.findall(r\"page: (0x\\S+)\", Color.remove_color(ret))\n                min_page = get_min_page(r)\n                if min_page is not None:\n                    return min_page & 0xffff_ffff_c000_0000 # ~((1 << PUD_SHIFT) - 1)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_VMEMMAP_END():\n        if is_x86_64() or is_arm64():\n            return KernelAddressHeuristicFinder.consts().VMEMMAP_END\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_end_of_fixed_addresses():\n        if not is_x86() and not is_arm64():\n            return\n\n        kversion = Kernel.kernel_version()\n\n        # plan 1 (available v2.6.27 ~)\n        if is_x86():\n            if kversion and \"2.6.27\" <= kversion:\n                addr = Symbol.get_ksymaddr(\"__native_set_fixmap\")\n                if addr:\n                    res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res, skip_msb_check=True)\n                    for x in g:\n                        return x\n\n        # plan 2 (available v3.19 ~)\n        if is_arm64():\n            if kversion and \"3.19\" <= kversion:\n                addr = Symbol.get_ksymaddr(\"__set_fixmap\")\n                if addr:\n                    res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                    g = KernelAddressHeuristicFinderUtil.aarch64_cmp_const(res, skip_msb_check=True)\n                    for x in g:\n                        if x <= 1:\n                            continue\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sizeof_cpu_entry_area():\n        if not is_x86_32():\n            return None\n\n        kversion = Kernel.kernel_version()\n        if kversion and \"4.14\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"get_cpu_entry_area\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_x86_imul_const(res, skip_msb_check=True)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_mem_section():\n        if not is_x86_32() and not is_arm32():\n            return None\n\n        # Since mem_map and mem_section are mutually exclusive, make sure that mem_map is not being used\n        if KernelAddressHeuristicFinder.get_mem_map() is not None:\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            addr = Symbol.get_ksymaddr(\"mem_section\")\n            if addr:\n                return addr\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.4.0 or later)\n        if kversion and \"2.4\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"free_pages\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_32():\n                    # 0xc12f491b <free_pages+27>:  mov    eax,DWORD PTR [eax*8-0x3d19e3a0]\n                    # gef> x/w -0x3d19e3a0\n                    # 0xc2e61c60 <mem_section>:       0xf708000f\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_array8_base(res)\n                elif is_arm32():\n                    # 0xc0501dd4 <free_pages+8>:   movw    r3, #45144      @ 0xb058\n                    # 0xc0501dd8 <free_pages+12>:  movt    r3, #49664      @ 0xc200\n                    # 0xc0501df0 <free_pages+36>:  movwcc  r2, #17344      @ 0x43c0\n                    # 0xc0501df4 <free_pages+40>:  movtcc  r2, #49707      @ 0xc22b\n                    # gef> x/w 0xc200b058\n                    # 0xc200b058 <__pv_phys_pfn_offset>:   0x00060000\n                    # gef> x/w 0xc22b43c0\n                    # 0xc22b43c0 <mem_section>:   0x00000000\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, allow_cc=True)\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if v and not is_valid_addr(v):\n                        continue\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_mem_map():\n        if not is_x86_32() and not is_arm32():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            addr = Symbol.get_ksymaddr(\"mem_map\")\n            if addr:\n                v = read_int_from_memory(addr)\n                if v != 0:\n                    return v\n                return None\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.4.0 or later)\n        if kversion and \"2.4\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"free_pages\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_32():\n                    g = itertools.chain(\n                        # 0xd3bf91d9 <free_pages+13>:  mov    ecx,DWORD PTR ds:0xd4f337c4\n                        # gef> x/w 0xd4f337c4\n                        # 0xd4f337c4 <mem_map>:   0xf67fe000\n                        KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res),\n                        KernelAddressHeuristicFinderUtil.x86_noptr_ds(res),\n                    )\n                elif is_arm32():\n                    g = itertools.chain(\n                        # 0xc049f880 <free_pages+8>:   movw    r3, #46272      @ 0xb4c0\n                        # 0xc049f884 <free_pages+12>:  movt    r3, #49625      @ 0xc1d9\n                        # gef> x/w 0xc1d9b4c0\n                        # 0xc1d9b4c0 <mem_map>:   0xcbdd9000\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if v != 0:\n                        return v\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_page_address_htable():\n        if not is_x86_32() and not is_arm32():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"page_address_htable\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.5.41 or later)\n        if kversion and \"2.5.41\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"set_page_address\")\n            if addr:\n                res = gdb.execute(\"x/40i {:#x}\".format(addr), to_string=True)\n                if is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_lea_reg_const(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    if is_double_link_list(x):\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_clocksource_tsc():\n        if not is_x86():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"clocksource_tsc\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.16.8 or later)\n        if kversion and \"4.16.8\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"mark_tsc_unstable.part.0\") or Symbol.get_ksymaddr(\"mark_tsc_unstable.cold\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\", skip=2)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"eax\", skip=1)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_clocksource_list():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"clocksource_list\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.21 or later / v2.6.32 or later)\n        if kversion and \"2.6.21\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"clocksource_enqueue\") or Symbol.get_ksymaddr(\"clocksource_resume\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_capability_hooks():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"capability_hooks\")\n            if x:\n                return x\n\n        # plan 2 nothing\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_n_tty_ops():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"n_tty_ops\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.6 or later)\n        if kversion and \"4.6\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"n_tty_inherit_ops\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_x86_dword_ptr_src(res),\n                        KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res),\n                    )\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_tty_ldiscs():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"tty_ldiscs\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.37 or later)\n        if kversion and \"2.6.37\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"tty_register_ldisc\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_array4_base(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    for i in range(2):\n                        v = read_int_from_memory(x + current_arch.ptrsize * i)\n                        if not is_valid_addr(v):\n                            continue\n                        if kversion < \"5.13\":\n                            w = read_int32_from_memory(v)\n                            if w == 0x00005403: # magic\n                                return x\n                        else:\n                            w = read_int_from_memory(v)\n                            if not is_valid_addr(w):\n                                continue\n                            s = read_cstring_from_memory(w) # name\n                            if s and len(s) > 2:\n                                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sysctl_table_root():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sysctl_table_root\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.4 or later)\n        if kversion and \"3.4\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"register_sysctl\") or Symbol.get_ksymaddr(\"register_sysctl_sz\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\")\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"e[a-d]x\")\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_selinux_state():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"selinux_state\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v5.0 ~ v6.3)\n        if kversion and \"5.0\" <= kversion < \"6.4\":\n            addr = Symbol.get_ksymaddr(\"show_sid\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\")\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"e[a-d]x\")\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_ldr_reg_const(res, \"r0\")\n                for x in g:\n                    if not is_valid_addr(x):\n                        continue\n                    if is_arm32():\n                        v = read_int32_from_memory(x)\n                        if is_valid_addr(v):\n                            return v\n                    else:\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_apparmor_enabled():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"apparmor_enabled\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.12 or later)\n        if kversion and \"4.12\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"param_get_aauint\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_apparmor_initialized():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"apparmor_initialized\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.12 or later)\n        if kversion and \"4.12\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"param_get_aauint\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res, skip=1)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res, skip=1)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res, skip=1)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, skip=1)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_kernel_locked_down():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"kernel_locked_down\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v5.4 or later)\n        if kversion and \"5.4\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"lock_kernel_down\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_tomoyo_enabled():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"tomoyo_enabled\")\n            if x:\n                return x\n\n        # plan 2 nothing\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_mmap_min_addr():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"mmap_min_addr\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"vm.mmap_min_addr\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available v4.19.27 or later)\n        if kversion and \"4.19.27\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"expand_downwards\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sysctl_unprivileged_userfaultfd():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sysctl_unprivileged_userfaultfd\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"vm.unprivileged_userfaultfd\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sysctl_unprivileged_bpf_disabled():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sysctl_unprivileged_bpf_disabled\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.unprivileged_bpf_disabled\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available v4.9.91 ~ v5.18.19)\n        if kversion and \"4.9.91\" <= kversion < \"5.19\":\n            addr = Symbol.get_ksymaddr(\"__do_sys_bpf\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_kptr_restrict():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"kptr_restrict\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.kptr_restrict\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available v4.15 or later)\n        if kversion and \"4.15\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"kallsyms_show_value\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sysctl_perf_event_paranoid():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sysctl_perf_event_paranoid\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.perf_event_paranoid\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available v4.15 or later)\n        if kversion and \"4.15\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"kallsyms_show_value\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res, skip=1)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res, skip=1)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res, skip=1)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, skip=1)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_dmesg_restrict():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"dmesg_restrict\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.dmesg_restrict\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available v3.11 or later)\n        if kversion and \"3.11\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"check_syslog_permissions\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_kexec_load_disabled():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"kexec_load_disabled\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.kexec_load_disabled\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_loadpin_enabled():\n        # plan 1 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.loadpin.enabled\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_loadpin_enforce():\n        # plan 1 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.loadpin.enforce\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_ptrace_scope():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"ptrace_scope\")\n            if x:\n                return x\n\n        # plan 2 (from ksysctl)\n        if KernelAddressHeuristicFinder.USE_KSYSCTL:\n            x = Kernel.get_ksysctl(\"kernel.yama.ptrace_scope\")\n            if x:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_vdso_image_64():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_image_64\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.2 or later)\n        if kversion and \"4.2\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"arch_setup_additional_pages\")\n            if addr:\n                res = gdb.execute(\"x/40i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\", read_valid=True)\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if read_memory(v, 4) == b\"\\x7fELF\":\n                        return x\n\n                # another pattern\n                # gef> |x/40i arch_setup_additional_pages | grep mov\n                # 0xffffffff82401030 <arch_setup_additional_pages>:    mov eax,DWORD PTR [rip+0x43738a] # 0xffffffff828383c0 <vdso64_enabled>\n                # 0xffffffff8240103e <arch_setup_additional_pages+14>: mov edx,DWORD PTR [rip+0x1ffb24] # 0xffffffff82600b68 <vdso_image_64+8>\n                g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                for x in g:\n                    if not is_valid_addr(x):\n                        continue\n                    for i in range(10):\n                        v = read_int_from_memory(x - current_arch.ptrsize * i)\n                        if not is_valid_addr(v):\n                            continue\n                        if read_memory(v, 4) == b\"\\x7fELF\":\n                            return x - current_arch.ptrsize * i\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_vdso_image_x32():\n        if not is_x86_64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_image_x32\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.2 or later)\n        if kversion and \"4.2\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"compat_arch_setup_additional_pages\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\", read_valid=True)\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if read_memory(v, 4) == b\"\\x7fELF\" and read_memory(v + 0x12, 1) == b\"\\x3e\": # Elf.Machine\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_vdso_image_32():\n        if not is_x86():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_image_32\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.2 or later)\n        if kversion and \"4.2\" <= kversion:\n            if is_x86_64():\n                addr = Symbol.get_ksymaddr(\"compat_arch_setup_additional_pages\")\n                if addr:\n                    res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rdi\", read_valid=True)\n                    for x in g:\n                        v = read_int_from_memory(x)\n                        if read_memory(v, 4) == b\"\\x7fELF\" and read_memory(v + 0x12, 1) == b\"\\x03\": # Elf.Machine\n                            return x\n            elif is_x86_32():\n                addr = Symbol.get_ksymaddr(\"arch_setup_additional_pages\")\n                if addr:\n                    # pattern 1\n                    res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"eax\", read_valid=True)\n                    for x in g:\n                        v = read_int_from_memory(x)\n                        if read_memory(v, 4) == b\"\\x7fELF\":\n                            return x\n                    # pattern 2\n                    res = gdb.execute(\"x/40i {:#x}\".format(addr), to_string=True)\n                    g2 = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res)\n                    for x in g2:\n                        if read_int_from_memory(x) == 0x1000:\n                            v = read_int_from_memory(x - 4)\n                            if read_memory(v, 4) == b\"\\x7fELF\":\n                                return x - 4\n        return None\n\n    @staticmethod\n    def get_vdso_info():\n        if not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_info\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # vdso_info is introduced from v5.8\n        if kversion < \"5.8\":\n            return None\n\n        # plan 2 (available v5.8 or later)\n        if kversion and \"5.8\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"__vdso_init\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                for x in g:\n                    return x\n\n        # plan 3 (from .rodata)\n        \"\"\"\n        static struct vdso_abi_info vdso_info[] __ro_after_init = {\n            [VDSO_ABI_AA64] = {\n                .name = \"vdso\",\n                .vdso_code_start = vdso_start,\n                .vdso_code_end = vdso_end,\n            },\n        \"\"\"\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.ro_base and kinfo.ro_size:\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n            pos = -1\n            while True:\n                # search for aligned ELF header from .rodata\n                pos = ro_data.find(b\"\\x7fELF\", pos + 1)\n                if pos == -1:\n                    break\n                if pos % get_pagesize() != 0:\n                    continue\n\n                # calc address of ELF header\n                if is_32bit():\n                    vdso_addr_byteseq = p32(kinfo.ro_base + pos)\n                else:\n                    vdso_addr_byteseq = p64(kinfo.ro_base + pos)\n\n                # search for it from .rodata again\n                pos2 = -1\n                while True:\n                    pos2 = ro_data.find(vdso_addr_byteseq, pos2 + 1)\n                    if pos2 == -1:\n                        break\n                    if pos2 % current_arch.ptrsize != 0:\n                        continue\n                    maybe_vdso_info = kinfo.ro_base + pos2\n                    maybe_vdso_info -= current_arch.ptrsize\n                    name = read_int_from_memory(maybe_vdso_info)\n                    if not is_valid_addr(name):\n                        continue\n                    if read_cstring_from_memory(name) == \"vdso\":\n                        return maybe_vdso_info\n        return None\n\n    @staticmethod\n    def get_vdso_lookup():\n        if not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_lookup\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # vdso_info is introduced until v5.8\n        if kversion and (kversion < \"5.3\" or \"5.8\" <= kversion):\n            return None\n\n        # plan 2 (available v5.3 or later)\n        if kversion and \"5.3\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"__vdso_init\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                for x in g:\n                    return x\n\n        # plan 3 (from .rodata)\n        \"\"\"\n        static struct __vdso_abi vdso_lookup[VDSO_TYPES] __ro_after_init = {\n            {\n                .name = \"vdso\",\n                .vdso_code_start = vdso_start,\n                .vdso_code_end = vdso_end,\n            },\n        \"\"\"\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.ro_base and kinfo.ro_size:\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n            pos = -1\n            while True:\n                # search for aligned ELF header from .rodata\n                pos = ro_data.find(b\"\\x7fELF\", pos + 1)\n                if pos == -1:\n                    break\n                if pos % get_pagesize() != 0:\n                    continue\n\n                # calc address of ELF header\n                if is_32bit():\n                    vdso_addr_byteseq = p32(kinfo.ro_base + pos)\n                else:\n                    vdso_addr_byteseq = p64(kinfo.ro_base + pos)\n\n                # search for it from .rodata again\n                pos2 = -1\n                while True:\n                    pos2 = ro_data.find(vdso_addr_byteseq, pos2 + 1)\n                    if pos2 == -1:\n                        break\n                    if pos2 % current_arch.ptrsize != 0:\n                        continue\n                    maybe_vdso_lookup = kinfo.ro_base + pos2\n                    maybe_vdso_lookup -= current_arch.ptrsize\n                    name = read_int_from_memory(maybe_vdso_lookup)\n                    if not is_valid_addr(name):\n                        continue\n                    if read_cstring_from_memory(name) == \"vdso\":\n                        return maybe_vdso_lookup\n        return None\n\n    @staticmethod\n    def get_vdso_start():\n        if not is_arm32() and not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso_start\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (from vdso_info or vdso_lookup)\n        if kversion and is_arm64():\n            if \"5.8\" <= kversion:\n                vdso_info = KernelAddressHeuristicFinder.get_vdso_info()\n            else:\n                vdso_info = KernelAddressHeuristicFinder.get_vdso_lookup()\n            if vdso_info and is_valid_addr(vdso_info):\n                vdso_name = read_int_from_memory(vdso_info)\n                if is_valid_addr(vdso_name):\n                    if \"vdso\" == read_cstring_from_memory(vdso_name):\n                        x = read_int_from_memory(vdso_info + current_arch.ptrsize)\n                        return x\n\n        # plan 3 (from .rodata)\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.ro_base and kinfo.ro_size:\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n            pos = -1\n            while True:\n                # search for aligned ELF header from .rodata\n                pos = ro_data.find(b\"\\x7fELF\", pos + 1)\n                if pos == -1:\n                    break\n                if pos % get_pagesize() == 0:\n                    return kinfo.ro_base + pos\n        return None\n\n    @staticmethod\n    def get_vdso32_start():\n        if not is_arm64():\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vdso32_start\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (from vdso_info or vdso_lookup)\n        if kversion:\n            if \"5.8\" <= kversion:\n                vdso_info = KernelAddressHeuristicFinder.get_vdso_info()\n            else:\n                vdso_info = KernelAddressHeuristicFinder.get_vdso_lookup()\n            if vdso_info:\n                vdso_info_2 = vdso_info + current_arch.ptrsize * 6\n                if vdso_info_2 and is_valid_addr(vdso_info_2):\n                    vdso_name = read_int_from_memory(vdso_info_2)\n                    if is_valid_addr(vdso_name):\n                        if \"vdso32\" == read_cstring_from_memory(vdso_name):\n                            x = read_int_from_memory(vdso_info_2 + current_arch.ptrsize)\n                            return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_file_systems():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"file_systems\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.5.7 or later)\n        if kversion and \"2.5.7\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"unregister_filesystem\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res, read_valid=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res, read_valid=True)\n                elif is_arm64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, read_valid=True),\n                        KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res, read_valid=True),\n                    )\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, read_valid=True),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res, read_valid=True),\n                    )\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_printk_rb_static():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"printk_rb_static\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v5.13 or later)\n        if kversion and \"5.13\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"kmsg_dump_rewind\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res, read_valid=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res, read_valid=True)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res, read_valid=True)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res, read_valid=True)\n                for x in g:\n                    return read_int_from_memory(x)\n\n        # plan 3 (available v5.10 or later)\n        if kversion and \"5.10\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"kmsg_dump_rewind_nolock\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res, read_valid=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res, read_valid=True)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res, read_valid=True)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res, read_valid=True)\n                for x in g:\n                    return read_int_from_memory(x)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_log_first_idx():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"log_first_idx\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # this is old dmesg structure\n        if kversion and \"5.10\" <= kversion:\n            return False\n\n        # plan 2 (available v3.5 or later)\n        if kversion and \"3.5\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"devkmsg_open\")\n            if addr:\n                res = gdb.execute(\"x/50i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_mov_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative_ldr(res),\n                    )\n                for x in g:\n                    v = read_int32_from_memory(x)\n                    if is_valid_addr(v):\n                        continue\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_log_next_idx():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"log_next_idx\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # this is old dmesg structure\n        if kversion and \"5.10\" <= kversion:\n            return False\n\n        # plan 2 (available v3.5 or later)\n        if kversion and \"3.5\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"kmsg_dump_rewind_nolock\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res, skip=1)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res)\n                    g = list(g)[::-1]\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res, skip=1)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt_ldr(res, skip=1),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative_ldr(res, skip=1),\n                    )\n                for x in g:\n                    v = read_int32_from_memory(x)\n                    if v == 0:\n                        continue\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get___log_buf():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"__log_buf\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # this is old dmesg structure\n        if kversion and \"5.10\" <= kversion:\n            return False\n\n        # plan 2 (available v3.5 or later)\n        if kversion and \"3.5\" <= kversion:\n            log_buf_len = KernelAddressHeuristicFinder.get_log_buf_len()\n            if log_buf_len:\n                # static char *log_buf = __log_buf;\n                # static u32 log_buf_len = __LOG_BUF_LEN;\n                if is_32bit():\n                    # pattern1 (x86): log_buf_len -> log_buf\n                    # 0xc1ba30b8|+0x0000|+000: 0x00040000\n                    # 0xc1ba30bc|+0x0004|+001: 0xc1cf7720  ->  0x00000000\n                    # pattern2 (ARM): log_buf -> log_buf_len\n                    # 0xc03d26dc|+0x0000|+000: 0xc03ec9f8  ->  0x00000000\n                    # 0xc03d26e0|+0x0004|+001: 0x00004000\n                    pattern = [4, -4]\n                elif is_64bit():\n                    # pattern1 (x64): log_buf_len -> log_buf\n                    # 0xffffffffaa240720|+0x0000|+000: 0x0000000000020000\n                    # 0xffffffffaa240728|+0x0008|+001: 0xffffffffaa2f87dc  ->  0x0000000000000000\n                    # pattern1 (ARM64): log_buf_len -> log_buf\n                    # 0xffff000011256c68|+0x0000|+000: 0x0000000000020000\n                    # 0xffff000011256c70|+0x0008|+001: 0xffff0000113f5350 <__log_buf>  ->  0x0000000000000000\n                    # pattern2 (x64): log_buf_len -> log_buf (no-padding)\n                    # 0xffffffffa5c476cc|+0x0000|+000: 0xa62e9cf400040000\n                    # 0xffffffffa5c476d4|+0x0008|+001: 0x00000000ffffffff (=0xffffffffa62e9cf4)\n                    # pattern3 (x64): log_buf -> log_buf_len\n                    # 0xffffffff81c1df48|+0x0008|+001: 0xffffffff81d98e20  ->  0x0000000000000000\n                    # 0xffffffff81c1df50|+0x0010|+002: 0xffffffff00040000 (=0x00040000)\n                    pattern = [8, 4, -8]\n                for diff in pattern:\n                    log_buf = log_buf_len + diff\n                    __log_buf = read_int_from_memory(log_buf)\n                    if is_valid_addr(__log_buf):\n                        return __log_buf\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_log_buf_len():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"log_buf_len\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # this is old dmesg structure\n        if kversion and \"5.10\" <= kversion:\n            return False\n\n        # plan 2 (available v3.17 or later)\n        if kversion and \"3.17\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"log_buf_len_get\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative_ldr(res),\n                    )\n                for x in g:\n                    v = read_int32_from_memory(x)\n                    if v and (v & 0xfff) == 0:\n                        return x\n\n        # plan 3 (available v3.5 or later)\n        if kversion and \"3.5\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"do_syslog\")\n            if addr:\n                res = gdb.execute(\"x/300i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_dword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    # TODO\n                    g = []\n                elif is_arm32():\n                    # TODO\n                    g = []\n                for x in g:\n                    v = read_int32_from_memory(x)\n                    if v and (v & 0xfff) == 0:\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_idt_base():\n        if is_x86():\n            if is_qemu_system():\n                res = gdb.execute(\"monitor info registers\", to_string=True)\n                idtr = re.search(r\"IDT\\s*=\\s*(\\w+) (\\w+)\", res)\n                base, _limit = [int(idtr.group(i), 16) for i in range(1, 3)]\n                return base\n            elif is_vmware():\n                res = gdb.execute(\"monitor r idtr\", to_string=True)\n                r = re.search(r\"idtr base=(\\w+) limit=(\\w+)\", res)\n                base = int(r.group(1), 16)\n                return base\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_gdt_base():\n        if is_x86():\n            if is_qemu_system():\n                res = gdb.execute(\"monitor info registers\", to_string=True)\n                gdtr = re.search(r\"GDT\\s*=\\s*(\\w+) (\\w+)\", res)\n                base, _limit = [int(gdtr.group(i), 16) for i in range(1, 3)]\n                return base\n            elif is_vmware():\n                res = gdb.execute(\"monitor r gdtr\", to_string=True)\n                r = re.search(r\"gdtr base=(\\w+) limit=(\\w+)\", res)\n                base = int(r.group(1), 16)\n                return base\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_tss_base():\n        if is_x86():\n            if is_qemu_system():\n                res = gdb.execute(\"monitor info registers\", to_string=True)\n                tr = re.search(r\"TR\\s*=\\s*(\\w+) (\\w+) (\\w+) (\\w+)\", res)\n                _trseg, base, _limit, _attr = [int(tr.group(i), 16) for i in range(1, 5)]\n                return base\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_ldt_base():\n        if is_x86():\n            if is_qemu_system():\n                res = gdb.execute(\"monitor info registers\", to_string=True)\n                ldtr = re.search(r\"LDT\\s*=\\s*(\\w+) (\\w+) (\\w+) (\\w+)\", res)\n                _seg, base, _limit, _attr = [int(ldtr.group(i), 16) for i in range(1, 5)]\n                return base\n            elif is_vmware():\n                # `monitor r ldtr` is buggy\n                return None\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_node_data():\n        # when CONFIG_NUMA=y (maybe)\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"node_data\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.17 or later)\n        if kversion and \"2.6.17\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"first_online_pgdat\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_qword_ptr_array_base(res),\n                        KernelAddressHeuristicFinderUtil.x64_lea_reg_const(res),\n                    )\n                elif is_x86_32():\n                    # TODO\n                    g = []\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    # TODO\n                    g = []\n                for x in g:\n                    \"\"\"\n                    node_data[]: 0xffffdfab1c1be0b8\n\n                    gef> telescope 0xffffdfab1c1be0b8\n                    0xffffdfab1c1be0b8|+0x0000|+000: 0xffff00007fbf09c0  ->  0x0000000000001600\n                    0xffffdfab1c1be0c0|+0x0008|+001: 0x0000000000000000\n                    0xffffdfab1c1be0c8|+0x0010|+002: 0x0000000000000000\n\n                    gef> telescope 0xffff00007fbf09c0\n                    0xffff00007fbf09c0|+0x0000|+000: 0x0000000000001600\n                    0xffff00007fbf09c8|+0x0008|+001: 0x0000000000001b80\n                    0xffff00007fbf09d0|+0x0010|+002: 0x0000000000002100\n                    0xffff00007fbf09d8|+0x0018|+003: 0x0000000000002680\n                    0xffff00007fbf09e0|+0x0020|+004: 0x0000000000000000\n                    0xffff00007fbf09e8|+0x0028|+005: 0x0000000000000000\n                    0xffff00007fbf09f0|+0x0030|+006: 0x0000000000000000\n                    0xffff00007fbf09f8|+0x0038|+007: 0x0000000000000000\n                    0xffff00007fbf0a00|+0x0040|+008: 0x0000000000000000\n                    0xffff00007fbf0a08|+0x0048|+009: 0x0000000000000000\n                    0xffff00007fbf0a10|+0x0050|+010: 0x0000000000000000\n                    0xffff00007fbf0a18|+0x0058|+011: 0xffff00007fbf09c0  ->  0x0000000000001600\n                    0xffff00007fbf0a20|+0x0060|+012: 0xffffdfab1ba8a540\n                    0xffff00007fbf0a28|+0x0068|+013: 0xffffdfab1ba8a4e0\n                    0xffff00007fbf0a30|+0x0070|+014: 0x0000003f000006e0\n                    0xffff00007fbf0a38|+0x0078|+015: 0x0000000000040000\n                    0xffff00007fbf0a40|+0x0080|+016: 0x0000000000077153\n                    0xffff00007fbf0a48|+0x0088|+017: 0x0000000000080000\n                    0xffff00007fbf0a50|+0x0090|+018: 0x0000000000080000\n                    0xffff00007fbf0a58|+0x0098|+019: 0x0000000000080000\n                    0xffff00007fbf0a60|+0x00a0|+020: 0x0000000000002000\n                    0xffff00007fbf0a68|+0x00a8|+021: 0xffffdfab1b792690  ->  0x0000000000414d44 ('DMA'?)\n                    \"\"\"\n                    v = read_int_from_memory(x)\n                    if not v or not is_valid_addr(v):\n                        continue\n                    # avoid false positive\n                    if is_double_link_list(x):\n                        continue\n                    # avoid false positive\n                    water_mark0 = read_int_from_memory(v)\n                    if water_mark0 > 0x0000_1000_0000_0000:\n                        continue\n                    # ok\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_node_data0():\n        # when CONFIG_NUMA=n\n        # This method can only be called when `get_node_data()` fails.\n\n        kversion = Kernel.kernel_version()\n\n        # plan 1 (available v2.6.17 or later)\n        if kversion and \"2.6.17\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"first_online_pgdat\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rax\")\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"eax\")\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                    )\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if v and is_valid_addr(v):\n                        continue\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_prog_idr():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"prog_idr\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.13 or later)\n        # In certain cases it may return `prog_idr_lock` instead of `prog_idr`.\n        # It was not possible to distinguish them because their structures are very similar.\n        # However, `prog_idr` and `prog_idr_lock` are placed consecutively.\n        # Even if there is a slight deviation, there is no problem because the member\n        # identification logic of the caller (`kbpf` command) works.\n        if kversion and \"4.13\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"bpf_prog_free_id.part.0\") or Symbol.get_ksymaddr(\"bpf_prog_free_id\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_map_idr():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"map_idr\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.13 or later)\n        # In certain cases it may return `map_idr_lock` instead of `map_idr`.\n        # It was not possible to distinguish them because their structures are very similar.\n        # However, `map_idr` and `map_idr_lock` are placed consecutively.\n        # Even if there is a slight deviation, there is no problem because the member\n        # identification logic of the caller (`kbpf` command) works.\n        if kversion and \"4.13\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"bpf_map_free_id\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_vmap_area_list():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"vmap_area_list\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n        if \"6.9\" <= kversion:\n            return None\n\n        # plan 2 (available v4.7~)\n        if kversion and \"4.7\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"register_vmap_purge_notifier\")\n            if addr:\n                res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                    \"\"\"\n                    x86 or x64\n\n                    [~v5.1] mm/vmalloc.c\n                    vmap_notify_list     # rarely leads to long lists\n                    vmap_area_list       <- here\n\n                    [v5.2~v6.8] mm/vmalloc.c\n                    vmap_notify_list     # rarely leads to long lists\n                    free_vmap_area_list  <- here (false positive)\n                    vmap_area_list       <- here\n                    \"\"\"\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                    \"\"\"\n                    arm32 or arm64\n\n                    [~v6.8] mm/vmalloc.c\n                    vmap_notify_list     # rarely leads to long lists\n                    vmap_area_list       <- here\n                    free_vmap_area_list\n                    \"\"\"\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    if is_x86():\n                        if kversion < \"5.2\":\n                            count = 1\n                        else:\n                            count = 2\n                    else:\n                        count = 1\n                    for i in range(16):\n                        a = x + current_arch.ptrsize * i\n                        if is_double_link_list(a, min_len=5):\n                            count -= 1\n                        if count == 0:\n                            return a\n\n        # plan 3 (available v3.10 ~ v6.3: vread, v6.4~: vread_iter)\n        if kversion and \"3.17\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"vread\") or Symbol.get_ksymaddr(\"vread_iter\")\n            if addr:\n                res = gdb.execute(\"x/100i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res, read_valid=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_cmp_const(res, read_valid=True)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    if is_double_link_list(x):\n                        return x\n\n        # plan 4 (available v4.10~)\n        if kversion and \"4.10\" <= kversion:\n            addrs = Symbol.get_ksymaddr_multiple(\"s_next\")\n            if addrs:\n                for s_next in addrs:\n                    res = gdb.execute(\"x/20i {:#x}\".format(s_next), to_string=True)\n                    if is_x86_64():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"rsi\")\n                    elif is_x86_32():\n                        g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, \"e.x\")\n                    elif is_arm64():\n                        g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res, read_valid=True)\n                    elif is_arm32():\n                        g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                    for x in g:\n                        if is_double_link_list(x):\n                            return x\n\n        # plan 5 (available v2.6.28 ~ v5.1)\n        if kversion and \"2.6.28\" <= kversion < \"5.2\":\n            addr = Symbol.get_ksymaddr(\"__insert_vmap_area\")\n            if addr:\n                res = gdb.execute(\"x/100i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res, read_valid=True)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_dword_ptr_ds(res, read_valid=True)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_ldr(res)\n                elif is_arm32():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.arm32_movw_movt(res),\n                        KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res),\n                    )\n                for x in g:\n                    if is_double_link_list(x):\n                        return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_free_vmap_area_list():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"free_vmap_area_list\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.2\":\n            return None\n\n        # plan 2 (available v4.7~; here, always True)\n        addr = Symbol.get_ksymaddr(\"register_vmap_purge_notifier\")\n        if addr:\n            res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                \"\"\"\n                x86 or x64\n\n                [v5.2~v6.8] mm/vmalloc.c\n                vmap_notify_list     # rarely leads to long lists\n                free_vmap_area_list  <- here\n                vmap_area_list\n\n                [v6.9~] mm/vmalloc.c\n                vmap_notify_list     # rarely leads to long lists\n                free_vmap_area_list  <- here\n                \"\"\"\n            elif is_x86_32():\n                g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n            elif is_arm64():\n                g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                \"\"\"\n                arm32 or arm64\n\n                [v5.2~v6.8] mm/vmalloc.c\n                vmap_notify_list     # rarely leads to long lists\n                vmap_area_list       <- here (false positive)\n                free_vmap_area_list  <- here\n\n                [v6.9~] mm/vmalloc.c\n                vmap_notify_list     # rarely leads to long lists\n                free_vmap_area_list  <- here\n                \"\"\"\n            elif is_arm32():\n                g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n            for x in g:\n                if is_arm32() or is_arm64():\n                    if kversion < \"6.9\":\n                        count = 2\n                    else:\n                        count = 1\n                else:\n                    count = 1\n                for i in range(16):\n                    a = x + current_arch.ptrsize * i\n                    if is_double_link_list(a, min_len=3):\n                        count -= 1\n                    if count == 0:\n                        return a\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_timer_bases():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"timer_bases\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.8 or later)\n        if kversion and \"4.8\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"run_timer_softirq\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True),\n                        KernelAddressHeuristicFinderUtil.x64_lea_reg_const(res, skip_msb_check=True),\n                    )\n                    g2 = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True)\n                    g2 = KernelAddressHeuristicFinderUtil.x64_x86_dword_ptr_src(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, skip_msb_check=True)\n                    g2 = []\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, skip_msb_check=True)\n                    g2 = []\n\n                __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n                if __per_cpu_offset:\n                    # pattern1: per_cpu\n                    # pattern1-a:\n                    # 0xffffffff8cf25b05 <run_timer_softirq+5>:  mov rdi,0x24b40 <-- timer_bases\n                    # pattern1-b:\n                    # 0xffffffffa440831e <run_timer_softirq+46>: lea rbx,[rax+0x22400]\n                    for x in g:\n                        if not is_valid_addr(x) and (x & 0x7) == 0:\n                            return x\n                else:\n                    # pattern2: not per_cpu\n                    # 0xffffffff8aa6e450 <run_timer_softirq>:    mov rax,QWORD PTR [rip+0x7cfba9] # 0xffffffff8b23e000 <jiffies_64>\n                    # 0xffffffff8aa6e457 <run_timer_softirq+7>:  cmp rax,QWORD PTR [rip+0x7ce92a] # 0xffffffff8b23cd88 <timer_bases+8>\n                    # 0xffffffff8aa6e474 <run_timer_softirq+36>: mov rdx,QWORD PTR [rip+0x7cfb85] # 0xffffffff8b23e000 <jiffies_64>\n                    # 0xffffffff8aa6e47b <run_timer_softirq+43>: mov rax,QWORD PTR [rip+0x7ce906] # 0xffffffff8b23cd88 <timer_bases+8>\n                    jiffies = KernelAddressHeuristicFinder.get_jiffies()\n                    addrs = [x for x in g2 if (is_valid_addr(x) and (not jiffies or jiffies != x))]\n                    if addrs:\n                        return min(addrs)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_hrtimer_bases():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"hrtimer_bases\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v4.8 or later)\n        if kversion and \"4.8\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"hrtimer_run_queues\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = itertools.chain(\n                        KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True),\n                        KernelAddressHeuristicFinderUtil.x64_x86_byte_ptr(res, skip_msb_check=True),\n                        KernelAddressHeuristicFinderUtil.x64_lea_reg_const(res, skip_msb_check=True),\n                    )\n                    g2 = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, skip_msb_check=True)\n                    g2 = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, skip_msb_check=True)\n                    g2 = []\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, skip_msb_check=True)\n                    g2 = []\n\n                __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n                if __per_cpu_offset:\n                    # pattern1: per_cpu\n                    # pattern1-a:\n                    # 0xffffffff9b127acb: mov rbx,0x27040 <-- hrtimer_bases\n                    # pattern1-b:\n                    # 0xffffffffa440b87d <hrtimer_run_queues+13>: test BYTE PTR [rax+0x25b90],0x1\n                    # The exact value is 0x25b80, but don't worry about a slight deviation.\n                    # pattern1-c:\n                    # 0xffffffff818f57b5 <hrtimer_run_queues+21>: lea rbx,[rax+0x1df00]\n                    for x in g:\n                        if not is_valid_addr(x) and (x & 0x7) == 0:\n                            return x\n                else:\n                    # pattern2: not per_cpu\n                    # 0xffffffffbb8668bc <hrtimer_run_queues+12>: mov rdx,0xffffffffbc046138\n                    # 0xffffffffbb8668c3 <hrtimer_run_queues+19>: mov rcx,0xffffffffbc046178\n                    # 0xffffffffbb8668ca <hrtimer_run_queues+26>: mov rsi,0xffffffffbc0460f8\n                    # 0xffffffffbb8668d1 <hrtimer_run_queues+33>: mov rdi,0xffffffffbc046048 <-- hrtimer_bases+8\n                    addrs = [x for x in g2 if is_valid_addr(x)]\n                    if addrs:\n                        return min(addrs)\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_jiffies():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"jiffies\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.6.18 or later)\n        if kversion and \"2.6.18\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"jiffies_read\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_ldr(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_pci_root_buses():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"pci_root_buses\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v2.5.71 or later)\n        if kversion and \"2.5.71\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"pci_find_next_bus\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x86_noptr_ds(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res, read_valid=True)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res, read_valid=True)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_ioport_resource():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"ioport_resource\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v3.3 or later)\n        if kversion and \"3.3\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"pci_scan_bus\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, r\"r\\w+\")\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res, r\"e\\w+\")\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    name_ptr = read_int_from_memory(x + 0x8 * 2) # sizeof(resource_size_t) == 8\n                    if name_ptr and is_valid_addr(name_ptr):\n                        name = read_cstring_from_memory(name_ptr)\n                        if name == \"PCI IO\":\n                            return x\n                    name_ptr = read_int_from_memory(x + 0x4 * 2) # sizeof(resource_size_t) == 4\n                    if name_ptr and is_valid_addr(name_ptr):\n                        name = read_cstring_from_memory(name_ptr)\n                        if name == \"PCI IO\":\n                            return x\n\n        # plan 3 (from .rodata)\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.ro_base and kinfo.ro_size and is_valid_addr(kinfo.ro_base):\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n            if kinfo.rw_base and kinfo.rw_size:\n                rw_data = read_memory(kinfo.rw_base, min(kinfo.rw_size, 0x1000000))\n            else:\n                rw_data = ro_data\n            pos = -1\n            while True:\n                # search for aligned string from .rodata\n                pos = ro_data.find(b\"PCI IO\\x00\", pos + 1)\n                if pos == -1:\n                    break\n\n                # calc address of ELF header\n                if is_32bit():\n                    addr_byteseq = p32(kinfo.ro_base + pos)\n                else:\n                    addr_byteseq = p64(kinfo.ro_base + pos)\n\n                # search for it from .data\n                pos2 = -1\n                while True:\n                    pos2 = rw_data.find(addr_byteseq, pos2 + 1)\n                    if pos2 == -1:\n                        break\n                    if pos2 % current_arch.ptrsize != 0:\n                        continue\n                    # TODO: How to find the exact value of sizeof(resource_size_t)\n                    if kinfo.rw_base and kinfo.rw_size:\n                        maybe_ioport_resource = kinfo.rw_base + pos2 - current_arch.ptrsize * 2\n                    else:\n                        maybe_ioport_resource = kinfo.ro_base + pos2 - current_arch.ptrsize * 2\n                    return maybe_ioport_resource\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_iomem_resource():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"iomem_resource\")\n            if x:\n                return x\n\n        # plan 2 (from ioport_resource)\n        x = KernelAddressHeuristicFinder.get_ioport_resource()\n        if x:\n            # offsetof(resource, name)\n            offset_name = None\n            name_ptr = read_int_from_memory(x + 0x8 * 2) # sizeof(resource_size_t) == 8\n            if name_ptr and is_valid_addr(name_ptr):\n                name = read_cstring_from_memory(name_ptr)\n                if name == \"PCI IO\":\n                    offset_name = 0x8 * 2\n            if offset_name is None:\n                name_ptr = read_int_from_memory(x + 0x4 * 2) # sizeof(resource_size_t) == 4\n                if name_ptr and is_valid_addr(name_ptr):\n                    name = read_cstring_from_memory(name_ptr)\n                    if name == \"PCI IO\":\n                        offset_name = 0x4 * 2\n\n            # find \"PCI mem\"\n            if offset_name is not None:\n                for i in range(-30, 30):\n                    diff = (current_arch.ptrsize * i)\n                    name_ptr = read_int_from_memory(x + diff)\n                    if name_ptr and is_valid_addr(name_ptr):\n                        name = read_cstring_from_memory(name_ptr)\n                        if name == \"PCI mem\":\n                            return x + diff - offset_name\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_db_list():\n        # need DMA_SHARED_BUFFER=y\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"db_list\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        # plan 2 (available v5.10 or later)\n        if kversion and \"5.10\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"dma_buf_file_release\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                for x in g:\n                    # here, x points &db_list.lock\n                    v = x - current_arch.ptrsize * 2\n                    if is_double_link_list(v):\n                        return v\n\n        # plan 3 (available v3.17 ~ v5.9)\n        if kversion and \"3.17\" <= kversion < \"5.10\":\n            addr = Symbol.get_ksymaddr(\"dma_buf_release\")\n            if addr:\n                res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_ldr_pc_relative(res)\n                for x in g:\n                    # here, x points &db_list.lock\n                    v = x - current_arch.ptrsize * 2\n                    if is_double_link_list(v):\n                        return v\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_irq_desc_tree():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"irq_desc_tree\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and \"6.5\" <= kversion:\n            return False\n\n        # plan 2 (available v2.6.37 ~ v6.4)\n        if kversion and \"2.6.37\" <= kversion < \"6.5\":\n            addr = Symbol.get_ksymaddr(\"irq_to_desc\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_sparse_irqs():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"sparse_irqs\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and kversion < \"6.5\":\n            return False\n\n        # plan 2 (available v6.5 or later)\n        if kversion and \"6.5\" <= kversion:\n            addr = Symbol.get_ksymaddr(\"irq_to_desc\")\n            if addr:\n                res = gdb.execute(\"x/20i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_x86_32():\n                    g = KernelAddressHeuristicFinderUtil.x64_x86_mov_reg_const(res)\n                elif is_arm64():\n                    g = KernelAddressHeuristicFinderUtil.aarch64_adrp_add(res)\n                elif is_arm32():\n                    g = KernelAddressHeuristicFinderUtil.arm32_movw_movt(res)\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_slub_tlbflush_queue():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"slub_tlbflush_queue\")\n            if x:\n                return x\n\n        # plan 2 (from slub_tlbflush_worker)\n        addr = Symbol.get_ksymaddr(\"slub_tlbflush_worker\")\n        if addr:\n            res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n            elif is_x86_32():\n                # TODO\n                g = []\n            elif is_arm64():\n                # TODO\n                g = []\n            elif is_arm32():\n                # TODO\n                g = []\n\n            for x in g:\n                return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_slub_addr_base():\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            x = Symbol.get_ksymaddr(\"slub_addr_base\")\n            if x:\n                return x\n\n        kversion = Kernel.kernel_version()\n        if not kversion:\n            return None\n\n        if kversion < \"6.6\":\n            # plan 2 (available in 6.1-based from `alloc_slab_pv_page`)\n            # bruteforces all accesses into global variables in `alloc_slab_pv_page`\n            # In source, `slub_addr_base` is referenced only by `alloc_slab_meta`, but\n            # compiler seems to inline this function (because calls once, maybe)\n            addr = Symbol.get_ksymaddr(\"alloc_slab_pv_page\")\n            if addr:\n                res = gdb.execute(\"x/200i {:#x}\".format(addr), to_string=True)\n                r\"\"\"\n                gef> |x/200i alloc_slab_pv_page| grep -i 'qword ptr \\[rip\\+.*\\]'\n                0xffffffff8901e65a <alloc_slab_pv_page+394>: mov    rsi,QWORD PTR [rip+0x162c627]\n                0xffffffff8901e672 <alloc_slab_pv_page+418>: sub    rax,QWORD PTR [rip+0x12ec317]\n                0xffffffff8901e6a8 <alloc_slab_pv_page+472>: and    rcx,QWORD PTR [rip+0x162c5e1]\n                0xffffffff8901e758 <alloc_slab_pv_page+648>: mov    rax,QWORD PTR [rip+0x15432c1] <- this\n                gef>\n                \"\"\"\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    # TODO\n                    g = []\n                elif is_arm64():\n                    # TODO\n                    g = []\n                elif is_arm32():\n                    # TODO\n                    g = []\n\n                for x in g:\n                    v = read_int_from_memory(x)\n                    if v in [0xffff_ffff_ffff_ffff, 0xffff_ffff_ffff_feff, 1]:\n                        continue\n                    # the value of `slub_addr_base` is unmapped address.\n                    if not is_valid_addr(v):\n                        return x\n        else:\n            # plan 3 (available in 6.6-based from vaddr_ranges_debug_start)\n            addr = Symbol.get_ksymaddr(\"vaddr_ranges_debug_start\")\n            if addr:\n                res = gdb.execute(\"x/8i {:#x}\".format(addr), to_string=True)\n                if is_x86_64():\n                    g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n                elif is_x86_32():\n                    # TODO\n                    g = []\n                elif is_arm64():\n                    # TODO\n                    g = []\n                elif is_arm32():\n                    # TODO\n                    g = []\n\n                for x in g:\n                    return x\n        return None\n\n    @staticmethod\n    @switch_to_intel_syntax\n    def get_slub_addr_current():\n        if Kernel.kernel_version() < \"6.6\":\n            return None\n\n        # plan 1 (directly)\n        if KernelAddressHeuristicFinder.USE_DIRECTLY:\n            addr = Symbol.get_ksymaddr(\"slub_addr_current\")\n            if addr:\n                return\n\n        # plan 2 (from vaddr_ranges_first_valid_slab)\n        addr = Symbol.get_ksymaddr(\"vaddr_ranges_first_valid_slab\")\n        if addr:\n            res = gdb.execute(\"x/10i {:#x}\".format(addr), to_string=True)\n            if is_x86_64():\n                g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res)\n            elif is_x86_32():\n                # TODO\n                g = []\n            elif is_arm64():\n                # TODO\n                g = []\n            elif is_arm32():\n                # TODO\n                g = []\n\n            for x in g:\n                return x\n        return None\n\n\nKF = KernelAddressHeuristicFinder # for convenience using from python-interactive # noqa: F841\nKFU = KernelAddressHeuristicFinderUtil # for convenience using from python-interactive # noqa: F841\n\n\nclass Kernel:\n    \"\"\"A collection of utility functions that are related to kernel specific features.\"\"\"\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_maps():\n        maps = []\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --simple --disable-color\")\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n        res = list(filter(lambda line: \"*\" not in line, res))\n\n        if is_x86():\n            for line in res:\n                line = line.split()\n                if line[6] != \"KERN]\":\n                    continue\n                vaddr = int(line[0].split(\"-\")[0], 16)\n                size = int(line[2], 16)\n                perm = line[5][1:] # [xxx\n                maps.append([vaddr, size, perm])\n\n        elif is_arm32():\n            for line in res:\n                line = line.split()\n                vaddr = int(line[0].split(\"-\")[0], 16)\n                if line[5] != \"[PL0/---\" and vaddr != 0xffff_0000:\n                    continue\n                size = int(line[2], 16)\n                perm = line[6][4:7] # PL1/xxx\n                maps.append([vaddr, size, perm])\n\n        elif is_arm64():\n            for line in res:\n                line = line.split()\n                if line[5] != \"[EL0/---\":\n                    continue\n                vaddr = int(line[0].split(\"-\")[0], 16)\n                size = int(line[2], 16)\n                perm = line[6][4:7] # EL1/xxx\n                maps.append([vaddr, size, perm])\n\n        elif is_riscv64() or is_riscv32():\n            for line in res:\n                line = line.split()\n                if line[6] != \"KERN]\":\n                    continue\n                vaddr = int(line[0].split(\"-\")[0], 16)\n                size = int(line[2], 16)\n                perm = line[5][1:] # [xxx\n                maps.append([vaddr, size, perm])\n\n        if len(maps) <= 1:\n            if is_x86():\n                warn(\"Make sure you are in ring0 (=kernel mode); See pagewalk\")\n            elif is_arm32():\n                warn(\"Make sure you are in supervisor mode (=kernel mode); See pagewalk\")\n                warn(\"Make sure qemu 3.x or higher\")\n            elif is_arm64():\n                warn(\"Make sure you are in EL1 (=kernel mode); See pagewalk\")\n                warn(\"Make sure qemu 3.x or higher\")\n            elif is_riscv64() or is_riscv32():\n                warn(\"Make sure you are in S-mode (=kernel mode); See pagewalk\")\n            return None\n        else:\n            return maps\n\n    # No caching intentionally\n    @staticmethod\n    def get_kernel_base_hint():\n\n        # This function is designed for the case where the symbol is not available.\n        # Do not use Symbol.get_ksymaddr.\n\n        if is_x86():\n            if is_qemu_system():\n                # [5.8~]\n                # 0   #DE: Divide-by-zero ... 0x0010:0xffffffff82c01030 <asm_exc_divide_error>\n                # [~5.7]\n                # 0   #DE: Divide-by-zero ... 0x0010:0xffffffff8178cfc0 <divide_error>\n                res = gdb.execute(\"idtinfo -n\", to_string=True)\n                r = re.search(r\"Divide-by-zero.+\\S+:(\\S+)\\s+<\", res)\n                if r:\n                    div0_handler = int(r.group(1), 16)\n                    if is_valid_addr(div0_handler):\n                        return div0_handler\n\n            elif is_vmware():\n                res = gdb.execute(\"monitor r idtr\", to_string=True)\n                r = re.search(r\"idtr base=(\\S+) limit=(\\S+)\", res)\n                if r:\n                    base = int(r.group(1), 16)\n                    limit = int(r.group(2), 16)\n                    idt_data = read_memory(base, min(limit + 1, current_arch.ptrsize * 2 * 256))\n                    entries = slice_unpack(idt_data, current_arch.ptrsize * 2)\n                    idt0 = IdtInfoCommand.idt_unpack(entries[0])\n                    div0_handler = idt0.offset\n                    if is_valid_addr(div0_handler):\n                        return div0_handler\n\n            elif is_kdb(): # not kgdb\n                r = Symbol.get_symbol_by_monitor(\"asm_exc_divide_error\")\n                if r:\n                    return r\n                r = Symbol.get_symbol_by_monitor(\"divide_error\")\n                if r:\n                    return r\n\n        elif is_arm64():\n            # `VBAR` register has interrupt vector address\n            vbar = get_register(\"$VBAR\") or get_register(\"$VBAR_EL1\")\n            if is_valid_addr(vbar):\n                return vbar\n\n        elif is_riscv32() or is_riscv64():\n            # `stvec` register has interrupt vector address\n            stvec = get_register(\"stvec\")\n            if is_valid_addr(stvec):\n                return stvec\n\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_kernel_layout():\n        dic = {\n            \"maps\": None,\n            \"text_base\": None,\n            \"text_size\": None,\n            \"text_end\": None,\n            \"ro_base\": None,\n            \"ro_size\": None,\n            \"ro_end\": None,\n            \"rw_base\": None,\n            \"rw_size\": None,\n            \"rw_end\": None,\n            \"rwx\": False,\n            \"has_none\": False,\n        }\n        Kinfo = collections.namedtuple(\"Kinfo\", dic.keys())\n\n        if is_kdb():\n            # no-symbol, but monitor may be used\n            dic[\"text_base\"] = Symbol.get_symbol_by_monitor(\"_stext\")\n            dic[\"text_end\"] = Symbol.get_symbol_by_monitor(\"_etext\")\n            if dic[\"text_base\"] and dic[\"text_end\"]:\n                dic[\"text_size\"] = dic[\"text_end\"] - dic[\"text_base\"]\n\n            dic[\"rw_base\"] = Symbol.get_symbol_by_monitor(\"_stext\")\n            dic[\"rw_end\"] = Symbol.get_symbol_by_monitor(\"_etext\")\n            if dic[\"rw_base\"] and dic[\"rw_end\"]:\n                dic[\"rw_size\"] = dic[\"rw_end\"] - dic[\"rw_base\"]\n\n            dic[\"ro_base\"] = Symbol.get_symbol_by_monitor(\"__start_rodata\")\n            dic[\"ro_end\"] = Symbol.get_symbol_by_monitor(\"__end_rodata_aligned\") or \\\n                            Symbol.get_symbol_by_monitor(\"__end_rodata\")\n            if dic[\"ro_base\"] and dic[\"ro_end\"]:\n                dic[\"ro_size\"] = dic[\"ro_end\"] - dic[\"ro_base\"]\n\n            dic[\"has_none\"] = None in dic.values()\n            return Kinfo(*dic.values())\n\n        if is_kgdb():\n            # use symbol\n            dic[\"text_base\"] = Symbol.get_ksymaddr(\"_stext\")\n            dic[\"text_end\"] = Symbol.get_ksymaddr(\"_etext\")\n            if dic[\"text_base\"] and dic[\"text_end\"]:\n                dic[\"text_size\"] = dic[\"text_end\"] - dic[\"text_base\"]\n\n            dic[\"rw_base\"] = Symbol.get_ksymaddr(\"_stext\")\n            dic[\"rw_end\"] = Symbol.get_ksymaddr(\"_etext\")\n            if dic[\"rw_base\"] and dic[\"rw_end\"]:\n                dic[\"rw_size\"] = dic[\"rw_end\"] - dic[\"rw_base\"]\n\n            dic[\"ro_base\"] = Symbol.get_ksymaddr(\"__start_rodata\")\n            dic[\"ro_end\"] = Symbol.get_ksymaddr(\"__end_rodata_aligned\") or \\\n                            Symbol.get_ksymaddr(\"__end_rodata\")\n            if dic[\"ro_base\"] and dic[\"ro_end\"]:\n                dic[\"ro_size\"] = dic[\"ro_end\"] - dic[\"ro_base\"]\n\n            dic[\"has_none\"] = None in dic.values()\n            return Kinfo(*dic.values())\n\n        # Could not find the maps, so fast return\n        dic[\"maps\"] = Kernel.get_maps()\n        if dic[\"maps\"] is None:\n            dic[\"has_none\"] = None in dic.values()\n            return Kinfo(*dic.values())\n\n        # 1a. search for the kernel base exact way\n        if is_x86():\n            div0_handler = Kernel.get_kernel_base_hint()\n            if div0_handler is not None:\n                for i, (vaddr, size, _perm) in enumerate(dic[\"maps\"]):\n                    if vaddr <= div0_handler < vaddr + size:\n                        dic[\"text_base\"] = vaddr\n                        dic[\"text_size\"] = size\n                        dic[\"text_end\"] = vaddr + size\n                        text_base_map_index = i\n                        break\n\n        elif is_arm64():\n            vbar = Kernel.get_kernel_base_hint()\n            if vbar is not None:\n                for i, (vaddr, size, _perm) in enumerate(dic[\"maps\"]):\n                    if vaddr <= vbar < vaddr + size:\n                        dic[\"text_base\"] = vaddr\n                        dic[\"text_size\"] = size\n                        dic[\"text_end\"] = vaddr + size\n                        text_base_map_index = i\n                        break\n\n        elif is_riscv64() or is_riscv32():\n            stvec = Kernel.get_kernel_base_hint()\n            if stvec is not None:\n                for i, (vaddr, size, _perm) in enumerate(dic[\"maps\"]):\n                    if vaddr <= stvec < vaddr + size:\n                        dic[\"text_base\"] = vaddr\n                        dic[\"text_size\"] = size\n                        dic[\"text_end\"] = vaddr + size\n                        text_base_map_index = i\n                        break\n\n        # 1b. search for the kernel base heuristic way\n        if dic[\"text_base\"] is None:\n            # .text is usually noticeably larger than other areas.\n            # It just determines this size heuristically and detects it, but it works well in most cases.\n            TEXT_REGION_MIN_SIZE = 0x100000\n\n            for i, (vaddr, size, perm) in enumerate(dic[\"maps\"]):\n                if perm == \"R-X\" and size >= TEXT_REGION_MIN_SIZE:\n                    dic[\"text_base\"] = vaddr\n                    dic[\"text_size\"] = size\n                    dic[\"text_end\"] = vaddr + size\n                    text_base_map_index = i\n                    break\n            else:\n                # not found, maybe old kernel\n                for i, (vaddr, size, perm) in enumerate(dic[\"maps\"]):\n                    if perm == \"RWX\" and size >= TEXT_REGION_MIN_SIZE:\n                        dic[\"text_base\"] = vaddr\n                        dic[\"text_size\"] = size\n                        dic[\"text_end\"] = vaddr + size\n                        text_base_map_index = i\n                        break\n                else:\n                    # Not found, so fast return\n                    dic[\"has_none\"] = None in dic.values()\n                    return Kinfo(*dic.values())\n\n        # 2a. search for the kernel RO base\n        # If the -enable-kvm option for qemu-system is not enabled,\n        # there might be multiple 'r-- but non-.rodata' regions between .text and .rodata.\n        #   [  .text    ]\n        #   [  .text    ]\n        #   [ ??? (r--) ]\n        #   [ ??? (r--) ]\n        #   [ ??? (r--) ]\n        #   [ .rodata   ] <- near the top of this area has \"Linux version\"\n        #   [ .rodata   ]\n        # In other words, .rodata may not be located immediately after .text.\n        # This has been observed on qemu with Debian 11 on x86_64.\n        # Therefore, detection based solely on location may produce incorrect results.\n        # As a result, detection also checks for the presence of the string \"Linux version\"\n        # near the beginning of the .rodata page.\n        for i, (vaddr, size, perm) in enumerate(dic[\"maps\"][text_base_map_index + 1:]):\n            if perm == \"R--\":\n                if dic[\"ro_base\"] is None:\n                    if not is_valid_addr(vaddr):\n                        continue\n                    data = read_memory(vaddr, get_pagesize())\n                    if b\"Linux version\" in data:\n                        dic[\"ro_base\"] = vaddr\n                        dic[\"ro_size\"] = size\n                        dic[\"ro_end\"] = vaddr + size\n                        ro_base_map_index = text_base_map_index + i\n                elif dic[\"ro_end\"] == vaddr:\n                    # merge contiguous region.\n                    # This is important because .rodata may be split into GLOBAL and non-GLOBAL areas.\n                    dic[\"ro_size\"] += size\n                    dic[\"ro_end\"] += size\n                    ro_base_map_index = text_base_map_index + i\n                else:\n                    break\n\n        # 2b. search for the kernel RO base by region size\n        # Some kernels do not have the string \"Linux version\" at the beginning of the .rodata.\n        #   [  .text    ]\n        #   [  .text    ]\n        #   [ ??? (r--) ]\n        #   [ ??? (r--) ]\n        #   [ ??? (r--) ]\n        #   [ .rodata   ] <- There is no \"Linux Version\" near the top of this area.\n        #   [ .rodata   ] <- but these .rodata total is large enough to determine .rodata.\n        #   [ .rodata   ]\n        if dic[\"ro_base\"] is None:\n            RO_REGION_MIN_SIZE = 0x100000\n            for i, (vaddr, size, perm) in enumerate(dic[\"maps\"][text_base_map_index + 1:]):\n                if perm == \"R--\":\n                    if dic[\"ro_base\"] is None:\n                        if size >= RO_REGION_MIN_SIZE:\n                            dic[\"ro_base\"] = vaddr\n                            dic[\"ro_size\"] = size\n                            dic[\"ro_end\"] = vaddr + size\n                            ro_base_map_index = text_base_map_index + i\n                    elif dic[\"ro_end\"] == vaddr:\n                        # merge contiguous region.\n                        # This is important because .rodata may be split into GLOBAL and non-GLOBAL areas.\n                        dic[\"ro_size\"] += size\n                        dic[\"ro_end\"] += size\n                        ro_base_map_index = text_base_map_index + i\n                    else:\n                        break\n\n        # 2c. search for the kernel RO base for old kernel\n        # If it can not detect .rodata, maybe it is an old kernel (32-bit?).\n        # Old kernel is no-NX, so .rodata is RWX.\n        # Detected .text range includes .rodata, so use heuristic search and split.\n        #   [  .text  ] <- maybe .text is larger than 0x8000 (it fails in certain cases if 0x7000)\n        #   [  .text  ]\n        #   [  .text  ]\n        #   [  .text  ] <- end of this area has [0x00, 0x00, 0x00, ...]\n        #   [ .rodata ] <- near the top of this area has \"Linux version\"\n        #   [ .rodata ]\n        #   [ .rodata ]\n        if dic[\"ro_base\"] is None:\n            dic[\"rwx\"] = True\n            start = dic[\"text_base\"] + get_pagesize() * 8\n            end = dic[\"text_base\"] + dic[\"text_size\"]\n            block_size = 0x20\n            zero_data = b\"\\0\" * block_size\n            for addr in range(start, end, get_pagesize()):\n                data_prev = read_memory(addr - block_size, block_size)\n                if data_prev == zero_data:\n                    data = read_memory(addr, get_pagesize())\n                    if b\"Linux version\" in data:\n                        dic[\"ro_base\"] = addr\n                        dic[\"ro_size\"] = end - addr\n                        dic[\"ro_end\"] = end\n                        dic[\"text_size\"] -= dic[\"ro_size\"]\n                        # In this case, rw_base is not detected.\n                        # This is because ksymaddr-remote appears to provide better results.\n                        dic[\"rw_base\"] = 0\n                        dic[\"rw_size\"] = 0\n                        dic[\"rw_end\"] = 0\n                        break\n            else:\n                # Not found, so fast return\n                dic[\"has_none\"] = None in dic.values()\n                return Kinfo(*dic.values())\n\n        else:\n            # 3. Search for the kernel RW base.\n            # If ro_base can be detected, the RW area is searched starting after ro_base.\n            # TODO: A fixed size is currently used, but better algorithms may exist.\n            RW_REGION_MIN_SIZE = 0x20000\n            if dic[\"ro_base\"] is not None:\n                for vaddr, size, perm in dic[\"maps\"][ro_base_map_index + 1:]:\n                    if perm == \"RW-\":\n                        if dic[\"rw_base\"] is None:\n                            if size >= RW_REGION_MIN_SIZE:\n                                dic[\"rw_base\"] = vaddr\n                                dic[\"rw_size\"] = size\n                                dic[\"rw_end\"] = vaddr + size\n                                break\n\n        dic[\"has_none\"] = None in dic.values()\n        return Kinfo(*dic.values())\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_kernel_base():\n\n        def resolve_syms_safely(syms):\n            for sym in syms:\n                try:\n                    return to_unsigned_long(gdb.parse_and_eval(sym))\n                except gdb.error:\n                    pass\n            return None\n\n        # kdb specific\n        if is_kdb():\n            return Symbol.get_symbol_by_monitor(\"_stext\")\n\n        # fast path\n        hint = Kernel.get_kernel_base_hint()\n        if hint: # invalid if arm32\n            stext = resolve_syms_safely([\"_stext\"])\n            if stext:\n                handler = None\n                if is_x86():\n                    handler = resolve_syms_safely([\"asm_exc_divide_error\", \"divide_error\"])\n                elif is_arm64():\n                    handler = resolve_syms_safely([\"vectors\"])\n                elif is_riscv32() or is_riscv64():\n                    handler = resolve_syms_safely([\"handle_exception\"])\n                if handler:\n                    diff = hint - handler\n                    if diff & get_pagesize_mask_low() == 0:\n                        return stext - diff\n\n        if is_kgdb():\n            # Kernel.get_kernel_layout is too slow, so return if not found with fast path\n            return None\n\n        # slow path\n        kinfo = Kernel.get_kernel_layout()\n        return kinfo.text_base\n\n    class KernelVersion:\n        def __init__(self, address, version_string, major, minor, patch):\n            self.address = address\n            self.version_string = version_string\n            self.major = major\n            self.minor = minor\n            self.patch = patch\n            self.version_tuple = (major, minor, patch)\n            return\n\n        def to_version_tuple(self, _v):\n            v = _v.split(\".\")\n            if len(v) == 2:\n                return (int(v[0]), int(v[1]), 0)\n            elif len(v) == 3:\n                return (int(v[0]), int(v[1]), int(v[2]))\n            raise\n\n        def __ge__(self, v):\n            return self.to_version_tuple(v) <= self.version_tuple\n\n        def __gt__(self, v):\n            return self.to_version_tuple(v) < self.version_tuple\n\n        def __le__(self, v):\n            return self.to_version_tuple(v) >= self.version_tuple\n\n        def __lt__(self, v):\n            return self.to_version_tuple(v) > self.version_tuple\n\n        def __eq__(self, v):\n            return self.to_version_tuple(v) == self.version_tuple\n\n        def __ne__(self, v):\n            return self.to_version_tuple(v) != self.version_tuple\n\n        def __str__(self):\n            return \"{:d}.{:d}.{:d}\".format(*self.version_tuple)\n\n    @staticmethod\n    @Cache.cache_this_session_skip_None_cache\n    def kernel_version():\n        # fast path\n        linux_banner = None\n        if is_kdb():\n            linux_banner = Symbol.get_symbol_by_monitor(\"linux_banner\")\n        if linux_banner is None:\n            linux_banner = Symbol.get_ksymaddr(\"linux_banner\")\n        if linux_banner and is_valid_addr(linux_banner):\n            version_string = read_cstring_from_memory(linux_banner, 0x200).rstrip()\n            r = re.search(r\"Linux version (\\d)\\.(\\d+)\\.(\\d+)\", version_string)\n            if r:\n                major, minor, patch = int(r.group(1)), int(r.group(2)), int(r.group(3))\n                return Kernel.KernelVersion(linux_banner, version_string, major, minor, patch)\n\n        # slow path\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.has_none:\n            return None\n        area = []\n        for addr in kinfo.maps: # resolve search range\n            if addr[0] < kinfo.text_base:\n                continue\n            if kinfo.rw_base and addr[0] >= kinfo.rw_base:\n                continue\n            area.append([addr[0], addr[0] + addr[1]])\n        if area == []:\n            return None\n        for start, end in area: # find version string\n            try:\n                data = read_memory(start, end - start)\n            except gdb.MemoryError:\n                continue\n            data = \"\".join([chr(x) for x in data])\n            r = re.findall(r\"(Linux version (?:\\d+\\.[\\d.]*\\d)[ -~]+)\", data)\n            if not r:\n                continue\n\n            version_string = r[0]\n            address = start + data.find(version_string)\n\n            r = re.search(r\"Linux version (\\d)\\.(\\d+)\\.(\\d+)\", version_string)\n            major, minor, patch = int(r.group(1)), int(r.group(2)), int(r.group(3))\n\n            return Kernel.KernelVersion(address, version_string, major, minor, patch)\n        return None\n\n    @staticmethod\n    @Cache.cache_this_session_skip_None_cache\n    def kernel_cmdline():\n        saved_command_line = None\n        if is_kdb():\n            saved_command_line = Symbol.get_symbol_by_monitor(\"saved_command_line\")\n        if saved_command_line is None:\n            saved_command_line = KernelAddressHeuristicFinder.get_saved_command_line()\n        if saved_command_line is None:\n            return None\n        try:\n            ptr = read_int_from_memory(saved_command_line)\n            cmdline = read_cstring_from_memory(ptr, max_length=0x1000)\n            Kcmdline = collections.namedtuple(\"Kcmdline\", [\"address\", \"cmdline\"])\n            return Kcmdline(ptr, cmdline)\n        except Exception:\n            return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_ksysctl(sym):\n        try:\n            res = gdb.execute(\"ksysctl --quiet --no-pager --exact --filter {:s}\".format(sym), to_string=True)\n            return int(res.split()[1], 16)\n        except (gdb.error, IndexError, ValueError):\n            return None\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_slab_type():\n        # Cases where ksymaddr-remote is not working properly\n        if not Symbol.get_ksymaddr(\"commit_creds\"):\n            return \"Unknown\"\n\n        if gdb.execute(\"ksymaddr-remote --quiet --no-pager slub_\", to_string=True):\n            kversion = Kernel.kernel_version()\n            if kversion < \"6.2\":\n                return \"SLUB\"\n            else:\n                # care for both deactivate_slab and deactivate_slab.cold\n                if gdb.execute(\"ksymaddr-remote --quiet --no-pager deactivate_slab\", to_string=True):\n                    return \"SLUB\"\n                else:\n                    return \"SLUB_TINY\"\n\n        # care for both cache_reap and cache_reap.cold\n        if gdb.execute(\"ksymaddr-remote --quiet --no-pager cache_reap\", to_string=True):\n            return \"SLAB\"\n\n        if gdb.execute(\"ksymaddr-remote --quiet --no-pager slob_\", to_string=True):\n            return \"SLOB\"\n        return \"Unknown\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def slab_page_str():\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.17\":\n            return \"page\"\n        else:\n            return \"slab\"\n\n    @staticmethod\n    @Cache.cache_this_session\n    def get_page_virt_pair():\n        allocator = Kernel.get_slab_type()\n\n        if allocator in [\"SLUB\", \"SLUB_TINY\"]:\n            # get valid page and vaddr pair\n            command = {\"SLUB\": \"slub-dump --node --skip-sheaf\", \"SLUB_TINY\": \"slub-tiny-dump\"}[allocator]\n            for n in [8, 16, 32, 64, 128, 192, 256, 512]:\n                # this function calls slub-dump, but it called from slub-dump itself.\n                # * get_page_virt_pair\n                #   -> slub-dump    <-- first\n                #     -> page2virt\n                #       -> get_VMEMMAP_START\n                #         -> get_page_virt_pair\n                #           -> slub-dump    <-- recursively\n                # To avoid infinite recursion, must add the `--skip-page2virt` option\n                # when calling slub-dump from page2virt.\n                ret = gdb.execute(\n                    \"{:s} --simple --no-pager --quiet --skip-page2virt kmalloc-{:d}\".format(command, n),\n                    to_string=True,\n                )\n                r1 = re.findall(r\"(?:active|partial|node) page: (0x\\S\\S+)\", Color.remove_color(ret))\n                r2 = re.findall(r\"virtual address: (0x\\S+|\\?\\?\\?)\", Color.remove_color(ret))\n                valid_pairs = [(p, v) for p, v in zip(r1, r2) if v != \"???\"]\n                if valid_pairs:\n                    page = int(valid_pairs[0][0], 16)\n                    vaddr = int(valid_pairs[0][1], 16)\n                    break\n            else:\n                return False\n\n        elif allocator == \"SLAB\":\n            # get valid page and vaddr pair\n            ret = gdb.execute(\"slab-dump --simple --cpu 0 --no-pager --quiet kmalloc-256\", to_string=True)\n            r1 = re.search(r\"node\\[\\d+\\]\\.slabs_(?:partial|full): (0x\\S+)\", Color.remove_color(ret))\n            r2 = re.search(r\"virtual address \\(s_mem & ~0xfff\\): (0x\\S+)\", Color.remove_color(ret))\n            if not r1 or not r2:\n                return False\n            page = int(r1.group(1), 16)\n            vaddr = int(r2.group(1), 16)\n\n        elif allocator == \"SLOB\":\n            # get valid page and vaddr pair\n            ret = gdb.execute(\"slob-dump --simple --large --no-pager --quiet\", to_string=True)\n            r1 = re.search(r\"page: (0x\\S+)\", Color.remove_color(ret))\n            r2 = re.search(r\"virtual address: (0x\\S+)\", Color.remove_color(ret))\n            if not r1 or not r2:\n                return False\n            page = int(r1.group(1), 16)\n            vaddr = int(r2.group(1), 16)\n\n        else:\n            return False\n\n        return page, vaddr\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_slab_contains(addr, allow_unaligned=False, keep_color=False):\n        if not is_valid_addr(addr):\n            return None\n        ret = gdb.execute(\"slab-contains --quiet {:#x}\".format(addr), to_string=True).strip()\n        if not ret:\n            return None\n        if not allow_unaligned and \"(unaligned?)\" in ret:\n            return None\n        if keep_color:\n            return ret\n        return Color.remove_color(ret)\n\n    @staticmethod\n    @Cache.cache_until_next\n    def p2v(paddr): # return list\n        ret = gdb.execute(\"p2v {:#x}\".format(paddr), to_string=True)\n        return [int(x, 16) for x in re.findall(r\"Phys: \\S+ -> Virt: (\\S+)\", ret)]\n\n    @staticmethod\n    @Cache.cache_until_next\n    def v2p(vaddr):\n        # v2p is slow since it needs maps parsing for each time.\n        # more faster using gva2gpa if available.\n        try:\n            ret = gdb.execute(\"monitor gva2gpa {:#x}\".format(vaddr), to_string=True)\n            r = re.search(r\"gpa: (0x\\S+)\", ret)\n            if r:\n                return int(r.group(1), 16)\n        except gdb.error:\n            pass\n\n        ret = gdb.execute(\"v2p {:#x}\".format(vaddr), to_string=True)\n        r = re.search(r\"Virt: 0x\\S+ -> Phys: (0x\\S+)\", ret)\n        if r:\n            return int(r.group(1), 16)\n        return None\n\n    @staticmethod\n    def page2virt(page):\n        ret = gdb.execute(\"page2virt {:#x}\".format(page), to_string=True)\n        r = re.search(r\"Virt: (\\S+)\", ret)\n        if r:\n            return int(r.group(1), 16)\n        return None\n\n    @staticmethod\n    def virt2page(virt):\n        ret = gdb.execute(\"virt2page {:#x}\".format(virt), to_string=True)\n        r = re.search(r\"Page: (\\S+)\", ret)\n        if r:\n            return int(r.group(1), 16)\n        return None\n\n\n@register_command\nclass KernelbaseCommand(GenericCommand):\n    \"\"\"Display kernel base address.\"\"\"\n\n    _cmdline_ = \"kbase\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if args.rescan:\n            Cache.reset_gef_caches(all=True)\n\n        # resolve text_base, ro_base\n        self.quiet_info(\"Wait for memory scan\")\n        kinfo = Kernel.get_kernel_layout()\n\n        self.out = []\n        if kinfo.text_base:\n            self.out.append(\"kernel text:   {:#x}-{:#x} ({:#x} bytes)\".format(kinfo.text_base, kinfo.text_end, kinfo.text_size))\n            gdb.execute(f\"set $kbase = {kinfo.text_base:#x}\")\n        else:\n            err(\"Failed to resolve kernel text\")\n        if kinfo.ro_base:\n            self.out.append(\"kernel rodata: {:#x}-{:#x} ({:#x} bytes)\".format(kinfo.ro_base, kinfo.ro_end, kinfo.ro_size))\n            gdb.execute(f\"set $kro_base = {kinfo.ro_base:#x}\")\n        else:\n            err(\"Failed to resolve kernel rodata\")\n        if kinfo.rw_base:\n            self.out.append(\"kernel data:   {:#x}-{:#x} ({:#x} bytes)\".format(kinfo.rw_base, kinfo.rw_end, kinfo.rw_size))\n            gdb.execute(f\"set $kdata_base = {kinfo.rw_base:#x}\")\n        else:\n            err(\"Failed to resolve kernel data\")\n        if self.out:\n            gef_print(\"\\n\".join(self.out))\n        return\n\n\n@register_command\nclass KernelVersionCommand(GenericCommand):\n    \"\"\"Display kernel version string.\"\"\"\n\n    _cmdline_ = \"kversion\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if args.rescan:\n            Cache.reset_gef_caches(all=True)\n\n        self.quiet_info(\"Wait for memory scan\")\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            self.quiet_err(\"Failed to resolve\")\n            return\n\n        self.out = []\n        self.out.append(\"{:#x}: {:s}\".format(kversion.address, kversion.version_string))\n        if self.out:\n            gef_print(\"\\n\".join(self.out))\n        return\n\n\n@register_command\nclass KernelCmdlineCommand(GenericCommand):\n    \"\"\"Display kernel command-line string.\"\"\"\n\n    _cmdline_ = \"kcmdline\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if args.rescan:\n            Cache.reset_gef_caches(all=True)\n\n        self.quiet_info(\"Wait for memory scan\")\n        kcmdline = Kernel.kernel_cmdline()\n        if kcmdline is None:\n            self.quiet_err(\"Failed to resolve\")\n            return\n\n        self.out = []\n        self.out.append(\"{:#x}: '{:s}'\".format(kcmdline.address, kcmdline.cmdline))\n        if self.out:\n            gef_print(\"\\n\".join(self.out))\n        return\n\n\n@register_command\nclass KernelCurrentCommand(GenericCommand):\n    \"\"\"Display current task.\"\"\"\n\n    _cmdline_ = \"kcurrent\"\n    _category_ = \"06-c. Qemu-system/KGDB Cooperation - Linux Basic\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n        self.__per_cpu_offset = None\n        self.cpu_offset = None\n        self.offset_comm = None\n        return\n\n    @staticmethod\n    def get_each_cpu_offset(__per_cpu_offset):\n        \"\"\"\n        Note that the number of CPUs and the number of threads may not match.\n        x64 example:\n        len(gdb.selected_inferior().threads()) == 2; but __per_cpu_offset entry is 1\n        0xffffffff93980680|+0x0000|+000: 0xffff9724c7800000  ->  0x0000000000000000\n        0xffffffff93980688|+0x0008|+001: 0xffffffff93d0d000\n        0xffffffff93980690|+0x0010|+002: 0xffffffff93d0d000\n        Therefore, when the same address is repeated, it is considered to be the end.\n        \"\"\"\n        cpu_offset = []\n        i = 0\n        while True:\n            off = read_int_from_memory(__per_cpu_offset + i * current_arch.ptrsize)\n            \"\"\"\n            off itself may refer to inaccessible memory.\n            x86 example:\n            __per_cpu_offset: 0xc6a27440\n            0xc6a27440|+0x0000|+000: 0x2d849000 -> inaccessible\n            0xc6a27444|+0x0004|+001: 0x00000000\n            \"\"\"\n            if (off <= 0x10) or (off & 0xf):\n                break\n            if len(cpu_offset) >= 1 and off == cpu_offset[-1]:\n                cpu_offset.pop() # remove last one\n                break\n            cpu_offset.append(off)\n            i += 1\n        return cpu_offset\n\n    def get_cpu_offset(self):\n        # use cache\n        if self.cpu_offset:\n            self.quiet_info(\"__per_cpu_offset: {:#x}\".format(self.__per_cpu_offset))\n            self.quiet_info(\"Num of cpu: {:d} (guessed)\".format(len(self.cpu_offset)))\n            return self.cpu_offset\n\n        # resolve __per_cpu_offset\n        __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n\n        # not found\n        if __per_cpu_offset is None:\n            self.quiet_err(\"Failed to resolve `__per_cpu_offset`\")\n            return None\n\n        # found\n        self.quiet_info(\"__per_cpu_offset: {:#x}\".format(__per_cpu_offset))\n        self.__per_cpu_offset = __per_cpu_offset\n\n        self.cpu_offset = KernelCurrentCommand.get_each_cpu_offset(__per_cpu_offset)\n        self.quiet_info(\"Num of cpu: {:d} (guessed)\".format(len(self.cpu_offset)))\n        return self.cpu_offset\n\n    def get_comm_str(self, task_addr):\n        if self.offset_comm is None:\n            ret = gdb.execute(\"ktask --no-pager --meta\", to_string=True)\n            r = re.search(r\"offsetof\\(task_struct, comm\\): (0x\\S+)\", ret)\n            if r is not None:\n                self.offset_comm = int(r.group(1), 16)\n            else:\n                self.quiet_err(\"ktask is failed\")\n                self.offset_comm = False\n\n        if self.offset_comm is False:\n            return \"???\"\n\n        comm = read_cstring_from_memory(task_addr + self.offset_comm)\n        return comm or \"???\"\n\n    def dump_current_arm(self):\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        threads = sorted(threads, key=lambda th: th.num)\n        for thread in threads:\n            thread.switch() # change thread\n            task = KernelAddressHeuristicFinder.get_current_task_for_current_thread()\n            if task is None:\n                continue\n            if is_valid_addr(task):\n                cpu_num = thread.num - 1 # ?\n                gef_print(\"current (cpu{:d}): {:#x} {:s}\".format(cpu_num, task, self.get_comm_str(task)))\n        orig_thread.switch() # revert thread\n        orig_frame.select()\n        return\n\n    def dump_current_x86(self):\n        current_task = KernelAddressHeuristicFinder.get_current_task()\n        if not current_task:\n            self.quiet_err(\"Failed to resolve `current_task`\")\n            return\n\n        cpu_bases = self.get_cpu_offset()\n\n        if cpu_bases:\n            # pattern 1. Offset from __per_cpu_offset.\n            self.quiet_info(\"current_task: {:#x}\".format(current_task))\n            task_offset = current_task\n            for i, cpu_base in enumerate(cpu_bases):\n                task = read_int_from_memory(AddressUtil.align_address(cpu_base + task_offset))\n                if not is_valid_addr(task):\n                    break\n                gef_print(\"current (cpu{:d}): {:#x} {:s}\".format(i, task, self.get_comm_str(task)))\n        else:\n            # pattern 2: current_task is the address that stores a pointer to the current task (not per_cpu).\n            self.quiet_info(\"__per_cpu_offset is unused\")\n            task = read_int_from_memory(current_task)\n            if is_valid_addr(task):\n                gef_print(\"current: {:#x} {:s}\".format(task, self.get_comm_str(task)))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if is_arm32() or is_arm64():\n            self.dump_current_arm()\n        elif is_x86():\n            self.dump_current_x86()\n        return\n\n\n@register_command\nclass KernelTaskCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display process list.\"\"\"\n\n    _cmdline_ = \"ktask\"\n    _category_ = \"06-f. Qemu-system/KGDB Cooperation - Linux Task\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"comm string REGEXP filter.\")\n    parser.add_argument(\"-T\", \"--task-filter\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"task address filter.\")\n    parser.add_argument(\"-m\", \"--print-maps\", action=\"store_true\",\n                        help=\"print memory map for each user-land process.\")\n    parser.add_argument(\"-r\", \"--print-regs\", action=\"store_true\",\n                        help=\"print general registers saved on kstack for each user-land process.\")\n    parser.add_argument(\"-i\", \"--print-all-id\", action=\"store_true\",\n                        help=\"print suid, sgid, euid, egid, fsuid and fsgid.\")\n    parser.add_argument(\"-t\", \"--print-thread\", action=\"store_true\",\n                        help=\"display by thread (LWP), not by process.\")\n    parser.add_argument(\"-F\", \"--print-fd\", action=\"store_true\",\n                        help=\"print file descriptors for each user process.\")\n    parser.add_argument(\"-s\", \"--print-sighand\", action=\"store_true\",\n                        help=\"print signal handlers for each user process.\")\n    parser.add_argument(\"-S\", \"--print-seccomp\", action=\"store_true\",\n                        help=\"dump the seccomp filter. If the tool is available, it dumps orig_prog; otherwise, it disassembles bpf_func.\")\n    parser.add_argument(\"-N\", \"--print-namespace\", action=\"store_true\",\n                        help=\"print namespaces for each user process.\")\n    parser.add_argument(\"-u\", \"--user-process-only\", action=\"store_true\",\n                        help=\"display user-land process (+ thread) only.\")\n    parser.add_argument(\"--init-task\", type=AddressUtil.parse_address,\n                        help=\"specifies the address of init_task.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"enable all option.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified task_struct structure:\",\n        \"\",\n        \"    +-init_task-+\",\n        \"    | list_head |---+    +-->+-kstack----------+    +--->+-vm_area_struct--+\",\n        \"    +-----------+   |    |   | (thread_info)   |    |    | vm_start        |\",\n        \"                    |    |   | STACK_END_MAGIC |    |    | vm_end          |\",\n        \"+-------------------+    |   | ...             |    |    | vm_next (~6.1)  |\",\n        \"|                        |   | ...             |    |    | ...             |\",\n        \"|   +-task_struct---+    |   | ...             |    |    | vm_flags        |\",\n        \"|   | (thread_info) |    |   | ...             |    |    | vm_file         |-----+\",\n        \"|   | ...           |    |   | pt_regs         |    |    | ...             |     |\",\n        \"|   | stack         |----+   +-----------------+    |    +-----------------+     |\",\n        \"|   | ...           |                               |                            |\",\n        \"+-->| tasks         |-->...               +---------+<------------------------+  |\",\n        \"    | ...           |                     |                                   |  |\",\n        \"    | mm            |-->+-mm_struct----+  |  +-------->+-maple_node(6.1~)--+  |  |\",\n        \"    | ...           |   | mmap (~6.1)  |--+  |         | ...               |  |  |\",\n        \"    | pid           |   | ...          |     |         | mr64|ma64|alloc   |  |  |\",\n        \"    | tid           |   | mm_mt (6.1~) |     |         |   ...             |  |  |\",\n        \"    | ...           |   |   ma_root    |-----+         |   slot[]          |--+  |\",\n        \"    | stack_canary  |   | ...          |               +-------------------+     |\",\n        \"    | ...           |   +--------------+                                         |\",\n        \"    | group_leader  |                                         +------------------+       +-mount----------+\",\n        \"    | ...           |         +-->+-cred--------------+       |                          | ...            |\",\n        \"    | thread_group  |-->...   |   | ...               |       |                          | mnt_parent     |-->mount\",\n        \"    | ...           |         |   | uid, gid          |       |                          | mnt_mountpoint |-->dentry\",\n        \"    | cred          |---------+   | suid, sgid        |       |                       +->| mnt (vfsmount) |\",\n        \"    | ...           |             | euid, egid        |       |                       |  |   mnt_root     |-->dentry\",\n        \"    | comm[16]      |             | fsuid, fsgid      |       |                       |  |   ...          |\",\n        \"    | ...           |             | ..., user_ns, ... |       |                       |  | ...            |\",\n        \"    | files         |--+          +-------------------+       |                       |  +----------------+\",\n        \"    | ...           |  |                                      |                       |\",\n        \"    | nsproxy       |------->+-nsproxy----------------+       |                       | +--->+-dentry-----+\",\n        \"    | ...           |  |     | count                  |       |                       | |    | ...        |\",\n        \"    | sighand       |-----+  | uts_ns, ipc_ns, mnt_ns |       |                       | |    | d_parent   |-->dentry\",\n        \"    | ...           |  |  |  | pid_ns_for_children    |       |                       | |    | ...        |\",\n        \"    | seccomp       |  |  |  | net_ns, time_ns, ...   |       |                       | |    | d_inode    |--+\",\n        \"    | ...           |  |  |  +------------------------+       |                       | |    | d_iname    |  |\",\n        \"    +---------------+  |  |                                   |                       | |    | ...        |  |\",\n        \"                       |  +->+-sighand_struct----+            |                       | |    +------------+  |\",\n        \"                       |     | ...               |            v                       | |                    |\",\n        \"                       |     | action[64]        |            +-->+-file-----------+  | | +------------------+\",\n        \"+----------------------+     +-------------------+            |   | ...            |  | | |\",\n        \"|                                                             |   | f_path         |  | | v\",\n        \"+-->+-files_struct-+  +-->+-fdtable---+  +-->+-file*[]-----+  |   |   mnt          |--+ | +->+-inode------+\",\n        \"    | ...          |  |   | max_fds   |  |   | [0]         |--+   |   dentry       |----+ |  | ...        |\",\n        \"    | fdt          |--+   | fd        |--+   | ...         |      | f_inode (3.9~) |------+  | i_ino      |\",\n        \"    | ...          |      | ...       |      | [max_fds-1] |      | ...            |         | ...        |\",\n        \"    +--------------+      +-----------+      +-------------+      +----------------+         +------------+\",\n        \"\",\n        \"This command will only track tasks that can be tracked from `init_task` or the result of `kcurrent` command.\",\n        \"Other tasks (such as `swapper/1` if thread 1 is running some task) will not be detected.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__()\n        # task_struct\n        self.offset_tasks = None\n        self.offset_mm = None\n        self.offset_stack = None\n        self.offset_pid = None\n        self.offset_kcanary = None\n        self.offset_group_leader = None\n        self.offset_thread_group = None\n        self.offset_comm = None\n        self.offset_cred = None\n        self.offset_files = None\n        self.offset_sighand = None\n        self.offset_nsproxy = None\n        self.offset_signal = None\n        self.offset_seccomp = None\n        # files_struct\n        self.offset_fdt = None\n        # kstack\n        self.offset_ptregs = None\n        # cred\n        self.offset_uid = None\n        self.offset_user_ns = None\n        # vm_area_struct\n        self.offset_vm_mm = None\n        self.offset_vm_flags = None\n        self.offset_vm_file = None\n        # file\n        self.offset_mnt = None\n        self.offset_dentry = None\n        # dentry\n        self.offset_d_iname = None\n        self.offset_d_parent = None\n        self.offset_d_inode = None\n        # inode\n        self.offset_i_ino = None\n        # signal\n        self.offset_thread_head = None\n        # sighand_struct\n        self.offset_action = None\n        self.sizeof_action = None\n        # seccomp_filter\n        self.offset_prev = None\n        self.offset_prog = None\n        # bpf_prog\n        self.offset_bpf_func = None\n        self.offset_orig_prog = None\n        return\n\n    def get_offset_tasks(self, init_task):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).tasks\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        # search for init_task->tasks\n        for i in range(0x200):\n            offset_tasks = current_arch.ptrsize * i\n            if is_double_link_list(init_task + offset_tasks, min_len=5):\n                return offset_tasks\n        return None\n\n    def get_task_list(self, init_task, offset_tasks):\n        pos = init_task + offset_tasks\n        task_list = [pos]\n        # validating candidate offset\n        while True:\n            try:\n                pos = read_int_from_memory(pos)\n            except gdb.MemoryError:\n                return None\n            if pos in task_list:\n                break\n            task_list.append(pos)\n        return [x - offset_tasks for x in task_list]\n\n    def get_offset_mm(self, task_addr, offset_tasks):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct list_head tasks;\n        #ifdef CONFIG_SMP\n            struct plist_node {\n                int prio;\n                struct list_head prio_list;\n                struct list_head node_list;\n            } pushable_tasks;\n            struct rb_node {\n                unsigned long __rb_parent_color;\n                struct rb_node *rb_right;\n                struct rb_node *rb_left;\n            } pushable_dl_tasks; // v3.14~\n        #endif\n            struct mm_struct *mm;\n            struct mm_struct *active_mm;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).mm\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if kversion < \"6.17\":\n            offset_mm = offset_tasks + 2 * current_arch.ptrsize\n            r = read_int_from_memory(task_addr + offset_mm)\n            if 0 < r <= 0xffff:\n                # maybe prio, so CONFIG_SMP is y\n                if \"3.14\" <= kversion:\n                    offset_mm = offset_tasks + 10 * current_arch.ptrsize\n                else:\n                    offset_mm = offset_tasks + 7 * current_arch.ptrsize\n        else:\n            offset_mm = offset_tasks + 10 * current_arch.ptrsize\n        return offset_mm\n\n    def get_offset_comm(self, task_addrs):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).comm\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        for i in range(0x300):\n            offset_comm = i * current_arch.ptrsize\n            valid = True\n            for task in task_addrs:\n                if not is_ascii_string(task + offset_comm):\n                    valid = False\n                    break\n                s = read_cstring_from_memory(task + offset_comm)\n                # very common name, so for speeding up, we assume that offset is found\n                if s == \"swapper/0\":\n                    break\n                if len(s) < 2:\n                    valid = False\n                    break\n            if valid:\n                return offset_comm\n        return None\n\n    def get_offset_cred(self, task_addrs, offset_comm):\n        \"\"\"\n        struct task_struct {\n            ...\n            const struct cred __rcu *real_cred; // These may point to the same address\n            const struct cred __rcu *cred;      // These may point to the same address\n        #ifdef CONFIG_KEYS\n            struct key *cached_requested_key;\n        #endif\n            char comm[TASK_COMM_LEN];\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).cred\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        # backward search from `comm`\n        for i in range(0x2):\n            offset_cred = offset_comm - ((i + 1) * current_arch.ptrsize)\n            for task in task_addrs:\n                val1 = read_int_from_memory(task + offset_cred)\n                val2 = read_int_from_memory(task + offset_cred - current_arch.ptrsize)\n                if val1 == val2 and val1 != 0:\n                    return offset_cred\n        return None\n\n    def get_offset_stack(self, task_addrs):\n        \"\"\"\n        struct task_struct {\n            ...\n        #ifdef CONFIG_THREAD_INFO_IN_TASK\n            struct thread_info thread_info;\n        #endif\n            volatile long state;\n            void *stack;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).stack\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        for i in range(0x100):\n            found = False\n            zcount = 0\n            for task in task_addrs:\n                v = read_int_from_memory(task + current_arch.ptrsize * i)\n                if v == 0:\n                    zcount += 1\n                    continue\n                if (v & 0x1fff) != 0:\n                    break\n                if not is_valid_addr(v):\n                    break\n            else:\n                found = True\n\n            # For unknown reasons, processes without a stack are sometimes observed.\n            # 0xffffa122c17db000 U   106     chal.sh ... 0xffffa43100218000 0xd16ef01535a35500\n            # 0xffffa122c17da000 U   108     socat   ... 0xffffa43100278000 0x3d378b9e6f59bf00\n            # 0xffffa122c17dc000 U   109     chal    ... 0xffffa431002d4000 0x277c67d5e5854500\n            # 0xffffa122c17dd000 K   110     3       ... 0x0000000000000000 0x22a999743f180500 <-- here\n            # Therefore, a small number of NULL pointers are allowed.\n            if zcount > len(task_addrs) // 10:\n                found = False\n\n            if found is False:\n                continue\n\n            offset_stack = current_arch.ptrsize * i\n            return offset_stack\n        return None\n\n    def get_thread_info(self, task_addr, offset_stack):\n        # fast path\n        try:\n            return task_addr + to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).thread_info\")\n            )\n        except gdb.error:\n            try:\n                # task_struct exists but has no thread_info member\n                gdb.parse_and_eval(\"(struct task_struct*)0\")\n                return read_int_from_memory(task_addr + offset_stack)\n            except gdb.error:\n                pass\n\n        # slow path\n        kstack = read_int_from_memory(task_addr + offset_stack)\n        if not is_valid_addr(kstack):\n            return None\n        stack_top_val = read_int32_from_memory(kstack)\n        if stack_top_val == 0x57ac6e9d: # STACK_END_MAGIC\n            \"\"\"\n            struct task_struct {\n            #ifdef CONFIG_THREAD_INFO_IN_TASK\n                struct thread_info thread_info;\n            #endif\n                ...\n            \"\"\"\n            return task_addr # CONFIG_THREAD_INFO_IN_TASK=y\n        else:\n            return kstack # CONFIG_THREAD_INFO_IN_TASK=n\n\n    def has_seccomp(self, task_addr):\n        thread_info = self.get_thread_info(task_addr, self.offset_stack)\n        if thread_info is None:\n            return None\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if is_x86():\n            if \"5.11\" <= kversion:\n                syscall_work = read_int_from_memory(thread_info + current_arch.ptrsize)\n                return bool(syscall_work & (1 << 0)) # SYSCALL_WORK_SECCOMP\n            elif \"4.9\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 8)) # TIF_SECCOMP\n            elif \"4.1\" <= kversion:\n                flags = read_int32_from_memory(thread_info + current_arch.ptrsize)\n                return bool(flags & (1 << 8)) # TIF_SECCOMP\n            else:\n                flags = read_int32_from_memory(thread_info + current_arch.ptrsize * 2)\n                return bool(flags & (1 << 8)) # TIF_SECCOMP\n        elif is_arm32():\n            if \"6.0\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 23)) # TIF_SECCOMP\n            elif \"5.16\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 7)) # TIF_SECCOMP\n            elif \"5.15\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 23)) # TIF_SECCOMP\n            elif \"5.11\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 7)) # TIF_SECCOMP\n            elif \"5.10\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 23)) # TIF_SECCOMP\n            elif \"4.3\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 7)) # TIF_SECCOMP\n            elif \"3.8\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 11)) # TIF_SECCOMP\n            else:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 21)) # TIF_SECCOMP\n        elif is_arm64():\n            if \"3.16\" <= kversion:\n                flags = read_int_from_memory(thread_info)\n                return bool(flags & (1 << 11)) # TIF_SECCOMP\n            else:\n                # unimplemented\n                return None\n        return None\n\n    def get_offset_ptregs(self, task_addrs, offset_stack):\n        # calc kstack address pattern\n        kstacks_raw = []\n        for task in task_addrs:\n            kstack = read_int_from_memory(task + offset_stack)\n            if kstack == 0:\n                continue\n            kstacks_raw.append(kstack)\n\n        # calc kstack size\n        kstacks = sorted({x & 0xffff for x in kstacks_raw}) # uniq and sort\n        diffs = []\n        for i in range(len(kstacks) - 1):\n            diff = kstacks[i + 1] - kstacks[i]\n            diffs.append(diff)\n        if len(diffs) == 0:\n            kstack_size = get_pagesize() * 2\n        else:\n            kstack_size = min(diffs)\n\n        # check\n        while kstack_size >= 0x2000:\n            for kstack in kstacks_raw:\n                if not is_valid_addr(kstack + kstack_size - current_arch.ptrsize):\n                    kstack_size //= 2\n                    break # for, then retry while\n            else:\n                break # while\n\n        if is_x86_64():\n            \"\"\"\n            struct pt_regs {\n                unsigned long r15;\n                unsigned long r14;\n                unsigned long r13;\n                unsigned long r12;\n                unsigned long rbp;\n                unsigned long rbx;\n                unsigned long r11;\n                unsigned long r10;\n                unsigned long r9;\n                unsigned long r8;\n                unsigned long rax;\n                unsigned long rcx;\n                unsigned long rdx;\n                unsigned long rsi;\n                unsigned long rdi;\n                unsigned long orig_rax;\n                unsigned long rip;\n                unsigned long cs;\n                unsigned long eflags;\n                unsigned long rsp;\n                unsigned long ss;\n            };\n            \"\"\"\n            ptregs_size = current_arch.ptrsize * 21\n\n            # Sometimes register values are stored a short distance away from the bottom of the kstack.\n            # It is unclear whether this depends on the kernel version.\n            # In 6.10.11 it was at offset 0, and in 6.10.0-rc2 it was at offset 16.\n            # For this reason, dynamic detection is used.\n            # TODO: Dynamic detection may also be necessary for x86, ARM, and ARM64.\n            for i in range(8):\n                init_process_kstack = read_int_from_memory(task_addrs[1] + offset_stack)\n                init_process_kstack_end = init_process_kstack + kstack_size\n                v = read_int_from_memory(init_process_kstack_end - current_arch.ptrsize * (i + 1))\n                if v == 0x2b: # ss segment default value\n                    bottom_offset = current_arch.ptrsize * i\n                    break\n            else:\n                bottom_offset = 0\n        elif is_x86_32():\n            \"\"\"\n            struct pt_regs {\n                long ebx;\n                long ecx;\n                long edx;\n                long esi;\n                long edi;\n                long ebp;\n                long eax;\n                int xds;\n                int xes;\n                int xfs;\n                int xgs;\n                long orig_eax;\n                long eip;\n                int xcs;\n                long eflags;\n                long esp;\n                int xss;\n            };\n            \"\"\"\n            ptregs_size = current_arch.ptrsize * 17\n            bottom_offset = current_arch.ptrsize * 2 # ?\n        elif is_arm64():\n            \"\"\"\n            struct pt_regs {\n                u64 regs[31];\n                u64 sp;\n                u64 pc;\n                u64 pstate;\n                u64 orig_x0;\n                u64 syscallno;\n                u64 orig_addr_limit;\n                u64 pmr_save;\n                u64 stackframe[2];\n                u64 lockdep_hardirqs;\n                u64 exit_rcu;\n            };\n            \"\"\"\n            ptregs_size = current_arch.ptrsize * 35\n            bottom_offset = current_arch.ptrsize * 7\n        elif is_arm32():\n            \"\"\"\n            struct pt_regs {\n                unsigned long uregs[18];\n            };\n            \"\"\"\n            ptregs_size = current_arch.ptrsize * 18\n            bottom_offset = current_arch.ptrsize * 2 # ?\n        else:\n            return None\n\n        offset_ptregs = kstack_size - ptregs_size - bottom_offset\n        return kstack_size, offset_ptregs\n\n    def get_regs(self, kstack, offset_ptregs):\n        if is_x86_64():\n            regs_name = [\n                \"r15\", \"r14\", \"r13\", \"r12\", \"rbp\", \"rbx\", \"r11\", \"r10\",\n                \"r9\", \"r8\", \"rax\", \"rcx\", \"rdx\", \"rsi\", \"rdi\", \"orig_rax\",\n                \"rip\", \"cs\", \"eflags\", \"rsp\", \"ss\",\n            ]\n        elif is_x86_32():\n            regs_name = [\n                \"ebx\", \"ecx\", \"edx\", \"esi\", \"edi\", \"ebp\", \"eax\", \"ds\",\n                \"es\", \"fs\", \"gs\", \"orig_eax\", \"eip\", \"cs\", \"eflags\", \"esp\", \"ss\",\n            ]\n        elif is_arm64():\n            regs_name = [\n                \"x0\", \"x1\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\", \"x7\",\n                \"x8\", \"x9\", \"x10\", \"x11\", \"x12\", \"x13\", \"x14\", \"x15\",\n                \"x16\", \"x17\", \"x18\", \"x19\", \"x20\", \"x21\", \"x22\", \"x23\",\n                \"x24\", \"x25\", \"x26\", \"x27\", \"x28\", \"x29\", \"x30\",\n                \"sp\", \"pc\", \"pstate\", \"orig_x0\",\n            ]\n        elif is_arm32():\n            regs_name = [\n                \"r0\", \"r1\", \"r2\", \"r3\", \"r4\", \"r5\", \"r6\",\n                \"r7\", \"r8\", \"r9\", \"r10\", \"r11\", \"r12\",\n                \"sp\", \"lr\", \"pc\", \"cpsr\", \"orig_r0\",\n            ]\n\n        ptregs_addr = kstack + offset_ptregs\n        ptregs_size = len(regs_name) * current_arch.ptrsize\n        regs_data = read_memory(ptregs_addr, ptregs_size)\n\n        # maybe kernel thread\n        if is_x86():\n            if regs_data == b\"\\0\" * len(regs_data):\n                return None\n        elif is_arm32():\n            kernel_thread_regs = p32(0) * (len(regs_name) - 2) + p32(0x13) + p32(0)\n            if regs_data == kernel_thread_regs:\n                return None\n        elif is_arm64():\n            kernel_thread_regs = p64(0) * (len(regs_name) - 2) + p64(0x5) + p64(0)\n            if regs_data == kernel_thread_regs:\n                return None\n\n        # get regs value\n        regs_data = slice_unpack(regs_data, current_arch.ptrsize)\n        regs = {}\n        for name, value in zip(regs_name, regs_data):\n            regs[name] = value\n        return regs\n\n    def get_offset_pid(self, task_addrs):\n        \"\"\"\n        struct task_struct {\n            ...\n            pid_t pid; // int\n            pid_t tgid; // int\n            ...\n        };\n\n        0xc6d1e888:     0xc6d1f048      0xc6d1c1c8      0x0000008c      0xc6d1e894\n        0xc6d1e898:     0xc6d1e894      0xc6d1e89c      0xc6d1e89c      0xc6d1e8a4\n        0xc6d1e8a8:     0x00000000      0x00000000      0xc7830660      0xc7830660\n        0xc6d1e8b8:     0x00000008      0x00000000      0xc6d51300      0x00000000\n        0xc6d1e8c8:     0x00000000      0xc6d514e0      0x00000017      0x000000a9\n        0xc6d1e8d8:     0x00000005      0x00000000      0x00000000      0x00000000\n        0xc6d1e8e8:     0x00000000      0x00000011      0x00000000      0x00000000\n        0xc6d1e8f8:     0x00000000      0x00000000      0x00000000      0x00000000\n        0xc6d1e908:     0xc245a8d0      0x00000000      0x00000000      0x00000000\n        0xc6d1e918:     0x00000000      0x00000000      0x00000000      0x00000000\n        0xc6d1e928:     0x00000031*     0x00000031      0xc7834000      0xc7834000\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).pid\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        pid_max = 0x400000 if is_64bit() else 0x8000\n        for i in range(0x400):\n            found = False\n            seen_pid = []\n            # swapper/0 has pid 0. Don't use it as it will cause false positives.\n            for j, task in enumerate(task_addrs[1:]):\n                v1 = read_int32_from_memory(task + (i + 0) * 4)\n                v2 = read_int32_from_memory(task + (i + 1) * 4)\n                if j == 0 and v1 != 1: # init process has always 1\n                    break\n                if v1 == 0 or pid_max < v1: # pid is 1 ~ pid_max\n                    break\n                if v2 == 0 or pid_max < v2: # tgid is 1 ~ pid_max\n                    break\n                if v1 in seen_pid:\n                    break\n                seen_pid.append(v1)\n            else:\n                found = True\n\n            if found is False:\n                continue\n\n            offset_pid = i * 4\n            return offset_pid\n        return None\n\n    def get_offset_canary(self, task_addrs, offset_pid):\n        \"\"\"\n        struct task_struct {\n            ...\n            pid_t pid;\n            pid_t tgid;\n        #ifdef CONFIG_STACKPROTECTOR\n            unsigned long stack_canary;\n        #endif\n            struct task_struct __rcu *real_parent;\n            struct task_struct __rcu *parent;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).stack_canary\")\n            )\n        except gdb.error:\n            try:\n                # task_struct exists but has no stack_canary member\n                gdb.parse_and_eval(\"(struct task_struct*)0\")\n                return None\n            except gdb.error:\n                pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        offset_stack_canary = align_to_ptrsize(offset_pid + 4 + 4)\n        found = True\n        for task in task_addrs:\n            v1 = read_int_from_memory(task + offset_stack_canary)\n            v2 = read_int_from_memory(task + offset_stack_canary + current_arch.ptrsize)\n\n            if v1 == v2: # stack canary != real_parent\n                found = False\n                break\n\n            if kversion and \"4.13\" <= kversion:\n                if is_64bit() and (v1 & 0xff) != 0: # 32-bit canary does not have 0xXXXXXX00\n                    found = False\n                    break\n\n        if found:\n            return offset_stack_canary\n        return None\n\n    def get_offset_group_leader(self, offset_pid, offset_kcanary):\n        \"\"\"\n        struct task_struct {\n            ...\n            pid_t pid;\n            pid_t tgid;\n        #ifdef CONFIG_STACKPROTECTOR\n            unsigned long stack_canary;\n        #endif\n            struct task_struct __rcu *real_parent;\n            struct task_struct __rcu *parent;\n            struct list_head children;\n            struct list_head sibling;\n            struct task_struct *group_leader;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).group_leader\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if offset_kcanary is None:\n            offset_real_parent = align_to_ptrsize(offset_pid + 4 + 4)\n        else:\n            offset_real_parent = offset_kcanary + current_arch.ptrsize\n        offset_group_leader = offset_real_parent + current_arch.ptrsize * (1 + 1 + 2 + 2)\n        return offset_group_leader\n\n    def get_offset_thread_group(self, offset_group_leader):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct task_struct *group_leader;\n            struct list_head ptraced;\n            struct list_head ptrace_entry;\n            struct pid *thread_pid;           // v4.19~\n            struct hlist_node pid_links[4];   // v4.19~\n            struct pid_link pids[3];          // ~v4.18\n            struct list_head thread_group;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).thread_group\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if \"4.19\" <= kversion:\n            offset_thread_group = offset_group_leader + current_arch.ptrsize * (1 + 2 + 2 + 1 + (2 * 4))\n        else:\n            offset_thread_group = offset_group_leader + current_arch.ptrsize * (1 + 2 + 2 + (3 * 3))\n        return offset_thread_group\n\n    def get_offset_signal(self, offset_nsproxy):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct nsproxy *nsproxy;\n            struct signal_struct *signal;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).signal\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        return offset_nsproxy + current_arch.ptrsize\n\n    def get_offset_seccomp(self, task_addrs, offset_signal):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct signal_struct *signal;\n            struct sighand_struct __rcu *sighand;\n            sigset_t blocked;\n            sigset_t real_blocked;\n            sigset_t saved_sigmask;\n            struct sigpending {\n                struct list_head list;\n                sigset_t signal;\n            } pending;\n            unsigned long sas_ss_sp;\n            size_t sas_ss_size;\n            unsigned int sas_ss_flags;\n            struct callback_head *task_works;\n        #ifdef CONFIG_AUDIT\n        #ifdef CONFIG_AUDITSYSCALL\n            struct audit_context *audit_context;\n        #endif\n            kuid_t loginuid;\n            unsigned int sessionid;\n        #endif\n            struct seccomp {\n                int mode;\n                atomic_t filter_count;\n                struct seccomp_filter *filter;\n            } seccomp;\n            ...\n        }\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).seccomp\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        # search for seccomped process\n        for task in task_addrs:\n            if self.has_seccomp(task):\n                seccomped_task = task\n                break\n        else:\n            # Not found\n            return None\n\n        \"\"\"\n        0xffff99353fe721d8|+0x0000|+000: 0xffff99353fe6e600 <- &task_struct.signal\n        0xffff99353fe721e0|+0x0008|+001: 0x0000000000004002\n        0xffff99353fe721e8|+0x0010|+002: 0x0000000000000000\n        0xffff99353fe721f0|+0x0018|+003: 0x0000000000000000\n        0xffff99353fe721f8|+0x0020|+004: 0xffff99353fe721f8 <- &task_struct.pending.list\n        0xffff99353fe72200|+0x0028|+005: 0xffff99353fe721f8\n        0xffff99353fe72208|+0x0030|+006: 0x0000000000000000\n        0xffff99353fe72210|+0x0038|+007: 0x0000000000000000\n        0xffff99353fe72218|+0x0040|+008: 0x0000000000000000\n        0xffff99353fe72220|+0x0048|+009: 0x0000000000000002\n        0xffff99353fe72228|+0x0050|+010: 0x0000000000000000\n        0xffff99353fe72230|+0x0058|+011: 0x0000000000000000\n        0xffff99353fe72238|+0x0060|+012: 0xffffffffffffffff\n        0xffff99353fe72240|+0x0068|+013: 0x0000002300000002 <- &task_struct.seccomp\n        0xffff99353fe72248|+0x0070|+014: 0xffff9934c39e2300 <- &task_struct.seccomp.filter\n        0xffff99353fe72250|+0x0078|+015: 0x0000000000000003\n        0xffff99353fe72258|+0x0080|+016: 0x0000000000000004\n        \"\"\"\n        # search for sigpending\n        base = offset_signal + current_arch.ptrsize\n        for i in range(0x100):\n            if is_double_link_list(seccomped_task + base + current_arch.ptrsize * i):\n                base += current_arch.ptrsize * i * 2\n                break\n        else:\n            # Could not find sigpending\n            return None\n\n        # search for seccomp\n        for i in range(0x100):\n            offset_filter = base + current_arch.ptrsize * i\n\n            filt = read_int_from_memory(seccomped_task + offset_filter)\n            if not is_valid_addr(filt):\n                continue\n\n            mode = read_int32_from_memory(seccomped_task + offset_filter - 4 * 2)\n            filtcnt = read_int32_from_memory(seccomped_task + offset_filter - 4)\n\n            \"\"\"\n            #define SECCOMP_MODE_DISABLED 0\n            #define SECCOMP_MODE_STRICT   1\n            #define SECCOMP_MODE_FILTER   2\n            \"\"\"\n            if mode == 0 or filtcnt == 0:\n                continue\n            offset_seccomp = offset_filter - 4 * 2\n            return offset_seccomp\n\n        return None\n\n    def get_offset_prev(self, task_addrs, offset_seccomp):\n        \"\"\"\n        struct seccomp_filter {\n            refcount_t refs; // v5.9~\n            refcount_t users; // v5.9~\n            refcount_t usage; // ~v5.8\n            bool log; // v4.14~\n            bool wait_killable_recv; // v5.19~\n            struct action_cache cache; // v5.11~\n            struct seccomp_filter *prev;\n            struct bpf_prog *prog;\n            struct notification *notif; // v5.0~\n            struct mutex notify_lock; // v5.0~\n            wait_queue_head_t wqh; // v5.9~\n        };\n\n        [Example x64; v6.12.3]\n        0xffff976901e9a300|+0x0000|+000: 0x0000000100000001 // refs, users\n        0xffff976901e9a308|+0x0008|+001: 0x0000000000000000 // log, wait_killable_recv\n        0xffff976901e9a310|+0x0010|+002: 0x1000000000000007 // cache\n        0xffff976901e9a318|+0x0018|+003: 0x0000000000000000 // ...\n        0xffff976901e9a320|+0x0020|+004: 0x0000000000000000\n        0xffff976901e9a328|+0x0028|+005: 0x0000008000000000\n        0xffff976901e9a330|+0x0030|+006: 0x0000000000000000\n        0xffff976901e9a338|+0x0038|+007: 0x0000000000000000\n        0xffff976901e9a340|+0x0040|+008: 0x0000000000000000\n        0xffff976901e9a348|+0x0048|+009: 0xffffffffffff8000\n        0xffff976901e9a350|+0x0050|+010: 0x0000000000000000\n        0xffff976901e9a358|+0x0058|+011: 0x0000000000000000\n        0xffff976901e9a360|+0x0060|+012: 0x0000000000000000\n        0xffff976901e9a368|+0x0068|+013: 0x0000000000000000\n        0xffff976901e9a370|+0x0070|+014: 0x0000000000000000\n        0xffff976901e9a378|+0x0078|+015: 0x0000000000000000\n        0xffff976901e9a380|+0x0080|+016: 0x0000000000000000 // ...\n        0xffff976901e9a388|+0x0088|+017: 0xffffffffffff8000 // cache\n        0xffff976901e9a390|+0x0090|+018: 0x0000000000000000 // prev\n        0xffff976901e9a398|+0x0098|+019: 0xffffaf7c0008d000  ->  0x0000000000030001 // bpf_prog\n        0xffff976901e9a3a0|+0x00a0|+020: 0x0000000000000000\n        0xffff976901e9a3a8|+0x00a8|+021: 0x0000000000000000\n        0xffff976901e9a3b0|+0x00b0|+022: 0x0000000000000000\n        0xffff976901e9a3b8|+0x00b8|+023: 0xffff976901e9a3b8  ->  [loop detected]\n        0xffff976901e9a3c0|+0x00c0|+024: 0xffff976901e9a3b8  ->  [loop detected]\n\n        [Example x64; v5.10.0]\n        0xffff8c1f827f39c0|+0x0000|+000: 0x0000000100000001 // refs, users\n        0xffff8c1f827f39c8|+0x0008|+001: 0x0000000000000000 // log\n        0xffff8c1f827f39d0|+0x0010|+002: 0xffff8c1f827f3780  ->  0x0000000100000001 // prev\n        0xffff8c1f827f39d8|+0x0018|+003: 0xffffa1b3c032b000  ->  0x0000000000030001 // bpf_prog\n        0xffff8c1f827f39e0|+0x0020|+004: 0x0000000000000000\n        0xffff8c1f827f39e8|+0x0028|+005: 0x0000000000000000\n        0xffff8c1f827f39f0|+0x0030|+006: 0x0000000000000000\n        0xffff8c1f827f39f8|+0x0038|+007: 0xffff8c1f827f39f8  ->  [loop detected]\n        0xffff8c1f827f3a00|+0x0040|+008: 0xffff8c1f827f39f8  ->  [loop detected]\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct seccomp_filter*)0).prev\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if offset_seccomp is None:\n            return None\n\n        for task in task_addrs:\n            if not self.has_seccomp(task):\n                continue\n\n            mode = read_int32_from_memory(task + self.offset_seccomp)\n            if mode != 2: # SECCOMP_MODE_FILTER\n                continue\n\n            filter_count = read_int32_from_memory(task + self.offset_seccomp + 4)\n            if filter_count == 0:\n                continue # something is wrong\n\n            filter_ = read_int_from_memory(task + self.offset_seccomp + 4 + 4)\n            for i in range(0x100):\n                # prev\n                x = read_int_from_memory(filter_ + current_arch.ptrsize * i)\n                if (x & 0x7) or (x != 0 and not is_valid_addr(x)): # must be aligned or NULL\n                    continue\n                # prog\n                y = read_int_from_memory(filter_ + current_arch.ptrsize * (i + 1))\n                if (y & 0xfff) or not is_valid_addr(y): # must be page aligned\n                    continue\n                bpf_prog = read_int_from_memory(y)\n                if is_valid_addr(bpf_prog): # not address\n                    continue\n\n                return current_arch.ptrsize * i\n        return None\n\n    def get_offset_prog(self, offset_prev):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct seccomp_filter*)0).prog\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if offset_prev is None:\n            return None\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if kversion < \"3.16\":\n            return None\n\n        return offset_prev + current_arch.ptrsize\n\n    def get_offset_bpf_func(self, task_addrs, offset_seccomp, offset_prog):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct bpf_prog*)0).bpf_func\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if offset_seccomp is None:\n            return None\n        if offset_prog is None:\n            return None\n\n        def is_executable(x):\n            maps = Kernel.get_maps()\n            for start, size, perm in maps:\n                if start <= x and x < start + size:\n                    return perm.endswith(\"X\")\n            return False\n\n        for task in task_addrs:\n            if not self.has_seccomp(task):\n                continue\n\n            filter_ = read_int_from_memory(task + offset_seccomp + 4 + 4)\n            bpf_prog = read_int_from_memory(filter_ + offset_prog)\n            for i in range(0x100):\n                x = read_int_from_memory(bpf_prog + current_arch.ptrsize * i)\n                if is_valid_addr(x) and is_executable(x):\n                    if read_int_from_memory(x) == 0: # something is wrong\n                        continue\n                    return current_arch.ptrsize * i\n        return None\n\n    def get_offset_orig_prog(self, offset_bpf_func):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct bpf_prog*)0).orig_prog\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if offset_bpf_func is None:\n            return None\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if \"5.12\" <= kversion:\n            return offset_bpf_func + current_arch.ptrsize * 2\n        elif \"4.1\" <= kversion:\n            return offset_bpf_func - current_arch.ptrsize\n        elif \"3.18\" <= kversion:\n            return offset_bpf_func - current_arch.ptrsize * 2\n        elif \"3.16\" <= kversion:\n            return offset_bpf_func - current_arch.ptrsize\n        return None\n\n    def get_offset_thread_head(self, task_addr, offset_signal):\n        \"\"\"\n        struct signal_struct {\n            refcount_t sigcnt;\n            atomic_t live;\n            int nr_threads;\n            int quick_threads;\n            struct list_head thread_head;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct signal_struct*)0).thread_head\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        signal = read_int_from_memory(task_addr + offset_signal)\n        for i in range(10):\n            x = read_int_from_memory(signal + current_arch.ptrsize * i)\n            y = read_int_from_memory(signal + current_arch.ptrsize * (i + 1))\n            if is_valid_addr(x) and is_valid_addr(y):\n                offset_thread_head = current_arch.ptrsize * i\n                return offset_thread_head\n        return None\n\n    def get_offset_files(self, task_addrs, offset_comm):\n        \"\"\"\n        struct task_struct {\n            ...\n            char comm[TASK_COMM_LEN];\n            struct nameidata *nameidata;\n        #ifdef CONFIG_SYSVIPC\n            struct sysv_sem {\n                struct sem_undo_list *undo_list;\n            } sysvsem;\n            struct sysv_shm {\n                struct list_head shm_clist;\n            } sysvshm;\n        #endif\n        #ifdef CONFIG_DETECT_HUNG_TASK\n            unsigned long last_switch_count;\n            unsigned long last_switch_time;\n        #endif\n            struct thread_struct thread; // ~v4.1\n            struct fs_struct *fs;\n            struct files_struct *files; <-- here\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).files\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        base = offset_comm + 16 # comm\n        base += current_arch.ptrsize # nameidata\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if \"4.2\" <= kversion:\n            repeat_times = 6\n        else:\n            # sizeof(struct thread_struct) is very large, need more exproring\n            repeat_times = 100\n        for i in range(repeat_times):\n            # check fs\n            v1 = read_int_from_memory(task_addrs[0] + base + current_arch.ptrsize * i)\n            if not is_valid_addr(v1):\n                continue\n            if is_valid_addr(read_int_from_memory(v1)):\n                continue\n            # check files\n            v2 = read_int_from_memory(task_addrs[0] + base + current_arch.ptrsize * (i + 1))\n            if not is_valid_addr(v2):\n                continue\n            if is_valid_addr(read_int_from_memory(v2)):\n                continue\n            # found\n            offset_files = base + current_arch.ptrsize * (i + 1)\n            return offset_files\n        return None\n\n    def get_offset_fdt(self, task_addrs, offset_files):\n        \"\"\"\n        struct files_struct {\n            atomic_t count; // int\n            bool resize_in_progress;   // v4.2~\n            wait_queue_head_t {        // v4.2~\n                spinlock_t lock;       // v4.2~\n                struct list_head head; // v4.2~\n            } resize_wait;             // v4.2~\n            struct fdtable __rcu *fdt; <-- here\n            struct fdtable {\n                unsigned int max_fds;\n                struct file __rcu **fd;\n                unsigned long *close_on_exec;\n                unsigned long *open_fds;\n                unsigned long *full_fds_bits;\n                struct rcu_head rcu;\n            } fdtab;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct files_struct*)0).fdt\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        MAX_FDS_DEFAULT = AddressUtil.get_memory_alignment(in_bits=True)\n        files = read_int_from_memory(task_addrs[0] + offset_files)\n        for i in range(1, 0x100):\n            v = read_int_from_memory(files + current_arch.ptrsize * i)\n            if v != MAX_FDS_DEFAULT:\n                continue\n            offset_fdt = current_arch.ptrsize * (i - 1)\n            return offset_fdt\n        return None\n\n    def get_offset_uid(self, init_task_cred_ptr):\n        \"\"\"\n        struct cred {\n            atomic_t usage; // ~v6.1.69, v6.2~v6.6.7\n            atomic_long_t usage; // v6.1.69~v6.1.143, v6.6.8~\n        #ifdef CONFIG_DEBUG_CREDENTIALS // ~v6.6.7\n            atomic_t subscribers; // ~v6.6.7\n            void *put_addr; // ~v6.6.7\n            unsigned magic; // ~v6.6.7\n        #endif // ~v6.6.7\n            kuid_t uid;\n            kgid_t gid;\n            kuid_t suid;\n            kgid_t sgid;\n            kuid_t euid;\n            kgid_t egid;\n            kuid_t fsuid;\n            kgid_t fsgid;\n            unsigned securebits;\n            kernel_cap_t cap_inheritable;\n            kernel_cap_t cap_permitted;\n            kernel_cap_t cap_effective;\n            kernel_cap_t cap_bset;\n            kernel_cap_t cap_ambient;\n            ...\n        };\n\n        [Example x64]\n            0xffffffff820460c0:     0x0000000000000004      0x0000000000000000\n            0xffffffff820460d0:     0x0000000000000000      0x0000000000000000\n            0xffffffff820460e0:     0x0000000000000000      0x0000000000000000\n            0xffffffff820460f0:     0x0000003fffffffff      0x0000003fffffffff\n            0xffffffff82046100:     0x0000003fffffffff      0x0000000000000000\n            0xffffffff82046110:     0x0000000000000000      0x0000000000000000\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct cred*)0).uid\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if kversion < \"6.1.69\":\n            offset_uid = 4\n        elif kversion < \"6.2\":\n            offset_uid = current_arch.ptrsize\n        elif kversion < \"6.6.8\":\n            offset_uid = 4\n        else:\n            offset_uid = current_arch.ptrsize\n\n        if kversion < \"6.6.8\":\n            init_task_cred = read_int_from_memory(init_task_cred_ptr)\n            uid_gid_size = 4 * 8 # uid_t:4byte. len([uid,gid,suid,sgid,euid,egid,fsuid,fsgid]) == 8\n            ret = read_memory(init_task_cred + offset_uid, uid_gid_size)\n            if ret == b\"\\0\" * uid_gid_size:\n                pass\n            else:\n                offset_uid += 4 + current_arch.ptrsize + 4\n        return offset_uid\n\n    def get_offset_user_ns(self, init_task_cred_ptr, offset_uid):\n        \"\"\"\n        struct cred {\n            ...\n            kernel_cap_t cap_bset;\n            kernel_cap_t cap_ambient; // v4.3~\n        #ifdef CONFIG_KEYS\n            unsigned char jit_keyring;\n            struct key *session_keyring;\n            struct key *process_keyring;\n            struct key *thread_keyring;\n            struct key *request_key_auth;\n        #endif\n        #ifdef CONFIG_SECURITY\n            void *security;\n        #endif\n            struct user_struct *user;\n            struct user_namespace *user_ns;\n            struct ucounts *ucounts; // v5.12.17~\n            struct group_info *group_info;\n            union {\n                int non_rcu;\n                struct rcu_head rcu;\n            };\n        } __randomize_layout;\n\n        [Example x64; CONFIG_KEYS=y, CONFIG_SECURITY=y]\n        0xffffffffbb454580|+0x0000|+000: 0x0000000000000004\n        0xffffffffbb454588|+0x0008|+001: 0x0000000000000000\n        0xffffffffbb454590|+0x0010|+002: 0x0000000000000000\n        0xffffffffbb454598|+0x0018|+003: 0x0000000000000000\n        0xffffffffbb4545a0|+0x0020|+004: 0x0000000000000000\n        0xffffffffbb4545a8|+0x0028|+005: 0x0000000000000000\n        0xffffffffbb4545b0|+0x0030|+006: 0x000001ffffffffff\n        0xffffffffbb4545b8|+0x0038|+007: 0x000001ffffffffff\n        0xffffffffbb4545c0|+0x0040|+008: 0x000001ffffffffff  // cap_bset\n        0xffffffffbb4545c8|+0x0048|+009: 0x0000000000000000  // cap_ambilent\n        0xffffffffbb4545d0|+0x0050|+010: 0x0000000000000000  // jit_keyring\n        0xffffffffbb4545d8|+0x0058|+011: 0x0000000000000000  // session_keyring\n        0xffffffffbb4545e0|+0x0060|+012: 0x0000000000000000  // process_keyring\n        0xffffffffbb4545e8|+0x0068|+013: 0x0000000000000000  // thread_keyring\n        0xffffffffbb4545f0|+0x0070|+014: 0x0000000000000000  // request_key_auth\n        0xffffffffbb4545f8|+0x0078|+015: 0xffff998d8106cb68  ->  0xffff998d81052eb0 // security\n        0xffffffffbb454600|+0x0080|+016: 0xffffffffbb44c6c0  ->  0x0000004e00000075 // user\n        0xffffffffbb454608|+0x0088|+017: 0xffffffffbb44c740  ->  0x0000000000000001 // user_ns\n\n        [Example x64; CONFIG_KEYS=y, CONFIG_SECURITY=y]\n        0xffff9ec6c88379c0|+0x0000|+000: 0x000000000000000a\n        0xffff9ec6c88379c8|+0x0008|+001: 0x0000000000000000\n        0xffff9ec6c88379d0|+0x0010|+002: 0x0000000000000000\n        0xffff9ec6c88379d8|+0x0018|+003: 0x0000000000000000\n        0xffff9ec6c88379e0|+0x0020|+004: 0x0000000000000000\n        0xffff9ec6c88379e8|+0x0028|+005: 0x0000000000000000\n        0xffff9ec6c88379f0|+0x0030|+006: 0x000001ffffffffff\n        0xffff9ec6c88379f8|+0x0038|+007: 0x000001ffffffffff\n        0xffff9ec6c8837a00|+0x0040|+008: 0x000001ffffffffff  // cap_bset\n        0xffff9ec6c8837a08|+0x0048|+009: 0x0000000000000000  // cap_ambient\n        0xffff9ec6c8837a10|+0x0050|+010: 0x0000000000000000  // jit_keyring\n        0xffff9ec6c8837a18|+0x0058|+011: 0xffff9ec6c4643700  ->  0x182031ce00000006 // session_keyring\n        0xffff9ec6c8837a20|+0x0060|+012: 0x0000000000000000  // process_keyring\n        0xffff9ec6c8837a28|+0x0068|+013: 0x0000000000000000  // thread_keyring\n        0xffff9ec6c8837a30|+0x0070|+014: 0x0000000000000000  // request_key_auth\n        0xffff9ec6c8837a38|+0x0078|+015: 0xffff9ec6c8873fe0  ->  0xffff9ec6c1052eb0 // security\n        0xffff9ec6c8837a40|+0x0080|+016: 0xffffffffbb64c5c0  ->  0x0000004f00000084 // user\n        0xffff9ec6c8837a48|+0x0088|+017: 0xffff9ec6c820eaa0  ->  0x0000000000000001 // user_ns\n\n        [Example ARM64; CONFIG_KEYS=n, CONFIG_SECURITY=y]\n        0xffffd9e53efef538|+0x0000|+000: 0x0000000000000004\n        0xffffd9e53efef540|+0x0008|+001: 0x0000000000000000\n        0xffffd9e53efef548|+0x0010|+002: 0x0000000000000000\n        0xffffd9e53efef550|+0x0018|+003: 0x0000000000000000\n        0xffffd9e53efef558|+0x0020|+004: 0x0000000000000000\n        0xffffd9e53efef560|+0x0028|+005: 0x0000000000000000\n        0xffffd9e53efef568|+0x0030|+006: 0x000001ffffffffff\n        0xffffd9e53efef570|+0x0038|+007: 0x000001ffffffffff\n        0xffffd9e53efef578|+0x0040|+008: 0x000001ffffffffff  // cap_bset\n        0xffffd9e53efef580|+0x0048|+009: 0x0000000000000000  // cap_ambient\n        0xffffd9e53efef588|+0x0050|+010: 0x0000000000000000  // security\n        0xffffd9e53efef590|+0x0058|+011: 0xffffd9e53efeeb10  ->  0x000000000000002a // user\n        0xffffd9e53efef598|+0x0060|+012: 0xffffd9e53efeeb98  ->  0x0000000000000001 // user_ns\n\n        [Example x86; CONFIG_KEYS=y, CONFIG_SECURITY=y]\n        0xc1aabbe0|+0x0000|+000: 0x00000004\n        0xc1aabbe4|+0x0004|+001: 0x00000000\n        0xc1aabbe8|+0x0008|+002: 0x00000000\n        0xc1aabbec|+0x000c|+003: 0x00000000\n        0xc1aabbf0|+0x0010|+004: 0x00000000\n        0xc1aabbf4|+0x0014|+005: 0x00000000\n        0xc1aabbf8|+0x0018|+006: 0x00000000\n        0xc1aabbfc|+0x001c|+007: 0x00000000\n        0xc1aabc00|+0x0020|+008: 0x00000000\n        0xc1aabc04|+0x0024|+009: 0x00000000\n        0xc1aabc08|+0x0028|+010: 0x00000000\n        0xc1aabc0c|+0x002c|+011: 0x00000000\n        0xc1aabc10|+0x0030|+012: 0xffffffff\n        0xc1aabc14|+0x0034|+013: 0x000001ff\n        0xc1aabc18|+0x0038|+014: 0xffffffff\n        0xc1aabc1c|+0x003c|+015: 0x000001ff\n        0xc1aabc20|+0x0040|+016: 0xffffffff  // cap_bset\n        0xc1aabc24|+0x0044|+017: 0x000001ff\n        0xc1aabc28|+0x0048|+018: 0x00000000  // cap_abmient\n        0xc1aabc2c|+0x004c|+019: 0x00000000\n        0xc1aabc30|+0x0050|+020: 0x00000000  // jit_keyring\n        0xc1aabc34|+0x0054|+021: 0x00000000  // session_keyring\n        0xc1aabc38|+0x0058|+022: 0x00000000  // process_keyring\n        0xc1aabc3c|+0x005c|+023: 0x00000000  // thread_keyring\n        0xc1aabc40|+0x0060|+024: 0x00000000  // request_key_auth\n        0xc1aabc44|+0x0064|+025: 0xc201e8b0  ->  0xc20ecd94 // security\n        0xc1aabc48|+0x0068|+026: 0xc1aa6b80  ->  0x00000068 // user\n        0xc1aabc4c|+0x006c|+027: 0xc1aa6be0  ->  0x00000001 // user_ns\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct cred*)0).user_ns\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        # uid_t:4byte. len([uid,gid,suid,sgid,euid,egid,fsuid,fsgid]) == 8\n        uid_gid_size = 4 * 8\n        sizeof_securebits = 4\n        if \"4.3\" <= kversion:\n            # cap_t:8byte. len([cap_inheritable,cap_permitted,cap_effective,cap_bset,cap_ambient]) == 5\n            cap_size = 8 * 5\n        else:\n            # cap_t:8byte. len([cap_inheritable,cap_permitted,cap_effective,cap_bset]) == 4\n            cap_size = 8 * 4\n\n        \"\"\"\n        struct user_namespace {\n            struct uid_gid_map uid_map;\n            ...\n        };\n\n        struct uid_gid_map { /* 64 bytes -- 1 cache line */\n            u32 nr_extents; // ~v6.11\n            union {\n                struct {\n                    struct uid_gid_extent extent[UID_GID_MAP_MAX_BASE_EXTENTS];\n                    u32 nr_extents; v6.12~\n                };\n                struct {\n                    struct uid_gid_extent *forward;\n                    struct uid_gid_extent *reverse;\n                };\n            };\n        };\n        \"\"\"\n        if kversion < \"6.12\":\n            offset_nr_extents = 0\n        else:\n            offset_nr_extents = 60\n\n        for i in range(10):\n            offset_user_ns = offset_uid + uid_gid_size + sizeof_securebits\n            offset_user_ns = align_to_ptrsize(offset_user_ns)\n            offset_user_ns += cap_size + current_arch.ptrsize * i\n            v = read_int_from_memory(init_task_cred_ptr + offset_user_ns)\n            if not is_valid_addr(v):\n                continue\n            w = read_int_from_memory(v + offset_nr_extents)\n            if w == 1:\n                return offset_user_ns\n        return None\n\n    class MapleTree:\n        \"\"\"Linux v6.1 introduces maple_tree. This is a simple parser.\"\"\"\n        MT_FLAGS_HEIGHT_MASK = 0x7c\n        MT_FLAGS_HEIGHT_OFFSET = 0x02\n        MAPLE_NODE_TYPE_SHIFT = 0x03\n        MAPLE_NODE_TYPE_MASK = 0x0f\n        MAPLE_NODE_POINTER_MASK = 0xff\n        MAPLE_DENSE = 0\n        MAPLE_LEAF_64 = 1\n        MAPLE_RANGE_64 = 2\n        MAPLE_ARANGE_64 = 3\n\n        def __init__(self, mm, quiet):\n            self.quiet = quiet\n            kversion = Kernel.kernel_version()\n            \"\"\"\n            struct mm_struct {\n                struct {\n                    struct {\n                        atomic_t mm_count;\n                    } ____cacheline_aligned_in_smp; // v6.4~\n                    struct maple_tree {\n                        union {\n                            spinlock_t ma_lock;\n                            lockdep_map_p ma_external_lock;\n                        };\n                        unsigned int ma_flags; // v6.6~\n                        void __rcu *ma_root; // this points root maple_node. (lower 8-bits are some flags)\n                        unsigned int ma_flags; // ~v6.5\n                    } mm_mt;\n                    ...\n                } __randomize_layout;\n                ...\n            };\n            \"\"\"\n\n            # ____cacheline_aligned_in_smp attribute, spinlock_t and lockdep_map_p can be different size\n            # in each environment or situation, so search for it heuristically.\n            for i in range(0x20):\n                x = read_int_from_memory(mm + current_arch.ptrsize * i)\n                \"\"\"\n                [x64 v6.4.2]\n                0xffff8bedc104db00|+0x0000|+000: 0x0000000000000000   // union  <-- mm_mt\n                0xffff8bedc104db08|+0x0008|+001: 0xffff8bedc1a6601e   // ma_root\n                0xffff8bedc104db10|+0x0010|+002: 0x000000000000030b   // ma_flags\n\n                [x64 v6.6.1]\n                0xffff972801b78a38|+0x0040|+008: 0x0000000000000000   // (the end of cacheline?)\n                0xffff972801b78a40|+0x0040|+008: 0x0000030b00000000   // ma_flags || union  <-- mm_mt\n                0xffff972801b78a48|+0x0048|+009: 0xffff972801b0cc1e   // ma_root\n                \"\"\"\n                if is_valid_addr(x) and (x & 0xff) in [0x1e, 0x0e]:\n                    offset_ma_root = current_arch.ptrsize * i\n                    if kversion < \"6.6\":\n                        offset_ma_flags = offset_ma_root + current_arch.ptrsize\n                    else:\n                        offset_ma_flags = offset_ma_root - 4\n                        if is_64bit() and read_int32_from_memory(mm + offset_ma_flags) == 0:\n                            offset_ma_flags = offset_ma_root - 8\n                    break\n            else:\n                raise\n\n            self.ma_root_raw = read_int_from_memory(mm + offset_ma_root)\n            self.ma_flags = read_int32_from_memory(mm + offset_ma_flags)\n            self.max_depth = (self.ma_flags & self.MT_FLAGS_HEIGHT_MASK) >> self.MT_FLAGS_HEIGHT_OFFSET\n\n            if is_64bit():\n                self.MAPLE_NODE_SLOTS = 31\n                self.MAPLE_RANGE64_SLOTS = 16\n                self.MAPLE_ARANGE64_SLOTS = 10\n                self.MAPLE_ALLOC_SLOTS = self.MAPLE_NODE_SLOTS - 1\n                self.maple_range_64_offset_slot = current_arch.ptrsize * self.MAPLE_RANGE64_SLOTS\n                self.maple_arange_64_offset_slot = current_arch.ptrsize * self.MAPLE_ARANGE64_SLOTS\n                self.maple_alloc_offset_slot = current_arch.ptrsize * 2\n            else:\n                self.MAPLE_NODE_SLOTS = 63\n                self.MAPLE_RANGE64_SLOTS = 32\n                self.MAPLE_ARANGE64_SLOTS = 21\n                self.MAPLE_ALLOC_SLOTS = self.MAPLE_NODE_SLOTS - 2\n                self.maple_range_64_offset_slot = current_arch.ptrsize * self.MAPLE_RANGE64_SLOTS\n                self.maple_arange_64_offset_slot = current_arch.ptrsize * self.MAPLE_ARANGE64_SLOTS\n                self.maple_alloc_offset_slot = current_arch.ptrsize * 3\n\n            self.seen = set()\n            self.iters = self.parse_node(self.ma_root_raw, 1)\n            return\n\n        def get_next(self, _=None):\n            # iterate all `vm_area_struct` pointers\n            for addr in self.iters:\n                return addr\n            return None\n\n        def parse_node(self, entry, depth):\n            if entry in self.seen:\n                return\n            self.seen.add(entry)\n\n            if self.max_depth < depth:\n                return\n\n            pointer = entry & ~(self.MAPLE_NODE_POINTER_MASK)\n            node_type = (entry >> self.MAPLE_NODE_TYPE_SHIFT) & self.MAPLE_NODE_TYPE_MASK\n\n            if node_type == self.MAPLE_DENSE:\n                slot_top = pointer + self.maple_alloc_offset_slot\n                for i in range(self.MAPLE_ALLOC_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        if is_valid_addr(slot):\n                            yield slot\n            elif node_type == self.MAPLE_LEAF_64:\n                slot_top = pointer + self.maple_range_64_offset_slot\n                for i in range(self.MAPLE_RANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        if is_valid_addr(slot):\n                            yield slot\n            elif node_type == self.MAPLE_RANGE_64:\n                slot_top = pointer + self.maple_range_64_offset_slot\n                for i in range(self.MAPLE_RANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        yield from self.parse_node(slot, depth + 1)\n            elif node_type == self.MAPLE_ARANGE_64:\n                slot_top = pointer + self.maple_arange_64_offset_slot\n                for i in range(self.MAPLE_ARANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        yield from self.parse_node(slot, depth + 1)\n            return\n\n    def get_vm_area_struct(self, mm):\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None, None\n        if kversion < \"6.1\":\n            \"\"\"\n            struct mm_struct {\n                struct {\n                    struct vm_area_struct *mmap;\n                    ...\n                } __randomize_layout;\n            };\n            \"\"\"\n            offset_mmap = 0\n            vm_area_struct = read_int_from_memory(mm + offset_mmap)\n\n            \"\"\"\n            struct vm_area_struct {\n                unsigned long vm_start;\n                unsigned long vm_end;\n                struct vm_area_struct *vm_next, *vm_prev;\n                struct rb_node vm_rb;\n                unsigned long rb_subtree_gap;\n                struct mm_struct *vm_mm;\n                pgprot_t vm_page_prot;\n                unsigned long vm_flags;\n                struct {\n                    struct rb_node rb;\n                    unsigned long rb_subtree_last;\n                } shared;\n                struct list_head anon_vma_chain;\n                struct anon_vma *anon_vma;\n                const struct vm_operations_struct *vm_ops;\n                unsigned long vm_pgoff;\n                struct file *vm_file;\n                ...\n            };\n            \"\"\"\n\n            def get_next_vma_area_struct(current):\n                return read_int_from_memory(current + current_arch.ptrsize * 2)\n\n        else: # \"6.1\" <= kversion\n            \"\"\"\n            struct mm_struct {\n                struct {\n                    struct {\n                        atomic_t mm_count;\n                    } ____cacheline_aligned_in_smp; // v6.4~\n                    struct maple_tree {\n                        union {\n                            spinlock_t ma_lock;\n                            lockdep_map_p ma_external_lock;\n                        };\n                        unsigned int ma_flags; // v6.6~\n                        void __rcu *ma_root; // this points root maple_node. (lower 8-bits are some flags)\n                        unsigned int ma_flags; // ~v6.5\n                    } mm_mt;\n                    ...\n                } __randomize_layout;\n                ...\n            };\n\n            struct maple_node {\n                union {\n                    struct {\n                        struct maple_pnode *parent;\n                        void __rcu *slot[MAPLE_NODE_SLOTS]; // 64-bit: 31; 32-bit: 63\n                    };\n                    struct {\n                        void *pad;\n                        struct rcu_head rcu;\n                        struct maple_enode *piv_parent;\n                        unsigned char parent_slot;\n                        enum maple_type type;\n                        unsigned char slot_len;\n                        unsigned int ma_flags;\n                    };\n                    struct maple_range_64 {\n                        struct maple_pnode *parent;\n                        unsigned long pivot[MAPLE_RANGE64_SLOTS - 1];     // 64-bit: 15; 32-bit: 31\n                        union {\n                            void __rcu *slot[MAPLE_RANGE64_SLOTS];        // 64-bit: 16; 32-bit: 32\n                            struct {\n                                void __rcu *pad[MAPLE_RANGE64_SLOTS - 1]; // 64-bit: 15; 32-bit: 31\n                                struct maple_metadata meta;\n                            };\n                        };\n                    } mr64;\n                    struct maple_arange_64 {\n                        struct maple_pnode *parent;\n                        unsigned long pivot[MAPLE_ARANGE64_SLOTS - 1]; // 64-bit: 9;  32-bit: 20\n                        void __rcu *slot[MAPLE_ARANGE64_SLOTS];        // 64-bit: 10; 32-bit: 21\n                        unsigned long gap[MAPLE_ARANGE64_SLOTS];       // 64-bit: 10; 32-bit: 21\n                        struct maple_metadata meta;\n                    } ma64;\n                    struct maple_alloc {\n                        unsigned long total;\n                        unsigned char node_count;\n                        unsigned int request_count;\n                        struct maple_alloc *slot[MAPLE_ALLOC_SLOTS]; // 64-bit: 30; 32-bit: 31\n                    } alloc;\n                };\n            };\n            \"\"\"\n            get_next_vma_area_struct = self.MapleTree(mm, self.args.quiet).get_next\n            vm_area_struct = get_next_vma_area_struct()\n\n            \"\"\"\n            struct vm_area_struct {\n                unsigned long vm_start;\n                unsigned long vm_end;\n                struct mm_struct *vm_mm;\n                pgprot_t vm_page_prot;\n                unsigned long vm_flags;\n            #ifdef CONFIG_PER_VMA_LOCK                 // v6.4~\n                int vm_lock_seq;                       // v6.4~\n                struct vma_lock *vm_lock;              // v6.4~\n                bool detached;                         // v6.4~\n            #endif                                     // v6.4~\n                struct {                               // v6.2~\n                    struct rb_node rb;                 // v6.2~\n                    unsigned long rb_subtree_last;     // v6.2~\n                } shared;                              // v6.2~\n                union {                                // ~v6.1\n                    struct {                           // ~v6.1\n                        struct rb_node rb;             // ~v6.1\n                        unsigned long rb_subtree_last; // ~v6.1\n                    } shared;                          // ~v6.1\n                    struct anon_vma_name *anon_name;   // ~v6.1\n                };                                     // ~v6.1\n                struct list_head anon_vma_chain;\n                struct anon_vma *anon_vma;\n                const struct vm_operations_struct *vm_ops;\n                unsigned long vm_pgoff;\n                struct file *vm_file;\n                ...\n            };\n            \"\"\"\n        return vm_area_struct, get_next_vma_area_struct\n\n    def get_offset_vm_mm(self, task_addrs, offset_mm):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct vm_area_struct*)0).vm_mm\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        for task in task_addrs:\n            mm = read_int_from_memory(task + offset_mm)\n            if mm == 0:\n                continue\n\n            vm_area_struct, _ = self.get_vm_area_struct(mm)\n            if vm_area_struct is None:\n                return None\n\n            current = vm_area_struct\n            while True:\n                x = read_int_from_memory(current)\n                if x == mm:\n                    break\n                current += current_arch.ptrsize\n            offset_vm_mm = current - vm_area_struct\n            return offset_vm_mm\n        return None\n\n    def get_offset_vm_flags(self, offset_vm_mm):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct vm_area_struct*)0).vm_flags\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if is_64bit():\n            offset_vm_flags = offset_vm_mm + 8 * 2\n        elif is_x86_32():\n            cr4 = get_register(\"cr4\", use_monitor=True)\n            if (cr4 >> 5) & 1: # PAE check\n                offset_vm_flags = offset_vm_mm + 8 * 2\n            else:\n                offset_vm_flags = offset_vm_mm + 4 * 2\n        elif is_arm32():\n            ret = gdb.execute(\"pagewalk --no-pager --disable-color\", to_string=True)\n            if \"using long description\" in ret:\n                offset_vm_flags = offset_vm_mm + 8 * 2\n            else:\n                offset_vm_flags = offset_vm_mm + 4 * 2\n        return offset_vm_flags\n\n    def get_offset_vm_file(self, task_addrs, offset_mm, offset_vm_flags):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct vm_area_struct*)0).vm_file\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        for i in range(50):\n            found = True\n            for task in task_addrs:\n                # skip kernel thread\n                mm = read_int_from_memory(task + offset_mm)\n                if mm == 0:\n                    continue\n\n                \"\"\"\n                normal case:\n                [x64 5.10.127; corjail; sh]\n                0xffff9df049f75cc0|+0x0000|+000: 0x0000564e44351000 // vm_start\n                0xffff9df049f75cc8|+0x0008|+001: 0x0000564e4437f000 // vm_end\n                0xffff9df049f75cd0|+0x0010|+002: 0xffff9df049f75000 // vm_next\n                0xffff9df049f75cd8|+0x0018|+003: 0x0000000000000000 // vm_prev\n                0xffff9df049f75ce0|+0x0020|+004: 0xffff9df049f75021 // vm_rb.__rb_parent_color\n                0xffff9df049f75ce8|+0x0028|+005: 0x0000000000000000 // vm_rb.rb_right\n                0xffff9df049f75cf0|+0x0030|+006: 0x0000000000000000 // vm_rb.rb_left\n                0xffff9df049f75cf8|+0x0038|+007: 0x0000564e44351000 // rb_subtree_gap\n                0xffff9df049f75d00|+0x0040|+008: 0xffff9df0426c8800 // vm_mm\n                0xffff9df049f75d08|+0x0048|+009: 0x8000000000000025 // vm_page_prot\n                0xffff9df049f75d10|+0x0050|+010: 0x0000000008000871 // vm_flags\n                0xffff9df049f75d18|+0x0058|+011: 0xffff9df049f75059 // shared.rb.__rb_parent_color\n                0xffff9df049f75d20|+0x0060|+012: 0x0000000000000000 // shared.rb.rb_right\n                0xffff9df049f75d28|+0x0068|+013: 0x0000000000000000 // shared.rb.rb_left\n                0xffff9df049f75d30|+0x0070|+014: 0x000000000000002d // shared.rb_subtree_last\n                0xffff9df049f75d38|+0x0078|+015: 0xffff9df049f75d38 // anon_vma_chain.next\n                0xffff9df049f75d40|+0x0080|+016: 0xffff9df049f75d38 // anon_vma_chain.prev\n                0xffff9df049f75d48|+0x0088|+017: 0x0000000000000000 // anon_vma\n                0xffff9df049f75d50|+0x0090|+018: 0xffffffff9b034380 // vm_ops\n                0xffff9df049f75d58|+0x0098|+019: 0x0000000000000000 // vm_pgoff\n                0xffff9df049f75d60|+0x00a0|+020: 0xffff9df0427a5800 // vm_file\n\n                rare case: both vm_ops and vm_file are NULL\n                [x64; 5.10.127; corjail; dockerd]\n                0xffff9df04678aa80|+0x0000|+000: 0x000000c000000000 // vm_start\n                0xffff9df04678aa88|+0x0008|+001: 0x000000c000400000 // vm_end\n                0xffff9df04678aa90|+0x0010|+002: 0xffff9df04670d9c0 // vm_next\n                0xffff9df04678aa98|+0x0018|+003: 0x0000000000000000 // vm_prev\n                0xffff9df04678aaa0|+0x0020|+004: 0xffff9df04670d9e1 // vm_rb.__rb_parent_color\n                0xffff9df04678aaa8|+0x0028|+005: 0x0000000000000000 // vm_rb.rb_right\n                0xffff9df04678aab0|+0x0030|+006: 0x0000000000000000 // vm_rb.rb_left\n                0xffff9df04678aab8|+0x0038|+007: 0x000000c000000000 // rb_subtree_gap\n                0xffff9df04678aac0|+0x0040|+008: 0xffff9df0426ca800 // vm_mm\n                0xffff9df04678aac8|+0x0048|+009: 0x8000000000000025 // vm_page_prot\n                0xffff9df04678aad0|+0x0050|+010: 0x0000000008100073 // vm_flags\n                0xffff9df04678aad8|+0x0058|+011: 0x0000000000000000 // shared.rb.__rb_parent_color\n                0xffff9df04678aae0|+0x0060|+012: 0x0000000000000000 // shared.rb.rb_right\n                0xffff9df04678aae8|+0x0068|+013: 0x0000000000000000 // shared.rb.rb_left\n                0xffff9df04678aaf0|+0x0070|+014: 0x0000000000000000 // shared.rb_subtree_last\n                0xffff9df04678aaf8|+0x0078|+015: 0xffff9df04676ea90 // anon_vma_chain.next\n                0xffff9df04678ab00|+0x0080|+016: 0xffff9df04676ea90 // anon_vma_chain.prev\n                0xffff9df04678ab08|+0x0088|+017: 0xffff9df04279e318 // anon_vma\n                0xffff9df04678ab10|+0x0090|+018: 0x0000000000000000 // vm_ops\n                0xffff9df04678ab18|+0x0098|+019: 0x000000000c000000 // vm_pgoff\n                0xffff9df04678ab20|+0x00a0|+020: 0x0000000000000000 // vm_file\n\n                normal case:\n                [x64 6.6.0; trust_storage; init]\n                0xffff000001ee6630|+0x0000|+000: 0x0000aaaac690d000 // vm_start\n                0xffff000001ee6638|+0x0008|+001: 0x0000aaaac69d4000 // vm_end\n                0xffff000001ee6640|+0x0010|+002: 0xffff0000010a84c0 // vm_mm\n                0xffff000001ee6648|+0x0018|+003: 0x0020000000000fc3 // vm_page_prot\n                0xffff000001ee6650|+0x0020|+004: 0x0000000000000075 // vm_flags\n                0xffff000001ee6658|+0x0028|+005: 0x0000000000000003 // vm_lock_seq\n                0xffff000001ee6660|+0x0030|+006: 0xffff000001ee7168 // vm_lock\n                0xffff000001ee6668|+0x0038|+007: 0x0000000000000000 // detached\n                0xffff000001ee6670|+0x0040|+008: 0xffff000005f831a1 // shared.rb.__rb_parent_color\n                0xffff000001ee6678|+0x0048|+009: 0x0000000000000000 // shared.rb.rb_right\n                0xffff000001ee6680|+0x0050|+010: 0x0000000000000000 // shared.rb.rb_left\n                0xffff000001ee6688|+0x0058|+011: 0x00000000000000c6 // shared.rb_subtree_last\n                0xffff000001ee6690|+0x0060|+012: 0xffff000001ee6690 // anon_vma_chain.next\n                0xffff000001ee6698|+0x0068|+013: 0xffff000001ee6690 // anon_vma_chain.prev\n                0xffff000001ee66a0|+0x0070|+014: 0x0000000000000000 // anon_vma\n                0xffff000001ee66a8|+0x0078|+015: 0xffffa4277c4d80c8 // vm_ops\n                0xffff000001ee66b0|+0x0080|+016: 0x0000000000000000 // vm_pgoff\n                0xffff000001ee66b8|+0x0088|+017: 0xffff00000025d400 // vm_file\n                \"\"\"\n                vm_area_struct, _ = self.get_vm_area_struct(mm)\n                ptr_anon_vma_chain = vm_area_struct + offset_vm_flags + current_arch.ptrsize * i\n                if not is_double_link_list(ptr_anon_vma_chain):\n                    found = False\n                    break\n                ptr_anon_vma = vm_area_struct + offset_vm_flags + current_arch.ptrsize * (i + 2)\n                anon_vma = read_int_from_memory(ptr_anon_vma)\n                if anon_vma != 0 and not is_valid_addr(anon_vma): # allow NULL\n                    found = False\n                    break\n                ptr_vm_ops = vm_area_struct + offset_vm_flags + current_arch.ptrsize * (i + 3)\n                vm_ops = read_int_from_memory(ptr_vm_ops)\n                if vm_ops != 0 and not is_valid_addr(vm_ops): # allow NULL\n                    found = False\n                    break\n                ptr_vm_file = vm_area_struct + offset_vm_flags + current_arch.ptrsize * (i + 5)\n                vm_file = read_int_from_memory(ptr_vm_file)\n                if vm_file != 0 and not is_valid_addr(vm_file): # allow NULL\n                    found = False\n                    break\n            if found:\n                return offset_vm_flags + current_arch.ptrsize * (i + 5)\n        return None\n\n    def get_mm(self, task, offset_mm):\n        mm = read_int_from_memory(task + offset_mm)\n        if mm == 0:\n            return []\n\n        vm_areas = []\n        VmArea = collections.namedtuple(\"VmArea\", \"start end flags file\")\n        current, get_next_vma_area_struct = self.get_vm_area_struct(mm)\n        while current:\n            vm_start = read_int_from_memory(current)\n            vm_end = read_int_from_memory(current + current_arch.ptrsize)\n            vm_flags = read_int_from_memory(current + self.offset_vm_flags)\n            vm_file = read_int_from_memory(current + self.offset_vm_file)\n            filepath = self.get_filepath(vm_file)\n            perm = Permission(value=vm_flags)\n            vm_areas.append(VmArea(vm_start, vm_end, str(perm), filepath))\n            current = get_next_vma_area_struct(current)\n        return vm_areas\n\n    def get_offset_mnt(self, file):\n        \"\"\"\n        [~v6.4]\n        struct file {\n            union {                           // ~v5.19\n                struct llist_node fu_llist;   // ~v5.19\n                struct rcu_head fu_rcuhead;   // ~v5.19\n            } f_u;                            // ~v5.19\n            union {                           // v6.0~\n                struct llist_node f_llist;    // v6.0~\n                struct rcu_head f_rcuhead;    // v6.0~\n                unsigned int f_iocb_flags;    // v6.0~\n            };                                // v6.0~\n            struct path {\n                struct vfsmount *mnt;\n                struct dentry *dentry;\n            } f_path;\n            struct inode *f_inode;            // v3.9~\n            ...\n        };\n\n        [v6.5~v6.11]\n        struct file {\n            union {\n                struct callback_head {\n                    struct callback_head *next;\n                    void (*func)(struct callback_head *head);\n                } f_task_work; // v6.8~;\n                struct llist_node f_llist;\n                struct rcu_head f_rcuhead; // ~v6.7 (=callback_head)\n                unsigned int f_iocb_flags;\n            };\n            spinlock_t f_lock;\n            fmode_t f_mode;\n            atomic_long_t f_count;\n            struct mutex f_pos_lock;\n            loff_t f_pos;\n            unsigned int f_flags;\n            struct fown_struct {\n                rwlock_t lock;\n                struct pid *pid;\n                enum pid_type pid_type;\n                kuid_t uid, euid;\n                int signum;\n            } f_owner;\n            const struct cred *f_cred;\n            struct file_ra_state {\n                pgoff_t start;\n                unsigned int size;\n                unsigned int async_size;\n                unsigned int ra_pages;\n                unsigned int mmap_miss;\n                loff_t prev_pos;\n            } f_ra;\n            struct path {\n                struct vfsmount *mnt;\n                struct dentry *dentry;\n            } f_path;\n            struct inode *f_inode;\n            ...\n        };\n\n        [v6.12~]\n        struct file {\n            atomic_long_t f_count; // v6.12\n            file_ref_t f_ref; // v6.13~v6.14\n            spinlock_t f_lock;\n            fmode_t f_mode;\n            const struct file_operations *f_op;\n            struct address_space *f_mapping;\n            void *private_data;\n            struct inode *f_inode;\n            unsigned int f_flags;\n            unsigned int f_iocb_flags;\n            const struct cred *f_cred;\n            struct fown_struct *f_owner; // v6.15~\n            /* --- cacheline 1 boundary (64 bytes) --- */\n            struct path {\n                struct vfsmount *mnt;\n                struct dentry *dentry;\n            } f_path;\n            union {\n                struct mutex f_pos_lock;\n                u64 f_pipe;\n            };\n            loff_t f_pos;\n            ...\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct file*)0).f_path\")\n            ) + to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct path*)0).mnt\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if not is_valid_addr(file):\n            return None\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if kversion < \"6.5\":\n            offset_mnt = current_arch.ptrsize * 2\n        elif \"6.5\" <= kversion < \"6.12\":\n            # plan 1\n            \"\"\"\n            gef> slab-contains 0xffff9f49811d33e0\n            slab: 0xfffff93f800474c0\n            kmem_cache: 0xffff9f4981048c00\n            base: 0xffff9f49811d3000\n            name: mnt_cache  size: 0x140  num_pages: 0x1 (unaligned?)\n            \"\"\"\n            for i in range(0x40):\n                cand_offset_mnt = current_arch.ptrsize * i\n                mnt = read_int_from_memory(file + cand_offset_mnt)\n                # f_path.mnt points in the middle of the chunk, so the \"unaligned?\" warning is not a problem\n                ret = Kernel.get_slab_contains(mnt, allow_unaligned=True)\n                if not ret:\n                    continue\n                if \"mnt_cache\" in ret:\n                    offset_mnt = cand_offset_mnt\n                    break\n            else:\n                # plan 2\n                \"\"\"\n                It has also been observed when mnt_cache is not used.\n                In this case, the 2 previous elements from ext4_inode_cache or shmem_inode_cache\n                seem to be the relevant pointer.\n\n                0xffff8b864013a298|+0x0098|+019: 0xffff8b86436e4da0 (task_group) <-- here is mnt but various slab names\n                0xffff8b864013a2a0|+0x00a0|+020: 0xffff8b86404079c0 (kmalloc-rcl-192)\n                0xffff8b864013a2a8|+0x00a8|+021: 0xffff8b864041e0a8 (ext4_inode_cache) <- unique (`*_inode_cache`)\n\n                0xffff8b864013a698|+0x0098|+019: 0xffff8b8640171020 (task_group) <-- here is mnt but various slab names\n                0xffff8b864013a6a0|+0x00a0|+020: 0xffff8b86436159c0 (kmalloc-rcl-192)\n                0xffff8b864013a6a8|+0x00a8|+021: 0xffff8b8643730640 (shmem_inode_cache) <- unique (`*_inode_cache`)\n                \"\"\"\n                for i in range(0x40):\n                    cand_offset_mnt = current_arch.ptrsize * i\n                    mnt = read_int_from_memory(file + cand_offset_mnt)\n                    ret = Kernel.get_slab_contains(mnt, allow_unaligned=True)\n                    if not ret:\n                        continue\n                    if \"inode_cache\" in ret:\n                        offset_mnt = cand_offset_mnt - current_arch.ptrsize * 2\n                        break\n                else:\n                    raise\n        elif \"6.12\" <= kversion:\n            if is_64bit():\n                offset_mnt = 64\n            else:\n                \"\"\"\n                0x811f3180|+0x0000|+000: f_count        : 0x00000004\n                0x811f3184|+0x0004|+001: f_lock         : 0x00000000\n                0x811f3188|+0x0008|+002: f_mode         : 0x004a801d\n                0x811f318c|+0x000c|+003: f_op           : 0x80a0e040  ->  0x00000000\n                0x811f3190|+0x0010|+004: f_mapping      : 0x813a2140  ->  0x813a2050  ->  0x000589ed\n                0x811f3194|+0x0014|+005: private_data   : 0x00000000\n                0x811f3198|+0x0018|+006: f_inode        : 0x813a2050  ->  0x000589ed\n                0x811f319c|+0x001c|+007: f_flags        : 0x00020020\n                0x811f31a0|+0x0020|+008: f_iocb_flags   : 0x00000000\n                0x811f31a4|+0x0024|+009: f_cred         : 0x81378280  ->  0x00000005\n                0x811f31a8|+0x0028|+010: f_path.mnt     : 0x810043d0  ->  0x81402088  ->  0x00210000\n                0x811f31ac|+0x002c|+011: f_path.dentry  : 0x814fd990  ->  0x00400008\n                0x811f31b0|+0x0030|+012: mutex.owner    : 0x00000000\n                0x811f31b4|+0x0034|+013: mutex.wait_lock: 0x00000000\n                0x811f31b8|+0x0038|+014:                : 0x00000000\n\n                pattern of sizeof(lock) == 0:\n                0xc33c7100|+0x0000|+000: f_lock,f_mode         : 0x0c4a801d\n                0xc33c7104|+0x0004|+001: f_op                  : 0xc1f9bee0  ->  0x00000000\n                0xc33c7108|+0x0008|+002: f_mapping             : 0xc3491150  ->  0xc3491068  ->  0x000d89ed\n                0xc33c710c|+0x000c|+003: private_data          : 0x00000000\n                0xc33c7110|+0x0010|+004: f_inode               : 0xc3491068  ->  0x000d89ed\n                0xc33c7114|+0x0014|+005: f_flags               : 0x00008020\n                0xc33c7118|+0x0018|+006: f_iocb_flags          : 0x00000000\n                0xc33c711c|+0x001c|+007: f_cred                : 0xc30ba080  ->  0x00000004\n                0xc33c7120|+0x0020|+008: f_owner               : 0x00000000\n                0xc33c7124|+0x0024|+009: f_path.mnt            : 0xc38b4f10  ->  0xc3459300  ->  0x00100000\n                0xc33c7128|+0x0028|+010: f_path.dentry         : 0xc3459580  ->  0x00200000\n                0xc33c712c|+0x002c|+011: mutex.owner           : 0x00000000\n                0xc33c7130|+0x0030|+012: mutex.wait_{lock,list}: 0xc33c7130  ->  [loop detected]\n                0xc33c7134|+0x0034|+013:                       : 0xc33c7130  ->  [loop detected]\n                \"\"\"\n                for i in range(16):\n                    cand_offset_mnt = current_arch.ptrsize * (i + 9)\n                    # f_path.mnt\n                    if not is_valid_addr_addr(file + cand_offset_mnt):\n                        continue\n                    # f_path.mnt.mnt_root\n                    x = read_int_from_memory(read_int_from_memory(file + cand_offset_mnt))\n                    if not is_valid_addr(x):\n                        continue\n                    # f_path.dentry\n                    if not is_valid_addr_addr(file + cand_offset_mnt + current_arch.ptrsize):\n                        continue\n                    offset_mnt = cand_offset_mnt\n                    break\n                else:\n                    raise\n        return offset_mnt\n\n    def get_offset_dentry(self, offset_mnt):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct file*)0).f_path\")\n            ) + to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct path*)0).dentry\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        return offset_mnt + current_arch.ptrsize\n\n    def get_offset_d_iname(self, dentry):\n        \"\"\"\n        struct dentry {\n            unsigned int d_flags;\n            seqcount_spinlock_t d_seq;\n            struct hlist_bl_node d_hash;\n            struct dentry *d_parent;\n                                           // Padding can be added here\n            struct qstr {\n                union {\n                    struct {\n                        HASH_LEN_DECLARE;\n                    };\n                    u64 hash_len;\n                };\n                const unsigned char *name; // this points d_iname\n            } d_name;\n            struct inode *d_inode;\n            unsigned char d_iname[DNAME_INLINE_LEN];\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct dentry*)0).d_iname\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        current = dentry\n        while True:\n            name = read_int_from_memory(current)\n            if 0 < name - current <= 0x20:\n                offset_d_iname = name - dentry\n                break\n            current += current_arch.ptrsize\n        return offset_d_iname\n\n    def get_offset_d_inode(self, offset_d_iname):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct dentry*)0).d_inode\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        return offset_d_iname - current_arch.ptrsize\n\n    def get_offset_d_parent(self, dentry, offset_d_iname):\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct dentry*)0).d_parent\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        offset_dname_name = offset_d_iname - current_arch.ptrsize * 2\n        # skip if padding\n        while read_int_from_memory(dentry + offset_dname_name) != dentry + offset_d_iname:\n            offset_dname_name -= current_arch.ptrsize\n\n        offset_d_parent = offset_dname_name - 8 - current_arch.ptrsize\n        # skip if padding\n        while True:\n            if is_valid_addr_addr(dentry + offset_d_parent): # roughly check\n                parent = read_int_from_memory(dentry + offset_d_parent)\n                if (parent & 0b11) == 0: # align check\n                    parent_parent = read_int_from_memory(parent + offset_d_parent)\n                    if is_valid_addr(parent_parent):\n                        break\n            offset_d_parent -= current_arch.ptrsize\n        return offset_d_parent\n\n    def get_offset_i_ino(self, inode):\n        \"\"\"\n        struct inode {\n            umode_t i_mode;\n            unsigned short i_opflags;\n            kuid_t i_uid;\n            kgid_t i_gid;\n            unsigned int i_flags;\n        #ifdef CONFIG_FS_POSIX_ACL\n            struct posix_acl *i_acl;\n            struct posix_acl *i_default_acl;\n        #endif\n            const struct inode_operations *i_op;\n            struct super_block *i_sb;\n            struct address_space *i_mapping;\n        #ifdef CONFIG_SECURITY\n            void *i_security;\n        #endif\n            unsigned long i_ino;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct inode*)0).i_no\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        current = inode + 2 + 2 + 4 + 4 + 4\n\n        # now, `current` points i_acl or i_op\n        while True:\n            v = read_int_from_memory(current)\n            if v == 0:\n                current += current_arch.ptrsize\n                continue\n            if is_64bit() and v == 0xffff_ffff_ffff_ffff:\n                current += current_arch.ptrsize\n                continue\n            elif is_32bit() and v == 0xffff_ffff:\n                current += current_arch.ptrsize\n                continue\n            elif is_valid_addr(v):\n                current += current_arch.ptrsize\n                continue\n            offset_i_ino = current - inode\n            break\n        return offset_i_ino\n\n    def get_ino(self, file):\n        dentry = read_int_from_memory(file + self.offset_dentry)\n        inode = read_int_from_memory(dentry + self.offset_d_inode)\n        i_ino = read_int_from_memory(inode + self.offset_i_ino)\n        return i_ino\n\n    def get_filepath(self, file):\n        if not is_valid_addr(file):\n            return \"\"\n\n        if file in self.filepath_cache:\n            return self.filepath_cache[file]\n\n        \"\"\"\n        struct path {\n            struct vfsmount *mnt;\n            struct dentry *dentry;\n        } f_path;\n\n        struct mount {\n            struct hlist_node mnt_hash;\n            struct mount *mnt_parent;\n            struct dentry *mnt_mountpoint;\n            struct vfsmount {\n                struct dentry *mnt_root;\n                struct super_block *mnt_sb;\n                int mnt_flags;\n                struct mnt_idmap *mnt_idmap; // v6.2~\n                struct user_namespace *mnt_userns; // v5.12~v6.1\n            } mnt; <-- f_path.mnt points here\n            ...\n        };\n        \"\"\"\n\n        def is_root(vfsmnt, dentry):\n            mnt_root = read_int_from_memory(vfsmnt + offset_vfsmount_mnt_root)\n            parent = read_int_from_memory(dentry + self.offset_d_parent)\n            return dentry == mnt_root or parent == dentry\n\n        def is_global_root(mnt):\n            parent = read_int_from_memory(mnt + offset_mount_mnt_parent)\n            return parent == mnt\n\n        def read_dentry_str(dentry):\n            # Try d_shortname (inline name) directly\n            name = read_cstring_from_memory(dentry + self.offset_d_iname)\n            if name:\n                return name\n\n            # Try d_name.name pointer (no padding case)\n            # Validate pointer before dereferencing\n            for back in [2, 3]:\n                name_ptr = read_int_from_memory(\n                    dentry + self.offset_d_iname - current_arch.ptrsize * back\n                )\n                if not is_valid_addr(name_ptr) or (name_ptr & 0b11) != 0:\n                    continue\n                name = read_cstring_from_memory(name_ptr)\n                if name:\n                    return name\n            return \"\"\n\n        offset_vfsmount_mnt_root = 0\n        offset_mount_mnt_parent = current_arch.ptrsize * 2\n        offset_mount_mnt_mountpoint = current_arch.ptrsize * 3\n        offset_mount_mnt = current_arch.ptrsize * 4\n\n        filepath = []\n\n        dentry = read_int_from_memory(file + self.offset_dentry)\n        vfsmnt = read_int_from_memory(file + self.offset_mnt)\n        mnt = vfsmnt - offset_mount_mnt\n\n        while True:\n            if is_root(vfsmnt, dentry):\n                if is_global_root(mnt):\n                    name = read_dentry_str(dentry)\n                    filepath.append(name)\n                    break\n                else:\n                    dentry = read_int_from_memory(mnt + offset_mount_mnt_mountpoint)\n                    mnt = read_int_from_memory(mnt + offset_mount_mnt_parent)\n                    vfsmnt = mnt + offset_mount_mnt\n                    continue\n            else:\n                name = read_dentry_str(dentry)\n                filepath.append(name)\n                dentry = read_int_from_memory(dentry + self.offset_d_parent)\n\n        filepath = os.path.join(*filepath[::-1])\n        if filepath in [\"UNIX\", \"NETLINK\", \"TCP\", \"TCPv6\", \"UDP\", \"UDPv6\", \"PACKET\"]:\n            filepath = \"socket:[{:d}]\".format(self.get_ino(file))\n        elif filepath and not filepath.startswith(\"/\"):\n            filepath = \"anon_inode:{:s}\".format(filepath)\n        elif filepath == \"\":\n            filepath = \"pipe:[{:d}]\".format(self.get_ino(file))\n\n        self.filepath_cache[file] = filepath\n        return filepath\n\n    def add_lwp_task(self, task_addrs):\n        lwp_task_addrs = []\n        kversion = Kernel.kernel_version()\n\n        for task in task_addrs:\n            seen = []\n            if kversion < \"6.7\":\n                lwp = task\n                while lwp not in seen:\n                    seen.append(lwp)\n                    try:\n                        lwp = read_int_from_memory(lwp + self.offset_thread_group) - self.offset_thread_group\n                    except gdb.MemoryError:\n                        break\n                lwp_task_addrs.extend(seen)\n\n            else:\n                signal = read_int_from_memory(task + self.offset_signal)\n                head = signal + self.offset_thread_head\n                seen = [head]\n                curr = read_int_from_memory(head)\n                while curr not in seen:\n                    seen.append(curr)\n                    lwp = curr - self.offset_thread_group\n                    lwp_task_addrs.append(lwp)\n                    try:\n                        curr = read_int_from_memory(curr)\n                    except gdb.MemoryError:\n                        break\n        return lwp_task_addrs\n\n    def get_offset_nsproxy(self, task_addr, offset_files):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct files_struct *files;\n        #ifdef CONFIG_IO_URING\n            struct io_uring_task *io_uring;\n        #endif\n            struct nsproxy *nsproxy;\n            struct signal_struct *signal;\n            struct sighand_struct __rcu *sighand;\n            sigset_t blocked;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).nsproxy\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        offset_nsproxy = offset_files + current_arch.ptrsize\n        v = read_int_from_memory(task_addr + offset_nsproxy + current_arch.ptrsize * 3) # blocked\n        if not is_valid_addr(v):\n            # CONFIG_IO_URING=n\n            return offset_nsproxy\n        # CONFIG_IO_URING=y\n        return offset_nsproxy + current_arch.ptrsize\n\n    def get_offset_sighand(self, task_addr, offset_files):\n        \"\"\"\n        struct task_struct {\n            ...\n            struct files_struct *files;\n        #ifdef CONFIG_IO_URING\n            struct io_uring_task *io_uring;\n        #endif\n            struct nsproxy *nsproxy;\n            struct signal_struct *signal;\n            struct sighand_struct __rcu *sighand;\n            sigset_t blocked;\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct task_struct*)0).sighand\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        offset_sighand = offset_files + current_arch.ptrsize * 3\n        if not is_valid_addr(read_int_from_memory(task_addr + offset_sighand + current_arch.ptrsize)): # blocked\n            # CONFIG_IO_URING=n\n            return offset_sighand\n        # CONFIG_IO_URING=y\n        return offset_sighand + current_arch.ptrsize\n\n    def get_offset_action(self, sighand):\n        \"\"\"\n        [v5.3~]\n        struct sighand_struct {\n            spinlock_t siglock;\n            refcount_t count;\n            struct wait_queue_head {\n                spinlock_t lock;\n                struct list_head head;\n            } signalfd_wqh;\n            struct k_sigaction {\n                struct sigaction {\n                    __sighandler_t sa_handler;\n                    unsigned long sa_flags;\n                #ifdef __ARCH_HAS_SA_RESTORER\n                    __sigrestore_t sa_restorer;\n                #endif\n                    sigset_t sa_mask;\n                } sa;\n            #ifdef __ARCH_HAS_KA_RESTORER\n                __sigrestore_t ka_restorer;\n            #endif\n            } action[_NSIG]; // 64\n        };\n\n        [~v5.2]\n        struct sighand_struct {\n            refcount_t count;\n            struct k_sigaction {\n                struct sigaction sa;\n            #ifdef __ARCH_HAS_KA_RESTORER\n                __sigrestore_t ka_restorer;\n            #endif\n            } action[_NSIG]; // 64\n            spinlock_t siglock;\n            wait_queue_head_t signalfd_wqh;\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct sighand_struct*)0).action\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            return None\n        if \"5.3\" <= kversion:\n            # search for signalfd_wqh.list_head\n            found = False\n            for i in range(1, 30):\n                offset_list_head = current_arch.ptrsize * i\n                head = sighand + offset_list_head\n                if not is_valid_addr(head):\n                    continue\n\n                current = read_int_from_memory(head)\n                seen = []\n                while True:\n                    if current == head:\n                        found = True\n                        break\n                    if not is_valid_addr(current):\n                        break\n                    if current in seen:\n                        break\n                    seen.append(current)\n                    current = read_int_from_memory(current)\n                if found:\n                    break\n\n            if not found:\n                return None\n\n            offset_action = offset_list_head + current_arch.ptrsize * 2\n\n        else: # < 5.3\n            offset_action = current_arch.ptrsize\n        return offset_action\n\n    def get_sizeof_action(self, task_addrs, offset_sighand, offset_action, offset_mm):\n        \"\"\"\n        case 1 (x64)\n        0xffff8f63011e4400|+0x0000|+000: 0x0000000100000000\n        0xffff8f63011e4408|+0x0008|+001: 0x0000000000000000\n        0xffff8f63011e4410|+0x0010|+002: 0xffff8f63593e11e0  ->  [loop detected]\n        0xffff8f63011e4418|+0x0018|+003: 0xffff8f63593e11e0  ->  0xffff8f63011e4410  ->  [loop detected]\n        0xffff8f63011e4420|+0x0020|+004: 0x0000000000000000 <- action[0]\n        0xffff8f63011e4428|+0x0028|+005: 0x0000000014000000\n        0xffff8f63011e4430|+0x0030|+006: 0x00007f3ec71d0d60\n        0xffff8f63011e4438|+0x0038|+007: 0x0000000000000000\n        0xffff8f63011e4440|+0x0040|+008: 0x0000000000000000 <- action[1]\n        0xffff8f63011e4448|+0x0048|+009: 0x0000000014000000\n        0xffff8f63011e4450|+0x0050|+010: 0x00007f3ec71d0d60\n        0xffff8f63011e4458|+0x0058|+011: 0x0000000000000000\n        0xffff8f63011e4460|+0x0060|+012: 0x0000562e3b34bdf0 <- action[2]\n        0xffff8f63011e4468|+0x0068|+013: 0x0000000044000000\n        0xffff8f63011e4470|+0x0070|+014: 0x00007f3ec71d0d60\n        0xffff8f63011e4478|+0x0078|+015: 0x0000000000000000\n        0xffff8f63011e4480|+0x0080|+016: 0x0000562e3b34bdf0 <- action[3]\n        0xffff8f63011e4488|+0x0088|+017: 0x0000000044000000\n        0xffff8f63011e4490|+0x0090|+018: 0x00007f3ec71d0d60\n        0xffff8f63011e4498|+0x0098|+019: 0x0000000000000000\n        ...\n\n        case 2 (arm64)\n        0xffff000003080000|+0x0000|+000: 0x0000000100000000\n        0xffff000003080008|+0x0008|+001: 0x0000000000000000\n        0xffff000003080010|+0x0010|+002: 0xffff000003080010  ->  [loop detected]\n        0xffff000003080018|+0x0018|+003: 0xffff000003080010  ->  [loop detected]\n        0xffff000003080020|+0x0020|+004: 0x0000000000000000 <- action[0]\n        0xffff000003080028|+0x0028|+005: 0x0000000000000000\n        0xffff000003080030|+0x0030|+006: 0x0000000000000000\n        0xffff000003080038|+0x0038|+007: 0x0000000000000000\n        0xffff000003080040|+0x0040|+008: 0x000000000051dc20 <- action[1]\n        0xffff000003080048|+0x0048|+009: 0x0000000000000000\n        0xffff000003080050|+0x0050|+010: 0x0000000000000002\n        0xffff000003080058|+0x0058|+011: 0xfffffffe7ffbfeff\n        0xffff000003080060|+0x0060|+012: 0x0000000000000001 <- action[2]\n        0xffff000003080068|+0x0068|+013: 0x0000000000000000\n        0xffff000003080070|+0x0070|+014: 0x0000000000000002\n        0xffff000003080078|+0x0078|+015: 0xfffffffe7ffbfeff\n        0xffff000003080080|+0x0080|+016: 0x0000000000000000 <- action[3]\n        0xffff000003080088|+0x0088|+017: 0x0000000000000000\n        0xffff000003080090|+0x0090|+018: 0x0000000000000000\n        0xffff000003080098|+0x0098|+019: 0x0000000000000000\n        ...\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(\n                gdb.parse_and_eval(\"sizeof(struct k_sigaction)\")\n            )\n        except gdb.error:\n            pass\n\n        # slow path\n        if is_32bit():\n            possible_sizes = [0x10, 0x14, 0x18]\n        else:\n            possible_sizes = [0x18, 0x20, 0x28]\n\n        # calc sizeof(action[0])\n        sizeof_action = 0xffff_ffff_ffff_ffff\n        for task in task_addrs:\n            mm = read_int_from_memory(task + offset_mm)\n            if mm == 0:\n                # for speed up; ignore if kernel thread\n                continue\n\n            sighand = read_int_from_memory(task + offset_sighand)\n            current = sighand + offset_action\n            found_offset_case1 = []\n            found_offset_case2 = []\n\n            for i in range(64 * 4):\n                offset = current_arch.ptrsize * i\n\n                # check case 1 (sa_flags)\n                v = read_int_from_memory(current + offset)\n                # SA_RESTORER, SA_RESTART, SA_NODEFER, SA_RESTART|SA_RESTORER, SA_NODEFER|SA_RESTORER\n                if v in [0x0400_0000, 0x1000_0000, 0x4000_0000, 0x1400_0000, 0x4400_0000]:\n                    found_offset_case1.append(offset)\n\n                # check case 2 (sa_mask)\n                v = read_int64_from_memory(current + offset)\n                if bin(v)[2:].count(\"1\") > 56: # heuristic threshold\n                    found_offset_case2.append(offset)\n\n            if len(found_offset_case1) >= 2:\n                sizeof_action_tmp = min(y - x for x, y in zip(found_offset_case1[:-1], found_offset_case1[1:]))\n                # it is minimum size, so fast return\n                if sizeof_action_tmp in possible_sizes:\n                    return sizeof_action_tmp\n                # not minimum size, so check next task\n                sizeof_action = min(sizeof_action, sizeof_action_tmp)\n\n            if len(found_offset_case2) >= 2:\n                sizeof_action_tmp = min(y - x for x, y in zip(found_offset_case2[:-1], found_offset_case2[1:]))\n                # it is minimum size, so fast return\n                if sizeof_action_tmp in possible_sizes:\n                    return sizeof_action_tmp\n                # not minimum size, so check next task\n                sizeof_action = min(sizeof_action, sizeof_action_tmp)\n\n        if sizeof_action != 0xffff_ffff_ffff_ffff:\n            for ps in possible_sizes:\n                if sizeof_action % ps == 0:\n                    return sizeof_action\n        return None\n\n    def initialize(self):\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            self.quiet_err(\"Could not find Linux kernel\")\n            return False\n\n        # init_task\n        if self.args.init_task is not None:\n            init_task = self.args.init_task\n        else:\n            init_task = KernelAddressHeuristicFinder.get_init_task()\n        if init_task is None:\n            self.quiet_err(\"Could not find init_task\")\n            return False\n        self.quiet_info(\"init_task: {:#x}\".format(init_task))\n\n        # task_struct->tasks\n        if self.offset_tasks is None:\n            self.offset_tasks = self.get_offset_tasks(init_task)\n        if self.offset_tasks is None:\n            self.quiet_err(\"Could not find task_struct->tasks\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, tasks): {:#x}\".format(self.offset_tasks))\n\n        # task addresses\n        task_addrs = self.get_task_list(init_task, self.offset_tasks)\n        if task_addrs is None:\n            self.quiet_err(\"Failed to list each tasks\")\n            return False\n        self.quiet_info(\"Number of tasks: {:d}\".format(len(task_addrs)))\n\n        # task_struct->mm\n        if self.offset_mm is None:\n            self.offset_mm = self.get_offset_mm(task_addrs[0], self.offset_tasks)\n        if self.offset_mm is None:\n            self.quiet_err(\"Could not find task_struct->mm\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, mm): {:#x}\".format(self.offset_mm))\n\n        # task_struct->stack\n        if self.offset_stack is None:\n            self.offset_stack = self.get_offset_stack(task_addrs)\n        if self.offset_stack is None:\n            self.quiet_err(\"Could not find task_struct->stack\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, stack): {:#x}\".format(self.offset_stack))\n\n        # task_struct->pid\n        if self.offset_pid is None:\n            self.offset_pid = self.get_offset_pid(task_addrs)\n        if self.offset_pid is None:\n            self.quiet_err(\"Could not find task_struct->pid\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, pid): {:#x}\".format(self.offset_pid))\n\n        # task_struct->stack_canary\n        if self.offset_kcanary is None:\n            self.offset_kcanary = self.get_offset_canary(task_addrs, self.offset_pid)\n        if self.offset_kcanary is None:\n            self.quiet_info(\"offsetof(task_struct, stack_canary): None\")\n        else:\n            self.quiet_info(\"offsetof(task_struct, stack_canary): {:#x}\".format(self.offset_kcanary))\n\n        # task_struct->comm\n        if self.offset_comm is None:\n            self.offset_comm = self.get_offset_comm(task_addrs)\n        if self.offset_comm is None:\n            self.quiet_err(\"Could not find task_struct->comm[TASK_CMM_LEN]\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, comm): {:#x}\".format(self.offset_comm))\n\n        # task_struct->cred\n        if self.offset_cred is None:\n            self.offset_cred = self.get_offset_cred(task_addrs, self.offset_comm)\n        if self.offset_cred is None:\n            self.quiet_err(\"Could not find task_struct->cred\")\n            return False\n        self.quiet_info(\"offsetof(task_struct, cred): {:#x}\".format(self.offset_cred))\n\n        # cred.uid\n        if self.offset_uid is None:\n            self.offset_uid = self.get_offset_uid(task_addrs[0] + self.offset_cred)\n        if self.offset_uid is None:\n            self.quiet_err(\"Could not find cred->uid\")\n            return False\n        self.quiet_info(\"offsetof(cred, uid): {:#x}\".format(self.offset_uid))\n\n        # kstack_top->saved_ptregs\n        if self.args.print_regs:\n            if self.offset_ptregs is None:\n                self.kstack_size, self.offset_ptregs = self.get_offset_ptregs(task_addrs, self.offset_stack)\n            if self.offset_ptregs is None:\n                self.quiet_err(\"Could not find saved ptregs\")\n                return False\n            self.quiet_info(\"kstack size: {:#x}\".format(self.kstack_size))\n            self.quiet_info(\"offsetof(kstack_top, saved ptregs): {:#x}\".format(self.offset_ptregs))\n\n        # vm_area_struct->vm_mm\n        # vm_area_struct->vm_flags\n        # vm_area_struct->vm_file\n        # file->f_path.mnt\n        # file->f_path.dentry\n        # dentry->d_iname\n        # dentry->d_parent\n        # dentry->d_inode\n        # inode->i_ino\n        if self.args.print_maps or self.args.print_fd:\n            if self.offset_vm_mm is None:\n                self.offset_vm_mm = self.get_offset_vm_mm(task_addrs, self.offset_mm)\n            if self.offset_vm_mm is None:\n                self.quiet_err(\"Could not find vm_area_struct->vm_mm\")\n                return False\n            self.quiet_info(\"offsetof(vm_area_struct, vm_mm): {:#x}\".format(self.offset_vm_mm))\n\n            if self.offset_vm_flags is None:\n                self.offset_vm_flags = self.get_offset_vm_flags(self.offset_vm_mm)\n            if self.offset_vm_flags is None:\n                self.quiet_err(\"Could not find vm_area_struct->vm_flags\")\n                return False\n            self.quiet_info(\"offsetof(vm_area_struct, vm_flags): {:#x}\".format(self.offset_vm_flags))\n\n            if self.offset_vm_file is None:\n                self.offset_vm_file = self.get_offset_vm_file(task_addrs, self.offset_mm, self.offset_vm_flags)\n            if self.offset_vm_file is None:\n                self.quiet_err(\"Could not find vm_area_struct->vm_file\")\n                return False\n            self.quiet_info(\"offsetof(vm_area_struct, vm_file): {:#x}\".format(self.offset_vm_file))\n\n            if self.offset_mnt is None:\n                mm = read_int_from_memory(task_addrs[1] + self.offset_mm)\n                current, _ = self.get_vm_area_struct(mm)\n                self.quiet_info(\"vm_area_struct (init process): {:#x}\".format(current))\n                vm_file = read_int_from_memory(current + self.offset_vm_file)\n                self.quiet_info(\"vm_file (init process): {:#x}\".format(vm_file))\n                self.offset_mnt = self.get_offset_mnt(vm_file)\n            if self.offset_mnt is None:\n                self.quiet_err(\"Could not find file->f_path.mnt\")\n                return False\n            self.quiet_info(\"offsetof(file, f_path.mnt): {:#x}\".format(self.offset_mnt))\n\n            if self.offset_dentry is None:\n                self.offset_dentry = self.get_offset_dentry(self.offset_mnt)\n            self.quiet_info(\"offsetof(file, f_path.dentry): {:#x}\".format(self.offset_dentry))\n\n            if self.offset_d_iname is None:\n                mm = read_int_from_memory(task_addrs[1] + self.offset_mm)\n                current, _ = self.get_vm_area_struct(mm)\n                vm_file = read_int_from_memory(current + self.offset_vm_file)\n                dentry = read_int_from_memory(vm_file + self.offset_dentry)\n                self.offset_d_iname = self.get_offset_d_iname(dentry)\n            self.quiet_info(\"offsetof(dentry, d_iname): {:#x}\".format(self.offset_d_iname))\n\n            if self.offset_d_inode is None:\n                self.offset_d_inode = self.get_offset_d_inode(self.offset_d_iname)\n            self.quiet_info(\"offsetof(dentry, d_inode): {:#x}\".format(self.offset_d_inode))\n\n            if self.offset_d_parent is None:\n                dentry = read_int_from_memory(vm_file + self.offset_dentry)\n                self.offset_d_parent = self.get_offset_d_parent(dentry, self.offset_d_iname)\n            self.quiet_info(\"offsetof(dentry, d_parent): {:#x}\".format(self.offset_d_parent))\n\n            if self.offset_i_ino is None:\n                dentry = read_int_from_memory(vm_file + self.offset_dentry)\n                inode = read_int_from_memory(dentry + self.offset_d_inode)\n                self.offset_i_ino = self.get_offset_i_ino(inode)\n            self.quiet_info(\"offsetof(inode, i_ino): {:#x}\".format(self.offset_i_ino))\n\n        # task_struct->files\n        if self.args.print_fd or self.args.print_sighand or self.args.print_namespace or \\\n            (\"6.7\" <= kversion and self.args.print_thread) or self.args.print_seccomp:\n            if self.offset_files is None:\n                self.offset_files = self.get_offset_files(task_addrs, self.offset_comm)\n            if self.offset_files is None:\n                self.quiet_err(\"Could not find task_struct->files\")\n                return False\n            self.quiet_info(\"offsetof(task_struct, files): {:#x}\".format(self.offset_files))\n\n        # files_struct->fdt\n        if self.args.print_fd:\n            if self.offset_fdt is None:\n                self.offset_fdt = self.get_offset_fdt(task_addrs, self.offset_files)\n            if self.offset_fdt is None:\n                self.quiet_err(\"Could not find files_struct->fdt\")\n                return False\n            self.quiet_info(\"offsetof(files_struct, fdt): {:#x}\".format(self.offset_fdt))\n\n        # cred->user_ns\n        # task_struct->nsproxy\n        if self.args.print_namespace or (\"6.7\" <= kversion and self.args.print_thread) or self.args.print_seccomp:\n            if self.offset_user_ns is None:\n                init_cred = read_int_from_memory(task_addrs[0] + self.offset_cred)\n                self.offset_user_ns = self.get_offset_user_ns(init_cred, self.offset_uid)\n            if self.offset_user_ns is None:\n                self.quiet_err(\"Could not find cred->user_ns\")\n                return False\n            self.quiet_info(\"offsetof(cred, user_ns): {:#x}\".format(self.offset_user_ns))\n\n            if self.offset_nsproxy is None:\n                self.offset_nsproxy = self.get_offset_nsproxy(task_addrs[0], self.offset_files)\n            if self.offset_nsproxy is None:\n                self.quiet_err(\"Could not find task_struct->nsproxy\")\n                return False\n            self.quiet_info(\"offsetof(task_struct, nsproxy): {:#x}\".format(self.offset_nsproxy))\n\n        # task_struct->group_leader\n        # task_struct->thread_group\n        # task_struct->signal (6.7~)\n        # signal->thread_head (6.7~)\n        if self.args.print_thread:\n            if self.offset_group_leader is None:\n                self.offset_group_leader = self.get_offset_group_leader(self.offset_pid, self.offset_kcanary)\n            self.quiet_info(\"offsetof(task_struct, group_leader): {:#x}\".format(self.offset_group_leader))\n\n            if self.offset_thread_group is None:\n                self.offset_thread_group = self.get_offset_thread_group(self.offset_group_leader)\n            if self.offset_thread_group is None:\n                self.quiet_err(\"Could not find task_struct->thread_group\")\n                return False\n            if \"6.7\" <= kversion:\n                self.quiet_info(\"offsetof(task_struct, thread_node): {:#x}\".format(self.offset_thread_group))\n            else:\n                self.quiet_info(\"offsetof(task_struct, thread_group): {:#x}\".format(self.offset_thread_group))\n\n            if \"6.7\" <= kversion:\n                if self.offset_signal is None:\n                    self.offset_signal = self.get_offset_signal(self.offset_nsproxy)\n                self.quiet_info(\"offsetof(task_struct, signal): {:#x}\".format(self.offset_signal))\n\n                if self.offset_thread_head is None:\n                    self.offset_thread_head = self.get_offset_thread_head(task_addrs[0], self.offset_signal)\n                self.quiet_info(\"offsetof(signal, thread_head): {:#x}\".format(self.offset_thread_head))\n\n        # task_struct->sighand\n        if self.args.print_sighand:\n            if self.offset_sighand is None:\n                self.offset_sighand = self.get_offset_sighand(task_addrs[0], self.offset_files)\n            if self.offset_sighand is None:\n                self.quiet_err(\"Could not find task_struct->sighand\")\n                return False\n            self.quiet_info(\"offsetof(task_struct, sighand): {:#x}\".format(self.offset_sighand))\n\n            if self.offset_action is None:\n                sighand = read_int_from_memory(task_addrs[1] + self.offset_sighand)\n                self.offset_action = self.get_offset_action(sighand)\n            if self.offset_action is None:\n                self.quiet_err(\"Could not find sighand_struct->action\")\n                return False\n            self.quiet_info(\"offsetof(sighand_struct, action): {:#x}\".format(self.offset_action))\n\n            if self.sizeof_action is None:\n                self.sizeof_action = self.get_sizeof_action(\n                    task_addrs, self.offset_sighand, self.offset_action, self.offset_mm,\n                )\n            if self.sizeof_action is None:\n                self.quiet_err(\"Could not find sizeof(action[0])\")\n                return False\n            self.quiet_info(\"sizeof(action[0]): {:#x}\".format(self.sizeof_action))\n\n            self.signame_list = {\n                1: \"SIGHUP\",\n                2: \"SIGINT\",\n                3: \"SIGQUIT\",\n                4: \"SIGILL\",\n                5: \"SIGTRAP\",\n                6: \"SIGABRT\",\n                7: \"SIGBUS\",\n                8: \"SIGFPE\",\n                9: \"SIGKILL\",\n                10: \"SIGUSR1\",\n                11: \"SIGSEGV\",\n                12: \"SIGUSR2\",\n                13: \"SIGPIPE\",\n                14: \"SIGALRM\",\n                15: \"SIGTERM\",\n                16: \"SIGSTKFLT\",\n                17: \"SIGCHLD\",\n                18: \"SIGCONT\",\n                19: \"SIGSTOP\",\n                20: \"SIGTSTP\",\n                21: \"SIGTTIN\",\n                22: \"SIGTTOU\",\n                23: \"SIGURG\",\n                24: \"SIGXCPU\",\n                25: \"SIGXFSZ\",\n                26: \"SIGVTALRM\",\n                27: \"SIGPROF\",\n                28: \"SIGWINCH\",\n                29: \"SIGIO\",\n                30: \"SIGPWR\",\n                31: \"SIGSYS\",\n                32: \"SIGCANCEL\", # from glibc source code\n                33: \"SIGSETXID\", # from glibc source code\n                34: \"SIGRTMIN\",\n                # 35 ... 49: SIGRTMIN+i\n                # 50 ... 63: SIGRTMAX-i\n                64: \"SIGRTMAX\",\n            }\n            for i in range(35, 50):\n                self.signame_list[i] = \"SIGRTMIN+{:d}\".format(i - 34)\n            for i in range(63, 49, -1):\n                self.signame_list[i] = \"SIGRTMAX-{:d}\".format(64 - i)\n\n        # task_struct->seccomp\n        if self.args.print_seccomp:\n            if self.offset_signal is None:\n                self.offset_signal = self.get_offset_signal(self.offset_nsproxy)\n            self.quiet_info(\"offsetof(task_struct, signal): {:#x}\".format(self.offset_signal))\n\n            if self.offset_seccomp is None:\n                self.offset_seccomp = self.get_offset_seccomp(task_addrs, self.offset_signal)\n            if self.offset_seccomp is None:\n                self.quiet_err(\"Could not find task_struct->seccomp\")\n                return False\n            self.quiet_info(\"offsetof(task_struct, seccomp): {:#x}\".format(self.offset_seccomp))\n\n            if self.offset_prev is None:\n                self.offset_prev = self.get_offset_prev(task_addrs, self.offset_seccomp)\n            if self.offset_prev is None:\n                self.quiet_err(\"Could not find seccomp_filter->prev\")\n                return False\n            self.quiet_info(\"offsetof(seccomp_filter, prev): {:#x}\".format(self.offset_prev))\n\n            if self.offset_prog is None:\n                self.offset_prog = self.get_offset_prog(self.offset_prev)\n            if self.offset_prog is None:\n                self.quiet_err(\"Could not find seccomp_filter->prog\")\n                return False\n            self.quiet_info(\"offsetof(seccomp_filter, prog): {:#x}\".format(self.offset_prog))\n\n            if self.offset_bpf_func is None:\n                self.offset_bpf_func = self.get_offset_bpf_func(task_addrs, self.offset_seccomp, self.offset_prog)\n            if self.offset_bpf_func is None:\n                self.quiet_err(\"Could not find bpf_prog->bpf_func\")\n                return False\n            self.quiet_info(\"offsetof(bpf_prog, bpf_func): {:#x}\".format(self.offset_bpf_func))\n\n            if self.offset_orig_prog is None:\n                self.offset_orig_prog = self.get_offset_orig_prog(self.offset_bpf_func)\n            if self.offset_orig_prog is None:\n                self.quiet_err(\"Could not find bpf_prog->orig_prog\")\n                return False\n            self.quiet_info(\"offsetof(bpf_prog, orig_prog): {:#x}\".format(self.offset_orig_prog))\n\n            self.offset_jited_len = 16\n\n            try:\n                self.seccomp_tools_command = [GefUtil.which(\"ceccomp\"), \"disasm\", \"-c\", \"always\"]\n                self.quiet_info(\"ceccomp is found\")\n            except FileNotFoundError:\n                try:\n                    self.seccomp_tools_command = [GefUtil.which(\"seccomp-tools\"), \"disasm\"]\n                    self.quiet_info(\"seccomp-tools is found\")\n                    if is_arm32():\n                        self.quiet_warn(\"`seccomp-tools` is not supported on ARM32. \"\n                                        \"Consider using `ceccomp` instead, as it supports ARM32.\")\n                        self.quiet_info(\"GEF uses `capstone-disassemble bpf_func`\")\n                        self.seccomp_tools_command = None\n                except FileNotFoundError:\n                    self.quiet_info(\"Could not find ceccomp or seccomp-tools, GEF uses `capstone-disassemble bpf_func`\")\n                    self.seccomp_tools_command = None\n\n        return task_addrs\n\n    def get_current_task_list(self):\n        args = self.args # backup\n        try:\n            res = gdb.execute(\"kcurrent --quiet\", to_string=True)\n        except gdb.error:\n            return {}\n        # kcurrent calls ktask itself, so self.args will be overwritten. this is workaround.\n        self.args = args # revert\n\n        tmp_current_tasks = {}\n        for line in res.splitlines():\n            r = re.search(r\"current \\(cpu(\\d+)\\): (0x\\S+) .+\", line.strip())\n            if r:\n                cpu = int(r.group(1))\n                task = int(r.group(2), 16)\n                new_list = tmp_current_tasks.get(task, []) + [cpu]\n                tmp_current_tasks[task] = new_list\n                continue\n            r = re.search(r\"current: (0x\\S+) .+\", line.strip())\n            if r:\n                cpu = 0\n                task = int(r.group(1), 16)\n                new_list = tmp_current_tasks.get(task, []) + [cpu]\n                tmp_current_tasks[task] = new_list\n                continue\n\n        current_tasks = {}\n        for k, v in tmp_current_tasks.items():\n            if len(v) > 1:\n                # It is unclear whether this case can occur.\n                current_tasks[k] = \"cpu{:d},..\".format(min(v))\n            else:\n                current_tasks[k] = \"cpu{:d}\".format(v[0])\n        return current_tasks\n\n    def dump(self, task_addrs):\n        # add current tasks (cpuN > 0)\n        current_tasks = self.get_current_task_list()\n        to_add_tasks = [task for task in current_tasks.keys() if task not in task_addrs]\n        task_addrs = task_addrs[:1] + to_add_tasks + task_addrs[1:]\n\n        # LWP\n        if self.args.print_thread:\n            task_addrs = self.add_lwp_task(task_addrs)\n\n        # print legend\n        if not self.args.quiet:\n            fmt = \"{:<18s} {:7s} {:3s} {:<7s} {:<16s} {:<18s} [{:s}] {:<8s} {:<18s} {:<18s}\"\n            if self.args.print_all_id:\n                ids_str = [\"uid\", \"gid\", \"suid\", \"sgid\", \"euid\", \"egid\", \"fsuid\", \"fsgid\"]\n                uids_fmt = \"{:>5s} {:>5s} {:>5s} {:>5s} {:>5s} {:>5s} {:>5s} {:>5s}\"\n            else:\n                ids_str = [\"uid\", \"gid\"]\n                uids_fmt = \"{:>5s} {:>5s}\"\n            uids_str = uids_fmt.format(*ids_str)\n            legend = [\n                \"task\", \"current\", \"K/U\", \"lwpid\", \"task->comm\", \"task->cred\",\n                uids_str, \"seccomp\", \"kstack\", \"kcanary\",\n            ]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if self.args.print_namespace:\n            kversion = Kernel.kernel_version()\n            nsproxy_members = [\"count\", \"uts_ns\", \"ipc_ns\", \"mnt_ns\", \"pid_ns_for_children\", \"net_ns\"]\n            if \"5.6\" <= kversion:\n                nsproxy_members += [\"time_ns\", \"time_ns_for_children\"]\n            if \"4.6\" <= kversion:\n                nsproxy_members += [\"cgroup_ns\"]\n            if task_addrs:\n                init_cred = read_int_from_memory(task_addrs[0] + self.offset_cred)\n                init_user_ns = read_int_from_memory(init_cred + self.offset_user_ns)\n                init_nsproxy = read_int_from_memory(task_addrs[0] + self.offset_nsproxy)\n\n        # task parse\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for task in tqdm(task_addrs, leave=False, desc=\"task\"):\n            comm_string = read_cstring_from_memory(task + self.offset_comm)\n            if self.args.filter:\n                if not any(re_pattern.search(comm_string) for re_pattern in self.args.filter):\n                    continue\n\n            if self.args.task_filter:\n                if task not in self.args.task_filter:\n                    continue\n\n            kstack = read_int_from_memory(task + self.offset_stack)\n            pid = read_int32_from_memory(task + self.offset_pid)\n            cred = read_int_from_memory(task + self.offset_cred)\n\n            # current\n            currentN = current_tasks.get(task, \"-\")\n\n            # get process type (kernel or user-land)\n            mm = read_int_from_memory(task + self.offset_mm)\n            if mm == 0 or pid == 0:\n                proctype = \"K\"\n            else:\n                proctype = \"U\"\n\n            if self.args.user_process_only:\n                if proctype == \"K\":\n                    continue\n\n            # get process type (main process or not)\n            if self.args.print_thread:\n                leader = read_int_from_memory(task + self.offset_group_leader)\n                if leader != task:\n                    proctype += \"T\"\n\n            # uid\n            if self.args.print_all_id:\n                uids = [read_int32_from_memory(cred + self.offset_uid + j * 4) for j in range(8)]\n                uids_fmt = \"{:>5d},{:>5d},{:>5d},{:>5d},{:>5d},{:>5d},{:>5d},{:>5d}\"\n            else:\n                uids = [read_int32_from_memory(cred + self.offset_uid + j * 4) for j in range(2)]\n                uids_fmt = \"{:>5d},{:>5d}\"\n            uids_str = uids_fmt.format(*uids)\n\n            # kcanary\n            if self.offset_kcanary:\n                kcanary = read_int_from_memory(task + self.offset_kcanary)\n                kcanary = \"{:#018x}\".format(kcanary)\n            else:\n                kcanary = \"None\"\n\n            # seccomp\n            if self.has_seccomp(task):\n                seccomp = \"Enabled\"\n            else:\n                seccomp = \"Disabled\"\n\n            # make output\n            self.out.append(\"{:#018x} {:<7s} {:<3s} {:<7d} {:<16s} {:#018x} [{:s}] {:<8s} {:#018x} {:<18s}\".format(\n                task, currentN, proctype, pid, comm_string, cred, uids_str, seccomp, kstack, kcanary,\n            ).rstrip())\n\n            # skip additional information when swapper/N\n            if pid == 0:\n                continue\n\n            additional = False\n\n            # additional information (maps)\n            if self.args.print_maps:\n                additional = True\n                mms = self.get_mm(task, self.offset_mm)\n                if mms:\n                    self.out.append(titlify(\"memory map of `{:s}`\".format(comm_string)))\n                    for mm in mms:\n                        self.out.append(\"{:#018x}-{:#018x} {:s} {:s}\".format(\n                            mm.start, mm.end, mm.flags, mm.file,\n                        ).rstrip())\n\n            # additional information (regs)\n            if proctype == \"U\" and self.args.print_regs:\n                additional = True\n                regs = self.get_regs(kstack, self.offset_ptregs)\n                nr_table = get_syscall_table().nr_table\n                syscall_nr_regs = [\"orig_rax\", \"orig_eax\", \"r7\", \"x8\"]\n                if regs:\n                    self.out.append(titlify(\"registers of `{:s}`\".format(comm_string)))\n                    for k, v in regs.items():\n                        if k in syscall_nr_regs and v in nr_table:\n                            syscall_name = nr_table[v].name\n                            self.out.append(\"{:16s}: {:s} ({:s})\".format(\n                                k, AddressUtil.format_address(v, long_fmt=True), syscall_name,\n                            ))\n                        else:\n                            self.out.append(\"{:16s}: {:s}\".format(\n                                k, AddressUtil.format_address(v, long_fmt=True,\n                            )))\n\n            # additional information (files)\n            if proctype == \"U\" and self.args.print_fd:\n                additional = True\n                self.out.append(titlify(\"file descriptors of `{:s}`\".format(comm_string)))\n\n                fmt = \"{:3s} {:18s} {:18s} {:18s} {:s}\"\n                legend = [\"fd\", \"struct file\", \"struct dentry\", \"struct inode\", \"path\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                files = read_int_from_memory(task + self.offset_files)\n                fdt = read_int_from_memory(files + self.offset_fdt)\n                if is_valid_addr(fdt):\n                    max_fds = read_int32_from_memory(fdt)\n                    array = read_int_from_memory(fdt + current_arch.ptrsize)\n                    for i in range(max_fds):\n                        file = read_int_from_memory(array + current_arch.ptrsize * i)\n                        if file == 0:\n                            continue\n                        dentry = read_int_from_memory(file + self.offset_dentry)\n                        inode = read_int_from_memory(dentry + self.offset_d_inode)\n                        filepath = self.get_filepath(file)\n                        self.out.append(\"{:<3d} {:#018x} {:#018x} {:#018x} {:s}\".format(\n                            i, file, dentry, inode, filepath,\n                        ))\n\n            # additional information (sighands)\n            if proctype == \"U\" and self.args.print_sighand:\n                additional = True\n                self.out.append(titlify(\"sighandlers of `{:s}`\".format(comm_string)))\n\n                fmt = \"{:14s} {:18s} {:18s} {:18s}\"\n                legend = [\"sig\", \"sigaction\", \"handler\", \"flags\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                sighand = read_int_from_memory(task + self.offset_sighand)\n                for i in range(64):\n                    sigaction = sighand + self.offset_action + self.sizeof_action * i\n                    signame = self.signame_list.get(i + 1, \"???\")\n                    handler = read_int_from_memory(sigaction + current_arch.ptrsize * 0)\n                    if handler == 0:\n                        handler = \"SIG_DFL\"\n                    elif handler == 1:\n                        handler = \"SIG_IGN\"\n                    elif handler == -1:\n                        handler = \"SIG_ERR\"\n                    else:\n                        handler = \"{:#018x}\".format(handler)\n                    flags = read_int_from_memory(sigaction + current_arch.ptrsize * 1)\n                    self.out.append(\"{:<2d} {:11s} {:#018x} {:18s} {:#018x}\".format(\n                        i + 1, signame, sigaction, handler, flags,\n                    ))\n\n            # additional information (namespace)\n            if proctype == \"U\" and self.args.print_namespace:\n                additional = True\n                self.out.append(titlify(\"namespace of `{:s}`\".format(comm_string)))\n\n                fmt = \"{:30s} {:18s} {:8s}\"\n                legend = [\"name\", \"value\", \"init_ns?\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                # user_ns (via real_cred)\n                real_cred = read_int_from_memory(task + self.offset_cred - current_arch.ptrsize)\n                user_ns = read_int_from_memory(real_cred + self.offset_user_ns)\n                is_init_ns = str(user_ns == init_user_ns)\n                self.out.append(\"{:30s} {:#018x} {:8s}\".format(\"real_cred->user_ns\", user_ns, is_init_ns).rstrip())\n\n                # other ns (via nsproxy)\n                nsproxy = read_int_from_memory(task + self.offset_nsproxy)\n                for i, name in enumerate(nsproxy_members):\n                    value = read_int_from_memory(nsproxy + current_arch.ptrsize * i)\n                    if i == 0:\n                        is_init_ns = \"-\"\n                    else:\n                        init_value = read_int_from_memory(init_nsproxy + current_arch.ptrsize * i)\n                        is_init_ns = str(value == init_value)\n                    self.out.append(\"{:30s} {:#018x} {:8s}\".format(\"nsproxy->\" + name, value, is_init_ns).rstrip())\n\n            # additional information (seccomp)\n            if proctype == \"U\" and self.args.print_seccomp:\n                if self.has_seccomp(task):\n                    additional = True\n                    self.out.append(titlify(\"seccomp of `{:s}`\".format(comm_string)))\n\n                    fmt = \"{:18s} {:25s} {:12s} {:18s}\"\n                    legend = [\"&task.seccomp\", \"mode\", \"filter_count\", \"filter\"]\n                    self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                    seccomp = task + self.offset_seccomp\n                    mode = read_int32_from_memory(seccomp)\n                    mode_define = {\n                        0: \"SECCOMP_MODE_DISABLED\",\n                        1: \"SECCOMP_MODE_STRICT\",\n                        2: \"SECCOMP_MODE_FILTER\",\n                    }.get(mode, \"UNKNOWN\")\n                    mode_str = \"{:d} ({:s})\".format(mode, mode_define)\n                    filter_count = read_int32_from_memory(seccomp + 4)\n                    filter_current = read_int_from_memory(seccomp + 4 * 2)\n                    self.out.append(\"{:#018x} {:25s} {:<12d} {:#018x}\".format(\n                        seccomp, mode_str, filter_count, filter_current,\n                    ))\n\n                    for i in tqdm(range(filter_count), leave=False, desc=\"filter\"):\n                        if not filter_current:\n                            break\n                        prog = read_int_from_memory(filter_current + self.offset_prog)\n                        filter_prev = read_int_from_memory(filter_current + self.offset_prev)\n                        bpf_func = read_int_from_memory(prog + self.offset_bpf_func)\n                        orig_prog = read_int_from_memory(prog + self.offset_orig_prog)\n                        jited_len = read_int32_from_memory(prog + self.offset_jited_len)\n\n                        self.out.append(\"\")\n                        self.out.append(\n                            \"[{:d}/{:d}] filter:{:#x} prev:{:#x} prog:{:#x} bpf_func:{:#x} jited_len:{:#x} orig_prog:{:#x}\".format(\n                                i + 1, filter_count, filter_current, filter_prev, prog, bpf_func, jited_len, orig_prog,\n                            )\n                        )\n\n                        if self.seccomp_tools_command and is_valid_addr(orig_prog):\n                            # use seccomp-tools or ceccomp\n                            cnt = read_int16_from_memory(orig_prog)\n                            prog = read_int_from_memory(orig_prog + current_arch.ptrsize)\n                            data = read_memory(prog, cnt * 8)\n                            tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"ktask\")\n                            os.fdopen(tmp_fd, \"wb\").write(data)\n                            ret = GefUtil.gef_execute_external(\n                                self.seccomp_tools_command + [tmp_path], as_list=True,\n                            )\n                            self.out.extend(ret)\n                            os.unlink(tmp_path)\n                        elif is_valid_addr(bpf_func):\n                            try:\n                                __import__(\"capstone\")\n                                # use capstone\n                                data = read_memory(bpf_func, jited_len)\n                                dump_count = 0\n                                for insn in Disasm.capstone_disassemble(bpf_func, jited_len, code=data.hex()):\n                                    msg = insn.colored_text(10)\n                                    self.out.append(msg)\n                                    dump_count += insn.size\n                                    if dump_count >= jited_len:\n                                        break\n                            except ImportError:\n                                ret = gdb.execute(\"x/40i {:#x}\".format(bpf_func), to_string=True).rstrip()\n                                self.out.append(ret)\n                                self.out.append(\"...\")\n                        else:\n                            self.err_add_out(\"Memory read error\")\n\n                        filter_current = filter_prev\n\n            # print separator\n            if additional:\n                self.out.append(titlify(\"\"))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if self.args.all:\n            self.args.print_maps = True\n            self.args.print_regs = True\n            self.args.print_all_id = True\n            self.args.print_thread = True\n            self.args.print_fd = True\n            self.args.print_sighand = True\n            self.args.print_seccomp = True\n            self.args.print_namespace = True\n\n        # initialize\n        self.filepath_cache = {}\n        ret = self.initialize()\n        if ret is False:\n            return\n        task_addrs = ret\n\n        # skip real parse if specified --meta option\n        if args.meta:\n            return\n\n        # parse\n        self.out = []\n        self.dump(task_addrs)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelFilesCommand(GenericCommand):\n    \"\"\"Display open files for each process (shortcut for `ktask -quF`).\"\"\"\n\n    _cmdline_ = \"kfiles\"\n    _category_ = \"06-f. Qemu-system/KGDB Cooperation - Linux Task\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        info(\"Redirect to `ktask -quF`\")\n\n        no_pager = \"\"\n        if args.no_pager:\n            no_pager = \"--no-pager\"\n        gdb.execute(\"ktask --user-process-only --print-fd --quiet {:s}\".format(no_pager))\n        return\n\n\n@register_command\nclass KernelSavedRegsCommand(GenericCommand):\n    \"\"\"Display saved registers for each process (shortcut for `ktask -qur`).\"\"\"\n\n    _cmdline_ = \"kregs\"\n    _category_ = \"06-f. Qemu-system/KGDB Cooperation - Linux Task\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        info(\"Redirect to `ktask -qur`\")\n\n        no_pager = \"\"\n        if args.no_pager:\n            no_pager = \"--no-pager\"\n        gdb.execute(\"ktask --user-process-only --print-regs --quiet {:s}\".format(no_pager))\n        return\n\n\n@register_command\nclass KernelSignalsCommand(GenericCommand):\n    \"\"\"Display signal handlers for each process (shortcut for `ktask -qus`).\"\"\"\n\n    _cmdline_ = \"ksighands\"\n    _category_ = \"06-f. Qemu-system/KGDB Cooperation - Linux Task\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        info(\"Redirect to `ktask -qus`\")\n\n        no_pager = \"\"\n        if args.no_pager:\n            no_pager = \"--no-pager\"\n        gdb.execute(\"ktask --user-process-only --print-sighand --quiet {:s}\".format(no_pager))\n        return\n\n\n@register_command\nclass KernelNamespacesCommand(GenericCommand):\n    \"\"\"Display namespaces for each process (shortcut for `ktask -quN`).\"\"\"\n\n    _cmdline_ = \"knamespaces\"\n    _category_ = \"06-f. Qemu-system/KGDB Cooperation - Linux Task\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        info(\"Redirect to `ktask -quN`\")\n\n        no_pager = \"\"\n        if args.no_pager:\n            no_pager = \"--no-pager\"\n        gdb.execute(\"ktask --user-process-only --print-namespace --quiet {:s}\".format(no_pager))\n        return\n\n\n@register_command\nclass KernelLoadCommand(GenericCommand):\n    \"\"\"Load the vmlinux without a load address.\"\"\"\n\n    _cmdline_ = \"kload\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"path\", metavar=\"VMLINUX_PATH\", type=str, help=\"path of the vmlinux.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    def do_invoke(self, args):\n        if not os.path.exists(args.path):\n            err(\"Invalid path\")\n            return\n\n        info(\"Wait for memory scan\")\n        text_base = Kernel.get_kernel_base()\n        if text_base is None:\n            err(\"The kernel base is unknown\")\n            return\n\n        gdb.execute(\"add-symbol-file {!r} {:#x}\".format(args.path, text_base))\n        return\n\n\n@register_command\nclass KernelModuleCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display kernel module list.\"\"\"\n\n    _cmdline_ = \"kmod\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    group = parser.add_mutually_exclusive_group(required=False)\n    group.add_argument(\"-s\", \"--resolve-symbol\", action=\"store_true\", help=\"try to resolve symbols.\")\n    group.add_argument(\"-a\", \"--apply-symbol\", action=\"store_true\",\n                        help=\"try to apply symbol in the form 'module_name.symbol'.\")\n    parser.add_argument(\"--symbol-unsort\", action=\"store_true\",\n                        help=\"print resolved symbols without sorting by address.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[], help=\"REGEXP filter.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified module structure:\",\n        \"\",\n        \"                   +-module------------------+\",\n        \"+-modules-----+    | ...                     |\",\n        \"| list_head   |--->| list                    |--->...\",\n        \"+-------------+    | name[]                  |\",\n        \"                   | ...                     |\",\n        \"                   | mem[] (v6.4~)           |\",\n        \"                   |     base                |\",\n        \"                   |     size                |\",\n        \"                   |     ...                 |\",\n        \"                   | init_layout (v4.5~v6.4) |\",\n        \"                   |     base                |\",\n        \"                   |     size                |\",\n        \"                   |     text_size           |\",\n        \"                   |     ro_size             |\",\n        \"                   |     ro_after_init_size  |\",\n        \"                   |     ...                 |\",\n        \"                   | module_core    (~v4.4)  |\",\n        \"                   | init_size      (~v4.4)  |\",\n        \"                   | core_size      (~v4.4)  |\",\n        \"                   | init_text_size (~v4.4)  |  +-->+-mod_kallsyms---+\",\n        \"                   | core_text_size (~v4.4)  |  |   | symtab         |\",\n        \"                   | ...                     |  |   | num_symtab     |\",\n        \"                   | kallsyms                |--+   | strtab         |\",\n        \"                   | ...                     |      | typetab (v5.2~)|\",\n        \"                   +-------------------------+      +----------------+\",\n        \"\",\n        \"Notes for -a option:\",\n        \"- You can check the added symbols with the `symbols` command.\",\n        \"- Added symbols are in the format `module_name.symbol` to avoid collisions.\",\n        \"  When used from the command line, they must be enclosed in single quotes.\",\n        \"  e.g., `p 'virtio_net.__this_module'`\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_modules_list(self, modules):\n        # use cache\n        if self.module_addrs:\n            return self.module_addrs\n\n        # slow path\n        if modules is None:\n            return None\n\n        module_addrs = []\n        current = modules\n        while True:\n            try:\n                addr = read_int_from_memory(current)\n            except gdb.MemoryError:\n                return None\n            if addr == modules:\n                break\n            module_addrs.append(addr - current_arch.ptrsize)\n            current = addr\n        return module_addrs\n\n    def get_offset_name(self, module_addrs):\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).name\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        for i in range(0x100):\n            offset_name = i * current_arch.ptrsize\n            valid = True\n            for module in module_addrs:\n                if not is_ascii_string(module + offset_name):\n                    valid = False\n                    break\n                s = read_cstring_from_memory(module + offset_name)\n                if len(s) < 2:\n                    valid = False\n                    break\n            if valid:\n                return offset_name\n\n        return None\n\n    def get_offset_mem(self, module_addrs): # v6.4~\n        \"\"\"\n        ac3b43283923440900b4f36ca5f9f0b1ca43b70e changed the module layout information structure\n        MOD_TEXT = 0,\n        MOD_DATA,\n        MOD_RODATA,\n        MOD_RO_AFTER_INIT,\n        MOD_INIT_TEXT,\n        MOD_INIT_DATA,\n        MOD_INIT_RODATA,\n\n        struct module {\n            enum module_state state;\n            struct list_head list;\n            char name[MODULE_NAME_LEN]; // 64 - sizeof(unsigned long) bytes\n        #ifdef CONFIG_STACKTRACE_BUILD_ID\n            unsigned char build_id[BUILD_ID_SIZE_MAX]; // 20 bytes\n        #endif\n            struct module_kobject mkobj;\n            struct module_attribute *modinfo_attrs;\n            const char *version;\n            const char *srcversion;\n            struct kobject *holders_dir;\n            const struct kernel_symbol *syms;\n            const s32 *crcs;\n            unsigned int num_syms;\n        #ifdef CONFIG_ARCH_USES_CFI_TRAPS\n            s32 *kcfi_traps;\n            s32 *kcfi_traps_end;\n        #endif\n        #ifdef CONFIG_SYSFS\n            struct mutex param_lock;\n        #endif\n            struct kernel_param *kp;\n            unsigned int num_kp;\n            unsigned int num_gpl_syms;\n            const struct kernel_symbol *gpl_syms;\n            const s32 *gpl_crcs;\n            bool using_gplonly_symbols;\n        #ifdef CONFIG_MODULE_SIG\n            bool sig_ok;\n        #endif\n            bool async_probe_requested;\n            unsigned int num_exentries;\n            struct exception_table_entry *extable;\n            int (*init)(void);\n            struct module_memory mem[MOD_MEM_NUM_TYPES] __module_memory_align;    <-- here\n            struct mod_arch_specific arch;\n            unsigned long taints;\n        #ifdef CONFIG_GENERIC_BUG\n            unsigned num_bugs;\n            struct list_head bug_list;\n            struct bug_entry *bug_table;\n        #endif\n        #ifdef CONFIG_KALLSYMS\n            struct mod_kallsyms __rcu *kallsyms;\n            struct mod_kallsyms core_kallsyms;\n            struct module_sect_attrs *sect_attrs;\n            struct module_notes_attrs *notes_attrs;\n        #endif\n        };\n\n        struct module_memory {\n            void *base;\n            void *rw_copy; // v6.13~\n            bool is_rox;   // v6.13~\n            unsigned int size;\n        #ifdef CONFIG_MODULES_TREE_LOOKUP\n            struct mod_tree_node mtn; (0x38)\n        #endif\n        };\n        \"\"\"\n        # fast path\n        try:\n            offset_mem = to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).mem\"))\n            offset_size = to_unsigned_long(gdb.parse_and_eval(\"&((struct module_memory*)0).size\"))\n            return offset_mem, offset_mem + offset_size\n        except gdb.error:\n            pass\n\n        # slow_path\n        MOD_TEXT = 0\n        MOD_DATA = 1\n        MOD_RODATA = 2\n        MOD_RO_AFTER_INIT = 3 # noqa: F841\n        MOD_INIT_TEXT = 4 # noqa: F841\n        MOD_INIT_DATA = 5 # noqa: F841\n        MOD_INIT_RODATA = 6 # noqa: F841\n        MOD_MEM_NUM_TYPES = 7 # noqa: F841\n        # TODO: only handles non init module type\n        for i in range(300):\n            offset_mem = i * current_arch.ptrsize\n            for sizeof_module_memory in (8, 0x48, 0x50):\n                valid = True\n                for module in module_addrs:\n                    for mem_type in (MOD_TEXT, MOD_DATA, MOD_RODATA):\n                        mem_ptr = module + offset_mem + mem_type * sizeof_module_memory\n                        # memory access check\n                        if not is_valid_addr(mem_ptr):\n                            valid = False\n                            break\n                        # base align check\n                        cand_base = read_int_from_memory(mem_ptr)\n                        if cand_base == 0 or cand_base & 0xfff:\n                            valid = False\n                            break\n                        # size check\n                        if sizeof_module_memory == 0x50:\n                            offset_size = current_arch.ptrsize * 2 + 4 # void*, void*, bool\n                        else:\n                            offset_size = current_arch.ptrsize # void*\n                        cand_size = read_int32_from_memory(mem_ptr + offset_size)\n                        if cand_size == 0 or cand_size > 0x10_0000:\n                            valid = False\n                            break\n                if valid:\n                    return offset_mem, offset_mem + offset_size\n        return None\n\n    def get_offset_init_layout(self, module_addrs): # v4.5 ~ v6.4\n        \"\"\"\n        struct module { // kernel v4.5~\n            enum module_state state;\n            struct list_head list;\n            char name[MODULE_NAME_LEN]; // 64 - sizeof(unsigned long) bytes\n        #ifdef CONFIG_STACKTRACE_BUILD_ID\n            unsigned char build_id[BUILD_ID_SIZE_MAX]; // 20 bytes\n        #endif\n            struct module_kobject mkobj;\n            struct module_attribute *modinfo_attrs;\n            const char *version;\n            const char *srcversion;\n            struct kobject *holders_dir;\n            const struct kernel_symbol *syms;\n            const s32 *crcs;\n            unsigned int num_syms;\n        #ifdef CONFIG_CFI_CLANG\n            cfi_check_fn cfi_check;\n        #endif\n        #ifdef CONFIG_SYSFS\n            struct mutex param_lock;\n        #endif\n            struct kernel_param *kp;\n            unsigned int num_kp;\n            unsigned int num_gpl_syms;\n            const struct kernel_symbol *gpl_syms;\n            const s32 *gpl_crcs;\n            bool using_gplonly_symbols;\n        #ifdef CONFIG_MODULE_SIG\n            bool sig_ok;\n        #endif\n            bool async_probe_requested;\n            unsigned int num_exentries;\n            struct exception_table_entry *extable;\n            int (*init)(void);\n            struct module_layout core_layout __module_layout_align;\n            struct module_layout init_layout;                                     <-- here\n        #ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC\n            struct module_layout data_layout;\n        #endif\n            struct mod_arch_specific arch;\n            unsigned long taints;\n        #ifdef CONFIG_GENERIC_BUG\n            unsigned num_bugs;\n            struct list_head bug_list;\n            struct bug_entry *bug_table;\n        #endif\n        #ifdef CONFIG_KALLSYMS\n            struct mod_kallsyms __rcu *kallsyms;\n            struct mod_kallsyms core_kallsyms;\n            struct module_sect_attrs *sect_attrs;\n            struct module_notes_attrs *notes_attrs;\n        #endif\n            ...\n        };\n\n        struct module_layout {\n            /* The actual code + data. */\n            void *base;\n            /* Total size. */\n            unsigned int size;\n            /* The size of the executable code.  */\n            unsigned int text_size;\n            /* Size of RO section of the module (text+rodata) */\n            unsigned int ro_size;\n            /* Size of RO after init section */\n            unsigned int ro_after_init_size;\n        #ifdef CONFIG_MODULES_TREE_LOOKUP\n            struct mod_tree_node mtn;\n        #endif\n        };\n\n        [Example arm32]\n            gef> x/128xw 0x00000000bf22b084\n            0xbf22b084:     0xbf1bb044      0xc1696530      0x00006773      0x00000000\n            0xbf22b094:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b0a4:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b0b4:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b0c4:     0x00000000      0xc1ec2d00      0xc1a11d80      0xbf1bb08c\n            0xbf22b0d4:     0xc1a11d8c      0xc1a11d80      0xc1628e38      0xc8e0b2c0\n            0xbf22b0e4:     0x00000003      0x00000007      0xbf22b080      0x00000000\n            0xbf22b0f4:     0xc8d4f380      0x00000000      0xc1e47400      0xc8f6d900\n            0xbf22b104:     0xc8f6d080      0xc8004300      0x00000000      0x00000000\n            0xbf22b114:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b124:     0xbf22b124      0xbf22b124      0xbf22a990      0x00000003\n            0xbf22b134:     0x00000000      0x00000000      0x00000000      0x00000001\n            0xbf22b144:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b154:     0x00000000      0xbf17e000      0x00000000      0x00000000\n            0xbf22b164:     0x00000000      0x00000000      0x00000000      0x00000000\n            0xbf22b174:     0x00000000      0x00000000      0x00000000      0xbf225000 <- init_layout.base\n            0xbf22b184:     0x00008000      0x00005000      0x00006000      0x00006000\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).init_layout\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        for i in range(300):\n            offset_init_layout = i * current_arch.ptrsize\n            valid = True\n            for module in module_addrs:\n                # memory access check\n                init_layout_ptr = module + offset_init_layout\n                if not is_valid_addr(init_layout_ptr):\n                    valid = False\n                    break\n                # base align check\n                cand_base = read_int_from_memory(init_layout_ptr)\n                if cand_base == 0 or cand_base & 0xfff:\n                    valid = False\n                    break\n                # size check\n                cand_size = read_int32_from_memory(init_layout_ptr + current_arch.ptrsize)\n                if cand_size == 0 or cand_size > 0x20_0000:\n                    valid = False\n                    break\n                # text_size check\n                cand_text_size = read_int32_from_memory(init_layout_ptr + current_arch.ptrsize + 4 * 1)\n                if cand_text_size == 0 or cand_text_size > 0x20_0000:\n                    valid = False\n                    break\n                # ro_size check\n                cand_ro_size = read_int32_from_memory(init_layout_ptr + current_arch.ptrsize + 4 * 2)\n                if cand_ro_size == 0 or cand_ro_size > 0x20_0000:\n                    valid = False\n                    break\n                # ro_after_init_size check\n                cand_ro_after_init_size = read_int32_from_memory(init_layout_ptr + current_arch.ptrsize + 4 * 3)\n                if cand_ro_after_init_size == 0 or cand_ro_after_init_size > 0x20_0000:\n                    valid = False\n                    break\n            if valid:\n                return offset_init_layout\n        return None\n\n    def get_offset_module_core(self, module_addrs): # ~v4.4\n        \"\"\"\n        struct module { // ~v4.4\n            enum module_state state;\n            struct list_head list;\n            char name[MODULE_NAME_LEN];\n            struct module_kobject mkobj;\n            struct module_attribute *modinfo_attrs;\n            const char *version;\n            const char *srcversion;\n            struct kobject *holders_dir;\n            const struct kernel_symbol *syms;\n            const unsigned long *crcs;\n            unsigned int num_syms;\n        #ifdef CONFIG_SYSFS\n            struct mutex param_lock;\n        #endif\n            struct kernel_param *kp;\n            unsigned int num_kp;\n            unsigned int num_gpl_syms;\n            const struct kernel_symbol *gpl_syms;\n            const unsigned long *gpl_crcs;\n        #ifdef CONFIG_UNUSED_SYMBOLS\n            const struct kernel_symbol *unused_syms;\n            const unsigned long *unused_crcs;\n            unsigned int num_unused_syms;\n            unsigned int num_unused_gpl_syms;\n            const struct kernel_symbol *unused_gpl_syms;\n            const unsigned long *unused_gpl_crcs;\n        #endif\n        #ifdef CONFIG_MODULE_SIG\n            bool sig_ok;\n        #endif\n            bool async_probe_requested;\n            const struct kernel_symbol *gpl_future_syms;\n            const unsigned long *gpl_future_crcs;\n            unsigned int num_gpl_future_syms;\n            unsigned int num_exentries;\n            struct exception_table_entry *extable;\n            int (*init)(void);\n            void *module_init ____cacheline_aligned;\n            /* Here is the actual code + data, vfree'd on unload. */\n            void *module_core;                                                    <-- here\n            /* Here are the sizes of the init and core sections */\n            unsigned int init_size, core_size;\n            /* The size of the executable code in each section. */\n            unsigned int init_text_size, core_text_size;\n        #ifdef CONFIG_MODULES_TREE_LOOKUP\n            struct mod_tree_node mtn_core;\n            struct mod_tree_node mtn_init;\n        #endif\n            unsigned int init_ro_size, core_ro_size;\n            struct mod_arch_specific arch;\n            unsigned int taints;\n        #ifdef CONFIG_GENERIC_BUG\n            unsigned num_bugs;\n            struct list_head bug_list;\n            struct bug_entry *bug_table;\n        #endif\n        #ifdef CONFIG_KALLSYMS\n            struct mod_kallsyms *kallsyms;                                        <-- here\n            struct mod_kallsyms core_kallsyms;\n            struct module_sect_attrs *sect_attrs;\n            struct module_notes_attrs *notes_attrs;\n        #endif\n            ...\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).module_core\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        for i in range(300):\n            offset_module_core = i * current_arch.ptrsize\n            valid = True\n            for module in module_addrs:\n                module_core_ptr = module + offset_module_core\n                # memory access check\n                if not is_valid_addr(module_core_ptr):\n                    valid = False\n                    break\n                # module_core align check\n                cand_module_core = read_int_from_memory(module_core_ptr)\n                if cand_module_core == 0 or cand_module_core & 0xfff:\n                    valid = False\n                    break\n                # init_size check\n                cand_init_size = read_int32_from_memory(module_core_ptr + current_arch.ptrsize)\n                if cand_init_size > 0x10_0000:\n                    valid = False\n                    break\n                # core_size check\n                cand_core_size = read_int32_from_memory(module_core_ptr + current_arch.ptrsize + 4 * 1)\n                if cand_core_size == 0 or cand_core_size > 0x10_0000:\n                    valid = False\n                    break\n                # init_text_size check\n                cand_init_text_size = read_int32_from_memory(module_core_ptr + current_arch.ptrsize + 4 * 2)\n                if cand_init_text_size > 0x10_0000:\n                    valid = False\n                    break\n                # core_text_size check\n                cand_core_text_size = read_int32_from_memory(module_core_ptr + current_arch.ptrsize + 4 * 3)\n                if cand_core_text_size == 0 or cand_core_text_size > 0x10_0000:\n                    valid = False\n                    break\n            if valid:\n                return offset_module_core\n        return None\n\n    def get_offset_kallsyms(self, module_addrs):\n        \"\"\"\n        struct mod_kallsyms {\n            Elf_Sym *symtab;\n            unsigned int num_symtab;\n            char *strtab;\n            char *typetab; // v5.2~\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).kallsyms\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        kversion = Kernel.kernel_version()\n        for i in range(300):\n            offset_kallsyms = i * current_arch.ptrsize\n            valid = True\n            for module in module_addrs:\n                kallsyms_ptr = module + offset_kallsyms\n                # access check\n                if not is_valid_addr(kallsyms_ptr):\n                    valid = False\n                    break\n                # kallsyms access check\n                cand_kallsyms = read_int_from_memory(kallsyms_ptr)\n                if not is_valid_addr(cand_kallsyms):\n                    valid = False\n                    break\n                # struct mod_kallsyms member access check\n                cand_symtab = read_int_from_memory(cand_kallsyms)\n                if not is_valid_addr(cand_symtab):\n                    valid = False\n                    break\n                cand_num_symtab = read_int_from_memory(cand_kallsyms + current_arch.ptrsize * 1)\n                if is_valid_addr(cand_num_symtab) or cand_num_symtab == 0:\n                    valid = False\n                    break\n                cand_strtab = read_int_from_memory(cand_kallsyms + current_arch.ptrsize * 2)\n                if not is_valid_addr(cand_strtab):\n                    valid = False\n                    break\n                if \"5.2\" <= kversion:\n                    cand_typetab = read_int_from_memory(cand_kallsyms + current_arch.ptrsize * 3)\n                    if not is_valid_addr(cand_typetab):\n                        valid = False\n                        break\n            if valid:\n                return offset_kallsyms\n        return None\n\n    def initialize(self):\n        if hasattr(self, \"initialized\"):\n            return True\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        # modules\n        self.modules = KernelAddressHeuristicFinder.get_modules()\n        if self.modules is None:\n            self.quiet_err(\"Could not find modules (CONFIG_MODULES may not be set)\")\n            return False\n        self.quiet_info(\"modules: {:#x}\".format(self.modules))\n\n        # modules list\n        self.module_addrs = self.get_modules_list(self.modules)\n        if self.module_addrs is None:\n            return False\n        if self.module_addrs == []:\n            self.quiet_err(\"Could not find any modules\")\n            return False\n\n        # module->name\n        self.offset_name = self.get_offset_name(self.module_addrs)\n        if self.offset_name is None:\n            self.quiet_err(\"Could not find module->name[MODULE_NAME_LEN]\")\n            return False\n        self.quiet_info(\"offsetof(module, name): {:#x}\".format(self.offset_name))\n\n        # modules->{mem,mem_size,module_core}\n        if \"6.4\" <= kversion:\n            ret = self.get_offset_mem(self.module_addrs)\n            if ret is None:\n                self.quiet_err(\"Could not find module->mem\")\n                return False\n            self.offset_mem, self.offset_mem_size = ret\n            self.quiet_info(\"offsetof(module, mem): {:#x}\".format(self.offset_mem))\n            self.quiet_info(\"offsetof(module, mem.size): {:#x}\".format(self.offset_mem_size))\n        elif \"4.5\" <= kversion:\n            self.offset_init_layout = self.get_offset_init_layout(self.module_addrs)\n            if self.offset_init_layout is None:\n                self.quiet_err(\"Could not find module->init_layout\")\n                return False\n            self.quiet_info(\"offsetof(module, init_layout): {:#x}\".format(self.offset_init_layout))\n        else: # kversion < v4.5\n            self.offset_module_core = self.get_offset_module_core(self.module_addrs)\n            if self.offset_module_core is None:\n                self.quiet_err(\"Could not find module->module_core\")\n                return False\n            self.quiet_info(\"offsetof(module, module_core): {:#x}\".format(self.offset_module_core))\n\n        # module->kallsyms\n        self.offset_kallsyms = self.get_offset_kallsyms(self.module_addrs)\n        if self.offset_kallsyms is None:\n            self.quiet_err(\"Could not find module->kallsyms\")\n            return False\n        self.quiet_info(\"offsetof(module, kallsyms): {:#x}\".format(self.offset_kallsyms))\n\n        self.initialized = True\n        return True\n\n    def parse_kallsyms(self, kallsyms):\n        kversion = Kernel.kernel_version()\n\n        symtab = read_int_from_memory(kallsyms + current_arch.ptrsize * 0)\n        sizeof_symtab_entry = 24 if is_64bit() else 16\n        num_symtab = read_int_from_memory(kallsyms + current_arch.ptrsize * 1)\n        strtab = read_int_from_memory(kallsyms + current_arch.ptrsize * 2)\n        strtab_pos = 0\n        if \"5.2\" <= kversion:\n            typetab = read_int_from_memory(kallsyms + current_arch.ptrsize * 3)\n\n        #gef_print(\"symtab: {:#x}\".format(symtab))\n        #gef_print(\"sizeof_symtab_entry: {:#x}\".format(sizeof_symtab_entry))\n        #gef_print(\"num_symab: {:#x}\".format(num_symtab))\n        #gef_print(\"strtab: {:#x}\".format(strtab))\n        #if \"5.2\" <= kversion:\n        #    gef_print(\"typetab: {:#x}\".format(typetab))\n\n        entries = []\n        tqdm = GefUtil.get_tqdm(not self.args.quiet and not self.args.apply_symbol)\n        for i in tqdm(range(num_symtab), leave=False):\n            sym_addr = read_int_from_memory(symtab + sizeof_symtab_entry * i + current_arch.ptrsize)\n            sym_name = read_cstring_from_memory(strtab + strtab_pos)\n            strtab_pos += len(sym_name) + 1\n\n            if \"5.2\" <= kversion:\n                sym_type = chr(read_int8_from_memory(typetab + i))\n            elif \"5.0\" <= kversion:\n                # st_size\n                if is_64bit():\n                    sym_type = chr(read_int8_from_memory(symtab + sizeof_symtab_entry * i + 16))\n                else:\n                    sym_type = chr(read_int8_from_memory(symtab + sizeof_symtab_entry * i + 8))\n            else:\n                # st_info\n                if is_64bit():\n                    sym_type = chr(read_int8_from_memory(symtab + sizeof_symtab_entry * i + 4))\n                else:\n                    sym_type = chr(read_int8_from_memory(symtab + sizeof_symtab_entry * i + 12))\n            entries.append([sym_addr, sym_type, sym_name])\n        return entries\n\n    def print_symbol(self, entries, symbol_unsort):\n        self.out.append(titlify(\"module symbols\"))\n        # symbol_unsort is used for debugging.\n        if not symbol_unsort:\n            entries = sorted(entries)\n        # add output\n        for sym_addr, sym_type, sym_name in entries:\n            self.out.append(\"{:#018x} {:s} {:s}\".format(sym_addr, sym_type, sym_name))\n        self.out.append(titlify(\"\"))\n        return\n\n    def apply_symbol(self, module_name, text_base, entries):\n        # remove old file\n        sym_elf_path = os.path.join(GEF_TEMP_DIR, \"kmod-{:s}.elf\".format(module_name))\n        if os.path.exists(sym_elf_path):\n            os.unlink(sym_elf_path)\n\n        # make blank ELF\n        text_base &= get_pagesize_mask_high()\n        text_end = entries[-1][0]\n        blank_elf = AddSymbolTemporaryCommand.create_blank_elf(text_base, text_end)\n        if blank_elf is None:\n            self.quiet_err(\"Failed to create blank ELF\")\n            return\n\n        # create command\n        cmd_string_arr = []\n        for sym_addr, sym_type, sym_name in entries:\n            if sym_addr < text_base:\n                continue\n\n            if sym_type in [\"T\", \"t\", \"W\", None]:\n                type_flag = \"function\"\n            else:\n                type_flag = \"object\"\n            if sym_type and sym_type in \"abcdefghijklmnopqrstuvwxyz\":\n                global_flag = \"local\"\n            else:\n                global_flag = \"global\"\n\n            # higher address needs relative\n            relative_addr = sym_addr - text_base\n            cmd_string_arr.append(\"--add-symbol\")\n            cmd_string_arr.append(\"{:s}.{:s}=.text:{:#x},{:s},{:s}\".format(\n                # modules often contain the same symbols, such as \"__this_module\".\n                # to avoid collisions, register them in the form \"module_name.symbol\".\n                module_name, sym_name, relative_addr, global_flag, type_flag,\n            ))\n\n        # embedding symbols\n        objcopy = GefUtil.which(Config.get_gef_setting(\"gef.objcopy_command\"))\n        processed_count = 0\n        for cmd_string_arr_sliced in slicer(cmd_string_arr, 10000 * 2):\n            subprocess.check_output([objcopy] + cmd_string_arr_sliced + [blank_elf])\n            processed_count += len(cmd_string_arr_sliced) // 2\n        self.quiet_info(\"{:s}: {:d} entries were processed\".format(module_name, processed_count))\n        os.rename(blank_elf, sym_elf_path)\n\n        # apply\n        cmd = \"add-symbol-file {!r} {:#x}\".format(sym_elf_path, text_base)\n        self.quiet_info(\"Execute `{:s}`\".format(cmd))\n        gdb.execute(cmd, to_string=True)\n        return\n\n    def parse_module(self):\n        if not self.args.apply_symbol:\n            if not self.args.quiet:\n                fmt = \"{:<18s} {:<24s} {:<18s} {:<18s}\"\n                legend = [\"module\", \"module->name\", \"base\", \"size\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        kversion = Kernel.kernel_version()\n        tqdm = GefUtil.get_tqdm(not self.args.quiet and not self.args.apply_symbol)\n        for module in tqdm(self.module_addrs, leave=False):\n            name_string = read_cstring_from_memory(module + self.offset_name)\n            if self.args.filter:\n                if not any(re_pattern.search(name_string) for re_pattern in self.args.filter):\n                    continue\n\n            if \"6.4\" <= kversion:\n                base = read_int_from_memory(module + self.offset_mem)\n                size = read_int32_from_memory(module + self.offset_mem_size)\n            elif \"4.5\" <= kversion:\n                base = read_int_from_memory(module + self.offset_init_layout)\n                size = read_int32_from_memory(module + self.offset_init_layout + current_arch.ptrsize)\n            else: # kversion < \"4.5\"\n                base = read_int_from_memory(module + self.offset_module_core)\n                size = read_int32_from_memory(module + self.offset_module_core + current_arch.ptrsize + 4)\n\n            if not self.args.apply_symbol:\n                self.out.append(\"{:#018x} {:<24s} {:#018x} {:#018x}\".format(module, name_string, base, size))\n\n            if self.args.resolve_symbol:\n                kallsyms = read_int_from_memory(module + self.offset_kallsyms)\n                entries = self.parse_kallsyms(kallsyms)\n                self.print_symbol(entries, self.args.symbol_unsort)\n\n            elif self.args.apply_symbol:\n                kallsyms = read_int_from_memory(module + self.offset_kallsyms)\n                entries = self.parse_kallsyms(kallsyms)\n                self.apply_symbol(name_string, base, entries)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        # initialize\n        self.module_addrs = None\n        ret = self.initialize()\n        if not ret:\n            self.quiet_err(\"Failed to initialize\")\n            return\n\n        # get module addrs\n        if not self.module_addrs:\n            self.module_addrs = self.get_modules_list(self.modules)\n        if self.module_addrs is None:\n            return\n        if self.module_addrs == []:\n            self.quiet_err(\"Could not find any modules\")\n            return\n        self.quiet_info(\"Num of modules: {:#x}\".format(len(self.module_addrs)))\n\n        # parse modules\n        self.out = []\n        self.parse_module()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelModuleLoadCommand(GenericCommand):\n    \"\"\"Load the kernel module without a load address.\"\"\"\n\n    _cmdline_ = \"kmod-load\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"name\", type=str, help=\"name of the loaded module to search for by `kmod`.\")\n    parser.add_argument(\"path\", type=str, help=\"path to compiled kernel module.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} sample /path/to/sample.ko\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"It is useful if you have a kernel module with debuginfo at hand.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_modules_list(self, modules):\n        # use cache\n        if self.module_addrs:\n            return self.module_addrs\n\n        # slow path\n        if modules is None:\n            return None\n\n        module_addrs = []\n        current = modules\n        while True:\n            try:\n                addr = read_int_from_memory(current)\n            except gdb.MemoryError:\n                return None\n            if addr == modules:\n                break\n            module_addrs.append(addr - current_arch.ptrsize)\n            current = addr\n        return module_addrs\n\n    def get_offset_name(self, module_addrs):\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).name\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        for i in range(0x100):\n            offset_name = i * current_arch.ptrsize\n            valid = True\n            for module in module_addrs:\n                if not is_ascii_string(module + offset_name):\n                    valid = False\n                    break\n                s = read_cstring_from_memory(module + offset_name)\n                if len(s) < 2:\n                    valid = False\n                    break\n            if valid:\n                return offset_name\n\n        return None\n\n    def get_offset_sect_attrs(self, module_addrs):\n        \"\"\"\n        struct attribute {\n            const char *name;\n            umode_t mode;\n        #ifdef CONFIG_DEBUG_LOCK_ALLOC\n            bool ignore_lockdep:1;\n            struct lock_class_key *key;\n            struct lock_class_key skey;\n        #endif\n        };\n\n        struct module_sect_attrs {\n            struct attribute_group {\n                const char *name;\n                umode_t (*is_visible)(struct kobject *, struct attribute *, int);\n                umode_t (*is_bin_visible)(struct kobject *, struct bin_attribute *, int); // v4.4~\n                size_t (*bin_size)(struct kobject *, const struct bin_attribute *, int); // v6.13~\n                struct attribute **attrs;\n                struct bin_attribute **bin_attrs; // v3.11~v6.12\n                union {\n                    struct bin_attribute **bin_attrs;\n                    const struct bin_attribute *const *bin_attrs_new;\n                }; // v6.13~\n            } grp;\n            unsigned int nsections;\n            struct module_sect_attr {\n                struct bin_attribute { // v5.7~\n                    struct attribute attr;\n                    size_t size;\n                    void *private;\n                    struct address_space *(*f_mapping)(void); // v5.15~\n                    struct address_space *mapping; // v5.12~5.14\n                    ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t);\n                    ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *, char *, loff_t, size_t); // v6.13~\n                    ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t);\n                    ssize_t (*write_new)(struct file *, struct kobject *, const struct bin_attribute *, char *, loff_t, size_t); // v6.13~\n                    loff_t (*llseek)(struct file *, struct kobject *, struct bin_attribute *, loff_t, int); // v6.7~\n                    int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr, struct vm_area_struct *vma);\n                } battr;\n                struct module_attribute { // ~v5.6\n                    struct attribute attr;\n                    ssize_t (*show)(struct module_attribute *, struct module_kobject *, char *);\n                    ssize_t (*store)(struct module_attribute *, struct module_kobject *, const char *, size_t count);\n                    void (*setup)(struct module *, const char *);\n                    int (*test)(struct module *);\n                    void (*free)(struct module *);\n                } mattr;\n                char *name; // ~v5.6\n                unsigned long address;\n            } attrs[];\n        };\n        \"\"\"\n        # fast path\n        try:\n            return to_unsigned_long(gdb.parse_and_eval(\"&((struct module*)0).sect_attrs\"))\n        except gdb.error:\n            pass\n\n        # slow_path\n        for i in range(300):\n            offset_sect_attrs = current_arch.ptrsize * i\n            valid = True\n            for module in module_addrs:\n                # access check\n                if not is_valid_addr(module + offset_sect_attrs):\n                    valid = False\n                    break\n                sect_attrs = read_int_from_memory(module + offset_sect_attrs)\n                if not is_valid_addr(sect_attrs):\n                    valid = False\n                    break\n                firstname = read_int_from_memory(sect_attrs + self.offset_firstname)\n                if not is_valid_addr(firstname):\n                    valid = False\n                    break\n                sectname = read_cstring_from_memory(firstname)\n                # well formed kernel module sections *should* only start with these prefixes\n                # might be better to do a length based heuristic?\n                if sectname is None or not sectname.startswith((\".\", \"__\")):\n                    if sectname and len(sectname) >= 4:\n                        self.quiet_info(\n                            \"possible section name (rejected for not starting with . or __): {:s}\".format(sectname),\n                        )\n                    valid = False\n                    break\n            if valid:\n                return offset_sect_attrs\n        return None\n\n    def initialize(self):\n        if hasattr(self, \"initialized\"):\n            return True\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        if kversion < \"3.0\":\n            self.quiet_err(\"Unsupported before v3.0\")\n            return False\n\n        # modules\n        self.modules = KernelAddressHeuristicFinder.get_modules()\n        if self.modules is None:\n            self.quiet_err(\"Could not find modules (maybe, CONFIG_MODULES is not set)\")\n            return False\n        self.quiet_info(\"modules: {:#x}\".format(self.modules))\n\n        # modules list\n        self.module_addrs = self.get_modules_list(self.modules)\n        if self.module_addrs is None:\n            return False\n        if self.module_addrs == []:\n            self.quiet_err(\"Could not find any modules\")\n            return False\n\n        # module->name\n        self.offset_name = self.get_offset_name(self.module_addrs)\n        if self.offset_name is None:\n            self.quiet_err(\"Could not find module->name[MODULE_NAME_LEN]\")\n            return False\n        self.quiet_info(\"offsetof(module, name): {:#x}\".format(self.offset_name))\n\n        # module->{nsections,firstname}\n        if kversion < \"3.11\":\n            self.offset_nsections = current_arch.ptrsize * 3\n            self.offset_firstname = current_arch.ptrsize * 4\n        elif kversion < \"4.4\":\n            self.offset_nsections = current_arch.ptrsize * 4\n            self.offset_firstname = current_arch.ptrsize * 5\n        elif kversion < \"6.13\":\n            self.offset_nsections = current_arch.ptrsize * 5\n            self.offset_firstname = current_arch.ptrsize * 6\n        else:\n            self.offset_nsections = current_arch.ptrsize * 6\n            self.offset_firstname = current_arch.ptrsize * 7\n\n        # module->{address,module_sect_attr}\n        if kversion < \"5.7\":\n            self.offset_address = self.offset_firstname + current_arch.ptrsize * 8\n            self.sizeof_module_sect_attr = current_arch.ptrsize * 9\n        elif kversion < \"5.12\":\n            self.offset_address = self.offset_firstname + current_arch.ptrsize * 7\n            self.sizeof_module_sect_attr = current_arch.ptrsize * 8\n        elif kversion < \"6.7\":\n            self.offset_address = self.offset_firstname + current_arch.ptrsize * 8\n            self.sizeof_module_sect_attr = current_arch.ptrsize * 9\n        elif kversion < \"6.13\":\n            self.offset_address = self.offset_firstname + current_arch.ptrsize * 9\n            self.sizeof_module_sect_attr = current_arch.ptrsize * 10\n        else:\n            self.offset_address = self.offset_firstname + current_arch.ptrsize * 11\n            self.sizeof_module_sect_attr = current_arch.ptrsize * 12\n\n        # module->sect_attrs\n        self.offset_sect_attrs = self.get_offset_sect_attrs(self.module_addrs)\n        if self.offset_sect_attrs is None:\n            self.quiet_err(\"Could not find module->sect_attrs\")\n            return False\n        self.quiet_info(\"offsetof(module, sect_attrs): {:#x}\".format(self.offset_sect_attrs))\n\n        self.initialized = True\n        return True\n\n    def kmod_load(self):\n        for module in self.module_addrs:\n            name_string = read_cstring_from_memory(module + self.offset_name)\n            if name_string != self.args.name:\n                continue\n\n            # get nsections\n            sect_attrs = read_int_from_memory(module + self.offset_sect_attrs)\n            nsections = read_int_from_memory(sect_attrs + self.offset_nsections) & 0xffff_ffff\n            self.quiet_info(\"nsections = {}\".format(nsections))\n\n            # get each section name and address\n            sections = []\n            for i in range(nsections):\n                name_ptr = read_int_from_memory(sect_attrs + self.offset_firstname + self.sizeof_module_sect_attr * i)\n                name = read_cstring_from_memory(name_ptr)\n                addr = read_int_from_memory(sect_attrs + self.offset_address + self.sizeof_module_sect_attr * i)\n                self.quiet_info(\"name={:s}, addr={:#x}\".format(name, addr))\n                sections.append((name, addr))\n\n                # unneeded, but for convenience\n                gdb.execute(\"set ${:s} = {:#x}\".format(name.replace(\".\", \"\").replace(\"-\", \"\"), addr))\n\n            # load\n            command = \" \".join(['-s {:s} {:#x}'.format(name, addr) for (name, addr) in sections])\n            gdb.execute(\"add-symbol-file {!r} {:s}\".format(self.args.path, command))\n            break\n        else:\n            self.quiet_err(\"Could not find {:s}\".format(self.args.name))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if not os.path.exists(args.path):\n            self.quiet_err(\"Could not find {:s}\".format(args.path))\n            return\n\n        # initialize\n        self.module_addrs = None\n        ret = self.initialize()\n        if not ret:\n            self.quiet_err(\"Failed to initialize\")\n            return\n\n        # get module addrs\n        if not self.module_addrs:\n            self.module_addrs = self.get_modules_list(self.modules)\n        if self.module_addrs is None:\n            return\n        if self.module_addrs == []:\n            self.quiet_err(\"Could not find any modules\")\n            return\n        self.quiet_info(\"Num of modules: {:#x}\".format(len(self.module_addrs)))\n\n        # doit\n        self.kmod_load()\n        return\n\n\n@register_command\nclass KernelBlockDevicesCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display block device list.\"\"\"\n\n    _cmdline_ = \"kbdev\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"If there are too many block devices, detection may fail.\",\n        \"This is because block devices are not managed in a single location,\",\n        \"so the list of bdev_cache obtained from the slub-dump results is used.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        self.offset_bd_dev = None\n        return\n\n    def get_bdev_list(self):\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            ret = gdb.execute(\"slub-dump --quiet --no-pager -vv bdev_cache\", to_string=True)\n        elif allocator == \"SLUB_TINY\":\n            ret = gdb.execute(\"slub-tiny-dump --quiet --no-pager bdev_cache\", to_string=True)\n        else:\n            self.quiet_err(\"Unsupported: SLAB, SLOB, Unknown allocator\")\n            return None\n\n        bdevs = []\n        for line in ret.splitlines():\n            line = Color.remove_color(line)\n            r = re.search(r\"(0x\\S+) \\(in-use\\)\", line)\n            if not r:\n                continue\n            bdev = int(r.group(1), 16)\n            bdevs.append(bdev)\n        return bdevs\n\n    @staticmethod\n    def get_bdev_name(major, minor):\n        # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt\n        # https://github.com/lrs-lang/lib/blob/master/src/dev/lib.rs\n        dev_name_list = {\n            0: \"???\",\n            4: \"/dev/root\",\n            7: \"/dev/loop{:d}\",\n            9: \"/dev/md{:d}\",\n            11: \"/dev/scd{0:d} (sr{0:d})\",\n            12: \"/dev/dos_cd{:d}\",\n            15: \"/dev/sonycd\",\n            16: \"/dev/gscd\",\n            17: \"/dev/optcd\",\n            18: \"/dev/sjcd\",\n            20: \"/dev/hitcd\",\n            23: \"/dev/mcd\",\n            24: \"/dev/cdu535\",\n            29: \"/dev/aztcd\",\n            30: \"/dev/cm205cd\",\n            32: \"/dev/cm206cd\",\n            35: \"/dev/slram\",\n            37: \"/dev/z2ram\",\n            41: \"/dev/bpcd\",\n            43: \"/dev/nb{:d}\",\n            46: \"/dev/pcd{:d}\",\n            47: \"/dev/pf{:d}\",\n            59: \"/dev/pda{:d}\",\n            92: \"/dev/ppdd{:d}\",\n            97: \"/dev/pktcdvd\",\n            99: \"/dev/jsfd\",\n            103: \"/dev/audit\",\n            115: \"/dev/nwfs/v{:d}\",\n            147: \"/dev/drbd{:d}\",\n            152: \"/dev/etherd/{:d}\",\n            199: \"/dev/vx/dsk/*/*\",\n            201: \"/dev/vx/dmp/*/*\",\n            258: \"/dev/blockrom{:d}\",\n        }\n\n        if major in dev_name_list:\n            return dev_name_list[major].format(minor)\n\n        def common_pattern(kind_sep, kind_max, devstr, sym_start=\"a\"):\n            kind = minor // kind_sep\n            num = minor % kind_sep\n            if kind < kind_max:\n                dev = \"/dev/{:s}{:s}\".format(devstr, chr(ord(sym_start) + kind))\n                if num:\n                    dev = \"{:s}{:d}\".format(dev, num)\n                return dev\n            return \"???\"\n\n        def common_pattern_num_p(kind_sep, kind_max, devstr, kind_offset=0):\n            kind = minor // kind_sep\n            num = minor % kind_sep\n            if kind_max is None or kind < kind_max:\n                dev = \"/dev/{:s}{:d}\".format(devstr, kind + kind_offset)\n                if num:\n                    dev = \"{:s}p{:d}\".format(dev, num)\n                return dev\n            return \"???\"\n\n        def iterate_pattern(kind_sep, kind_max, dev_str, sym_start):\n\n            def gen():\n                cs = \"abcdefghijklmnopqrstuvwxyz\"\n                for c in cs:\n                    yield c\n                for c1 in cs:\n                    for c2 in cs:\n                        yield c1 + c2\n                return\n\n            name_list = list(gen())\n            kind = minor // kind_sep\n            num = minor % kind_sep\n            if kind < (kind_max or len(name_list)):\n                offset = name_list.index(sym_start)\n                dev = \"/dev/{:s}{:s}\".format(dev_str, name_list[offset + kind])\n                if num:\n                    dev = \"{:s}{:d}\".format(dev, num)\n                return dev\n            return \"???\"\n\n        if major == 1:\n            if 0 <= minor < 250:\n                return \"/dev/ram{:d}\".format(minor)\n            elif minor == 250:\n                return \"/dev/initrd\"\n        elif major == 2:\n            if 0 <= minor < 128:\n                num = minor % 4\n            elif 128 <= minor < 256:\n                num = 4 + minor % 4\n            else:\n                return \"???\"\n            fd_type = (minor % 128) & ~0b11\n            type_dic = {\n                0: \"\",\n                4: \"d360\",\n                8: \"h1200\",\n                12: \"u360\",\n                16: \"u720\",\n                20: \"h360\",\n                24: \"h720\",\n                28: \"u1440\",\n                32: \"u2880\",\n                36: \"CompaQ\",\n                40: \"h1440\",\n                44: \"u1680\",\n                48: \"h410\",\n                52: \"u820\",\n                56: \"h1476\",\n                60: \"u1722\",\n                64: \"h420\",\n                68: \"u830\",\n                72: \"h1494\",\n                76: \"u1743\",\n                80: \"h880\",\n                84: \"u1040\",\n                88: \"u1120\",\n                92: \"h1600\",\n                96: \"u1760\",\n                100: \"u1920\",\n                104: \"u3200\",\n                108: \"u3520\",\n                112: \"u3840\",\n                116: \"u1840\",\n                120: \"u800\",\n                124: \"u1600\",\n            }\n            if fd_type in type_dic:\n                return \"/dev/fd{:d}{:s}\".format(num, type_dic[fd_type])\n        elif major == 3:\n            return common_pattern(64, 2, \"hd\", sym_start=\"a\")\n        elif major == 8:\n            return iterate_pattern(16, 16, \"sd\", sym_start=\"a\")\n        elif major == 13:\n            return common_pattern(64, 4, \"xd\")\n        elif major == 14:\n            return common_pattern(64, 4, \"dos_hd\")\n        elif major == 19:\n            if 0 <= minor < 8:\n                return \"/dev/double{:d}\".format(minor)\n            elif 128 <= minor < 136:\n                return \"/dev/cdouble{:d}\".format(minor - 128)\n        elif major == 21:\n            return common_pattern(64, 2, \"mfm\")\n        elif major == 22:\n            return common_pattern(64, 2, \"hd\", sym_start=\"c\")\n        elif 25 <= major < 28:\n            if 0 <= minor < 4:\n                return \"/dev/sbpcd{:d}\".format(minor + (major - 25) * 4)\n        elif major == 28: # 28 are duplicates\n            if is_m68k():\n                return common_pattern(16, 16, \"ad\")\n            else:\n                if 0 <= minor < 4:\n                    return \"/dev/sbpcd{:d}\".format(minor + (major - 25) * 4)\n        elif major == 31:\n            if 0 <= minor < 8:\n                return \"/dev/rom{:d}\".format(minor)\n            elif 8 <= minor < 16:\n                return \"/dev/rrom{:d}\".format(minor - 8)\n            elif 16 <= minor < 24:\n                return \"/dev/flash{:d}\".format(minor - 16)\n            elif 24 <= minor < 32:\n                return \"/dev/rflash{:d}\".format(minor - 24)\n        elif 33 <= major < 35:\n            return common_pattern(64, 2, \"hd\", sym_start=[\"e\", \"g\"][major - 33])\n        elif major == 36:\n            return common_pattern(64, 4, \"ed\")\n        elif major == 40:\n            if minor == 0:\n                return \"/dev/eza\"\n            elif 1 <= minor < 64:\n                return \"/dev/eza{:d}\".format(minor)\n        elif major == 44:\n            return common_pattern(16, 16, \"ftl\")\n        elif major == 45:\n            return common_pattern(16, 4, \"pd\")\n        elif 48 <= major < 56:\n            return common_pattern_num_p(8, 32, \"rd/c{:d}d\".format(major - 48))\n        elif 56 <= major < 58:\n            return common_pattern(64, 2, \"hd\", sym_start=[\"i\", \"k\"][major - 56])\n        elif major == 64:\n            if minor == 0:\n                return \"/dev/scramdisk/master\"\n            elif 1 <= minor:\n                return \"/dev/scramdisk/{:d}\".format(minor)\n        elif 65 <= major < 72:\n            return iterate_pattern(16, 16, \"sd\", sym_start=[\"q\", \"ag\", \"aw\", \"bm\", \"cc\", \"cs\", \"di\"][major - 65])\n        elif 72 <= major < 80:\n            return common_pattern_num_p(16, 16, \"ida/c{:d}d\".format(major - 72))\n        elif 80 <= major < 88:\n            return iterate_pattern(16, 16, \"i2o/hd\", sym_start=[\"a\", \"q\", \"ag\", \"aw\", \"bm\", \"cc\", \"cs\", \"di\"][major - 80])\n        elif 88 <= major < 92:\n            return common_pattern(64, 2, \"hd\", sym_start=[\"m\", \"o\", \"q\", \"s\"][major - 88])\n        elif major == 93:\n            return common_pattern(16, 16, \"nftl\")\n        elif major == 94:\n            return common_pattern(4, 26, \"dasd\")\n        elif major == 96:\n            return common_pattern(16, 16, \"inftl\")\n        elif major == 98:\n            return common_pattern(16, 26, \"ubd\")\n        elif major == 101:\n            return common_pattern_num_p(16, 16, \"amiraid/ar\")\n        elif major == 102:\n            return common_pattern(16, 16, \"cbd/\")\n        elif 104 <= major < 112:\n            return common_pattern_num_p(16, 16, \"cciss/c{:d}d\".format(major - 104))\n        elif major == 112:\n            return iterate_pattern(8, 64, \"iseries/vd\", sym_start=\"a\")\n        elif major == 113:\n            return iterate_pattern(1, None, \"iseries/vcd\", sym_start=\"a\")\n        elif major == 114:\n            return common_pattern_num_p(16, 16, \"ataraid/d\")\n        elif major == 116:\n            return common_pattern_num_p(16, 16, \"umem/d\")\n        elif major == 117:\n            if minor == 0:\n                return \"/dev/evms/block_device\"\n            elif 1 <= minor < 128:\n                return \"/dev/evms/legacyname{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/evms/EVMSname{:d}\".format(256 - minor)\n        elif 128 <= major < 136:\n            return iterate_pattern(16, 16, \"sd\", sym_start=[\"dy\", \"eo\", \"fe\", \"fu\", \"gk\", \"ha\", \"hq\", \"ig\"][major - 128])\n        elif 136 <= major < 144:\n            return common_pattern_num_p(16, 16, \"rd/c{:d}d\".format(major - 136 + 8))\n        elif major == 153:\n            return common_pattern_num_p(16, 16, \"emd/\")\n        elif 160 <= major < 162:\n            return common_pattern_num_p(32, 8, \"carmel/\", kind_offset=(major - 160) * 8) # codespell:ignore\n        elif major == 179:\n            return common_pattern_num_p(8, None, \"mmcblk\")\n        elif major == 180:\n            return common_pattern(8, 26, \"ub\")\n        elif major == 202:\n            return common_pattern(16, 16, \"xvd\")\n        elif 240 <= major < 255: # LOCAL/EXPERIMENTAL USE, but maybe this is virtio when qemu-system\n            return common_pattern(16, 16, \"vd\")\n        elif major == 256:\n            return common_pattern(16, 16, \"rfd\")\n        elif major == 257:\n            return common_pattern(8, 8, \"ssfdc\")\n        return \"???\"\n\n    def get_dev_num(self, bdev):\n        \"\"\"\n        [~v5.10]\n        struct block_device {\n            dev_t                       bd_dev;\n            ...\n        };\n\n        [v5.11~]\n        struct block_device {\n            sector_t                    bd_start_sect;      // sector_t: u64\n            sector_t                    bd_nr_sectors;      // sector_t: u64, v5.17~\n            struct gendisk             *bd_disk;            // v6.4~\n            struct request_queue       *bd_queue;           // v6.4~\n            struct disk_stats __percpu *bd_stats;\n            unsigned long               bd_stamp;\n            bool                        bd_read_only;       // 1byte + 3byte padding\n            dev_t                       bd_dev;\n            ...\n        };\n        \"\"\"\n        if self.offset_bd_dev is None:\n            kversion = Kernel.kernel_version()\n            if kversion < \"5.11\":\n                self.offset_bd_dev = 0\n            elif kversion < \"5.16\":\n                self.offset_bd_dev = 8 * 1 + current_arch.ptrsize * 2 + 4\n            elif kversion < \"6.4\":\n                self.offset_bd_dev = 8 * 2 + current_arch.ptrsize * 2 + 4\n            else:\n                self.offset_bd_dev = 8 * 2 + current_arch.ptrsize * 4 + 4\n\n        dev = read_int32_from_memory(bdev + self.offset_bd_dev)\n        major = dev >> 20\n        minor = dev & ((1 << 20) - 1)\n        name = KernelBlockDevicesCommand.get_bdev_name(major, minor)\n        return major, minor, name\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        bdevs = self.get_bdev_list()\n        if not bdevs:\n            self.quiet_err(\"Could not find any bdev\")\n            return\n\n        self.out = []\n        if not args.quiet:\n            fmt = \"{:<18s} {:<18s} {:<6s} {:<6s}\"\n            legend = [\"bdev\", \"name (guessed)\", \"major\", \"minor\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # ignore bdev if major is 0\n        bdevs = [bdev for bdev in bdevs if self.get_dev_num(bdev)[0] != 0]\n        if not bdevs:\n            self.quiet_err(\"Could not find any bdev (after filtering major == 0)\")\n            return\n\n        # parse major, minor and name\n        bdevs_with_info = []\n        for bdev in bdevs:\n            major, minor, name = self.get_dev_num(bdev)\n            bdevs_with_info.append([major, minor, name, bdev])\n\n        # print\n        for major, minor, name, bdev in sorted(bdevs_with_info):\n            self.out.append(\"{:#018x} {:<18s} {:<6d} {:<6d}\".format(bdev, name, major, minor).rstrip())\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelCharacterDevicesCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display character device list.\"\"\"\n\n    _cmdline_ = \"kcdev\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified cdev structure:\",\n        \"\",\n        \"+-chrdevs[255]-+    +-char_device_struct-+\",\n        \"| [0]          |--->| next               |--->...\",\n        \"| ...          |    | major              |\",\n        \"| [254]        |    | baseminor          |           +--->+-cdev--+  +-->+-kobject-+\",\n        \"+--------------+    | minorct            |           |    | kobj  |--+   | name    |\",\n        \"                    | name[64]           |           |    | ...   |      | ...     |\",\n        \"                    | cdev               |-----------+    | ops   |      | parent  |\",\n        \"                    +--------------------+           |    | ...   |      | ...     |\",\n        \"                                                     |    | dev   |      +---------+\",\n        \"+----------+    +-kobj_map----+    +-probe-+         |    | ...   |\",\n        \"| cdev_map |--->| probes[0]   |--->| next  |--->...  |    +-------+\",\n        \"+----------+    | ...         |    | dev   |         |\",\n        \"                | probes[254] |    | ...   |         |\",\n        \"                | lock        |    | data  |---------+\",\n        \"                +-------------+    +-------+\",\n        \"\",\n        \"The character devices are managed at chrdevs[] and cdev_map.\",\n        \"This command use each of them for getting structure information.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @staticmethod\n    def get_cdev_name(major, minor):\n        # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt\n        # https://github.com/lrs-lang/lib/blob/master/src/dev/lib.rs\n        dev_name_list = {\n            (1, 0): \"/dev/mem\", # Undocumented, but it seems to be used\n            (1, 1): \"/dev/mem\",\n            (1, 2): \"/dev/kmem\",\n            (1, 3): \"/dev/null\",\n            (1, 4): \"/dev/port\",\n            (1, 5): \"/dev/zero\",\n            (1, 6): \"/dev/core\",\n            (1, 7): \"/dev/full\",\n            (1, 8): \"/dev/random\",\n            (1, 9): \"/dev/urandom\",\n            (1, 10): \"/dev/aio\",\n            (1, 11): \"/dev/kmsg\",\n            (1, 12): \"/dev/oldmem\",\n            (5, 0): \"/dev/tty\",\n            (5, 1): \"/dev/console\",\n            (5, 2): \"/dev/ptmx\",\n            (5, 3): \"/dev/ttyprintk\",\n            (10, 0): \"/dev/logibm\",\n            (10, 1): \"/dev/psaux\",\n            (10, 2): \"/dev/inportbm\",\n            (10, 3): \"/dev/atibm\",\n            #(10, 4): \"/dev/jbm\", # duplicates\n            (10, 4): \"/dev/amigamouse\",\n            (10, 5): \"/dev/atarimouse\",\n            (10, 6): \"/dev/sunmouse\",\n            (10, 7): \"/dev/amigamouse1\",\n            (10, 8): \"/dev/smouse\",\n            (10, 9): \"/dev/pc110pad\",\n            (10, 10): \"/dev/adbmouse\",\n            (10, 11): \"/dev/vrtpanel\",\n            (10, 13): \"/dev/vpcmouse\",\n            (10, 14): \"/dev/touchscreen/ucb1x00\",\n            (10, 15): \"/dev/touchscreen/mk712\",\n            (10, 128): \"/dev/beep\",\n            (10, 130): \"/dev/watchdog\",\n            (10, 131): \"/dev/temperature\",\n            (10, 132): \"/dev/hwtrap\",\n            (10, 133): \"/dev/exttrp\",\n            (10, 134): \"/dev/apm_bios\",\n            (10, 135): \"/dev/rtc\",\n            (10, 137): \"/dev/vhci\",\n            (10, 139): \"/dev/openprom\",\n            (10, 140): \"/dev/relay8\",\n            (10, 141): \"/dev/relay16\",\n            (10, 143): \"/dev/pciconf\",\n            (10, 144): \"/dev/nvram\",\n            (10, 145): \"/dev/hfmodem\",\n            (10, 146): \"/dev/graphics\",\n            (10, 147): \"/dev/opengl\",\n            (10, 148): \"/dev/gfx\",\n            (10, 149): \"/dev/input/mouse\",\n            (10, 150): \"/dev/input/keyboard\",\n            (10, 151): \"/dev/led\",\n            (10, 152): \"/dev/kpoll\",\n            (10, 153): \"/dev/mergemem\",\n            (10, 154): \"/dev/pmu\",\n            (10, 156): \"/dev/lcd\",\n            (10, 157): \"/dev/ac\",\n            (10, 158): \"/dev/nwbutton\",\n            (10, 159): \"/dev/nwdebug\",\n            (10, 160): \"/dev/nwflash\",\n            (10, 161): \"/dev/userdma\",\n            (10, 162): \"/dev/smbus\",\n            (10, 163): \"/dev/lik\", # codespell:ignore\n            (10, 164): \"/dev/ipmo\",\n            (10, 165): \"/dev/vmmon\",\n            (10, 166): \"/dev/i2o/ctl\",\n            (10, 167): \"/dev/specialix_sxctl\",\n            (10, 168): \"/dev/tcldrv\",\n            (10, 169): \"/dev/specialix_rioctl\",\n            (10, 170): \"/dev/thinkpad/thinkpad\",\n            (10, 171): \"/dev/srripc\",\n            (10, 172): \"/dev/usemaclone\",\n            (10, 173): \"/dev/ipmikcs\",\n            (10, 174): \"/dev/uctrl\",\n            (10, 175): \"/dev/agpgart\",\n            (10, 176): \"/dev/gtrsc\",\n            (10, 177): \"/dev/cbm\",\n            (10, 178): \"/dev/jsflash\",\n            (10, 179): \"/dev/xsvc\",\n            (10, 180): \"/dev/vrbuttons\",\n            (10, 181): \"/dev/toshiba\",\n            (10, 182): \"/dev/perfctr\",\n            (10, 183): \"/dev/hwrng\",\n            (10, 184): \"/dev/cpu/microcode\",\n            (10, 186): \"/dev/atomicps\",\n            (10, 187): \"/dev/irnet\",\n            (10, 188): \"/dev/smbusbios\",\n            (10, 189): \"/dev/ussp_ctl\",\n            (10, 190): \"/dev/crash\",\n            (10, 191): \"/dev/pcl181\",\n            (10, 192): \"/dev/nas_xbus\",\n            (10, 193): \"/dev/d7s\",\n            (10, 194): \"/dev/zkshim\",\n            (10, 195): \"/dev/elographics/e2201\",\n            (10, 196): \"/dev/vfio/vfio\",\n            (10, 197): \"/dev/pxa3xx-gcu\",\n            (10, 198): \"/dev/sexec\",\n            (10, 199): \"/dev/scanners/cuecat\",\n            (10, 200): \"/dev/net/tun\",\n            (10, 201): \"/dev/button/gulpb\",\n            (10, 202): \"/dev/emd/ctl\",\n            (10, 203): \"/dev/cuse\",\n            (10, 204): \"/dev/video/em8300\",\n            (10, 205): \"/dev/video/em8300_mv\",\n            (10, 206): \"/dev/video/em8300_ma\",\n            (10, 207): \"/dev/video/em8300_sp\",\n            (10, 208): \"/dev/compaq/cpqphpc\",\n            (10, 209): \"/dev/compaq/cpqrid\",\n            (10, 210): \"/dev/impi/bt\",\n            (10, 211): \"/dev/impi/smic\",\n            (10, 212): \"/dev/watchdogs/0\",\n            (10, 213): \"/dev/watchdogs/1\",\n            (10, 214): \"/dev/watchdogs/2\",\n            (10, 215): \"/dev/watchdogs/3\",\n            (10, 216): \"/dev/fujitsu/apanel\",\n            (10, 217): \"/dev/ni/natmotn\",\n            (10, 218): \"/dev/kchuid\",\n            (10, 219): \"/dev/modems/mwave\",\n            (10, 220): \"/dev/mptctl\",\n            (10, 221): \"/dev/mvista/hssdsi\",\n            (10, 222): \"/dev/mvista/hasi\",\n            (10, 223): \"/dev/input/uinput\",\n            (10, 224): \"/dev/tpm\",\n            (10, 225): \"/dev/pps\",\n            (10, 226): \"/dev/systrace\",\n            (10, 227): \"/dev/mcelog\",\n            (10, 228): \"/dev/hpet\",\n            (10, 229): \"/dev/fuse\",\n            (10, 230): \"/dev/midishare\",\n            (10, 231): \"/dev/snapshot\",\n            (10, 232): \"/dev/kvm\",\n            (10, 233): \"/dev/kmview\",\n            (10, 234): \"/dev/btrfs-control\",\n            (10, 235): \"/dev/autofs\",\n            (10, 236): \"/dev/mapper/control\",\n            (10, 237): \"/dev/loop-control\",\n            (10, 238): \"/dev/vhost-net\",\n            (10, 239): \"/dev/uhid\",\n            (10, 240): \"/dev/userio\",\n            (10, 241): \"/dev/vhost-vsock\",\n            (10, 242): \"/dev/rfkill\",\n            (12, 2): \"/dev/ntpqic11\",\n            (12, 3): \"/dev/tpqic11\",\n            (12, 4): \"/dev/ntpqic24\",\n            (12, 5): \"/dev/tpqic24\",\n            (12, 6): \"/dev/ntpqic120\",\n            (12, 7): \"/dev/tpqic120\",\n            (12, 8): \"/dev/ntpqic150\",\n            (12, 9): \"/dev/tpqic150\",\n            (14, 0): \"/dev/mixer\",\n            (14, 1): \"/dev/sequencer\",\n            (14, 2): \"/dev/midi00\",\n            (14, 3): \"/dev/dsp\",\n            (14, 4): \"/dev/audio\",\n            (14, 7): \"/dev/audioctl\",\n            (14, 8): \"/dev/sequencer2\",\n            (14, 16): \"/dev/mixer1\",\n            (14, 17): \"/dev/patmgr0\",\n            (14, 18): \"/dev/midi01\",\n            (14, 19): \"/dev/dsp1\",\n            (14, 20): \"/dev/audio1\",\n            (14, 33): \"/dev/patmgr1\",\n            (14, 34): \"/dev/midi02\",\n            (14, 50): \"/dev/midi03\",\n            (30, 0): \"/dev/socksys\",\n            (30, 1): \"/dev/spx\",\n            (30, 32): \"/dev/inet/ip\",\n            (30, 33): \"/dev/inet/icmp\",\n            (30, 34): \"/dev/inet/ggp\",\n            (30, 35): \"/dev/inet/ipip\",\n            (30, 36): \"/dev/inet/tcp\",\n            (30, 37): \"/dev/inet/egp\",\n            (30, 38): \"/dev/inet/pup\",\n            (30, 39): \"/dev/inet/udp\",\n            (30, 40): \"/dev/inet/idp\",\n            (30, 41): \"/dev/inet/rawip\",\n            (31, 0): \"/dev/mpu401data\",\n            (31, 1): \"/dev/mpu401stat\",\n            (36, 0): \"/dev/route\",\n            (36, 1): \"/dev/skip\",\n            (36, 3): \"/dev/fwmonitor\",\n            (70, 0): \"/dev/apscfg\",\n            (70, 1): \"/dev/apsauth\",\n            (70, 2): \"/dev/apslog\",\n            (70, 3): \"/dev/apsdbg\",\n            (70, 64): \"/dev/apsisdn\",\n            (70, 65): \"/dev/apsasync\",\n            (70, 128): \"/dev/apsmon\",\n            (73, 0): \"/dev/ip2ipl0\",\n            (73, 1): \"/dev/ip2stat0\",\n            (73, 4): \"/dev/ip2ipl1\",\n            (73, 5): \"/dev/ip2stat1\",\n            (73, 8): \"/dev/ip2ipl2\",\n            (73, 9): \"/dev/ip2stat2\",\n            (73, 12): \"/dev/ip2ipl3\",\n            (73, 13): \"/dev/ip2stat\",\n            (95, 0): \"/dev/ipl\",\n            (95, 1): \"/dev/ipnat\",\n            (95, 2): \"/dev/ipstate\",\n            (95, 3): \"/dev/ipauth\",\n            (152, 0): \"/dev/etherd/ctl\",\n            (152, 1): \"/dev/etherd/err\",\n            (152, 2): \"/dev/etherd/raw\",\n            (200, 0): \"/dev/vx/config\",\n            (200, 1): \"/dev/vx/trace\",\n            (200, 2): \"/dev/vx/iod\",\n            (200, 3): \"/dev/vx/info\",\n            (200, 4): \"/dev/vx/task\",\n            (200, 5): \"/dev/vx/taskmon\",\n            (207, 0): \"/dev/cpqhealth/cpqw\",\n            (207, 1): \"/dev/cpqhealth/crom\",\n            (207, 2): \"/dev/cpqhealth/cdt\",\n            (207, 3): \"/dev/cpqhealth/cevt\",\n            (207, 4): \"/dev/cpqhealth/casr\",\n            (207, 5): \"/dev/cpqhealth/cecc\",\n            (207, 6): \"/dev/cpqhealth/cmca\",\n            (207, 7): \"/dev/cpqhealth/ccsm\",\n            (207, 8): \"/dev/cpqhealth/cnmi\",\n            (207, 9): \"/dev/cpqhealth/css\",\n            (207, 10): \"/dev/cpqhealth/cram\",\n            (207, 11): \"/dev/cpqhealth/cpci\",\n        }\n        if (major, minor) in dev_name_list:\n            return dev_name_list[major, minor]\n\n        dev_name_list2 = {\n            0: \"???\",\n            6: \"/dev/lp{:d}\",\n            16: \"/dev/gs4500\",\n            17: \"/dev/ttyH{:d}\",\n            18: \"/dev/cuh{:d}\",\n            19: \"/dev/ttyC{:d}\",\n            20: \"/dev/cub{:d}\",\n            21: \"/dev/sg{:d}\",\n            22: \"/dev/ttyD{:d}\",\n            23: \"/dev/cud{:d}\",\n            24: \"/dev/ttyE{:d}\",\n            25: \"/dev/cue{:d}\",\n            26: \"/dev/wvisfgrab\",\n            29: \"/dev/fb{:d}\",\n            32: \"/dev/ttyX{:d}\",\n            33: \"/dev/cux{:d}\",\n            34: \"/dev/scc{:d}\",\n            38: \"/dev/mlanai{:d}\",\n            40: \"/dev/mmetfgrab\",\n            41: \"/dev/yamm\",\n            43: \"/dev/ttyI{:d}\",\n            44: \"/dev/cui{:d}\",\n            46: \"/dev/ttyR{:d}\",\n            47: \"/dev/cur{:d}\",\n            48: \"/dev/ttyL{:d}\",\n            49: \"/dev/cul{:d}\",\n            51: \"/dev/bc{:d}\",\n            52: \"/dev/dcbri{:d}\",\n            54: \"/dev/holter{:d}\",\n            55: \"/dev/dsp56k\",\n            56: \"/dev/adb\",\n            57: \"/dev/ttyP{:d}\",\n            58: \"/dev/cup{:d}\",\n            59: \"/dev/firewall\",\n            64: \"/dev/enskip\",\n            66: \"/dev/yppcpci{:d}\",\n            67: \"/dev/cfs0\",\n            69: \"/dev/ma16\",\n            71: \"/dev/ttyF{:d}\",\n            72: \"/dev/cuf{:d}\",\n            74: \"/dev/SCI/{:d}\",\n            75: \"/dev/ttyW{:d}\",\n            76: \"/dev/cuw{:d}\",\n            77: \"/dev/qng\",\n            78: \"/dev/ttyM{:d}\",\n            79: \"/dev/cum{:d}\",\n            80: \"/dev/at200\",\n            82: \"/dev/winradio{:d}\",\n            83: \"/dev/mga_vid{:d}\",\n            84: \"/dev/ihcp{:d}\",\n            86: \"/dev/sch{:d}\",\n            87: \"/dev/controla{:d}\",\n            88: \"/dev/comx{:d}\",\n            89: \"/dev/i2c-{:d}\",\n            91: \"/dev/can{:d}\",\n            94: \"/dev/dcxx{:d}\",\n            97: \"/dev/pg{:d}\",\n            98: \"/dev/comedi{:d}\",\n            99: \"/dev/parport{:d}\",\n            100: \"/dev/phone{:d}\",\n            102: \"/dev/tlk{:d}\",\n            103: \"/dev/nnpfs{:d}\",\n            105: \"/dev/ttyV{:d}\",\n            106: \"/dev/cuv{:d}\",\n            107: \"/dev/3dfx\",\n            108: \"/dev/ppp\",\n            110: \"/dev/srnd{:d}\",\n            111: \"/dev/av{:d}\",\n            112: \"/dev/ttyM{:d}\", # same 78\n            113: \"/dev/cum{:d}\", # same 79\n            119: \"/dev/vnet{:d}\",\n            136: \"/dev/pts/{:d}\",\n            137: \"/dev/pts/{:d}\",\n            138: \"/dev/pts/{:d}\",\n            139: \"/dev/pts/{:d}\",\n            140: \"/dev/pts/{:d}\",\n            141: \"/dev/pts/{:d}\",\n            142: \"/dev/pts/{:d}\",\n            143: \"/dev/pts/{:d}\",\n            144: \"/dev/pppox{:d}\",\n            146: \"/dev/scramnet{:d}\",\n            147: \"/dev/aureal{:d}\",\n            148: \"/dev/ttyT{:d}\",\n            149: \"/dev/cut{:d}\",\n            150: \"/dev/rtf{:d}\",\n            151: \"/dev/dpti{:d}\",\n            153: \"/dev/spi{:d}\",\n            154: \"/dev/ttySR{:d}\",\n            155: \"/dev/cusr{:d}\",\n            158: \"/dev/gfax{:d}\",\n            160: \"/dev/gpib{:d}\",\n            166: \"/dev/ttyACM{:d}\",\n            167: \"/dev/cuacm{:d}\",\n            168: \"/dev/ecsa{:d}\",\n            169: \"/dev/ecsa8-{:d}\",\n            170: \"/dev/megarac{:d}\",\n            174: \"/dev/ttySI{:d}\",\n            175: \"/dev/cusi{:d}\",\n            176: \"/dev/nfastpci{:d}\",\n            178: \"/dev/clanvi{:d}\",\n            179: \"/dev/dvxirq{:d}\",\n            181: \"/dev/pcfclock{:d}\",\n            182: \"/dev/pethr{:d}\",\n            183: \"/dev/ss5136dn{:d}\",\n            184: \"/dev/pevss{:d}\",\n            185: \"/dev/intermezzo{:d}\",\n            186: \"/dev/obd{:d}\",\n            187: \"/dev/deskey{:d}\",\n            188: \"/dev/ttyUSB{:d}\",\n            189: \"/dev/cuusb{:d}\",\n            190: \"/dev/kctt{:d}\",\n            196: \"/dev/tor/{:d}\",\n            198: \"/dev/tpmp2/{:d}\",\n            199: \"/dev/vx/rdsk/*/*\",\n            201: \"/dev/vx/rdmp/*\",\n            202: \"/dev/cpu/{:d}/msr\",\n            203: \"/dev/cpu/{:d}/cpuid\",\n            208: \"/dev/ttyU{:d}\",\n            209: \"/dev/cuu{:d}\",\n            211: \"/dev/addinum/cpci1500/{:d}\",\n            216: \"/dev/rfcomm{:d}\",\n            217: \"/dev/curf{:d}\",\n            218: \"/dev/logicalco/bci/{:d}\",\n            219: \"/dev/logicalco/dci1300/{:d}\",\n            224: \"/dev/ttyY{:d}\",\n            225: \"/dev/cuy{:d}\",\n            226: \"/dev/dri/card{:d}\",\n            229: \"/dev/hvc{:d}\",\n            256: \"/dev/ttyEQ{:d}\",\n            257: \"/dev/ptlsec\",\n            259: \"/dev/icap{:d}\",\n            260: \"/dev/osd{:d}\",\n            261: \"/dev/accel/accel{:d}\",\n        }\n        if major in dev_name_list2:\n            return dev_name_list2[major].format(minor)\n\n        def pty_tty_pattern(devstr):\n            cs1 = \"pqrstuvwxyzabcde\"\n            cs2 = \"0123456789abcdef\"\n            return \"/dev/{:s}{:s}{:s}\".format(devstr, cs1[minor // 16], cs2[minor % 16])\n\n        if major == 2:\n            return pty_tty_pattern(\"pty\")\n        elif major == 3:\n            return pty_tty_pattern(\"tty\")\n        elif major == 4:\n            if 0 <= minor < 64:\n                return \"/dev/tty{:d}\".format(minor)\n            elif 64 <= minor < 256:\n                return \"/dev/ttyS{:d}\".format(minor - 64)\n        elif major == 5:\n            if 64 <= minor < 256:\n                return \"/dev/cua{:d}\".format(minor - 64)\n        elif major == 7:\n            if minor == 0:\n                return \"/dev/vcs\"\n            elif 1 <= minor < 64:\n                return \"/dev/vcs{:d}\".format(minor)\n            elif minor == 64:\n                return \"/dev/vcsu\"\n            elif 65 <= minor < 128:\n                return \"/dev/vcsu{:d}\".format(minor - 64)\n            elif minor == 128:\n                return \"/dev/vcsa\"\n            elif 129 <= minor < 192:\n                return \"/dev/vcsa{:d}\".format(minor - 128)\n        elif major == 9:\n            if 0 <= minor < 32:\n                return \"/dev/st{:d}\".format(minor)\n            elif 32 <= minor < 64:\n                return \"/dev/st{:d}l\".format(minor - 32)\n            elif 64 <= minor < 96:\n                return \"/dev/st{:d}m\".format(minor - 64)\n            elif 96 <= minor < 128:\n                return \"/dev/st{:d}a\".format(minor - 96)\n            elif 128 <= minor < 160:\n                return \"/dev/nst{:d}\".format(minor - 128)\n            elif 160 <= minor < 192:\n                return \"/dev/nst{:d}l\".format(minor - 160)\n            elif 192 <= minor < 224:\n                return \"/dev/nst{:d}m\".format(minor - 192)\n            elif 224 <= minor < 256:\n                return \"/dev/nst{:d}a\".format(minor - 224)\n        elif major == 11: # 11 are duplicates\n            if is_sparc32() or is_sparc32plus() or is_sparc64():\n                return \"/dev/kbd\"\n            elif is_hppa32() or is_hppa64():\n                return \"/dev/ttyB{:d}\".format(minor)\n        elif major == 13:\n            if 0 <= minor < 32:\n                return \"/dev/input/js{:d}\".format(minor)\n            elif 32 <= minor < 63:\n                return \"/dev/input/mouse{:d}\".format(minor - 32)\n            elif minor == 63:\n                return \"/dev/input/mice\"\n            elif 64 <= minor < 96:\n                return \"/dev/input/event{:d}\".format(minor - 64)\n        elif major == 15:\n            if 0 <= minor < 128:\n                return \"/dev/js{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/djs{:d}\".format(minor - 128)\n        elif major == 27:\n            if 0 <= minor < 4:\n                return \"/dev/qft{:d}\".format(minor)\n            elif 4 <= minor < 8:\n                return \"/dev/nqft{:d}\".format(minor - 4)\n            elif 16 <= minor < 20:\n                return \"/dev/zqft{:d}\".format(minor - 16)\n            elif 20 <= minor < 24:\n                return \"/dev/nzqft{:d}\".format(minor - 20)\n            elif 32 <= minor < 36:\n                return \"/dev/rawqft{:d}\".format(minor - 32)\n            elif 36 <= minor < 40:\n                return \"/dev/nrawqft{:d}\".format(minor - 36)\n        elif major == 28: # 28 are duplicates\n            if is_m68k():\n                return \"/dev/slm{:d}\".format(minor)\n            else:\n                return \"/dev/staliomem{:d}\".format(minor)\n        elif major == 35:\n            if 0 <= minor < 4:\n                return \"/dev/midi{:d}\".format(minor)\n            elif 64 <= minor < 67:\n                return \"/dev/rmidi{:d}\".format(minor - 64)\n            elif 128 <= minor < 132:\n                return \"/dev/smpte{:d}\".format(minor - 128)\n        elif major == 36:\n            if 16 <= minor < 32:\n                return \"/dev/tap{:d}\".format(minor - 16)\n        elif major == 37:\n            if 0 <= minor < 128:\n                return \"/dev/ht{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/nht{:d}\".format(minor - 128)\n        elif major == 39:\n            if 0 <= minor % 32 < 16:\n                return \"/dev/ml16p{:s}-a{:d}\".format(chr(ord(\"a\") + minor // 32), minor)\n            elif minor % 32 == 16:\n                return \"/dev/ml16p{:s}-d\".format(chr(ord(\"a\") + minor // 32))\n            elif 17 <= minor % 32 < 20:\n                return \"/dev/ml16p{:s}-c{:d}\".format(chr(ord(\"a\") + minor // 32), minor - 17)\n        elif major == 45:\n            if 0 <= minor < 64:\n                return \"/dev/isdn{:d}\".format(minor)\n            elif 64 <= minor < 128:\n                return \"/dev/isdncntl{:d}\".format(minor - 64)\n            elif 128 <= minor < 192:\n                return \"/dev/ippp{:d}\".format(minor - 128)\n            elif minor == 255:\n                return \"/dev/isdninfo\"\n        elif major == 53:\n            if 0 <= minor < 3:\n                return \"/dev/pd_bdm{:d}\".format(minor)\n            elif 4 <= minor < 7:\n                return \"/dev/icd_bdm{:d}\".format(minor)\n        elif major == 65:\n            if 0 <= minor < 4:\n                return \"/dev/plink{:d}\".format(minor)\n            elif 64 <= minor < 67:\n                return \"/dev/rplink{:d}\".format(minor - 64)\n            elif 128 <= minor < 132:\n                return \"/dev/plink{:d}d\".format(minor - 128)\n            elif 192 <= minor < 196:\n                return \"/dev/rplink{:d}d\".format(minor - 192)\n        elif major == 68:\n            if minor == 0:\n                return \"/dev/capi20\"\n            elif 1 <= minor < 20:\n                return \"/dev/capi20.{:02d}\".format(minor - 1)\n        elif major == 81:\n            if 0 <= minor < 64:\n                return \"/dev/video{:d}\".format(minor)\n            elif 64 <= minor < 128:\n                return \"/dev/radio{:d}\".format(minor - 64)\n            elif 128 <= minor < 192:\n                return \"/dev/swradio{:d}\".format(minor - 128)\n            elif 192 <= minor < 256:\n                return \"/dev/vbi{:d}\".format(minor - 192)\n        elif major == 85:\n            if minor == 0:\n                return \"/dev/shmiq\"\n            elif 1 <= minor:\n                return \"/dev/qcntl{:d}\".format(minor)\n        elif major == 90:\n            if 0 <= minor < 32:\n                if minor % 2 == 0:\n                    return \"/dev/mtd{:d}\".format(minor // 2)\n                elif minor % 2 == 1:\n                    return \"/dev/mtdr{:d}\".format(minor // 2)\n        elif major == 93:\n            if 0 <= minor < 128:\n                return \"/dev/iscc{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/isccctl{:d}\".format(minor - 128)\n        elif major == 96:\n            if 0 <= minor < 128:\n                return \"/dev/pt{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/npt{:d}\".format(minor - 128)\n        elif major == 101:\n            if minor == 0:\n                return \"/dev/mdspstat\"\n            elif 1 <= minor < 17:\n                return \"/dev/mdsp{:d}\".format(minor)\n        elif major == 114:\n            if 0 <= minor < 128:\n                return \"/dev/ise{:d}\".format(minor)\n            elif 128 <= minor < 256:\n                return \"/dev/isex{:d}\".format(minor - 128)\n        elif major == 115:\n            if 0 <= minor < 8:\n                return \"/dev/tipar{:d}\".format(minor)\n            elif 8 <= minor < 16:\n                return \"/dev/tiser{:d}\".format(minor - 8)\n            elif 16 <= minor < 48:\n                return \"/dev/tiusb{:d}\".format(minor - 16)\n        elif major == 117:\n            return \"/dev/cosa{:d}c{:d}\".format(minor // 16, minor % 16)\n        elif major == 118:\n            if minor == 0:\n                return \"/dev/ica\"\n            elif 1 <= minor:\n                return \"/dev/ica{:d}\".format(minor - 1)\n        elif major == 145:\n            if minor % 64 == 0:\n                return \"/dev/sam{:d}_mixer\".format(minor // 64)\n            elif minor % 64 == 1:\n                return \"/dev/sam{:d}_sequencer\".format(minor // 64)\n            elif minor % 64 == 2:\n                return \"/dev/sam{:d}_midi00\".format(minor // 64)\n            elif minor % 64 == 3:\n                return \"/dev/sam{:d}_dsp\".format(minor // 64)\n            elif minor % 64 == 4:\n                return \"/dev/sam{:d}_audio\".format(minor // 64)\n            elif minor % 64 == 6:\n                return \"/dev/sam{:d}_sndstat\".format(minor // 64)\n            elif minor % 64 == 18:\n                return \"/dev/sam{:d}_midi01\".format(minor // 64)\n            elif minor % 64 == 34:\n                return \"/dev/sam{:d}_midi02\".format(minor // 64)\n            elif minor % 64 == 50:\n                return \"/dev/sam{:d}_midi03\".format(minor // 64)\n        elif major == 156:\n            return \"/dev/ttySR{:d}\".format(minor + 256)\n        elif major == 157:\n            return \"/dev/cusr{:d}\".format(minor + 256)\n        elif major == 161:\n            if 0 <= minor < 16:\n                return \"/dev/ircomm{:d}\".format(minor)\n            elif 16 <= minor < 32:\n                return \"/dev/irlpt{:d}\".format(minor - 16)\n        elif major == 162:\n            if minor == 0:\n                return \"/dev/rawctl\",\n            elif 1 <= minor:\n                return \"/dev/raw/raw{:d}\".format(minor)\n        elif major == 164:\n                return \"/dev/ttyCH{:d}\".format(minor)\n        elif major == 165:\n            if 0 <= minor < 64:\n                return \"/dev/cuch{:d}\".format(minor)\n        elif major == 172:\n            if 0 <= minor < 128:\n                return \"/dev/ttyMX{:d}\".format(minor)\n            elif minor == 128:\n                return \"/dev/moxactl\"\n        elif major == 173:\n            if 0 <= minor < 128:\n                return \"/dev/cumx{:d}\".format(minor)\n        elif major == 177:\n            if 0 <= minor < 16:\n                return \"/dev/pcilynx/aux{:d}\".format(minor)\n            elif 16 <= minor < 32:\n                return \"/dev/pcilynx/rom{:d}\".format(minor - 16)\n            elif 32 <= minor < 48:\n                return \"/dev/pcilynx/ram{:d}\".format(minor - 32)\n        elif major == 180:\n            if 0 <= minor < 16:\n                return \"/dev/usb/lp{:d}\".format(minor)\n            elif 48 <= minor < 64:\n                return \"/dev/usb/scanner{:d}\".format(minor - 48)\n            elif minor == 64:\n                return \"/dev/usb/rio500\"\n            elif minor == 65:\n                return \"/dev/usb/usblcd\"\n            elif minor == 66:\n                return \"/dev/usb/cpad0\"\n            elif 96 <= minor < 112:\n                return \"/dev/usb/hiddev{:d}\".format(minor - 96)\n            elif 112 <= minor < 128:\n                return \"/dev/usb/auer{:d}\".format(minor - 112)\n            elif 128 <= minor < 132:\n                return \"/dev/usb/brlvgr{:d}\".format(minor - 128)\n            elif minor == 132:\n                return \"/dev/usb/idmouse\"\n            elif 133 <= minor < 141:\n                return \"/dev/usb/sisusbvga{:d}\".format(minor - 133 + 1)\n            elif minor == 144:\n                return \"/dev/usb/lcd\"\n            elif 160 <= minor < 176:\n                return \"/dev/usb/legousbtower{:d}\".format(minor - 160)\n            elif 176 <= minor < 192:\n                return \"/dev/usb/usbtmc{:d}\".format(minor - 176 + 1)\n            elif 192 <= minor < 210:\n                return \"/dev/usb/yurex{:d}\".format(minor - 192 + 1)\n        elif major == 192:\n            if minor == 0:\n                return \"/dev/profile\"\n            elif 1 <= minor:\n                return \"/dev/profile{:d}\".format(minor - 1)\n        elif major == 193:\n            if minor == 0:\n                return \"/dev/trace\"\n            elif 1 <= minor:\n                return \"/dev/trace{:d}\".format(minor - 1)\n        elif major == 194:\n            if minor % 16 == 0:\n                return \"/dev/mvideo/status{:d}\".format(minor // 16)\n            elif minor % 16 == 1:\n                return \"/dev/mvideo/stream{:d}\".format(minor // 16)\n            elif minor % 16 == 2:\n                return \"/dev/mvideo/frame{:d}\".format(minor // 16)\n            elif minor % 16 == 3:\n                return \"/dev/mvideo/rawframe{:d}\".format(minor // 16)\n            elif minor % 16 == 4:\n                return \"/dev/mvideo/codec{:d}\".format(minor // 16)\n            elif minor % 16 == 5:\n                return \"/dev/mvideo/video4linux{:d}\".format(minor // 16)\n        elif major == 195:\n            if 0 <= minor < 255:\n                return \"/dev/nvidia{:d}\".format(minor)\n            elif minor == 255:\n                return \"/dev/nvidiactl\"\n        elif major == 197:\n            if 0 <= minor < 128:\n                return \"/dev/tnf/t{:d}\".format(minor)\n            elif minor == 128:\n                return \"/dev/tnf/status\"\n            elif minor == 130:\n                return \"/dev/tnf/trace\"\n        elif major == 204:\n            if 0 <= minor < 4:\n                return \"/dev/ttyLU{:d}\".format(minor)\n            elif minor == 4:\n                return \"/dev/ttyFB0\"\n            elif 5 <= minor < 8:\n                return \"/dev/ttySA{:d}\".format(minor - 5)\n            elif 8 <= minor < 12:\n                return \"/dev/ttySC{:d}\".format(minor - 8)\n            elif 12 <= minor < 16:\n                return \"/dev/ttyFW{:d}\".format(minor - 12)\n            elif 16 <= minor < 32:\n                return \"/dev/ttyAM{:d}\".format(minor - 16)\n            elif 32 <= minor < 40:\n                return \"/dev/ttyDB{:d}\".format(minor - 32)\n            elif minor == 40:\n                return \"/dev/ttySG0\"\n            elif 41 <= minor < 44:\n                return \"/dev/ttySMX{:d}\".format(minor - 41)\n            elif 44 <= minor < 46:\n                return \"/dev/ttyMM{:d}\".format(minor - 44)\n            elif 46 <= minor < 50:\n                return \"/dev/ttyCPM{:d}\".format(minor - 46)\n            elif 50 <= minor < 82:\n                return \"/dev/ttyIOC{:d}\".format(minor - 50)\n            elif 82 <= minor < 84:\n                return \"/dev/ttyVR{:d}\".format(minor - 82)\n            elif 84 <= minor < 116:\n                return \"/dev/ttyIOC{:d}\".format(minor)\n            elif 116 <= minor < 148:\n                return \"/dev/ttySIOC{:d}\".format(minor - 116)\n            elif 148 <= minor < 154:\n                return \"/dev/ttyPSC{:d}\".format(minor - 148)\n            elif 154 <= minor < 170:\n                return \"/dev/ttyAT{:d}\".format(minor - 154)\n            elif 170 <= minor < 186:\n                return \"/dev/ttyNX{:d}\".format(minor - 170)\n            elif minor == 186:\n                return \"/dev/ttyJ0\"\n            elif 187 <= minor < 190:\n                return \"/dev/ttyUL{:d}\".format(minor - 187)\n            elif minor == 191:\n                return \"/dev/xvc0\"\n            elif 192 <= minor < 196:\n                return \"/dev/ttyPZ{:d}\".format(minor - 192)\n            elif 196 <= minor < 204:\n                return \"/dev/ttyTX{:d}\".format(minor - 196)\n            elif 205 <= minor < 209:\n                return \"/dev/ttySC{:d}\".format(minor - 205)\n            elif 209 <= minor < 213:\n                return \"/dev/ttyMAX{:d}\".format(minor - 209)\n        elif major == 205:\n            if 0 <= minor < 4:\n                return \"/dev/culu{:d}\".format(minor)\n            elif minor == 4:\n                return \"/dev/cufb0\"\n            elif 5 <= minor < 8:\n                return \"/dev/cusa{:d}\".format(minor - 5)\n            elif 8 <= minor < 12:\n                return \"/dev/cusc{:d}\".format(minor - 8)\n            elif 12 <= minor < 16:\n                return \"/dev/cufw{:d}\".format(minor - 12)\n            elif 16 <= minor < 32:\n                return \"/dev/cuam{:d}\".format(minor - 16)\n            elif 32 <= minor < 40:\n                return \"/dev/cudb{:d}\".format(minor - 32)\n            elif minor == 40:\n                return \"/dev/cusg0\"\n            elif 41 <= minor < 44:\n                return \"/dev/ttycusmx{:d}\".format(minor - 41)\n            elif 46 <= minor < 50:\n                return \"/dev/cucpm{:d}\".format(minor - 46)\n            elif 50 <= minor < 82:\n                return \"/dev/cuioc4{:d}\".format(minor - 50)\n            elif 82 <= minor < 84:\n                return \"/dev/cuvr{:d}\".format(minor - 82)\n        elif major == 206:\n            if 0 <= minor < 32:\n                return \"/dev/osst{:d}\".format(minor)\n            elif 32 <= minor < 64:\n                return \"/dev/osst{:d}l\".format(minor - 32)\n            elif 64 <= minor < 96:\n                return \"/dev/osst{:d}m\".format(minor - 64)\n            elif 96 <= minor < 128:\n                return \"/dev/osst{:d}a\".format(minor - 96)\n            elif 128 <= minor < 160:\n                return \"/dev/nosst{:d}\".format(minor - 128)\n            elif 160 <= minor < 192:\n                return \"/dev/nosst{:d}l\".format(minor - 160)\n            elif 192 <= minor < 224:\n                return \"/dev/nosst{:d}m\".format(minor - 192)\n            elif 224 <= minor < 256:\n                return \"/dev/nosst{:d}a\".format(minor - 224)\n        elif major == 210:\n            if minor % 10 == 0:\n                return \"/dev/sbei/wxcfg{:d}\".format(minor // 10)\n            elif minor % 10 == 1:\n                return \"/dev/sbei/dld{:d}\".format(minor // 10)\n            elif 2 <= minor % 10 < 6:\n                return \"/dev/sbei/wan{:d}{:d}\".format(minor // 10, minor % 10)\n            elif 6 <= minor % 10 < 10:\n                return \"/dev/sbei/wanc{:d}{:d}\".format(minor // 10, minor % 10)\n        elif major == 212:\n            if minor % 64 % 9 == 0:\n                return \"/dev/dvb/adapter{:d}/video{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 1:\n                return \"/dev/dvb/adapter{:d}/audio{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 2:\n                return \"/dev/dvb/adapter{:d}/sec{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 3:\n                return \"/dev/dvb/adapter{:d}/frontend{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 4:\n                return \"/dev/dvb/adapter{:d}/demux{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 5:\n                return \"/dev/dvb/adapter{:d}/dvr{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 6:\n                return \"/dev/dvb/adapter{:d}/ca{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 7:\n                return \"/dev/dvb/adapter{:d}/net{:d}\".format(minor // 64, minor % 64 // 9)\n            elif minor % 64 % 9 == 8:\n                return \"/dev/dvb/adapter{:d}/osd{:d}\".format(minor // 64, minor % 64 // 9)\n        elif major == 220:\n            if minor % 2 == 0:\n                return \"/dev/myricom/gm{:d}\".format(minor // 2)\n            elif minor % 2 == 1:\n                return \"/dev/myricom/gmp{:d}\".format(minor // 2)\n        elif major == 221:\n            if 0 <= minor < 4:\n                return \"/dev/bus/vme/m{:d}\".format(minor)\n            elif 4 <= minor < 8:\n                return \"/dev/bus/vme/s{:d}\".format(minor - 4)\n            elif minor == 8:\n                return \"/dev/bus/vme/ctl\"\n        elif major == 227:\n            if 1 <= minor:\n                return \"/dev/3270/tty{:d}\".format(minor)\n        elif major == 228:\n            if minor == 0:\n                return \"/dev/3270/tub\"\n            elif 1 <= minor:\n                return \"/dev/3270/tub{:d}\".format(minor)\n        elif major == 230:\n            if 0 <= minor < 32:\n                return \"/dev/iseries/vt{:d}\".format(minor)\n            elif 32 <= minor < 64:\n                return \"/dev/iseries/vt{:d}l\".format(minor - 32)\n            elif 64 <= minor < 96:\n                return \"/dev/iseries/vt{:d}m\".format(minor - 64)\n            elif 96 <= minor < 128:\n                return \"/dev/iseries/vt{:d}a\".format(minor - 96)\n            elif 128 <= minor < 160:\n                return \"/dev/iseries/nvt{:d}\".format(minor - 128)\n            elif 160 <= minor < 192:\n                return \"/dev/iseries/nvt{:d}l\".format(minor - 160)\n            elif 192 <= minor < 224:\n                return \"/dev/iseries/nvt{:d}m\".format(minor - 192)\n            elif 224 <= minor < 256:\n                return \"/dev/iseries/nvt{:d}a\".format(minor - 224)\n        elif major == 231:\n            if 0 <= minor < 64:\n                return \"/dev/infiniband/umad{:d}\".format(minor)\n            elif 64 <= minor < 128:\n                return \"/dev/infiniband/issm{:d}\".format(minor - 64)\n            elif 192 <= minor < 224:\n                return \"/dev/infiniband/uverbs{:d}\".format(minor - 192)\n        elif major == 232:\n            if minor % 10 == 0:\n                return \"/dev/biometric/sensor{:d}/fingerprint\".format(minor // 10)\n            elif minor % 10 == 1:\n                return \"/dev/biometric/sensor{:d}/iris\".format(minor // 10)\n            elif minor % 10 == 2:\n                return \"/dev/biometric/sensor{:d}/retina\".format(minor // 10)\n            elif minor % 10 == 3:\n                return \"/dev/biometric/sensor{:d}/voiceprint\".format(minor // 10)\n            elif minor % 10 == 4:\n                return \"/dev/biometric/sensor{:d}/facial\".format(minor // 10)\n            elif minor % 10 == 5:\n                return \"/dev/biometric/sensor{:d}/hand\".format(minor // 10)\n        elif major == 233:\n            if minor == 0:\n                return \"/dev/ipath\"\n            elif 1 <= minor < 5:\n                return \"/dev/ipath{:d}\".format(minor - 1)\n            elif minor == 129:\n                return \"/dev/ipath_sma\"\n            elif minor == 130:\n                return \"/dev/ipath_diag\"\n        return \"???\"\n\n    def get_chrdev_list(self): # [chrdev, chrdev, chrdev, ...]\n        \"\"\"\n        #define CHRDEV_MAJOR_HASH_SIZE 255\n        static struct char_device_struct {\n            struct char_device_struct *next;\n            unsigned int major;\n            unsigned int baseminor;\n            int minorct;\n            char name[64];\n            struct cdev *cdev;\n        } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];\n        \"\"\"\n        chrdevs = KernelAddressHeuristicFinder.get_chrdevs()\n        if chrdevs is None:\n            self.quiet_err(\"Could not find chrdevs\")\n            return None\n        self.quiet_info(\"chrdevs: {:#x}\".format(chrdevs))\n\n        chrdev_addrs = []\n        for i in range(255):\n            chrdevs_i = chrdevs + i * current_arch.ptrsize\n            if not is_valid_addr(chrdevs_i):\n                self.quiet_err(\"Memory read error\")\n                return None\n            addr = read_int_from_memory(chrdevs_i)\n            while addr and addr not in chrdev_addrs:\n                chrdev_addrs.append(addr)\n                if not is_valid_addr(addr):\n                    self.quiet_err(\"Memory read error\")\n                    return None\n                addr = read_int_from_memory(addr)\n        return chrdev_addrs\n\n    def get_cdev_list(self): # [[cdev, major, minor], [...] ...]\n        \"\"\"\n        struct kobj_map {\n            struct probe {\n                struct probe *next;\n                dev_t dev;\n                unsigned long range;\n                struct module *owner;\n                kobj_probe_t *get;\n                int (*lock)(dev_t, void *);\n                void *data;  // -> cdev\n            } *probes[255];\n            struct mutex *lock;\n        };\n        static struct kobj_map *cdev_map;\n\n        struct cdev {\n            struct kobject kobj;\n            struct module *owner;\n            const struct file_operations *ops;\n            struct list_head list;\n            dev_t dev;\n            unsigned int count;\n        } __randomize_layout;\n\n        struct kobject {\n            const char *name;\n            struct list_head entry;\n            struct kobject *parent;\n            struct kset *kset;\n            const struct kobj_type *ktype;\n            struct kernfs_node *sd;\n            struct kref kref;\n        #ifdef CONFIG_DEBUG_KOBJECT_RELEASE\n            struct delayed_work release;\n        #endif\n            unsigned int state_initialized:1;\n            unsigned int state_in_sysfs:1;\n            unsigned int state_add_uevent_sent:1;\n            unsigned int state_remove_uevent_sent:1;\n            unsigned int uevent_suppress:1;\n        };\n        \"\"\"\n        cdev_map = KernelAddressHeuristicFinder.get_cdev_map()\n        if cdev_map is None:\n            self.quiet_err(\"Could not find cdev_map\")\n            return None\n        self.quiet_info(\"cdev_map: {:#x}\".format(cdev_map))\n\n        try:\n            cdev_map_ = read_int_from_memory(cdev_map)\n            self.quiet_info(\"*cdev_map: {:#x}\".format(cdev_map_))\n        except Exception:\n            self.quiet_err(\"cdev_map is not initialized\")\n            return None\n\n        cdev_addrs = []\n        seen = []\n        for i in range(255):\n            addr = read_int_from_memory(cdev_map_ + i * current_arch.ptrsize)\n            while addr:\n                cdev = read_int_from_memory(addr + 6 * current_arch.ptrsize)\n                dev = read_int32_from_memory(addr + current_arch.ptrsize)\n                major = dev >> 20\n                minor = dev & ((1 << 20) - 1)\n                if cdev and cdev not in seen:\n                    cdev_addrs.append([cdev, major, minor])\n                    seen.append(cdev)\n                addr = read_int_from_memory(addr)\n        return cdev_addrs\n\n    def get_offset_ops(self, cdevs):\n        for i in range(3, 0x20):\n            offset_list = i * current_arch.ptrsize\n            valid = True\n            for cdev in cdevs:\n                pos_next = cdev + offset_list\n                pos_prev = cdev + offset_list + current_arch.ptrsize\n                list_entry_next = [pos_next]\n                list_entry_prev = [pos_prev]\n                while valid:\n                    # read check\n                    try:\n                        pos_next = read_int_from_memory(pos_next)\n                        pos_prev = read_int_from_memory(pos_prev) + current_arch.ptrsize\n                    except gdb.MemoryError: # memory read error\n                        valid = False\n                        break\n                    # list validate\n                    if pos_next in list_entry_next[1:]: # incomplete infinity loop detected\n                        valid = False\n                        break\n                    if pos_prev in list_entry_prev[1:]: # incomplete infinity loop detected\n                        valid = False\n                        break\n                    if pos_next == list_entry_next[0] and pos_prev == list_entry_prev[0]:\n                        break\n                    list_entry_next.append(pos_next)\n                    list_entry_prev.append(pos_prev)\n                if not valid:\n                    break\n            else:\n                # for loop is finished until last element\n                if valid:\n                    offset_ops = offset_list - current_arch.ptrsize\n                    self.quiet_info(\"offsetof(cdev, ops): {:#x}\".format(offset_ops))\n                    return offset_ops\n\n        self.quiet_err(\"Could not find offsetof(cdev, ops)\")\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        chrdev_addrs = self.get_chrdev_list()\n        if chrdev_addrs is None:\n            return\n        cdev_addrs = self.get_cdev_list()\n        if cdev_addrs is None:\n            return\n\n        # merge chrdev (from chrdevs)\n        merged = {}\n        for chrdev in chrdev_addrs:\n            major = read_int32_from_memory(chrdev + current_arch.ptrsize)\n            minor = read_int32_from_memory(chrdev + current_arch.ptrsize + 4)\n            name_string = read_cstring_from_memory(chrdev + current_arch.ptrsize + 4 * 3) or \"<None>\"\n            off = chrdev + current_arch.ptrsize + 4 * 3 + 64\n            while off % current_arch.ptrsize: # align\n                off += 1\n            cdev = read_int_from_memory(off)\n            merged[major, minor] = {\"chrdev\": chrdev, \"name\": name_string, \"cdev\": cdev}\n\n        # merge cdev (from cdev_map)\n        for cdev, major, minor in cdev_addrs:\n            kobj = read_int_from_memory(cdev)\n            name_string = read_cstring_from_memory(kobj) or \"<None>\"\n\n            if (major, minor) in merged:\n                if merged[major, minor][\"cdev\"] == 0:\n                    merged[major, minor][\"cdev\"] = cdev\n                if merged[major, minor][\"name\"] == \"<None>\":\n                    merged[major, minor][\"name\"] = name_string\n            else:\n                merged[major, minor] = {\"chrdev\": 0x0, \"name\": name_string, \"cdev\": cdev}\n\n        # add ops info\n        off_ops = self.get_offset_ops([v[\"cdev\"] for k, v in merged.items() if v[\"cdev\"]])\n        if off_ops is None:\n            return\n        for k in merged.keys():\n            if merged[k][\"cdev\"]:\n                merged[k][\"ops\"] = read_int_from_memory(merged[k][\"cdev\"] + off_ops)\n            else:\n                merged[k][\"ops\"] = 0x0\n            merged[k][\"ops_sym\"] = Symbol.get_symbol_string(merged[k][\"ops\"])\n\n        # add parent info\n        for k in merged.keys():\n            if merged[k][\"cdev\"]:\n                parent = read_int_from_memory(merged[k][\"cdev\"] + current_arch.ptrsize * 3)\n                merged[k][\"parent\"] = parent\n                if parent:\n                    if not is_valid_addr(parent):\n                        merged[k][\"parent_name\"] = \"???\"\n                    else:\n                        name = read_int_from_memory(parent)\n                        if name:\n                            merged[k][\"parent_name\"] = read_cstring_from_memory(name) or \"<None>\"\n                        else:\n                            merged[k][\"parent_name\"] = \"<None>\"\n                else:\n                    merged[k][\"parent_name\"] = \"<None>\"\n            else:\n                merged[k][\"parent\"] = 0x0\n                merged[k][\"parent_name\"] = \"<None>\"\n\n        # print\n        self.out = []\n        if not args.quiet:\n            fmt = \"{:<18s} {:<18s} {:<24s} {:<6s} {:<6s} {:<18s} {:<18s} {:18s} {:<s}\"\n            legend = [\n                \"chrdev\", \"name\", \"name (guessed)\", \"major\", \"minor\",\n                \"cdev\", \"cdev->kobj.parent\", \"parent_name\", \"cdev->ops\",\n            ]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for (major, minor), m in sorted(merged.items()):\n            guessed_name = KernelCharacterDevicesCommand.get_cdev_name(major, minor)\n            if not args.verbose:\n                if m[\"chrdev\"] == 0:\n                    continue\n            self.out.append(\"{:#018x} {:<18s} {:<24s} {:<6d} {:<6d} {:#018x} {:#018x} {:<18s} {:#018x}{:s}\".format(\n                m[\"chrdev\"], m[\"name\"], guessed_name, major, minor,\n                m[\"cdev\"], m[\"parent\"], m[\"parent_name\"], m[\"ops\"], m[\"ops_sym\"],\n            ))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelOperationsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display the members of commonly used function table (like struct file_operations) in the kernel.\"\"\"\n\n    _cmdline_ = \"kops\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    types = [\n        \"address_space_operations\",\n        \"ata_port_operations\",\n        \"btf_kind_operations\",\n        \"block_device_operations\",\n        \"clk_ops\",\n        \"configfs_item_operations\",\n        \"configfs_group_operations\",\n        \"damon_operations\",\n        \"dentry_operations\",\n        \"dev_pm_ops\",\n        \"dma_buf_ops\",\n        \"export_operations\",\n        \"file_operations\",\n        \"fs_context_operations\",\n        \"inode_operations\",\n        \"kobj_ns_type_operations\",\n        \"media_entity_operations\",\n        \"movable_operations\",\n        \"net_device_ops\",\n        \"page_ext_operations\",\n        \"parport_operations\",\n        \"pernet_operations\",\n        \"pipe_buf_operations\",\n        \"proc_ns_operations\",\n        \"proc_ops\",\n        \"regulator_ops\",\n        \"seq_operations\",\n        \"smp_operations\", # ARM only\n        \"super_operations\",\n        \"tty_ldisc_ops\",\n        \"tty_operations\",\n        \"tty_port_operations\",\n        \"ucsi_operations\",\n        \"vm_operations_struct\",\n    ]\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"name\", metavar=\"STRUCT_NAME\", choices=types, help=\"the structure name.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as ops.\")\n    parser.add_argument(\"-V\", \"--version\", help=\"use specific kernel version. (default: detected kernel version)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} file_operations\",\n        \"{0:s} -V 6.6.0 file_operations\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Currently it supports from 3.0 to 6.16.\",\n        \"\",\n        \"Supported structure:\",\n    ]\n    for t_grp in slicer(types, 4):\n        _note_.append(\"  \" + \", \".join(t_grp) + \",\")\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.types:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix: example: `kops TAB`\n            return [s for s in self.types if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.types if s and s.startswith(text.strip())]\n\n    def initialize(self, kversion):\n        if kversion.major < 3:\n            err(\"Unsupported before v3.0\")\n            return False\n\n        self.members = {}\n\n        def adapt_to_kernel_version(ops):\n            out = []\n            for entry in ops:\n                if len(entry) == 5:\n                    typ, name, minver, maxver, enabled = entry\n                    if not enabled:\n                        continue\n                else:\n                    typ, name, minver, maxver = entry\n\n                if minver and kversion < minver:\n                    continue\n                if maxver and maxver <= kversion:\n                    continue\n                out.append((typ, name))\n            return out\n\n        file_operations = [\n            # type       name                                       minver     maxver\n            [\"ptr\",      \"owner\",                                   None,      None],\n            [\"int\",      \"flags\",                                   \"6.10.0\",  None],\n            [\"func_ptr\", \"llseek\",                                  None,      None],\n            [\"func_ptr\", \"read\",                                    None,      None],\n            [\"func_ptr\", \"write\",                                   None,      None],\n            [\"func_ptr\", \"aio_read\",                                None,      \"4.1.0\"],\n            [\"func_ptr\", \"aio_write\",                               None,      \"4.1.0\"],\n            [\"func_ptr\", \"read_iter\",                               \"3.16.0\",  None],\n            [\"func_ptr\", \"write_iter\",                              \"3.16.0\",  None],\n            [\"func_ptr\", \"readdir\",                                 None,      \"3.11.0\"],\n            [\"func_ptr\", \"iopoll\",                                  \"5.1.0\",   None],\n            [\"func_ptr\", \"iterate\",                                 \"3.11.0\",  \"6.5.0\"],\n            [\"func_ptr\", \"iterate_shared\",                          \"4.7.0\",   None],\n            [\"func_ptr\", \"poll\",                                    None,      None],\n            [\"func_ptr\", \"unlocked_ioctl\",                          None,      None],\n            [\"func_ptr\", \"compat_ioctl\",                            None,      None],\n            [\"func_ptr\", \"mmap\",                                    None,      None],\n            [\"func_ptr\", \"mremap\",                                  \"3.19.0\",  \"4.3.0\"],\n            [\"ulong\",    \"mmap_supported_flags\",                    \"4.15.0\",  \"6.10.0\"],\n            [\"func_ptr\", \"open\",                                    None,      None],\n            [\"func_ptr\", \"flush\",                                   None,      None],\n            [\"func_ptr\", \"release\",                                 None,      None],\n            [\"func_ptr\", \"fsync\",                                   None,      None],\n            [\"func_ptr\", \"aio_fsync\",                               None,      \"4.9.0\"],\n            [\"func_ptr\", \"fasync\",                                  None,      None],\n            [\"func_ptr\", \"lock\",                                    None,      None],\n            [\"func_ptr\", \"sendpage\",                                None,      \"6.5.0\"],\n            [\"func_ptr\", \"get_unmapped_area\",                       None,      None],\n            [\"func_ptr\", \"check_flags\",                             None,      None],\n            [\"func_ptr\", \"flock\",                                   None,      None],\n            [\"func_ptr\", \"splice_write\",                            None,      None],\n            [\"func_ptr\", \"splice_read\",                             None,      None],\n            [\"func_ptr\", \"splice_eof\",                              \"6.5.0\",   None],\n            [\"func_ptr\", \"setlease\",                                None,      None],\n            [\"func_ptr\", \"fallocate\",                               None,      None],\n            [\"func_ptr\", \"show_fdinfo\",                             \"3.8.0\",   None],\n            [\"func_ptr\", \"copy_file_range\",                         \"4.5.0\",   None],\n            [\"func_ptr\", \"clone_file_range\",                        None,      \"4.19.289\"],\n            [\"func_ptr\", \"dedupe_file_range\",                       None,      \"4.19.289\"],\n            [\"func_ptr\", \"remap_file_range\",                        \"4.20.0\",  None],\n            [\"func_ptr\", \"fadvise\",                                 \"4.19.0\",  None],\n            [\"func_ptr\", \"uring_cmd\",                               \"5.19.0\",  None],\n            [\"func_ptr\", \"uring_cmd_iopoll\",                        \"6.1.0\",   None],\n            [\"func_ptr\", \"mmap_prepare\",                            \"6.16.0\",  None],\n        ]\n        self.members[\"file_operations\"] = adapt_to_kernel_version(file_operations)\n\n        tty_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"lookup\",                                  None,      None],\n            [\"func_ptr\", \"install\",                                 None,      None],\n            [\"func_ptr\", \"remove\",                                  None,      None],\n            [\"func_ptr\", \"open\",                                    None,      None],\n            [\"func_ptr\", \"close\",                                   None,      None],\n            [\"func_ptr\", \"shutdown\",                                None,      None],\n            [\"func_ptr\", \"cleanup\",                                 None,      None],\n            [\"func_ptr\", \"write\",                                   None,      None],\n            [\"func_ptr\", \"put_char\",                                None,      None],\n            [\"func_ptr\", \"flush_chars\",                             None,      None],\n            [\"func_ptr\", \"write_room\",                              None,      None],\n            [\"func_ptr\", \"chars_in_buffer\",                         None,      None],\n            [\"func_ptr\", \"ioctl\",                                   None,      None],\n            [\"func_ptr\", \"compat_ioctl\",                            None,      None],\n            [\"func_ptr\", \"set_termios\",                             None,      None],\n            [\"func_ptr\", \"throttle\",                                None,      None],\n            [\"func_ptr\", \"unthrottle\",                              None,      None],\n            [\"func_ptr\", \"stop\",                                    None,      None],\n            [\"func_ptr\", \"start\",                                   None,      None],\n            [\"func_ptr\", \"hangup\",                                  None,      None],\n            [\"func_ptr\", \"break_ctl\",                               None,      None],\n            [\"func_ptr\", \"flush_buffer\",                            None,      None],\n            [\"func_ptr\", \"ldisc_ok\",                                \"6.1.0\",   None],\n            [\"func_ptr\", \"set_ldisc\",                               None,      None],\n            [\"func_ptr\", \"wait_until_sent\",                         None,      None],\n            [\"func_ptr\", \"send_xchar\",                              None,      None],\n            [\"func_ptr\", \"tiocmget\",                                None,      None],\n            [\"func_ptr\", \"tiocmset\",                                None,      None],\n            [\"func_ptr\", \"resize\",                                  None,      None],\n            [\"func_ptr\", \"set_termiox\",                             None,      \"5.10.0\"],\n            [\"func_ptr\", \"get_icount\",                              None,      None],\n            [\"func_ptr\", \"get_serial\",                              \"4.19.0\",  None],\n            [\"func_ptr\", \"set_serial\",                              \"4.19.0\",  None],\n            [\"func_ptr\", \"show_fdinfo\",                             \"4.14.0\",  None],\n            [\"func_ptr\", \"poll_init (CONFIG_CONSOLE_POLL=y)\",       None,      None],\n            [\"func_ptr\", \"poll_get_char (CONFIG_CONSOLE_POLL=y)\",   None,      None],\n            [\"func_ptr\", \"poll_put_char (CONFIG_CONSOLE_POLL=y)\",   None,      None],\n            [\"func_ptr\", \"proc_show\",                               \"4.18.0\",  None],\n            [\"ptr\",      \"proc_fops\",                               None,      \"4.18.0\"],\n        ]\n        self.members[\"tty_operations\"] = adapt_to_kernel_version(tty_operations)\n\n        tty_ldisc_ops = [\n            # type       name                                       minver     maxver      additional_flag\n            [\"int\",      \"magic\",                                   None,      \"5.13.0\"],\n            [\"char*\",    \"name\",                                    None,      None],\n            [\"int\",      \"num\",                                     \"5.16.0\",  None],\n            [\"int\",      \"num\",                                     None,      \"5.15.121\", is_32bit()],\n            [\"int\",      \"flags\",                                   None,      \"5.15.121\", is_32bit()],\n            [\"int, int\", \"flags, num\",                              None,      \"5.15.121\", is_64bit()],\n            [\"func_ptr\", \"open\",                                    None,      None],\n            [\"func_ptr\", \"close\",                                   None,      None],\n            [\"func_ptr\", \"flush_buffer\",                            None,      None],\n            [\"func_ptr\", \"read\",                                    None,      None],\n            [\"func_ptr\", \"write\",                                   None,      None],\n            [\"func_ptr\", \"ioctl\",                                   None,      None],\n            [\"func_ptr\", \"compat_ioctl\",                            None,      None],\n            [\"func_ptr\", \"set_termios\",                             None,      None],\n            [\"func_ptr\", \"poll\",                                    None,      None],\n            [\"func_ptr\", \"hangup\",                                  None,      None],\n            [\"func_ptr\", \"receive_buf\",                             None,      None],\n            [\"func_ptr\", \"write_wakeup\",                            None,      None],\n            [\"func_ptr\", \"dcd_change\",                              None,      None],\n            [\"func_ptr\", \"fasync\",                                  \"3.11.0\",  \"4.6.0\"],\n            [\"func_ptr\", \"receive_buf2\",                            \"3.12.0\",  None],\n            [\"func_ptr\", \"lookahead_buf\",                           \"5.16.0\",  None],\n            [\"ptr\",      \"owner\",                                   None,      None],\n            [\"int\",      \"refcount\",                                None,      \"5.14.0\"],\n        ]\n        self.members[\"tty_ldisc_ops\"] = adapt_to_kernel_version(tty_ldisc_ops)\n\n        seq_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"start\",                                   None,      None],\n            [\"func_ptr\", \"stop\",                                    None,      None],\n            [\"func_ptr\", \"next\",                                    None,      None],\n            [\"func_ptr\", \"show\",                                    None,      None],\n        ]\n        self.members[\"seq_operations\"] = adapt_to_kernel_version(seq_operations)\n\n        inode_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"lookup\",                                  None,      None],\n            [\"func_ptr\", \"get_link\",                                \"4.5.0\",   None],\n            [\"func_ptr\", \"follow_link\",                             None,      \"4.5.0\"],\n            [\"func_ptr\", \"permission\",                              None,      None],\n            [\"func_ptr\", \"get_inode_acl\",                           \"6.2.0\",   None],\n            [\"func_ptr\", \"get_acl\",                                 \"3.1.0\",   \"6.1.39\"],\n            [\"func_ptr\", \"check_acl\",                               None,      \"3.1.0\"],\n            [\"func_ptr\", \"readlink\",                                None,      None],\n            [\"func_ptr\", \"put_link\",                                None,      \"4.5.0\"],\n            [\"func_ptr\", \"create\",                                  None,      None],\n            [\"func_ptr\", \"link\",                                    None,      None],\n            [\"func_ptr\", \"unlink\",                                  None,      None],\n            [\"func_ptr\", \"symlink\",                                 None,      None],\n            [\"func_ptr\", \"mkdir\",                                   None,      None],\n            [\"func_ptr\", \"rmdir\",                                   None,      None],\n            [\"func_ptr\", \"mknod\",                                   None,      None],\n            [\"func_ptr\", \"rename\",                                  None,      None],\n            [\"func_ptr\", \"truncate\",                                None,      \"3.8.0\"],\n            [\"func_ptr\", \"rename2\",                                 \"3.15.0\",  \"4.9.0\"],\n            [\"func_ptr\", \"setattr\",                                 None,      None],\n            [\"func_ptr\", \"getattr\",                                 None,      None],\n            [\"func_ptr\", \"setxattr\",                                None,      \"4.9.0\"],\n            [\"func_ptr\", \"getxattr\",                                None,      \"4.9.0\"],\n            [\"func_ptr\", \"listxattr\",                               None,      None],\n            [\"func_ptr\", \"removexattr\",                             None,      \"4.9.0\"],\n            [\"func_ptr\", \"fiemap\",                                  None,      None],\n            [\"func_ptr\", \"update_time\",                             \"3.5.0\",   None],\n            [\"func_ptr\", \"atomic_open\",                             \"3.6.0\",   None],\n            [\"func_ptr\", \"tmpfile\",                                 \"3.11.0\",  None],\n            [\"func_ptr\", \"get_acl\",                                 \"6.2.0\",   None],\n            [\"func_ptr\", \"set_acl\",                                 \"3.14.0\",  None],\n            [\"func_ptr\", \"dentry_open\",                             None,      \"4.2.0\"],\n            [\"func_ptr\", \"fileattr_set\",                            \"5.13.0\",  None],\n            [\"func_ptr\", \"fileattr_get\",                            \"5.13.0\",  None],\n            [\"func_ptr\", \"get_offset_ctx\",                          \"6.6.0\",   None],\n        ]\n        self.members[\"inode_operations\"] = adapt_to_kernel_version(inode_operations)\n\n        pernet_operations = [\n            # type       name                                       minver     maxver\n            [\"ptr\",      \"list.next\",                               None,      None],\n            [\"ptr\",      \"list.prev\",                               None,      None],\n            [\"func_ptr\", \"init\",                                    None,      None],\n            [\"func_ptr\", \"pre_exit\",                                \"5.3.0\",   None],\n            [\"func_ptr\", \"exit\",                                    None,      None],\n            [\"func_ptr\", \"exit_batch\",                              None,      None],\n            [\"func_ptr\", \"exit_batch_rtnl\",                         \"6.9.0\",   \"6.15.9\"],\n            [\"func_ptr\", \"exit_rtnl\",                               \"6.16.0\",  None],\n            [\"ptr\",      \"id\",                                      None,      None],\n            [\"long\",     \"size\",                                    None,      None],\n        ]\n        self.members[\"pernet_operations\"] = adapt_to_kernel_version(pernet_operations)\n\n        address_space_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"writepage\",                               None,      \"6.15.9\"],\n            [\"func_ptr\", \"read_folio\",                              \"5.19.0\",  None],\n            [\"func_ptr\", \"readpage\",                                None,      \"5.19.0\"],\n            [\"func_ptr\", \"writepages\",                              None,      None],\n            [\"func_ptr\", \"dirty_folio\",                             \"5.18.0\",  None],\n            [\"func_ptr\", \"set_page_dirty\",                          None,      \"5.18.0\"],\n            [\"func_ptr\", \"readpages\",                               None,      \"5.18.0\"],\n            [\"func_ptr\", \"readahead\",                               \"5.8.0\",   None],\n            [\"func_ptr\", \"write_begin\",                             None,      None],\n            [\"func_ptr\", \"write_end\",                               None,      None],\n            [\"func_ptr\", \"bmap\",                                    None,      None],\n            [\"func_ptr\", \"invalidate_folio\",                        \"5.18.0\",  None],\n            [\"func_ptr\", \"invalidatepage\",                          None,      \"5.18.0\"],\n            [\"func_ptr\", \"release_folio\",                           \"5.19.0\",  None],\n            [\"func_ptr\", \"releasepage\",                             None,      \"5.19.0\"],\n            [\"func_ptr\", \"free_folio\",                              \"5.19.0\",  None],\n            [\"func_ptr\", \"freepage\",                                None,      \"5.19.0\"],\n            [\"func_ptr\", \"direct_IO\",                               None,      None],\n            [\"func_ptr\", \"get_xip_mem\",                             None,      \"4.0.0\"],\n            [\"func_ptr\", \"migrate_folio\",                           \"6.0.0\",   None],\n            [\"func_ptr\", \"migratepage\",                             None,      \"5.20.0\"],\n            [\"func_ptr\", \"isolate_page\",                            \"4.8.0\",   \"5.20.0\"],\n            [\"func_ptr\", \"putback_page\",                            \"4.8.0\",   \"5.20.0\"],\n            [\"func_ptr\", \"launder_folio\",                           \"5.18.0\",  None],\n            [\"func_ptr\", \"launder_page\",                            None,      \"5.18.0\"],\n            [\"func_ptr\", \"is_partially_uptodate\",                   None,      None],\n            [\"func_ptr\", \"is_dirty_writeback\",                      \"3.11.0\",  None],\n            [\"func_ptr\", \"error_remove_page\",                       None,      \"6.8.0\"],\n            [\"func_ptr\", \"error_remove_folio\",                      \"6.8.0\",   None],\n            [\"func_ptr\", \"swap_activate\",                           \"3.6.0\",   None],\n            [\"func_ptr\", \"swap_deactivate\",                         \"3.6.0\",   None],\n            [\"func_ptr\", \"swap_rw\",                                 \"5.19.0\",  None],\n        ]\n        self.members[\"address_space_operations\"] = adapt_to_kernel_version(address_space_operations)\n\n        vm_operations_struct = [\n            # type       name                                            minver     maxver\n            [\"func_ptr\", \"open\",                                         None,      None],\n            [\"func_ptr\", \"close\",                                        None,      None],\n            [\"func_ptr\", \"may_split\",                                    \"5.11.0\",  None],\n            [\"func_ptr\", \"split\",                                        \"4.14.0\",  \"5.10.187\"],\n            [\"func_ptr\", \"mremap\",                                       \"4.3.9\",   None],\n            [\"func_ptr\", \"mprotect\",                                     \"5.11.0\",  None],\n            [\"func_ptr\", \"fault\",                                        None,      None],\n            [\"func_ptr\", \"huge_fault\",                                   \"4.11.0\",  None],\n            [\"func_ptr\", \"pmd_fault\",                                    \"4.3.0\",   \"4.11.0\"],\n            [\"func_ptr\", \"map_pages\",                                    \"3.15.0\",  None],\n            [\"func_ptr\", \"pagesize\",                                     \"4.17.0\",  None],\n            [\"func_ptr\", \"page_mkwrite\",                                 None,      None],\n            [\"func_ptr\", \"pfn_mkwrite\",                                  \"4.1.0\",   None],\n            [\"func_ptr\", \"access\",                                       None,      None],\n            [\"func_ptr\", \"name\",                                         \"3.16.0\",  None],\n            [\"func_ptr\", \"set_policy (CONFIG_NUMA=y)\",                   None,      None],\n            [\"func_ptr\", \"get_policy (CONFIG_NUMA=y)\",                   None,      None],\n            [\"func_ptr\", \"migrate (CONFIG_NUMA=y)\",                      None,      \"3.19.0\"],\n            [\"func_ptr\", \"find_special_page\",                            \"4.0.0\",   \"6.17.8\"],\n            [\"func_ptr\", \"find_normal_page (CONFIG_FIND_NORMAL_PAGE=y)\", \"6.18.0\",  None],\n            [\"func_ptr\", \"remap_pages\",                                  \"3.17.0\",  \"4.0.0\"],\n            [\"func_ptr\", \"remap_pages\",                                  \"3.7.0\",   \"3.16.59\"],\n        ]\n        self.members[\"vm_operations_struct\"] = adapt_to_kernel_version(vm_operations_struct)\n\n        super_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"alloc_inode\",                             None,      None],\n            [\"func_ptr\", \"destroy_inode\",                           None,      None],\n            [\"func_ptr\", \"free_inode\",                              \"5.2.0\",   None],\n            [\"func_ptr\", \"dirty_inode\",                             None,      None],\n            [\"func_ptr\", \"write_inode\",                             None,      None],\n            [\"func_ptr\", \"drop_inode\",                              None,      None],\n            [\"func_ptr\", \"evict_inode\",                             None,      None],\n            [\"func_ptr\", \"put_super\",                               None,      None],\n            [\"func_ptr\", \"write_super\",                             None,      \"3.6.0\"],\n            [\"func_ptr\", \"sync_fs\",                                 None,      None],\n            [\"func_ptr\", \"freeze_super\",                            \"3.19.0\",  None],\n            [\"func_ptr\", \"freeze_fs\",                               None,      None],\n            [\"func_ptr\", \"thaw_super\",                              \"3.19.0\",  None],\n            [\"func_ptr\", \"unfreeze_fs\",                             None,      None],\n            [\"func_ptr\", \"statfs\",                                  None,      None],\n            [\"func_ptr\", \"remount_fs\",                              None,      None],\n            [\"func_ptr\", \"umount_begin\",                            None,      None],\n            [\"func_ptr\", \"show_options\",                            None,      None],\n            [\"func_ptr\", \"show_devname\",                            None,      None],\n            [\"func_ptr\", \"show_path\",                               None,      None],\n            [\"func_ptr\", \"show_stats\",                              None,      None],\n            [\"func_ptr\", \"quota_read (CONFIG_QUOTA=y)\",             None,      None],\n            [\"func_ptr\", \"quota_write (CONFIG_QUOTA=y)\",            None,      None],\n            [\"func_ptr\", \"get_dquots (CONFIG_QUOTA=y)\",             \"3.19.0\",  None],\n            [\"func_ptr\", \"bdev_try_to_free_page\",                   None,      \"5.14.0\"],\n            [\"func_ptr\", \"nr_cached_objects\",                       \"3.1.0\",   None],\n            [\"func_ptr\", \"free_cached_objects\",                     \"3.1.0\",   None],\n            [\"func_ptr\", \"remove_bdev\",                             \"6.17.0\",  None],\n            [\"func_ptr\", \"shutdown\",                                \"6.5.0\",   None],\n        ]\n        self.members[\"super_operations\"] = adapt_to_kernel_version(super_operations)\n\n        dentry_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"d_revalidate\",                            None,      None],\n            [\"func_ptr\", \"d_weak_revalidate\",                       \"3.9.0\",   None],\n            [\"func_ptr\", \"d_hash\",                                  None,      None],\n            [\"func_ptr\", \"d_compare\",                               None,      None],\n            [\"func_ptr\", \"d_delete\",                                None,      None],\n            [\"func_ptr\", \"d_init\",                                  \"4.8.0\",   None],\n            [\"func_ptr\", \"d_release\",                               None,      None],\n            [\"func_ptr\", \"d_prune\",                                 \"3.2.0\",   None],\n            [\"func_ptr\", \"d_iput\",                                  None,      None],\n            [\"func_ptr\", \"d_dname\",                                 None,      None],\n            [\"func_ptr\", \"d_automount\",                             None,      None],\n            [\"func_ptr\", \"d_manage\",                                None,      None],\n            [\"func_ptr\", \"d_select_inode\",                          \"4.1.0\",   \"4.8.0\"],\n            [\"func_ptr\", \"d_real\",                                  \"4.4.0\",   None],\n            [\"func_ptr\", \"d_select_inode\",                          \"3.18.23\", \"3.19.0\"],\n            [\"func_ptr\", \"d_unalias_trylock\",                       \"6.14.0\",  None],\n            [\"func_ptr\", \"d_unalias_unlock\",                        \"6.14.0\",  None],\n        ]\n        self.members[\"dentry_operations\"] = adapt_to_kernel_version(dentry_operations)\n\n        block_device_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"submit_bio\",                              \"5.9.0\",   None],\n            [\"func_ptr\", \"poll_bio\",                                \"5.18.0\",  None],\n            [\"func_ptr\", \"open\",                                    None,      None],\n            [\"func_ptr\", \"release\",                                 None,      None],\n            [\"func_ptr\", \"rw_page\",                                 None,      \"6.3.0\"],\n            [\"func_ptr\", \"ioctl\",                                   None,      None],\n            [\"func_ptr\", \"compat_ioctl\",                            None,      None],\n            [\"func_ptr\", \"direct_access\",                           None,      \"4.12.0\"],\n            [\"func_ptr\", \"check_events\",                            None,      None],\n            [\"func_ptr\", \"media_changed\",                           None,      \"5.9.0\"],\n            [\"func_ptr\", \"unlock_native_capacity\",                  None,      None],\n            [\"func_ptr\", \"revalidate_disk\",                         None,      \"5.13.0\"],\n            [\"func_ptr\", \"getgeo\",                                  None,      None],\n            [\"func_ptr\", \"set_read_only\",                           \"5.11.0\",  None],\n            [\"func_ptr\", \"free_disk\",                               \"5.18.0\",  None],\n            [\"func_ptr\", \"swap_slot_free_notify\",                   None,      None],\n            [\"func_ptr\", \"report_zones\",                            \"4.20.0\",  None],\n            [\"func_ptr\", \"devnode\",                                 \"5.7.0\",   None],\n            [\"func_ptr\", \"get_unique_id\",                           \"5.16.0\",  None],\n            [\"ptr\",      \"owner\",                                   None,      None],\n            [\"ptr\",      \"pr_ops\",                                  \"4.4.0\",   None],\n            [\"func_ptr\", \"alternative_gpt_sector\",                  \"5.15.0\",  None],\n        ]\n        self.members[\"block_device_operations\"] = adapt_to_kernel_version(block_device_operations)\n\n        pipe_buf_operations = [\n            # type       name                                       minver     maxver\n            [\"int\",      \"can_merge\",                               None,      \"5.1.0\"],\n            [\"func_ptr\", \"map\",                                     None,      \"3.15.0\"],\n            [\"func_ptr\", \"unmap\",                                   None,      \"3.15.0\"],\n            [\"func_ptr\", \"confirm\",                                 None,      None],\n            [\"func_ptr\", \"release\",                                 None,      None],\n            [\"func_ptr\", \"try_steal\",                               None,      None],\n            [\"func_ptr\", \"get\",                                     None,      None],\n        ]\n        self.members[\"pipe_buf_operations\"] = adapt_to_kernel_version(pipe_buf_operations)\n\n        smp_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"smp_init_cpus (CONFIG_SMP=y)\",            \"3.7.0\",   None],\n            [\"func_ptr\", \"smp_prepare_cpus (CONFIG_SMP=y)\",         \"3.7.0\",   None],\n            [\"func_ptr\", \"smp_secondary_init (CONFIG_SMP=y)\",       \"3.7.0\",   None],\n            [\"func_ptr\", \"smp_boot_secondary (CONFIG_SMP=y)\",       \"3.7.0\",   None],\n            [\"func_ptr\", \"cpu_kill (CONFIG_HOTPLUG_CPU=y)\",         \"3.7.0\",   None],\n            [\"func_ptr\", \"cpu_die (CONFIG_HOTPLUG_CPU=y)\",          \"3.7.0\",   None],\n            [\"func_ptr\", \"cpu_can_disable (CONFIG_HOTPLUG_CPU=y)\",  \"4.3.0\",   None],\n            [\"func_ptr\", \"cpu_disable (CONFIG_HOTPLUG_CPU=y)\",      \"3.7.0\",   None],\n        ]\n        self.members[\"smp_operations\"] = adapt_to_kernel_version(smp_operations)\n\n        dma_buf_ops = [\n            # type         name                                     minver     maxver\n            [\"bool\",       \"cache_sgt_mapping\",                     \"5.7.0\",   \"6.15.9\"],\n            [\"bool, bool\", \"cache_sgt_mapping, dynamic_mapping\",    \"5.5.0\",   \"5.7.0\"],\n            [\"bool\",       \"cache_sgt_mapping\",                     \"5.3.0\",   \"5.4.265\"],\n            [\"func_ptr\",   \"attach\",                                \"3.2.0\",   None],\n            [\"func_ptr\",   \"detach\",                                \"3.2.0\",   None],\n            [\"func_ptr\",   \"pin\",                                   \"5.7.0\",   None],\n            [\"func_ptr\",   \"unpin\",                                 \"5.7.0\",   None],\n            [\"func_ptr\",   \"map_dma_buf\",                           \"3.2.0\",   None],\n            [\"func_ptr\",   \"unmap_dma_buf\",                         \"3.2.0\",   None],\n            [\"func_ptr\",   \"release\",                               \"3.2.0\",   None],\n            [\"func_ptr\",   \"begin_cpu_access\",                      \"3.4.0\",   None],\n            [\"func_ptr\",   \"end_cpu_access\",                        \"3.4.0\",   None],\n            [\"func_ptr\",   \"mmap\",                                  \"5.3.0\",   None],\n            [\"func_ptr\",   \"map_atomic\",                            \"4.12.0\",  \"4.19.0\"],\n            [\"func_ptr\",   \"unmap_atomic\",                          \"4.12.0\",  \"4.19.0\"],\n            [\"func_ptr\",   \"kmap_atomic\",                           \"3.4.0\",   \"4.12.0\"],\n            [\"func_ptr\",   \"kunmap_atomic\",                         \"3.4.0\",   \"4.12.0\"],\n            [\"func_ptr\",   \"map\",                                   \"4.12.0\",  \"5.6.0\"],\n            [\"func_ptr\",   \"unmap\",                                 \"4.12.0\",  \"5.6.0\"],\n            [\"func_ptr\",   \"kmap\",                                  \"3.4.0\",   \"4.12.0\"],\n            [\"func_ptr\",   \"kunmap\",                                \"3.4.0\",   \"4.12.0\"],\n            [\"func_ptr\",   \"mmap\",                                  \"3.5.0\",   \"5.3.0\"],\n            [\"func_ptr\",   \"vmap\",                                  \"3.5.0\",   None],\n            [\"func_ptr\",   \"vunmap\",                                \"3.5.0\",   None],\n        ]\n        self.members[\"dma_buf_ops\"] = adapt_to_kernel_version(dma_buf_ops)\n\n        ata_port_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"qc_defer\",                                None,      None],\n            [\"func_ptr\", \"check_atapi_dma\",                         None,      None],\n            [\"func_ptr\", \"qc_prep\",                                 None,      None],\n            [\"func_ptr\", \"qc_issue\",                                None,      None],\n            [\"func_ptr\", \"qc_fill_rtf\",                             None,      None],\n            [\"func_ptr\", \"qc_ncq_fill_rtf\",                         \"6.3.0\",   None],\n            [\"func_ptr\", \"cable_detect\",                            None,      None],\n            [\"func_ptr\", \"mode_filter\",                             None,      None],\n            [\"func_ptr\", \"set_piomode\",                             None,      None],\n            [\"func_ptr\", \"set_dmamode\",                             None,      None],\n            [\"func_ptr\", \"set_mode\",                                None,      None],\n            [\"func_ptr\", \"read_id\",                                 None,      None],\n            [\"func_ptr\", \"dev_config\",                              None,      None],\n            [\"func_ptr\", \"freeze\",                                  None,      None],\n            [\"func_ptr\", \"thaw\",                                    None,      None],\n            [\"func_ptr\", \"prereset\",                                None,      \"6.16.5\"],\n            [\"func_ptr\", \"softreset\",                               None,      \"6.16.5\"],\n            [\"func_ptr\", \"hardreset\",                               None,      \"6.16.5\"],\n            [\"func_ptr\", \"postreset\",                               None,      \"6.16.5\"],\n            [\"func_ptr\", \"reset.prereset\",                          \"6.17.0\",  None],\n            [\"func_ptr\", \"reset.softreset\",                         \"6.17.0\",  None],\n            [\"func_ptr\", \"reset.hardreset\",                         \"6.17.0\",  None],\n            [\"func_ptr\", \"reset.postreset\",                         \"6.17.0\",  None],\n            [\"func_ptr\", \"pmp_prereset\",                            None,      \"6.16.5\"],\n            [\"func_ptr\", \"pmp_softreset\",                           None,      \"6.16.5\"],\n            [\"func_ptr\", \"pmp_hardreset\",                           None,      \"6.16.5\"],\n            [\"func_ptr\", \"pmp_postreset\",                           None,      \"6.16.5\"],\n            [\"func_ptr\", \"pmp_reset.pmp_prereset\",                  \"6.17.0\",  None],\n            [\"func_ptr\", \"pmp_reset.pmp_softreset\",                 \"6.17.0\",  None],\n            [\"func_ptr\", \"pmp_reset.pmp_hardreset\",                 \"6.17.0\",  None],\n            [\"func_ptr\", \"pmp_reset.pmp_postreset\",                 \"6.17.0\",  None],\n            [\"func_ptr\", \"error_handler\",                           None,      None],\n            [\"func_ptr\", \"lost_interrupt\",                          None,      None],\n            [\"func_ptr\", \"post_internal_cmd\",                       None,      None],\n            [\"func_ptr\", \"sched_eh\",                                \"3.6.0\",   None],\n            [\"func_ptr\", \"end_eh\",                                  \"3.6.0\",   None],\n            [\"func_ptr\", \"scr_read\",                                None,      None],\n            [\"func_ptr\", \"scr_write\",                               None,      None],\n            [\"func_ptr\", \"pmp_attach\",                              None,      None],\n            [\"func_ptr\", \"pmp_detach\",                              None,      None],\n            [\"func_ptr\", \"set_lpm\",                                 None,      None],\n            [\"func_ptr\", \"port_suspend\",                            None,      None],\n            [\"func_ptr\", \"port_resume\",                             None,      None],\n            [\"func_ptr\", \"port_start\",                              None,      None],\n            [\"func_ptr\", \"port_stop\",                               None,      None],\n            [\"func_ptr\", \"host_stop\",                               None,      None],\n            [\"func_ptr\", \"sff_dev_select (CONFIG_ATA_SFF=y)\",       None,      None],\n            [\"func_ptr\", \"sff_set_devctl (CONFIG_ATA_SFF=y)\",       None,      None],\n            [\"func_ptr\", \"sff_check_status (CONFIG_ATA_SFF=y)\",     None,      None],\n            [\"func_ptr\", \"sff_check_altstatus (CONFIG_ATA_SFF=y)\",  None,      None],\n            [\"func_ptr\", \"sff_tf_load (CONFIG_ATA_SFF=y)\",          None,      None],\n            [\"func_ptr\", \"sff_tf_read (CONFIG_ATA_SFF=y)\",          None,      None],\n            [\"func_ptr\", \"sff_exec_command (CONFIG_ATA_SFF=y)\",     None,      None],\n            [\"func_ptr\", \"sff_data_xfer (CONFIG_ATA_SFF=y)\",        None,      None],\n            [\"func_ptr\", \"sff_irq_on (CONFIG_ATA_SFF=y)\",           None,      None],\n            [\"func_ptr\", \"sff_irq_check (CONFIG_ATA_SFF=y)\",        None,      None],\n            [\"func_ptr\", \"sff_irq_clear (CONFIG_ATA_SFF=y)\",        None,      None],\n            [\"func_ptr\", \"sff_drain_fifo (CONFIG_ATA_SFF=y)\",       None,      None],\n            [\"func_ptr\", \"bmdma_setup (CONFIG_ATA_BMDMA=y)\",        None,      None],\n            [\"func_ptr\", \"bmdma_start (CONFIG_ATA_BMDMA=y)\",        None,      None],\n            [\"func_ptr\", \"bmdma_stop (CONFIG_ATA_BMDMA=y)\",         None,      None],\n            [\"func_ptr\", \"bmdma_status (CONFIG_ATA_BMDMA=y)\",       None,      None],\n            [\"func_ptr\", \"em_show\",                                 None,      None],\n            [\"func_ptr\", \"em_store\",                                None,      None],\n            [\"func_ptr\", \"sw_activity_show\",                        None,      None],\n            [\"func_ptr\", \"sw_activity_store\",                       None,      None],\n            [\"func_ptr\", \"transmit_led_message\",                    \"3.11.0\",  None],\n            [\"func_ptr\", \"phy_reset\",                               None,      \"6.6.0\"],\n            [\"func_ptr\", \"eng_timeout\",                             None,      \"6.6.0\"],\n            [\"ptr\",      \"inherits\",                                None,      None],\n        ]\n        self.members[\"ata_port_operations\"] = adapt_to_kernel_version(ata_port_operations)\n\n        media_entity_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"get_fwnode_pad\",                          \"4.13.0\",  None],\n            [\"func_ptr\", \"link_setup\",                              None,      None],\n            [\"func_ptr\", \"link_validate\",                           \"3.5.0\",   None],\n            [\"func_ptr\", \"has_pad_interdep\",                        \"6.1.0\",   None],\n        ]\n        self.members[\"media_entity_operations\"] = adapt_to_kernel_version(media_entity_operations)\n\n        configfs_item_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"release\",                                 None,      None],\n            [\"func_ptr\", \"show_attribute\",                          None,      \"4.4.0\"],\n            [\"func_ptr\", \"store_attribute\",                         None,      \"4.4.0\"],\n            [\"func_ptr\", \"allow_link\",                              None,      None],\n            [\"func_ptr\", \"drop_link\",                               None,      None],\n        ]\n        self.members[\"configfs_item_operations\"] = adapt_to_kernel_version(configfs_item_operations)\n\n        configfs_group_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"make_item\",                               None,      None],\n            [\"func_ptr\", \"make_group\",                              None,      None],\n            [\"func_ptr\", \"commit_item\",                             None,      \"6.1.113\"],\n            [\"func_ptr\", \"disconnect_notify\",                       None,      None],\n            [\"func_ptr\", \"drop_item\",                               None,      None],\n            [\"func_ptr\", \"is_visible\",                              \"6.11.0\",  None],\n            [\"func_ptr\", \"is_bin_visible\",                          \"6.11.0\",  None],\n        ]\n        self.members[\"configfs_group_operations\"] = adapt_to_kernel_version(configfs_group_operations)\n\n        fs_context_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"free\",                                    \"5.1.0\",   None],\n            [\"func_ptr\", \"dup\",                                     \"5.1.0\",   None],\n            [\"func_ptr\", \"parse_param\",                             \"5.1.0\",   None],\n            [\"func_ptr\", \"parse_monolithic\",                        \"5.1.0\",   None],\n            [\"func_ptr\", \"get_tree\",                                \"5.1.0\",   None],\n            [\"func_ptr\", \"reconfigure\",                             \"5.1.0\",   None],\n        ]\n        self.members[\"fs_context_operations\"] = adapt_to_kernel_version(fs_context_operations)\n\n        export_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"encode_fh\",                               None,      None],\n            [\"func_ptr\", \"fh_to_dentry\",                            None,      None],\n            [\"func_ptr\", \"fh_to_parent\",                            None,      None],\n            [\"func_ptr\", \"get_name\",                                None,      None],\n            [\"func_ptr\", \"get_parent\",                              None,      None],\n            [\"func_ptr\", \"commit_metadata\",                         None,      None],\n            [\"func_ptr\", \"get_uuid\",                                \"4.0.0\",   None],\n            [\"func_ptr\", \"map_blocks\",                              \"4.0.0\",   None],\n            [\"func_ptr\", \"commit_blocks\",                           \"4.0.0\",   None],\n            [\"func_ptr\", \"fetch_iversion\",                          \"5.10.0\",  \"6.3.0\"],\n            [\"func_ptr\", \"permission\",                              \"6.14.0\",  None],\n            [\"func_ptr\", \"open\",                                    \"6.14.0\",  None],\n            [\"long\",     \"flags\",                                   \"5.10.0\",  None],\n        ]\n        self.members[\"export_operations\"] = adapt_to_kernel_version(export_operations)\n\n        dev_pm_ops = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"prepare\",                                 None,      None],\n            [\"func_ptr\", \"complete\",                                None,      None],\n            [\"func_ptr\", \"suspend\",                                 None,      None],\n            [\"func_ptr\", \"resume\",                                  None,      None],\n            [\"func_ptr\", \"freeze\",                                  None,      None],\n            [\"func_ptr\", \"thaw\",                                    None,      None],\n            [\"func_ptr\", \"poweroff\",                                None,      None],\n            [\"func_ptr\", \"restore\",                                 None,      None],\n            [\"func_ptr\", \"suspend_late\",                            \"3.4.0\",   None],\n            [\"func_ptr\", \"resume_early\",                            \"3.4.0\",   None],\n            [\"func_ptr\", \"freeze_late\",                             \"3.4.0\",   None],\n            [\"func_ptr\", \"thaw_early\",                              \"3.4.0\",   None],\n            [\"func_ptr\", \"poweroff_late\",                           \"3.4.0\",   None],\n            [\"func_ptr\", \"restore_early\",                           \"3.4.0\",   None],\n            [\"func_ptr\", \"suspend_noirq\",                           None,      None],\n            [\"func_ptr\", \"resume_noirq\",                            None,      None],\n            [\"func_ptr\", \"freeze_noirq\",                            None,      None],\n            [\"func_ptr\", \"thaw_noirq\",                              None,      None],\n            [\"func_ptr\", \"poweroff_noirq\",                          None,      None],\n            [\"func_ptr\", \"restore_noirq\",                           None,      None],\n            [\"func_ptr\", \"runtime_suspend\",                         None,      None],\n            [\"func_ptr\", \"runtime_resume\",                          None,      None],\n            [\"func_ptr\", \"runtime_idle\",                            None,      None],\n        ]\n        self.members[\"dev_pm_ops\"] = adapt_to_kernel_version(dev_pm_ops)\n\n        clk_ops = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"prepare\",                                 \"3.4.0\",   None],\n            [\"func_ptr\", \"unprepare\",                               \"3.4.0\",   None],\n            [\"func_ptr\", \"is_prepared\",                             \"3.10.0\",  None],\n            [\"func_ptr\", \"unprepare_unused\",                        \"3.10.0\",  None],\n            [\"func_ptr\", \"init (CONFIG_SH_CLK_CPG_LEGACY=y)\",       None,      \"3.4.0\"],\n            [\"func_ptr\", \"enable\",                                  None,      None],\n            [\"func_ptr\", \"disable\",                                 None,      None],\n            [\"func_ptr\", \"is_enabled\",                              \"3.4.0\",   None],\n            [\"func_ptr\", \"disable_unused\",                          \"3.8.0\",   None],\n            [\"func_ptr\", \"save_context\",                            \"4.20.0\",  None],\n            [\"func_ptr\", \"restore_context\",                         \"4.20.0\",  None],\n            [\"func_ptr\", \"recalc_rate\",                             \"3.4.0\",   None],\n            [\"func_ptr\", \"recalc\",                                  None,      \"3.4.0\"],\n            [\"func_ptr\", \"round_rate\",                              \"3.4.0\",   None],\n            [\"func_ptr\", \"determine_rate\",                          \"3.12.0\",  None],\n            [\"func_ptr\", \"set_parent\",                              \"3.4.0\",   None],\n            [\"func_ptr\", \"get_parent\",                              \"3.4.0\",   None],\n            [\"func_ptr\", \"set_rate\",                                None,      None],\n            [\"func_ptr\", \"set_rate_and_parent\",                     \"3.14.0\",  None],\n            [\"func_ptr\", \"set_parent\",                              None,      \"3.4.0\"],\n            [\"func_ptr\", \"round_rate\",                              None,      \"3.4.0\"],\n            [\"func_ptr\", \"recalc_accuracy\",                         \"3.14.0\",  None],\n            [\"func_ptr\", \"get_phase\",                               \"3.18.0\",  None],\n            [\"func_ptr\", \"set_phase\",                               \"3.18.0\",  None],\n            [\"func_ptr\", \"get_duty_cycle\",                          \"4.19.0\",  None],\n            [\"func_ptr\", \"set_duty_cycle\",                          \"4.19.0\",  None],\n            [\"func_ptr\", \"init\",                                    \"3.4.0\",   None],\n            [\"func_ptr\", \"terminate\",                               \"5.6.0\",   None],\n            [\"func_ptr\", \"debug_init\",                              \"3.15.0\",  None],\n        ]\n        self.members[\"clk_ops\"] = adapt_to_kernel_version(clk_ops)\n\n        parport_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"write_data\",                              None,      None],\n            [\"func_ptr\", \"read_data\",                               None,      None],\n            [\"func_ptr\", \"write_control\",                           None,      None],\n            [\"func_ptr\", \"read_control\",                            None,      None],\n            [\"func_ptr\", \"frob_control\",                            None,      None],\n            [\"func_ptr\", \"read_status\",                             None,      None],\n            [\"func_ptr\", \"enable_irq\",                              None,      None],\n            [\"func_ptr\", \"disable_irq\",                             None,      None],\n            [\"func_ptr\", \"data_forward\",                            None,      None],\n            [\"func_ptr\", \"data_reverse\",                            None,      None],\n            [\"func_ptr\", \"init_state\",                              None,      None],\n            [\"func_ptr\", \"save_state\",                              None,      None],\n            [\"func_ptr\", \"restore_state\",                           None,      None],\n            [\"func_ptr\", \"epp_write_data\",                          None,      None],\n            [\"func_ptr\", \"epp_read_data\",                           None,      None],\n            [\"func_ptr\", \"epp_write_addr\",                          None,      None],\n            [\"func_ptr\", \"epp_read_addr\",                           None,      None],\n            [\"func_ptr\", \"ecp_write_data\",                          None,      None],\n            [\"func_ptr\", \"ecp_read_data\",                           None,      None],\n            [\"func_ptr\", \"ecp_write_addr\",                          None,      None],\n            [\"func_ptr\", \"compat_write_data\",                       None,      None],\n            [\"func_ptr\", \"nibble_read_data\",                        None,      None],\n            [\"func_ptr\", \"byte_read_data\",                          None,      None],\n            [\"ptr\",      \"owner\",                                   None,      None],\n        ]\n        self.members[\"parport_operations\"] = adapt_to_kernel_version(parport_operations)\n\n        proc_ns_operations = [\n            # type       name                                       minver     maxver\n            [\"char*\",    \"name\",                                    None,      None],\n            [\"char*\",    \"real_ns_name\",                            \"4.12.0\",  None],\n            [\"int\",      \"type\",                                    None,      \"6.17.8\"],\n            [\"func_ptr\", \"get\",                                     None,      None],\n            [\"func_ptr\", \"put\",                                     None,      None],\n            [\"func_ptr\", \"install\",                                 None,      None],\n            [\"func_ptr\", \"owner\",                                   \"4.9.0\",   None],\n            [\"func_ptr\", \"get_parent\",                              \"4.9.0\",   None],\n            [\"func_ptr\", \"inum\",                                    \"3.8.0\",   \"3.19.0\"],\n        ]\n        self.members[\"proc_ns_operations\"] = adapt_to_kernel_version(proc_ns_operations)\n\n        net_device_ops = [\n            # type       name                                                   minver     maxver\n            [\"func_ptr\", \"ndo_init\",                                            None,      None],\n            [\"func_ptr\", \"ndo_uninit\",                                          None,      None],\n            [\"func_ptr\", \"ndo_open\",                                            None,      None],\n            [\"func_ptr\", \"ndo_stop\",                                            None,      None],\n            [\"func_ptr\", \"ndo_start_xmit\",                                      None,      None],\n            [\"func_ptr\", \"ndo_features_check\",                                  \"4.5.0\",   None],\n            [\"func_ptr\", \"ndo_select_queue\",                                    None,      None],\n            [\"func_ptr\", \"ndo_change_rx_flags\",                                 None,      None],\n            [\"func_ptr\", \"ndo_set_rx_mode\",                                     None,      None],\n            [\"func_ptr\", \"ndo_set_multicast_list\",                              None,      \"3.2.0\"],\n            [\"func_ptr\", \"ndo_set_mac_address\",                                 None,      None],\n            [\"func_ptr\", \"ndo_validate_addr\",                                   None,      None],\n            [\"func_ptr\", \"ndo_do_ioctl\",                                        None,      None],\n            [\"func_ptr\", \"ndo_eth_ioctl\",                                       \"5.15.0\",  None],\n            [\"func_ptr\", \"ndo_siocbond\",                                        \"5.15.0\",  None],\n            [\"func_ptr\", \"ndo_siocwandev\",                                      \"5.15.0\",  None],\n            [\"func_ptr\", \"ndo_siocdevprivate\",                                  \"5.15.0\",  None],\n            [\"func_ptr\", \"ndo_set_config\",                                      None,      None],\n            [\"func_ptr\", \"ndo_change_mtu\",                                      None,      None],\n            [\"func_ptr\", \"ndo_neigh_setup\",                                     None,      None],\n            [\"func_ptr\", \"ndo_tx_timeout\",                                      None,      None],\n            [\"func_ptr\", \"ndo_get_stats64\",                                     None,      None],\n            [\"func_ptr\", \"ndo_has_offload_stats\",                               \"4.9.0\",   None],\n            [\"func_ptr\", \"ndo_get_offload_stats\",                               \"4.9.0\",   None],\n            [\"func_ptr\", \"ndo_get_stats\",                                       None,      None],\n            [\"func_ptr\", \"ndo_vlan_rx_register\",                                None,      \"3.1.0\"],\n            [\"func_ptr\", \"ndo_vlan_rx_add_vid\",                                 None,      None],\n            [\"func_ptr\", \"ndo_vlan_rx_kill_vid\",                                None,      None],\n            [\"func_ptr\", \"ndo_poll_controller (CONFIG_NET_POLL_CONTROLLER=y)\",  None,      None],\n            [\"func_ptr\", \"ndo_netpoll_setup (CONFIG_NET_POLL_CONTROLLER=y)\",    None,      None],\n            [\"func_ptr\", \"ndo_netpoll_cleanup (CONFIG_NET_POLL_CONTROLLER=y)\",  None,      None],\n            [\"func_ptr\", \"ndo_busy_poll (CONFIG_NET_RX_BUSY_POLL=y)\",           \"3.11.0\",  \"4.11.0\"],\n            [\"func_ptr\", \"ndo_set_vf_mac\",                                      None,      None],\n            [\"func_ptr\", \"ndo_set_vf_vlan\",                                     None,      None],\n            [\"func_ptr\", \"ndo_set_vf_rate\",                                     \"3.16.0\",  None],\n            [\"func_ptr\", \"ndo_set_vf_tx_rate\",                                  None,      \"3.16.0\"],\n            [\"func_ptr\", \"ndo_set_vf_spoofchk\",                                 \"3.2.0\",   None],\n            [\"func_ptr\", \"ndo_set_vf_trust\",                                    \"4.4.0\",   None],\n            [\"func_ptr\", \"ndo_get_vf_config\",                                   None,      None],\n            [\"func_ptr\", \"ndo_set_vf_link_state\",                               \"3.11.0\",  None],\n            [\"func_ptr\", \"ndo_get_vf_stats\",                                    \"4.2.0\",   None],\n            [\"func_ptr\", \"ndo_set_vf_port\",                                     None,      None],\n            [\"func_ptr\", \"ndo_get_vf_port\",                                     None,      None],\n            [\"func_ptr\", \"ndo_set_vf_rss_query_en\",                             \"3.18.21\", \"3.19.0\"],\n            [\"func_ptr\", \"ndo_get_vf_guid\",                                     \"5.5.0\",   None],\n            [\"func_ptr\", \"ndo_set_vf_guid\",                                     \"4.6.0\",   None],\n            [\"func_ptr\", \"ndo_set_vf_rss_query_en\",                             \"4.1.0\",   None],\n            [\"func_ptr\", \"ndo_setup_tc\",                                        None,      None],\n            [\"func_ptr\", \"ndo_fcoe_enable (CONFIG_FCOE=y)\",                     None,      None],\n            [\"func_ptr\", \"ndo_fcoe_disable (CONFIG_FCOE=y)\",                    None,      None],\n            [\"func_ptr\", \"ndo_fcoe_ddp_setup (CONFIG_FCOE=y)\",                  None,      None],\n            [\"func_ptr\", \"ndo_fcoe_ddp_done (CONFIG_FCOE=y)\",                   None,      None],\n            [\"func_ptr\", \"ndo_fcoe_ddp_target CONFIG_FCOE=y)\",                  None,      None],\n            [\"func_ptr\", \"ndo_fcoe_get_hbainfo (CONFIG_FCOE=y)\",                \"3.3.0\",   None],\n            [\"func_ptr\", \"ndo_fcoe_get_wwn (CONFIG_LIBFCOE=y)\",                 \"3.2.0\",   None],\n            [\"func_ptr\", \"ndo_fcoe_get_wwn (CONFIG_FCOE=y)\",                    None,      \"3.2.0\"],\n            [\"func_ptr\", \"ndo_rx_flow_steer (CONFIG_RFS_ACCEL=y)\",              None,      None],\n            [\"func_ptr\", \"ndo_add_slave\",                                       None,      None],\n            [\"func_ptr\", \"ndo_del_slave\",                                       None,      None],\n            [\"func_ptr\", \"ndo_get_xmit_slave\",                                  \"5.8.0\",   None],\n            [\"func_ptr\", \"ndo_sk_get_lower_dev\",                                \"5.12.0\",  None],\n            [\"func_ptr\", \"ndo_fix_features\",                                    None,      None],\n            [\"func_ptr\", \"ndo_set_features\",                                    None,      None],\n            [\"func_ptr\", \"ndo_neigh_construct\",                                 \"3.3.0\",   None],\n            [\"func_ptr\", \"ndo_neigh_destroy\",                                   \"3.3.0\",   None],\n            [\"func_ptr\", \"ndo_fdb_add\",                                         \"3.5.0\",   None],\n            [\"func_ptr\", \"ndo_fdb_del\",                                         \"3.5.0\",   None],\n            [\"func_ptr\", \"ndo_fdb_del_bulk\",                                    \"5.19.0\",  None],\n            [\"func_ptr\", \"ndo_fdb_dump\",                                        \"3.5.0\",   None],\n            [\"func_ptr\", \"ndo_fdb_get\",                                         \"5.0.0\",   None],\n            [\"func_ptr\", \"ndo_mdb_add\",                                         \"6.4.0\",   None],\n            [\"func_ptr\", \"ndo_mdb_del\",                                         \"6.4.0\",   None],\n            [\"func_ptr\", \"ndo_mdb_del_bulk\",                                    \"6.8.0\",   None],\n            [\"func_ptr\", \"ndo_mdb_dump\",                                        \"6.4.0\",   None],\n            [\"func_ptr\", \"ndo_mdb_get\",                                         \"6.7.0\",   None],\n            [\"func_ptr\", \"ndo_bridge_setlink\",                                  \"3.8.0\",   None],\n            [\"func_ptr\", \"ndo_bridge_getlink\",                                  \"3.8.0\",   None],\n            [\"func_ptr\", \"ndo_bridge_dellink\",                                  \"3.9.0\",   None],\n            [\"func_ptr\", \"ndo_change_carrier\",                                  \"3.9.0\",   None],\n            [\"func_ptr\", \"ndo_get_phys_port_id\",                                \"3.12.0\",  None],\n            [\"func_ptr\", \"ndo_get_port_parent_id\",                              \"5.1.0\",   None],\n            [\"func_ptr\", \"ndo_get_phys_port_name\",                              \"4.1.0\",   None],\n            [\"func_ptr\", \"ndo_udp_tunnel_add\",                                  \"4.8.0\",   \"5.12.0\"],\n            [\"func_ptr\", \"ndo_udp_tunnel_del\",                                  \"4.8.0\",   \"5.12.0\"],\n            [\"func_ptr\", \"ndo_add_vxlan_port\",                                  \"3.12.0\",  \"4.8.0\"],\n            [\"func_ptr\", \"ndo_del_vxlan_port\",                                  \"3.12.0\",  \"4.8.0\"],\n            [\"func_ptr\", \"ndo_add_geneve_port\",                                 \"4.5.0\",   \"4.8.0\"],\n            [\"func_ptr\", \"ndo_del_geneve_port\",                                 \"4.5.0\",   \"4.8.0\"],\n            [\"func_ptr\", \"ndo_dfwd_add_station\",                                \"3.13.0\",  None],\n            [\"func_ptr\", \"ndo_dfwd_del_station\",                                \"3.13.0\",  None],\n            [\"func_ptr\", \"ndo_dfwd_start_xmit\",                                 \"3.13.0\",  \"4.13.0\"],\n            [\"func_ptr\", \"ndo_get_lock_subclass\",                               \"3.14.5\",  \"5.4.0\"],\n            [\"func_ptr\", \"ndo_features_check\",                                  \"3.18.4\",  \"4.5.0\"],\n            [\"func_ptr\", \"ndo_gso_check\",                                       \"3.18.0\",  \"3.18.4\"],\n            [\"func_ptr\", \"ndo_set_tx_maxrate\",                                  \"4.1.0\",   None],\n            [\"func_ptr\", \"ndo_get_iflink\",                                      \"4.1.0\",   None],\n            [\"func_ptr\", \"ndo_switch_parent_id_get (CONFIG_NET_SWITCHDEV=y)\",   \"3.19.0\",  \"4.1.0\"],\n            [\"func_ptr\", \"ndo_switch_port_stp_update (CONFIG_NET_SWITCHDEV=y)\", \"3.19.0\",  \"4.1.0\"],\n            [\"func_ptr\", \"ndo_change_proto_down\",                               \"4.3.0\",   \"5.17.0\"],\n            [\"func_ptr\", \"ndo_fill_metadata_dst\",                               \"4.3.0\",   None],\n            [\"func_ptr\", \"ndo_set_rx_headroom\",                                 \"4.6.0\",   None],\n            [\"func_ptr\", \"ndo_bpf\",                                             \"4.15.0\",  None],\n            [\"func_ptr\", \"ndo_xdp\",                                             \"4.8.0\",   \"4.15.0\"],\n            [\"func_ptr\", \"ndo_xdp_xmit\",                                        \"4.14.0\",  None],\n            [\"func_ptr\", \"ndo_xdp_get_xmit_slave\",                              \"5.15.0\",  None],\n            [\"func_ptr\", \"ndo_xsk_wakeup\",                                      \"5.4.0\",   None],\n            [\"func_ptr\", \"ndo_xsk_async_xmit\",                                  \"4.18.0\",  \"5.4.0\"],\n            [\"func_ptr\", \"ndo_xdp_flush\",                                       \"4.14.0\",  \"4.18.0\"],\n            [\"func_ptr\", \"ndo_get_devlink_port\",                                \"5.2.0\",   \"6.1.115\"],\n            [\"func_ptr\", \"ndo_get_devlink\",                                     \"5.1.0\",   \"5.2.0\"],\n            [\"func_ptr\", \"ndo_tunnel_ctl\",                                      \"5.8.0\",   None],\n            [\"func_ptr\", \"ndo_get_peer_dev\",                                    \"5.10.0\",  None],\n            [\"func_ptr\", \"ndo_fill_forward_path\",                               \"5.13.0\",  None],\n            [\"func_ptr\", \"ndo_get_tstamp\",                                      \"5.19.0\",  None],\n            [\"func_ptr\", \"ndo_hwtstamp_get\",                                    \"6.6.0\",   None],\n            [\"func_ptr\", \"ndo_hwtstamp_set\",                                    \"6.6.0\",   None],\n            [\"ptr\",      \"net_shaper_ops (CONFIG_NET_SHAPER=y)\",                \"6.12.0\",  None],\n        ]\n        self.members[\"net_device_ops\"] = adapt_to_kernel_version(net_device_ops)\n\n        page_ext_operations = [\n            # type       name                                       minver     maxver\n            [\"long\",     \"offset\",                                  \"4.9.0\",   None],\n            [\"long\",     \"size\",                                    \"4.9.0\",   None],\n            [\"func_ptr\", \"need\",                                    \"3.19.0\",  None],\n            [\"func_ptr\", \"init\",                                    \"3.19.0\",  None],\n            [\"bool\",     \"need_shared_flags\",                       \"6.3.0\",   None],\n        ]\n        self.members[\"page_ext_operations\"] = adapt_to_kernel_version(page_ext_operations)\n\n        ucsi_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"read_version\",                            \"6.11.0\",  None],\n            [\"func_ptr\", \"read_cci\",                                \"6.11.0\",  None],\n            [\"func_ptr\", \"poll_cci\",                                \"6.14.0\",  None],\n            [\"func_ptr\", \"read_message_in\",                         \"6.11.0\",  None],\n            [\"func_ptr\", \"sync_control\",                            \"6.11.0\",  None],\n            [\"func_ptr\", \"async_control\",                           \"6.11.0\",  None],\n            [\"func_ptr\", \"read\",                                    \"5.4.0\",   \"6.11.0\"],\n            [\"func_ptr\", \"sync_write\",                              \"5.4.0\",   \"6.11.0\"],\n            [\"func_ptr\", \"async_write\",                             \"5.4.0\",   \"6.11.0\"],\n            [\"func_ptr\", \"update_altmodes\",                         \"5.6.0\",   None],\n            [\"func_ptr\", \"update_connector\",                        \"6.10.0\",  None],\n            [\"func_ptr\", \"connector_status\",                        \"6.10.0\",  None],\n        ]\n        self.members[\"ucsi_operations\"] = adapt_to_kernel_version(ucsi_operations)\n\n        movable_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"isolate_page\",                            \"6.0.0\",   None],\n            [\"func_ptr\", \"migrate_page\",                            \"6.0.0\",   None],\n            [\"func_ptr\", \"pushback_page\",                           \"6.0.0\",   None],\n        ]\n        self.members[\"movable_operations\"] = adapt_to_kernel_version(movable_operations)\n\n        damon_operations = [\n            # type       name                                       minver     maxver\n            [\"int\",      \"id\",                                      \"5.18.0\",  None],\n            [\"func_ptr\", \"init\",                                    \"5.18.0\",  None],\n            [\"func_ptr\", \"update\",                                  \"5.18.0\",  None],\n            [\"func_ptr\", \"prepare_access_checks\",                   \"5.18.0\",  None],\n            [\"func_ptr\", \"check_accesses\",                          \"5.18.0\",  None],\n            [\"func_ptr\", \"reset_aggregated\",                        \"5.18.0\",  \"6.15.0\"],\n            [\"func_ptr\", \"get_scheme_score\",                        \"5.18.0\",  None],\n            [\"func_ptr\", \"apply_scheme\",                            \"5.18.0\",  None],\n            [\"func_ptr\", \"target_valid\",                            \"5.18.0\",  None],\n            [\"func_ptr\", \"cleanup_target\",                          \"6.17.0\",  None],\n            [\"func_ptr\", \"cleanup\",                                 \"5.18.0\",  None],\n        ]\n        self.members[\"damon_operations\"] = adapt_to_kernel_version(damon_operations)\n\n        proc_ops = [\n            # type       name                                       minver     maxver\n            [\"int\",      \"proc_flags\",                              \"5.7.0\",   None],\n            [\"func_ptr\", \"proc_open\",                               \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_read\",                               \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_read_iter\",                          \"5.10.0\",  None],\n            [\"func_ptr\", \"proc_write\",                              \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_lseek\",                              \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_release\",                            \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_poll\",                               \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_ioctl\",                              \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_compat_ioctl (CONFIG_COMPAT=y)\",     \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_mmap\",                               \"5.6.0\",   None],\n            [\"func_ptr\", \"proc_get_unmapped_area\",                  \"5.6.0\",   None],\n        ]\n        self.members[\"proc_ops\"] = adapt_to_kernel_version(proc_ops)\n\n        regulator_ops = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"list_voltage\",                            None,      None],\n            [\"func_ptr\", \"set_voltage\",                             None,      None],\n            [\"func_ptr\", \"map_voltage\",                             None,      None],\n            [\"func_ptr\", \"set_voltage_sel\",                         None,      None],\n            [\"func_ptr\", \"get_voltage\",                             None,      None],\n            [\"func_ptr\", \"get_voltage_sel\",                         None,      None],\n            [\"func_ptr\", \"set_current_limit\",                       None,      None],\n            [\"func_ptr\", \"get_current_limit\",                       None,      None],\n            [\"func_ptr\", \"set_input_current_limit\",                 \"4.2.0\",   None],\n            [\"func_ptr\", \"set_over_current_protection\",             \"4.3.0\",   None],\n            [\"func_ptr\", \"set_over_voltage_protection\",             \"5.14.0\",  None],\n            [\"func_ptr\", \"set_under_voltage_protection\",            \"5.14.0\",  None],\n            [\"func_ptr\", \"set_thermal_protection\",                  \"5.14.0\",  None],\n            [\"func_ptr\", \"set_active_discharge\",                    \"4.6.0\",   None],\n            [\"func_ptr\", \"enable\",                                  None,      None],\n            [\"func_ptr\", \"disable\",                                 None,      None],\n            [\"func_ptr\", \"is_enabled\",                              None,      None],\n            [\"func_ptr\", \"set_mode\",                                None,      None],\n            [\"func_ptr\", \"get_mode\",                                None,      None],\n            [\"func_ptr\", \"get_error_flags\",                         \"4.10.0\",  None],\n            [\"func_ptr\", \"enable_time\",                             None,      None],\n            [\"func_ptr\", \"set_ramp_delay\",                          \"3.6.0\",   None],\n            [\"func_ptr\", \"set_voltage_time\",                        \"4.9.0\",   None],\n            [\"func_ptr\", \"set_voltage_time_sel\",                    None,      None],\n            [\"func_ptr\", \"set_soft_start\",                          \"4.2.0\",   None],\n            [\"func_ptr\", \"get_status\",                              None,      None],\n            [\"func_ptr\", \"get_optimum_mode\",                        None,      None],\n            [\"func_ptr\", \"set_load\",                                \"4.1.0\",   None],\n            [\"func_ptr\", \"set_bypass\",                              \"3.7.0\",   None],\n            [\"func_ptr\", \"get_bypass\",                              \"3.7.0\",   None],\n            [\"func_ptr\", \"set_suspend_voltage\",                     None,      None],\n            [\"func_ptr\", \"set_suspend_enable\",                      None,      None],\n            [\"func_ptr\", \"set_suspend_disable\",                     None,      None],\n            [\"func_ptr\", \"set_suspend_mode\",                        None,      None],\n            [\"func_ptr\", \"resume\",                                  \"4.19.0\",  None],\n            [\"func_ptr\", \"resume_early\",                            \"4.16.0\",  \"4.19.0\"],\n            [\"func_ptr\", \"set_pull_down\",                           \"4.2.0\",   None],\n        ]\n        self.members[\"regulator_ops\"] = adapt_to_kernel_version(regulator_ops)\n\n        tty_port_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"carrier_raised\",                          \"5.15.0\",  None],\n            [\"func_ptr\", \"dtr_rts\",                                 \"5.15.0\",  None],\n            [\"func_ptr\", \"shutdown\",                                \"5.15.0\",  None],\n            [\"func_ptr\", \"activate\",                                \"5.15.0\",  None],\n            [\"func_ptr\", \"destruct\",                                \"5.15.0\",  None],\n        ]\n        self.members[\"tty_port_operations\"] = adapt_to_kernel_version(tty_port_operations)\n\n        kobj_ns_type_operations = [\n            # type       name                                       minver     maxver\n            [\"int\",      \"type\",                                    None,      None],\n            [\"func_ptr\", \"current_may_mount\",                       \"3.12.0\",  None],\n            [\"func_ptr\", \"grab_current_ns\",                         None,      None],\n            [\"func_ptr\", \"netlink_ns\",                              None,      None],\n            [\"func_ptr\", \"initial_ns\",                              None,      None],\n            [\"func_ptr\", \"drop_ns\",                                 None,      None],\n        ]\n        self.members[\"kobj_ns_type_operations\"] = adapt_to_kernel_version(kobj_ns_type_operations)\n\n        btf_kind_operations = [\n            # type       name                                       minver     maxver\n            [\"func_ptr\", \"check_meta\",                              \"4.18.0\",  None],\n            [\"func_ptr\", \"resolve\",                                 \"4.18.0\",  None],\n            [\"func_ptr\", \"check_member\",                            \"4.18.0\",  None],\n            [\"func_ptr\", \"check_kflag_member\",                      \"5.0.0\",   None],\n            [\"func_ptr\", \"log_details\",                             \"4.18.0\",  None],\n            [\"func_ptr\", \"show\",                                    \"5.10.0\",  None],\n            [\"func_ptr\", \"seq_show\",                                \"4.18.0\",  \"5.10.0\"],\n        ]\n        self.members[\"btf_kind_operations\"] = adapt_to_kernel_version(btf_kind_operations)\n\n        assert set(self.members.keys()) == set(self.types)\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        # parse version\n        if args.version:\n            r = re.search(r\"(\\d)\\.(\\d+)(?:\\.(\\d+))?\", args.version)\n            if r:\n                major, minor, patch = int(r.group(1)), int(r.group(2)), int(r.group(3) or 0)\n            else:\n                err(\"Failed to parse version string\")\n                return\n            kversion = Kernel.KernelVersion(None, args.version, major, minor, patch)\n        else:\n            self.quiet_info(\"Wait for memory scan\")\n            kversion = Kernel.kernel_version()\n            if kversion is None:\n                err(\"Could not find Linux kernel\")\n                return\n        self.quiet_info(\"Kernel version: {:d}.{:d}.{:d}\".format(kversion.major, kversion.minor, kversion.patch))\n\n        # initialize\n        if self.initialize(kversion) is False:\n            return\n\n        # get member\n        members = self.members[args.name]\n        if not members:\n            warn(\"Not defined in this version\")\n            return\n\n        # print\n        self.out = []\n        if args.address:\n            # show permission\n            if not args.quiet:\n                kinfo = Kernel.get_kernel_layout()\n                for vaddr, size, perm in kinfo.maps:\n                    if vaddr <= args.address and args.address < vaddr + size:\n                        perm_str = perm\n                        break\n                else:\n                    perm_str = \"???\"\n                self.out.append(\"Address: {:#x} Permission: {:s}\".format(args.address, perm_str))\n\n            # get name width\n            name_width = max(len(m[1]) for m in members)\n            try:\n                addrs = [read_int_from_memory(args.address + current_arch.ptrsize * i) for i in range(len(members))]\n            except gdb.MemoryError:\n                self.quiet_err(\"Memory read error\")\n                return\n\n            # legend\n            if not args.quiet:\n                fmt = \"{:5s} {:<10s} {:<{:d}s} {:s}\"\n                legend = [\"Index\", \"Type\", \"Name\", name_width, \"Value\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            # each entries\n            width = AddressUtil.get_format_address_width()\n            for idx, ((type_name, name), address) in enumerate(zip(members, addrs)):\n                if type_name == \"char*\":\n                    sym = \" {!r}\".format(read_cstring_from_memory(address))\n                else:\n                    sym = Symbol.get_symbol_string(address)\n                self.out.append(\"{:<5d} {:10s} {:{:d}s} {:#0{:d}x}{:s}\".format(\n                    idx, type_name, name, name_width, address, width, sym,\n                ))\n        else:\n            # legend\n            if not args.quiet:\n                fmt = \"{:5s} {:<10s} {:s}\"\n                legend = [\"Index\", \"Type\", \"Name\"]\n                self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            # each entries\n            for idx, (type_name, name) in enumerate(members):\n                self.out.append(\"{:<5d} {:10s} {:s}\".format(idx, type_name, name))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelSysctlCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the sysctl parameters.\"\"\"\n\n    _cmdline_ = \"ksysctl\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[], help=\"REGEXP filter.\")\n    parser.add_argument(\"-s\", \"--skip-symlink\", action=\"store_true\", help=\"do not follow symlink (net.* and user.*).\")\n    parser.add_argument(\"-e\", \"--exact\", action=\"store_true\", help=\"use exact match.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"dump zero-sized entries too.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified sysctl_table structure:\",\n        \"\",\n        \"   +-sysctl_table_root-+          +----->+-ctl_dir------+\",\n        \"   | default_set       |          |      | header       |\",\n        \"   |   ...             |          |      |   ctl_table  |---+\",\n        \"   |   dir             |          |      |   ...        |   |\",\n        \"   |     header        |          |      |   parent     |---|-->parent ctl_node\",\n        \"   |       ctl_table   |          |      |   ...        |   |\",\n        \"   |       ...         |          |      | root         |   |\",\n        \"   |       parent      |          |      |   rb_node    |---|-->ctl_node\",\n        \"   |       ...         |          |      +--------------+   |\",\n        \"   |     root          |          |                         |\",\n        \"   |       rb_node     |----+     |   +---------------------+\",\n        \"   |   ...             |    |     |   |\",\n        \"   +-------------------+    |     |   +->+-ctl_table(array)-+\",\n        \"                            |     |      | procname         |-->name[]\",\n        \"+---------------------------+     |      | data             |-->data[max_len]\",\n        \"|                                 |      | maxlen           |\",\n        \"+->+-ctl_node-----+               |      | mode             |\",\n        \"   | rb_node      |               |      | proc_handler     |\",\n        \"   |   color      |               |      +------------------+\",\n        \"   |   right      |--->ctl_node   |      | procname         |-->name[]\",\n        \"   |   left       |--->ctl_node   |      | data             |-->data[max_len]\",\n        \"   | header       |---------------+      | maxlen           |\",\n        \"   +--------------+                      | mode             |\",\n        \"                                         | proc_handler     |\",\n        \"                                         +------------------+\",\n        \"                                         | ...              |\",\n        \"                                         +------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    # Because this may be called repeatedly with different filter conditions,\n    # GEF caches the results for a short time.\n\n    @Cache.cache_until_next\n    def read_int_from_memory(self, addr):\n        return read_int_from_memory(addr)\n\n    @Cache.cache_until_next\n    def read_int8_from_memory(self, addr):\n        return read_int8_from_memory(addr)\n\n    @Cache.cache_until_next\n    def read_int32_from_memory(self, addr):\n        return read_int32_from_memory(addr)\n\n    @Cache.cache_until_next\n    def read_int64_from_memory(self, addr):\n        return read_int64_from_memory(addr)\n\n    @Cache.cache_until_next\n    def read_cstring_from_memory(self, addr):\n        return read_cstring_from_memory(addr)\n\n    @Cache.cache_until_next\n    def is_valid_addr(self, addr):\n        return is_valid_addr(addr)\n\n    def should_be_print(self, procname):\n        if self.args.filter == []:\n            return True\n\n        if self.args.exact:\n            for filt in self.args.filter:\n                if filt.pattern == procname:\n                    self.exact_found = True\n                    return True\n            return False\n\n        else:\n            for re_pattern in self.args.filter:\n                if re_pattern.search(procname):\n                    return True\n            return False\n\n    def dump_data(self, ctl_table, param_path, mode):\n        if not self.should_be_print(param_path):\n            return\n\n        maxlen = self.read_int32_from_memory(ctl_table + self.offset_maxlen)\n        # data\n        data_addr = self.read_int_from_memory(ctl_table + current_arch.ptrsize)\n        if data_addr and self.is_valid_addr(data_addr):\n            # type from handler\n            handler = self.read_int_from_memory(ctl_table + self.offset_handler)\n            # data length\n            if handler in self.str_types:\n                data_val = self.read_cstring_from_memory(data_addr)\n                self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {!r}\".format(\n                    param_path, data_addr, maxlen, mode, data_val,\n                )) # allow None\n            elif maxlen == 4:\n                data_val = self.read_int32_from_memory(data_addr)\n                self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {:#018x}\".format(\n                    param_path, data_addr, maxlen, mode, data_val,\n                ))\n            elif maxlen == 8:\n                data_val = self.read_int64_from_memory(data_addr)\n                self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {:#018x}\".format(\n                    param_path, data_addr, maxlen, mode, data_val,\n                ))\n            elif maxlen == 1:\n                data_val = self.read_int8_from_memory(data_addr)\n                self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {:#018x}\".format(\n                    param_path, data_addr, maxlen, mode, data_val,\n                ))\n            elif maxlen == 0:\n                if self.args.verbose:\n                    self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o}\".format(\n                        param_path, data_addr, maxlen, mode,\n                    ))\n            else:\n                # type from heuristic\n                data_val = self.read_cstring_from_memory(data_addr)\n                if data_val and data_val.isprintable() and len(data_val) >= 2:\n                    self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {!r}\".format(\n                        param_path, data_addr, maxlen, mode, data_val,\n                    ))\n                else:\n                    data_val = self.read_int_from_memory(data_addr)\n                    self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o} {:#018x}\".format(\n                        param_path, data_addr, maxlen, mode, data_val,\n                    ))\n        else:\n            if self.args.verbose:\n                self.out.append(\"{:<56s} {:#018x} {:#07x} {:#010o}\".format(\n                    param_path, data_addr, maxlen, mode,\n                ))\n\n        return\n\n    def redirect_root_for_symlink(self, ctl_table, pbar):\n        if self.args.skip_symlink:\n            return\n\n        ctset = None\n        root = self.read_int_from_memory(ctl_table + current_arch.ptrsize)\n        if self.is_valid_addr(root + self.offset_lookup):\n            lookup = self.read_int_from_memory(root + self.offset_lookup)\n            if lookup == Symbol.get_ksymaddr(\"net_ctl_header_lookup\"): # net.*\n                ctset = self.net_ctset\n            elif lookup == Symbol.get_ksymaddr(\"set_lookup\"): # user.*\n                ctset = self.user_ctset\n        if ctset:\n            symlink_rb_node = self.read_int_from_memory(ctset + current_arch.ptrsize + self.offset_rb_node)\n            if ctset not in self.seen_ctset:\n                self.seen_ctset.add(ctset)\n                self.sysctl_dump(symlink_rb_node, pbar)\n        return\n\n    def get_param_path(self, ctl_dir, ctl_table, parent_path):\n        procname = self.read_int_from_memory(ctl_table)\n        if procname == 0:\n            return None\n\n        procname_str = self.read_cstring_from_memory(procname)\n        if not procname_str: # None or \"\"\n            return None\n\n        param_path = (parent_path + \".\" + procname_str).lstrip(\".\")\n        self.parent_paths[ctl_dir] = param_path\n        return param_path\n\n    def sysctl_dump(self, rb_node, pbar):\n        if not rb_node:\n            return\n        if self.args.exact and self.exact_found:\n            return\n\n        if pbar is not None:\n            pbar.update(1)\n\n        # ctl_node.header (=ctl_dir)\n        ctl_dir = self.read_int_from_memory(rb_node + current_arch.ptrsize * 3)\n        if ctl_dir not in self.seen_ctl_dir:\n            self.seen_ctl_dir.add(ctl_dir)\n\n            # parent\n            parent = self.read_int_from_memory(ctl_dir + self.offset_parent)\n            parent_path = self.parent_paths.get(parent, \"\")\n\n            # ctl_table(s)\n            ctl_table = self.read_int_from_memory(ctl_dir)\n            while ctl_table not in self.seen_ctl_table:\n                self.seen_ctl_table.add(ctl_table)\n\n                # param_path\n                param_path = self.get_param_path(ctl_dir, ctl_table, parent_path)\n                if param_path is None:\n                    break\n\n                # mode\n                mode = self.read_int32_from_memory(ctl_table + self.offset_mode)\n\n                # dump\n                if (mode & 0o0120000) == 0o0120000: # symlink\n                    # `net.*` and `user.*` have a symlink attribute and they are redirected to another location.\n                    # These must be traced from another root.\n                    self.redirect_root_for_symlink(ctl_table, pbar)\n                elif (mode & 0o0040000) == 0o0040000: # directory\n                    pass\n                elif mode > 0o777:\n                    break\n                else:\n                    # If it's not a directory, it should hold data, so dump it.\n                    self.dump_data(ctl_table, param_path, mode)\n                    if self.args.exact and self.exact_found:\n                        return\n\n                # next array element\n                ctl_table += self.sizeof_ctl_table\n\n            # ctl_dir.rb_root->rb_node\n            ctl_dir_rb_node = self.read_int_from_memory(ctl_dir + self.offset_rb_node) & ~1 # remove RB_BLACK\n            self.sysctl_dump(ctl_dir_rb_node, pbar)\n\n        # ctl_node.node.rb_right\n        right = self.read_int_from_memory(rb_node + current_arch.ptrsize * 1) & ~1 # remove RB_BLACK\n        self.sysctl_dump(right, pbar)\n\n        # ctl_node.node.rb_left\n        left = self.read_int_from_memory(rb_node + current_arch.ptrsize * 2) & ~1 # remove RB_BLACK\n        self.sysctl_dump(left, pbar)\n        return\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        self.sysctl_table_root = KernelAddressHeuristicFinder.get_sysctl_table_root()\n        if self.sysctl_table_root is None:\n            self.quiet_err(\"Could not find sysctl_table_root\")\n            return False\n        self.quiet_info(\"sysctl_table_root: {:#x}\".format(self.sysctl_table_root))\n\n        \"\"\"\n        struct ctl_table_root {\n            struct ctl_table_set {\n                int (*is_seen)(struct ctl_table_set *);\n                struct ctl_dir dir;\n            } default_set;\n            struct ctl_table_set *(*lookup)(struct ctl_table_root *root);\n            void (*set_ownership)(struct ctl_table_header *head, struct ctl_table *table, kuid_t *uid, kgid_t *gid);\n            int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);\n        };\n\n        struct ctl_dir {\n            struct ctl_table_header {\n                union {\n                    struct {\n                        struct ctl_table *ctl_table;\n                        int ctl_table_size;               // v6.6~\n                        int used;\n                        int count;\n                        int nreg;\n                    };\n                    struct rcu_head {\n                        struct callback_head *next;\n                        void (*func)(struct callback_head *head);\n                    } rcu;\n                };\n                struct completion *unregistering;\n                struct ctl_table *ctl_table_arg;\n                struct ctl_table_root *root;\n                struct ctl_table_set *set;\n                struct ctl_dir *parent;\n                struct ctl_node *node;\n                struct hlist_head inodes;                 // v4.12.2~\n                struct list_head inodes;                  // v4.11~v4.12.1\n                struct hlist_head inodes;                 // v4.9.120~v4.9.337\n                enum {\n                    SYSCTL_TABLE_TYPE_DEFAULT,\n                    SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY,\n                } type;                                   // v6.10~\n            } header;\n            struct rb_root {\n                struct rb_node *rb_node;\n            } root;\n        };\n\n        struct ctl_node {\n            struct rb_node {\n                unsigned long  __rb_parent_color;\n                struct rb_node *rb_right;\n                struct rb_node *rb_left;\n            } node;\n            struct ctl_table_header *header;\n        };\n\n        struct ctl_table {\n            const char *procname;\n            void *data;\n            int maxlen;\n            umode_t mode;\n            struct ctl_table *child;                      // ~v6.4\n            enum {\n                SYSCTL_TABLE_TYPE_DEFAULT,\n                SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY\n            } type;                                       // v6.5~v6.10\n            proc_handler *proc_handler;\n            struct ctl_table_poll *poll;\n            void *extra1;\n            void *extra2;\n        };\n        \"\"\"\n\n        kversion = Kernel.kernel_version()\n\n        if is_64bit():\n            # struct ctl_dir\n            if kversion < \"4.9.120\":\n                self.offset_rb_node = 0x48\n            elif \"4.9.120\" <= kversion < \"4.10\":\n                self.offset_rb_node = 0x50\n            elif \"4.10\" <= kversion < \"4.11\":\n                self.offset_rb_node = 0x48\n            elif \"4.11\" <= kversion < \"4.12.2\":\n                self.offset_rb_node = 0x58\n            elif \"4.12.2\" <= kversion < \"6.10\":\n                self.offset_rb_node = 0x50\n            elif \"6.10\" <= kversion:\n                self.offset_rb_node = 0x58\n            self.offset_parent = 0x38\n            # struct ctl_table\n            self.offset_maxlen = 0x10\n            self.offset_mode = 0x14\n            if kversion < \"6.10\":\n                self.offset_handler = 0x20\n                self.sizeof_ctl_table = 0x40\n            else:\n                self.offset_handler = 0x18\n                self.sizeof_ctl_table = 0x38\n        else:\n            # struct ctl_dir\n            if kversion < \"4.9.120\":\n                self.offset_rb_node = 0x28\n                self.offset_parent = 0x20\n            elif \"4.9.120\" <= kversion < \"4.10\":\n                self.offset_rb_node = 0x2c\n                self.offset_parent = 0x20\n            elif \"4.10\" <= kversion < \"4.11\":\n                self.offset_rb_node = 0x28\n                self.offset_parent = 0x20\n            elif \"4.11\" <= kversion < \"4.12.2\":\n                self.offset_rb_node = 0x30\n                self.offset_parent = 0x20\n            elif \"4.12.2\" <= kversion < \"6.6\":\n                self.offset_rb_node = 0x2c\n                self.offset_parent = 0x20\n            elif \"6.6\" <= kversion < \"6.10\":\n                self.offset_rb_node = 0x30\n                self.offset_parent = 0x24\n            elif \"6.10\" <= kversion:\n                self.offset_rb_node = 0x34\n                self.offset_parent = 0x24\n            # struct ctl_table\n            self.offset_maxlen = 0x8\n            self.offset_mode = 0xc\n            if kversion < \"6.10\":\n                self.offset_handler = 0x14\n                self.sizeof_ctl_table = 0x24\n            else:\n                self.offset_handler = 0x10\n                self.sizeof_ctl_table = 0x20\n\n        # struct ctl_table_root\n        self.offset_lookup = current_arch.ptrsize + self.offset_rb_node + current_arch.ptrsize\n\n        # the root for `net.*`; init_nsproxy.net_ns.sysctls\n        self.net_ctset = None\n        init_net = KernelAddressHeuristicFinder.get_init_net()\n        if init_net:\n            current = init_net\n            is_seen = Symbol.get_ksymaddr(\"is_seen\")\n            if is_seen:\n                while True:\n                    v = self.read_int_from_memory(current)\n                    if v == is_seen:\n                        self.net_ctset = current\n                        break\n                    current += current_arch.ptrsize\n\n        # the root for `user.*`; init_user_ns.set\n        self.user_ctset = None\n        init_user_ns = KernelAddressHeuristicFinder.get_init_user_ns()\n        if init_user_ns:\n            current = init_user_ns\n            # set_is_seen is found in 3 places (v5.19~), so Symbol.get_ksymaddr should not be used.\n            set_is_seen = Symbol.get_ksymaddr_multiple(\"set_is_seen\")\n            if set_is_seen:\n                while True:\n                    v = self.read_int_from_memory(current)\n                    if v in set_is_seen:\n                        self.user_ctset = current\n                        break\n                    current += current_arch.ptrsize\n\n        # handle functions\n        known_str_types_handlers = [\n            \"addrconf_sysctl_stable_secret\",\n            \"cdrom_sysctl_info\",\n            \"devkmsg_sysctl_set_loglvl\",\n            \"numa_zonelist_order_handler\",\n            \"proc_allowed_congestion_control\",\n            \"proc_do_uts_string\",\n            \"proc_dostring\",\n            \"proc_dostring_coredump\",\n            \"proc_tcp_available_congestion_control\",\n            \"proc_tcp_available_ulp\",\n            \"seccomp_actions_logged_handler\",\n            \"set_default_qdisc\",\n        ]\n        self.str_types = []\n        for handler in known_str_types_handlers:\n            handler_addr = Symbol.get_ksymaddr(handler)\n            if handler_addr:\n                self.str_types.append(handler_addr)\n\n        self.root_ctl_dir = self.sysctl_table_root + current_arch.ptrsize\n        self.root_rb_node = self.read_int_from_memory(self.root_ctl_dir + self.offset_rb_node)\n        self.quiet_info(\"root_ctl_dir: {:#x}\".format(self.root_ctl_dir))\n        self.quiet_info(\"root_rb_node: {:#x}\".format(self.root_rb_node))\n\n        self.initialized = True\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.exact_found = False\n\n        if args.exact and not args.filter:\n            self.quiet_err(\"Filter string is needed\")\n            return\n\n        if args.rescan:\n            self.initialized = False\n            Cache.reset_gef_caches(all=True)\n\n        self.quiet_info(\"Wait for memory scan\")\n\n        if not self.initialize():\n            return\n\n        # legend\n        self.out = []\n        if not args.quiet:\n            fmt = \"{:<56s} {:<18s} {:<7s} {:<10s} {:<s}\"\n            legend = [\"ParamName\", \"ParamAddress\", \"MaxLen\", \"Mode\", \"ParamValue\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # progress setup\n        pbar = None\n        if not args.quiet:\n            try:\n                from tqdm import tqdm\n                pbar = tqdm(total=None, leave=False)\n            except ImportError:\n                pass\n\n        # parse rb_tree\n        self.seen_ctl_dir = set()\n        self.seen_ctl_table = set()\n        self.seen_ctset = set()\n        self.parent_paths = {self.root_ctl_dir: \"\"}\n        try:\n            # This try-except is a countermeasure to a parse error when CONFIG_RANDSTRUCT=y.\n            self.sysctl_dump(self.root_rb_node, pbar)\n        except gdb.MemoryError:\n            self.quiet_err(\"Memory read error\")\n            return\n        finally:\n            if pbar is not None:\n                pbar.close()\n\n        # print\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelFileSystemsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump filesystems.\"\"\"\n\n    _cmdline_ = \"kfilesystems\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n    _aliases_ = [\"kmounts\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-s\", \"--skip-mount-path\", action=\"store_true\", help=\"skip resolving path.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified file_systems structure:\",\n        \"\",\n        \"                  +-->+-file_system_type-+  +-->+-file_system_type-+  +-->...\",\n        \"                  |   | name             |  |   | name             |  |\",\n        \"+--------------+  |   | ...              |  |   | ...              |  |\",\n        \"| file_systems |--+   | next             |--+   | next             |--+\",\n        \"+--------------+      | fs_supers        |--+   | fs_supers        |\",\n        \"                      | ...              |  |   | ...              |\",\n        \"                      +------------------+  |   +------------------+\",\n        \"                                            |\",\n        \"   +----------------------------------------+\",\n        \"   |\",\n        \"   |   +-super_block-+   +-super_block-+             +-mount--------+\",\n        \"   |   | s_list      |   | s_list      |             | ...          |\",\n        \"   |   | ...         |   | ...         |             | mnt          |\",\n        \"   |   | s_mounts    |   | s_mounts    |---------+   |   mnt_root   |\",\n        \"   |   | ...         |   | ...         |         |   |   ...        |\",\n        \"   +-->| s_instances |-->| s_instances |-->...   |   | ...          |\",\n        \"       | ...         |   | ...         |         +-->| mnt_instance |\",\n        \"       +-------------+   +-------------+             | ...          |\",\n        \"                                                     +--------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # file_systems\n        self.file_systems = KernelAddressHeuristicFinder.get_file_systems()\n        if self.file_systems is None:\n            self.quiet_err(\"Could not find file_systems\")\n            return\n        self.quiet_info(\"file_systems: {:#x}\".format(self.file_systems))\n\n        \"\"\"\n        struct file_system_type {\n            const char *name;\n            int fs_flags;\n            int (*init_fs_context)(struct fs_context *); // v5.1~\n            const struct fs_parameter_spec *parameters; // v5.1~\n            struct dentry *(*mount) (struct file_system_type *, int, const char *, void *);\n            void (*kill_sb) (struct super_block *);\n            struct module *owner;\n            struct file_system_type * next;\n            struct hlist_head fs_supers;\n            struct lock_class_key s_lock_key;\n            struct lock_class_key s_umount_key;\n            struct lock_class_key s_vfs_rename_key;\n            struct lock_class_key s_writers_key[SB_FREEZE_LEVELS]; // v3.6~\n            struct lock_class_key i_lock_key;\n            struct lock_class_key i_mutex_key;\n            struct lock_class_key invalidate_lock_key; // v5.15~\n            struct lock_class_key i_mutex_dir_key;\n            struct lock_class_key i_alloc_sem_key; // ~v3.0\n        };\n        \"\"\"\n        # file_system_type->name\n        self.offset_name = 0\n        self.quiet_info(\"offsetof(file_system_type, name): {:#x}\".format(self.offset_name))\n\n        # file_system_type->next\n        for i in range(10):\n            offset_next = current_arch.ptrsize * i\n            valid = True\n            current = read_int_from_memory(self.file_systems)\n            seen = []\n            while current != 0:\n                if not is_valid_addr(current):\n                    valid = False\n                    break\n                seen.append(current)\n                name_addr = read_int_from_memory(current)\n                if not is_valid_addr(name_addr):\n                    valid = False\n                    break\n                name = read_cstring_from_memory(name_addr)\n                if len(name) == 0:\n                    valid = False\n                    break\n                current = read_int_from_memory(current + offset_next)\n                if current in seen:\n                    valid = False\n                    break\n\n            if len(seen) == 1:\n                valid = False\n\n            if valid:\n                self.offset_next = offset_next\n                break\n        else:\n            self.quiet_err(\"Could not find file_system_type->next\")\n            return False\n        self.quiet_info(\"offsetof(file_system_type, next): {:#x}\".format(self.offset_next))\n\n        self.offset_fs_supers = self.offset_next + current_arch.ptrsize\n        self.quiet_info(\"offsetof(file_system_type, fs_supers): {:#x}\".format(self.offset_fs_supers))\n\n        \"\"\"\n        struct super_block {\n            struct list_head s_list;\n            dev_t s_dev; // u32\n            unsigned char s_dirt; // ~v3.5\n            unsigned char s_blocksize_bits;\n            unsigned long s_blocksize;\n            ...\n            struct hlist_node s_instances;  <-- fs_supers points here\n            ...\n        } __randomize_layout;\n        \"\"\"\n        # super_block->s_dev\n        self.offset_s_dev = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(super_block, s_dev): {:#x}\".format(self.offset_s_dev))\n\n        # super_block->s_instances\n        current = read_int_from_memory(self.file_systems)\n        while True:\n            if current == 0:\n                self.quiet_err(\"Could not find file_systems who has valid fs_supers\")\n                return False\n            fs_supers = read_int_from_memory(current + self.offset_fs_supers)\n            if is_valid_addr(fs_supers):\n                break\n            current = read_int_from_memory(current + self.offset_next)\n\n        for i in range(1, 100):\n            offset_base = current_arch.ptrsize * i\n            \"\"\"\n            0xffff8cb085375800|+0x0000|+000: 0xffff8cb085373000  -> // s_list.next\n            0xffff8cb085375808|+0x0008|+001: 0xffff8cb088b77000  -> // s_list.prev\n            0xffff8cb085375810|+0x0010|+002: 0x0000000c00000021 // s_blocksize_bits, s_dev\n            0xffff8cb085375818|+0x0018|+003: 0x0000000000001000 // s_blocksize\n            0xffff8cb085375820|+0x0020|+004: 0x7fffffffffffffff\n            0xffff8cb085375828|+0x0028|+005: 0xffffffff8c33f260 <shmem_fs_type>\n            0xffff8cb085375830|+0x0030|+006: 0xffffffff8ba36da0 <shmem_ops>\n            \"\"\"\n            # check s_list\n            if not is_double_link_list(fs_supers - offset_base):\n                continue\n\n            # check s_blocksize\n            x = read_int_from_memory(fs_supers - offset_base + current_arch.ptrsize * 2 + 4 * 2)\n            if x == 0x1000:\n                self.offset_s_instances = offset_base\n                break\n        else:\n            self.quiet_err(\"Could not find super_block->s_instances\")\n            return False\n        self.quiet_info(\"offsetof(super_block, s_instances): {:#x}\".format(self.offset_s_instances))\n\n        \"\"\"\n        struct super_block { // ~v3.11\n            ...\n            struct list_head s_mounts; // v3.3~ <-- double link list\n            struct list_head s_dentry_lru;      <-- double link list\n            int s_nr_dentry_unused;\n            spinlock_t s_inode_lru_lock ____cacheline_aligned_in_smp;\n            struct list_head s_inode_lru;       <-- double link list\n            int s_nr_inodes_unused;\n            struct block_device *s_bdev;\n            struct backing_dev_info *s_bdi;\n            struct mtd_info *s_mtd;\n            struct hlist_node s_instances;  <-- fs_supers points here\n            ...\n        };\n\n        struct super_block { // v3.12~\n            ...\n            struct list_head s_mounts; // v3.12~v6.17\n            struct mount *s_mounts; // v6.18~\n            struct block_device *s_bdev;\n            struct bdev_handle *s_bdev_handle; // v6.6.47~v6.8\n            struct file *s_bdev_file; // v6.9~\n            struct backing_dev_info *s_bdi;\n            struct mtd_info *s_mtd;\n            struct hlist_node s_instances;  <-- fs_supers points here\n            ...\n        }; // ~v4.12\n        } __randomize_layout; // v4.13~\n        \"\"\"\n        # super_block->s_mounts\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.12\":\n            current = fs_supers - current_arch.ptrsize * 2\n            double_link_list_count = 0\n            while True:\n                if is_double_link_list(current):\n                    double_link_list_count += 1\n                if double_link_list_count == 3:\n                    difference = fs_supers - current\n                    self.offset_s_mounts = self.offset_s_instances - difference\n                    break\n                current -= current_arch.ptrsize\n        elif kversion < \"6.6.47\":\n            self.offset_s_mounts = self.offset_s_instances - current_arch.ptrsize * 5\n        elif kversion < \"6.18\":\n            self.offset_s_mounts = self.offset_s_instances - current_arch.ptrsize * 6\n        else:\n            self.offset_s_mounts = self.offset_s_instances - current_arch.ptrsize * 5\n        self.quiet_info(\"offsetof(super_block, s_mounts): {:#x}\".format(self.offset_s_mounts))\n\n        \"\"\"\n        struct mount { // <-- s_mounts points here (v6.18~)\n            struct hlist_node mnt_hash; // v3.13~ // ptrsize * 2\n            struct list_node mnt_hash; // ~v3.12 // ptrsize * 2\n            struct mount *mnt_parent;\n            struct dentry *mnt_mountpoint;\n            struct vfsmount {\n                struct dentry *mnt_root;\n                struct super_block *mnt_sb;\n                int mnt_flags;\n                struct user_namespace *mnt_userns; // v5.12~v6.1\n                struct mnt_idmap *mnt_idmap; // v6.2~\n            } mnt;\n            union {\n                struct rb_node mnt_node; // v6.12~ // ptrsize * 3\n                struct rcu_head mnt_rcu; // v3.13~ // ptrsize * 2\n                struct llist_node mnt_llist; // v3.18~ // ptrsize\n            };\n        #ifdef CONFIG_SMP\n            struct mnt_pcp __percpu *mnt_pcp;\n        #else\n            int mnt_count;\n            int mnt_writers;\n        #endif\n            struct list_head mnt_mounts;\n            struct list_head mnt_child;\n            struct list_head mnt_instance; // ~v6.17 // <-- s_mounts points here (~v6.17)\n            const char *mnt_devname;\n            ...\n        } __randomize_layout;\n        \"\"\"\n        # mount->mnt_instance\n        if kversion < \"6.18\":\n            common1 = current_arch.ptrsize * 4 # mnt_hash ~ mnt_mount_point\n            if kversion < \"5.12\":\n                sizeof_vfsmount = current_arch.ptrsize * 3\n            else:\n                sizeof_vfsmount = current_arch.ptrsize * 4\n            if kversion < \"3.13\":\n                sizeof_union = 0\n            elif kversion < \"6.12\":\n                sizeof_union = current_arch.ptrsize * 2\n            else:\n                sizeof_union = current_arch.ptrsize * 3\n            sizeof_ifdef = current_arch.ptrsize # for x86/x64/ARM/ARM64, CONFIG_SMP is 'y' in almost all cases\n            common2 = current_arch.ptrsize * 4 # mnt_mounts ~ mnt_child\n            self.offset_mount_mnt_instance = common1 + sizeof_vfsmount + sizeof_union + sizeof_ifdef + common2\n        else:\n            self.offset_mount_mnt_instance = 0\n\n        # mount->{mnt_parent,mnt_mountpoint,mnt}\n        self.offset_mount_mnt_parent = current_arch.ptrsize * 2\n        self.offset_mount_mnt_mountpoint = current_arch.ptrsize * 3\n        self.offset_mount_mnt = current_arch.ptrsize * 4\n\n        # vfsmount->mnt_root\n        self.offset_vfsmount_mnt_root = 0\n\n        self.initialized = True\n        return True\n\n    def get_fst_name(self, fst):\n        name_addr = read_int_from_memory(fst + self.offset_name)\n        name = read_cstring_from_memory(name_addr)\n        return name\n\n    def get_dev_num(self, dev):\n        major = dev >> 20\n        minor = dev & ((1 << 20) - 1)\n        name = KernelBlockDevicesCommand.get_bdev_name(major, minor)\n        return major, minor, name\n\n    def get_offset_d_iname(self, dentry):\n        if hasattr(self, \"offset_d_iname\") and self.offset_d_iname is not None:\n            return self.offset_d_iname\n\n        \"\"\"\n        struct dentry {\n            unsigned int d_flags;\n            seqcount_spinlock_t d_seq;\n            struct hlist_bl_node d_hash;\n            struct dentry *d_parent;\n            struct qstr {\n                union {\n                    struct {\n                        HASH_LEN_DECLARE;\n                    };\n                    u64 hash_len;\n                };\n                const unsigned char *name; // this points d_iname\n            } d_name;\n            struct inode *d_inode;\n            unsigned char d_iname[DNAME_INLINE_LEN];\n            ...\n        };\n        \"\"\"\n        current = dentry\n        while True:\n            name = read_int_from_memory(current)\n            if 0 < name - current <= 0x20:\n                offset_d_iname = name - dentry\n                break\n            current += current_arch.ptrsize\n\n        self.offset_d_iname = offset_d_iname\n        return offset_d_iname\n\n    def get_offset_d_parent(self, dentry, offset_d_iname):\n        if hasattr(self, \"offset_d_parent\") and self.offset_d_parent is not None:\n            return self.offset_d_parent\n\n        offset_dname_name = offset_d_iname - current_arch.ptrsize * 2\n        if read_int_from_memory(dentry + offset_dname_name) == 0: # skip if padding\n            offset_dname_name -= current_arch.ptrsize\n        offset_d_parent = offset_dname_name - 0x8 - current_arch.ptrsize\n        if read_int_from_memory(dentry + offset_d_parent) == 0: # skip if padding\n            offset_d_parent -= current_arch.ptrsize\n\n        self.offset_d_parent = offset_d_parent\n        return offset_d_parent\n\n    def get_mount(self, mnt_instance):\n        mount = mnt_instance - self.offset_mount_mnt_instance\n        return mount\n\n    def get_mount_point(self, mnt_instance):\n        mount = self.get_mount(mnt_instance)\n        vfsmnt = mount + self.offset_mount_mnt\n        dentry = read_int_from_memory(vfsmnt + self.offset_vfsmount_mnt_root)\n\n        if not is_valid_addr(dentry):\n            return None\n        offset_d_iname = self.get_offset_d_iname(dentry)\n        offset_d_parent = self.get_offset_d_parent(dentry, offset_d_iname)\n\n        def is_root(dentry):\n            return dentry == read_int_from_memory(dentry + offset_d_parent)\n\n        filepath = []\n        switched = False\n        while True:\n            if not is_valid_addr(vfsmnt):\n                return None\n            if not is_valid_addr(dentry):\n                return None\n\n            mnt_root = read_int_from_memory(vfsmnt + self.offset_vfsmount_mnt_root)\n            if dentry == mnt_root or is_root(dentry):\n                parent = read_int_from_memory(mount + self.offset_mount_mnt_parent)\n\n                # Global root?\n                if mount != parent:\n                    dentry = read_int_from_memory(mount + self.offset_mount_mnt_mountpoint)\n                    mount = parent\n                    vfsmnt = mount + self.offset_mount_mnt\n                    switched = True\n                    continue\n\n                name = read_cstring_from_memory(dentry + offset_d_iname)\n                if name is None:\n                    name_ptr = read_int_from_memory(dentry + offset_d_iname - current_arch.ptrsize * 2)\n                    name = read_cstring_from_memory(name_ptr)\n                filepath.append(name)\n                break\n\n            name = read_cstring_from_memory(dentry + offset_d_iname)\n            if name is None:\n                name_ptr = read_int_from_memory(dentry + offset_d_iname - current_arch.ptrsize * 2)\n                name = read_cstring_from_memory(name_ptr)\n            filepath.append(name)\n\n            parent = read_int_from_memory(dentry + offset_d_parent)\n            dentry = parent\n\n        filepath = os.path.join(*filepath[::-1])\n\n        # The reason is unclear, but this works.\n        if switched is False and filepath == \"/\":\n            next_mnt_instance = read_int_from_memory(mnt_instance)\n            if next_mnt_instance:\n                ret = self.get_mount_point(next_mnt_instance)\n                if ret:\n                    return ret\n            return \"-\", \"-\"\n\n        mount = self.get_mount(mnt_instance)\n        return mount, filepath\n\n    def get_dev_name(self, mnt_instance):\n        offset_mount_mnt_instance = current_arch.ptrsize * 14\n        offset_mount_mnt_devname = current_arch.ptrsize * 16\n\n        mnt = mnt_instance - offset_mount_mnt_instance\n        devname_p = read_int_from_memory(mnt + offset_mount_mnt_devname)\n        devname = read_cstring_from_memory(devname_p)\n        return devname\n\n    def parse_super_block(self, fst, super_block):\n        # name\n        name = self.get_fst_name(fst)\n\n        # dev\n        dev = read_int32_from_memory(super_block + self.offset_s_dev)\n        major, minor, devname = self.get_dev_num(dev)\n\n        # mount\n        s_mounts = read_int_from_memory(super_block + self.offset_s_mounts)\n        mount = self.get_mount(s_mounts)\n\n        # mount points\n        if self.args.skip_mount_path:\n            parsed_mount, mount_point = \"-\", \"???\"\n        else:\n            ret = self.get_mount_point(s_mounts)\n            if ret is None:\n                parsed_mount, mount_point = \"-\", \"???\"\n            else:\n                parsed_mount, mount_point = ret\n                if isinstance(parsed_mount, int):\n                    parsed_mount = \"{:#018x}\".format(parsed_mount)\n\n        # devname\n        if devname == \"???\":\n            devname = self.get_dev_name(s_mounts)\n        else:\n            devname += \" (guessed)\"\n\n        # dump\n        self.out.append(\"{:#018x} {:12s} {:#018x} {:20s} {:<6d} {:<6d} {:#018x} {:18s} {:s}\".format(\n            fst, name, super_block, devname, major, minor, mount, parsed_mount, mount_point,\n        ))\n        return\n\n    def parse_file_system_type(self, fst):\n        # fs_supers\n        fs_supers = read_int_from_memory(fst + self.offset_fs_supers)\n\n        if fs_supers == 0:\n            # fast return\n            name = self.get_fst_name(fst)\n            self.out.append(\"{:#018x} {:12s} {:18s} {:20s} {:6s} {:6s} {:18s} {:18s} {:s}\".format(\n                fst, name, \"-\", \"-\", \"-\", \"-\", \"-\", \"-\", \"-\",\n            ))\n            return\n\n        s_instances = fs_supers\n\n        # parse more\n        while s_instances:\n            super_block = s_instances - self.offset_s_instances\n            # parse super_block\n            self.parse_super_block(fst, super_block)\n            # go to next\n            s_instances = read_int_from_memory(s_instances)\n        return\n\n    def parse_file_systems(self):\n        if not self.args.quiet:\n            fmt = \"{:18s} {:12s} {:18s} {:20s} {:6s} {:6s} {:18s} {:18s} {:s}\"\n            legend = [\n                \"file_system_type\", \"fsname\", \"super_block\", \"devname\", \"major\", \"minor\",\n                \"s_mount\", \"(parsed) mount\", \"mount_point\",\n            ]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        fst = read_int_from_memory(self.file_systems)\n        while fst != 0:\n            # parse file_system_type\n            self.parse_file_system_type(fst)\n            # go to next\n            fst = read_int_from_memory(fst + self.offset_next)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"3.3\":\n            err(\"Unsupported before v3.3\")\n            return\n\n        if not self.initialize():\n            return\n\n        self.out = []\n        self.parse_file_systems()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelClockSourceCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the clocksource list.\"\"\"\n\n    _cmdline_ = \"kclock-source\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified clocksource structure:\",\n        \"\",\n        \"                        +-clocksource-+\",\n        \"                        | read        |\",\n        \"+-clocksource_list-+    | ...         |\",\n        \"| list_head        |--->| list        |--->...\",\n        \"+------------------+    | ...         |\",\n        \"                        +-------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_offset_list(self, clocksource):\n        \"\"\"\n        struct clocksource {\n            u64 (*read)(struct clocksource *cs);\n            u64 mask;\n            u32 mult;\n            u32 shift;\n            u64 max_idle_ns;\n            u32 maxadj;\n            u32 uncertainty_margin;\n        #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA\n            struct arch_clocksource_data archdata;\n        #endif\n            u64 max_cycles;\n            const char *name;\n            struct list_head list;\n            int rating;\n            enum clocksource_ids id;\n            enum vdso_clock_mode vdso_clock_mode;\n            unsigned long flags;\n            int (*enable)(struct clocksource *cs);\n            void (*disable)(struct clocksource *cs);\n            void (*suspend)(struct clocksource *cs);\n            void (*resume)(struct clocksource *cs);\n            void (*mark_unstable)(struct clocksource *cs);\n            void (*tick_stable)(struct clocksource *cs);\n        #ifdef CONFIG_CLOCKSOURCE_WATCHDOG\n            struct list_head wd_list;\n            u64 cs_last;\n            u64 wd_last;\n        #endif\n            struct module *owner;\n        };\n        \"\"\"\n        current = read_int_from_memory(clocksource)\n        for i in range(7, 20):\n            candidate_offset = i * current_arch.ptrsize\n            v = read_int_from_memory(current - candidate_offset)\n            if is_valid_addr(v):\n                return candidate_offset\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        clocksource_list = KernelAddressHeuristicFinder.get_clocksource_list()\n        if clocksource_list is None:\n            self.quiet_err(\"Could not find clocksource_list\")\n            return\n        self.quiet_info(\"clocksource_list: {:#x}\".format(clocksource_list))\n\n        offset_list = self.get_offset_list(clocksource_list)\n        if offset_list is None:\n            return\n        self.quiet_info(\"offsetof(clocksource, list): {:#x}\".format(offset_list))\n\n        self.out = []\n        width = AddressUtil.get_format_address_width()\n        if not args.quiet:\n            fmt = \"{:<{:d}s} {:20s} {:<{:d}s} {:<{:d}s}\"\n            legend = [\"address\", width, \"name\", \"read\", width, \"symbol\", width]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        current = read_int_from_memory(clocksource_list)\n        while current != clocksource_list:\n            cs = current - offset_list\n            read = read_int_from_memory(cs)\n            read_sym = Symbol.get_symbol_string(read, nosymbol_string=\" <NO_SYMBOL>\")\n            name_addr = read_int_from_memory(current - current_arch.ptrsize)\n            name = read_cstring_from_memory(name_addr)\n            self.out.append(\"{:#0{:d}x} {:20s} {:#0{:d}x}{:s}\".format(cs, width, name, read, width, read_sym))\n            current = read_int_from_memory(current)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelTimerCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the timer.\"\"\"\n\n    _cmdline_ = \"ktimer\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified timer structure (per-cpu):\",\n        \"\",\n        \"+-timer_bases[0]----+    +-timer_list--+    +-timer_list--+\",\n        \"| ...               |    | entry       |    | entry       |\",\n        \"| vectors[0]        |--->|   next      |--->|   next      |--->...\",\n        \"| ...               |    |   pprev     |    |   pprev     |\",\n        \"| vectors[512or576] |    | expires     |    | expires     |\",\n        \"| ...               |    | function    |    | function    |\",\n        \"+-timer_bases[1]----+    | ...         |    | ...         |\",\n        \"| ...               |    +-------------+    +-------------+\",\n        \"| vectors[0]        |\",\n        \"| ...               |\",\n        \"| vectors[512or576] |\",\n        \"| ...               |\",\n        \"+-------------------+\",\n        \"\",\n        \"Simplified hrtimer structure (per-cpu):\",\n        \"\",\n        \"+-hrtimer_cpu_bases-+\",\n        \"| ...               |\",\n        \"| clock_bases[0]    |   +--->+-hrtimer------+\",\n        \"|   ...             |   |    | node         |\",\n        \"|   clockid         |   |    |   node       |\",\n        \"|   ...             |   |    |     color    |\",\n        \"|   active          |   |    |     right    |--->hrtimer\",\n        \"|      rb_root      |   |    |     left     |--->hrtimer\",\n        \"|        rb_root    |---+    |   expires    |\",\n        \"|        ...        |        | ...          |\",\n        \"|   get_time        |        | function     |\",\n        \"|   ...             |        | ...          |\",\n        \"| ...               |        +--------------+\",\n        \"| clock_bases[8]    |\",\n        \"|   ...             |\",\n        \"+-------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # resolve __per_cpu_offset\n        __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n        if __per_cpu_offset is None:\n            self.quiet_info(\"__per_cpu_offset: Not found\")\n            self.cpu_offset = []\n        else:\n            self.quiet_info(\"__per_cpu_offset: {:#x}\".format(__per_cpu_offset))\n            self.cpu_offset = KernelCurrentCommand.get_each_cpu_offset(__per_cpu_offset)\n\n        ### classic timer (unit: tick)\n\n        # timer_bases\n        self.timer_bases = KernelAddressHeuristicFinder.get_timer_bases()\n        if not self.timer_bases:\n            self.quiet_err(\"timer_bases: Not found\")\n            return False\n        self.quiet_info(\"timer_bases: {:#x}\".format(self.timer_bases))\n\n        # per_cpu_timer_bases\n        if self.cpu_offset == []:\n            self.per_cpu_timer_bases = [self.timer_bases]\n        else:\n            self.per_cpu_timer_bases = [AddressUtil.align_address(x + self.timer_bases) for x in self.cpu_offset]\n\n        # len(timer_bases)\n        if Symbol.get_ksymaddr(\"sysctl_timer_migration\"):\n            self.nr_bases = 2\n        else:\n            self.nr_bases = 1\n        self.quiet_info(\"nr_bases: {:d}\".format(self.nr_bases))\n\n        # sizeof(struct timer_base)\n        \"\"\"\n        struct timer_base {\n            raw_spinlock_t lock;\n            struct timer_list *running_timer;\n        #ifdef CONFIG_PREEMPT_RT\n            spinlock_t expiry_lock;\n            atomic_t timer_waiters;\n        #endif\n            unsigned long clk;\n            unsigned long next_expiry;\n            unsigned int cpu;\n            bool next_expiry_recalc;\n            bool is_idle;\n            bool timers_pending;\n            DECLARE_BITMAP(pending_map, WHEEL_SIZE);\n            struct hlist_head vectors[WHEEL_SIZE];\n        } ____cacheline_aligned;\n        \"\"\"\n        self.roughly_sizeof_timer_base = 0\n        if self.nr_bases == 2:\n            timer_base = self.per_cpu_timer_bases[0]\n\n            i = 512\n            while True:\n                v = read_int_from_memory(timer_base + current_arch.ptrsize * i)\n                if v != 0 and not is_valid_addr(v):\n                    self.roughly_sizeof_timer_base = current_arch.ptrsize * i\n                    break\n                i += 1\n\n        # jiffies\n        self.jiffies = KernelAddressHeuristicFinder.get_jiffies()\n        if not self.jiffies:\n            self.quiet_err(\"jiffies: Not found\")\n            return False\n        self.quiet_info(\"jiffies: {:#x}\".format(self.jiffies))\n\n        ### High-resolution kernel timer (unit: nano seconds)\n\n        # hrtimer_bases\n        self.hrtimer_bases = KernelAddressHeuristicFinder.get_hrtimer_bases()\n        if not self.hrtimer_bases:\n            self.quiet_err(\"hrtimer_bases: Not found\")\n            return False\n        self.quiet_info(\"hrtimer_bases: {:#x}\".format(self.hrtimer_bases))\n\n        # per_cpu_hrtimer_bases\n        if self.cpu_offset == []:\n            self.per_cpu_hrtimer_cpu_bases = [self.hrtimer_bases]\n        else:\n            self.per_cpu_hrtimer_cpu_bases = [AddressUtil.align_address(x + self.hrtimer_bases) for x in self.cpu_offset]\n\n        \"\"\"\n        struct hrtimer_cpu_base {\n            raw_spinlock_t lock;\n            unsigned int cpu;\n            unsigned int active_bases;\n            unsigned int clock_was_set_seq;\n            unsigned int hres_active : 1,\n                         in_hrtirq : 1,\n                         hang_detected : 1,\n                         softirq_activated : 1;\n        #ifdef CONFIG_HIGH_RES_TIMERS\n            unsigned int nr_events;\n            unsigned short nr_retries;\n            unsigned short nr_hangs;\n            unsigned int max_hang_time;\n        #endif\n        #ifdef CONFIG_PREEMPT_RT\n            spinlock_t softirq_expiry_lock;\n            atomic_t timer_waiters;\n        #endif\n            ktime_t expires_next;\n            struct hrtimer *next_timer;\n            ktime_t softirq_expires_next;\n            struct hrtimer *softirq_next_timer;\n            struct hrtimer_clock_base {\n                struct hrtimer_cpu_base *cpu_base;\n                unsigned int index;\n                clockid_t clockid;\n                seqcount_raw_spinlock_t seq; // v4.16~\n                struct hrtimer *running; // v4.16~\n                struct timerqueue_head {\n                    struct rb_root_cached {          // v5.4~\n                        struct rb_root rb_root;      // v5.4~\n                        struct rb_node *rb_leftmost; // v5.4~\n                    } rb_root;                       // v5.4~\n                    struct rb_root head;             // ~v5.3\n                    struct timerqueue_node *next;    // ~v5.3\n                } active;\n                ktime_t (*get_time)(void); // ~v6.17\n                ktime_t offset;\n            } __hrtimer_clock_base_align clock_base[HRTIMER_MAX_CLOCK_BASES];\n        } ____cacheline_aligned;\n\n        DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =\n        {\n            .lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),\n            .clock_base =\n            {\n                {\n                    .index = HRTIMER_BASE_MONOTONIC,\n                    .clockid = CLOCK_MONOTONIC,\n                    .get_time = &ktime_get,               -------\n                },                                              ^\n                {                                               | calc this\n                    .index = HRTIMER_BASE_REALTIME,             |\n                    .clockid = CLOCK_REALTIME,                  v\n                    .get_time = &ktime_get_real,          -------\n                },\n                {\n                    .index = HRTIMER_BASE_BOOTTIME,\n                    .clockid = CLOCK_BOOTTIME,\n                    .get_time = &ktime_get_boottime,\n                },\n                {\n                    .index = HRTIMER_BASE_TAI,\n                    .clockid = CLOCK_TAI,\n                    .get_time = &ktime_get_clocktai,\n                },\n                {                                         // v4.16~\n                    .index = HRTIMER_BASE_MONOTONIC_SOFT,\n                    .clockid = CLOCK_MONOTONIC,\n                    .get_time = &ktime_get,\n                },\n                {                                         // v4.16~\n                    .index = HRTIMER_BASE_REALTIME_SOFT,\n                    .clockid = CLOCK_REALTIME,\n                    .get_time = &ktime_get_real,\n                },\n                {                                         // v4.16~\n                    .index = HRTIMER_BASE_BOOTTIME_SOFT,\n                    .clockid = CLOCK_BOOTTIME,\n                    .get_time = &ktime_get_boottime,\n                },\n                {                                         // v4.16~\n                    .index = HRTIMER_BASE_TAI_SOFT,\n                    .clockid = CLOCK_TAI,\n                    .get_time = &ktime_get_clocktai,\n                },\n            }\n        };\n        \"\"\"\n\n        hrtimer_cpu_base = self.per_cpu_hrtimer_cpu_bases[0]\n\n        ktime_get = Symbol.get_ksymaddr(\"ktime_get\")\n        ktime_get_real = Symbol.get_ksymaddr(\"ktime_get_real\")\n        ktime_get_ofs = None\n        ktime_get_real_ofs = None\n        i = 0\n        while True:\n            ofs = current_arch.ptrsize * i\n            try:\n                v = read_int_from_memory(hrtimer_cpu_base + ofs)\n            except gdb.MemoryError:\n                self.quiet_err(\"Memory read error\")\n                return False\n            if v == ktime_get:\n                ktime_get_ofs = ofs\n            elif v == ktime_get_real:\n                ktime_get_real_ofs = ofs\n            if ktime_get_ofs and ktime_get_real_ofs:\n                break\n            i += 1\n        self.sizeof_hrtimer_clock_base = ktime_get_real_ofs - ktime_get_ofs\n\n        clock_base_1 = ktime_get_ofs + current_arch.ptrsize + 8 # get_time, offset\n        self.offset_clock_base = clock_base_1 - self.sizeof_hrtimer_clock_base\n        self.offset_clockid = current_arch.ptrsize + 4 # cpu_base, index\n        self.offset_get_time = ktime_get_ofs - self.offset_clock_base\n        self.offset_rb_root = self.offset_get_time - current_arch.ptrsize * 2\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.16\":\n            self.num_of_clock_base = 4\n        else:\n            self.num_of_clock_base = 8\n\n        self.initialized = True\n        return True\n\n    def parse_rb_node(self, rb_node):\n        if not rb_node or not is_valid_addr(rb_node):\n            return []\n\n        right = read_int_from_memory(rb_node + current_arch.ptrsize * 1) & ~1 # remove RB_BLACK\n        left = read_int_from_memory(rb_node + current_arch.ptrsize * 2) & ~1 # remove RB_BLACK\n\n        ret = [rb_node]\n        if right:\n            ret += self.parse_rb_node(right)\n        if left:\n            ret += self.parse_rb_node(left)\n        return ret\n\n    def dump_hrtimer(self):\n        \"\"\"\n        struct hrtimer {\n            struct timerqueue_node {\n                struct rb_node {\n                    unsigned long __rb_parent_color;\n                    struct rb_node *rb_right;\n                    struct rb_node *rb_left;\n                } node;\n                ktime_t expires;\n            } node;\n            ktime_t _softexpires;\n            enum hrtimer_restart (*function)(struct hrtimer *);\n            struct hrtimer_clock_base *base;\n            u8 state;\n            u8 is_rel;\n            u8 is_soft;\n            u8 is_hard;\n        };\n        \"\"\"\n\n        clockid_dict = {\n            0: \"CLOCK_REALTIME\",\n            1: \"CLOCK_MONOTONIC\",\n            2: \"CLOCK_PROCESS_CPUTIME_ID\",\n            3: \"CLOCK_THREAD_CPUTIME_ID\",\n            4: \"CLOCK_MONOTONIC_RAW\",\n            5: \"CLOCK_REALTIME_COARSE\",\n            6: \"CLOCK_MONOTONIC_COARSE\",\n            7: \"CLOCK_BOOTTIME\",\n            8: \"CLOCK_REALTIME_ALARM\",\n            9: \"CLOCK_BOOTTIME_ALARM\",\n            10: \"CLOCK_SGI_CYCLE\",\n            11: \"CLOCK_TAI\",\n        }\n\n        for cpu, hrtimer_cpu_base in enumerate(self.per_cpu_hrtimer_cpu_bases):\n            clock_base = hrtimer_cpu_base + self.offset_clock_base\n            for base_n in range(self.num_of_clock_base):\n                htb = clock_base + self.sizeof_hrtimer_clock_base * base_n\n                clockid = read_int32_from_memory(htb + self.offset_clockid)\n                get_time = read_int_from_memory(htb + self.offset_get_time)\n                self.out.append(titlify(\"cpu{:d} hrtimer_clock_base[{:d}]: {:#x}  [{:s}; get_time: {:#x}{:s}]\".format(\n                    cpu, base_n, htb,\n                    clockid_dict.get(clockid, \"UNKNOWN\"),\n                    get_time,\n                    Symbol.get_symbol_string(get_time, nosymbol_string=\" <NO_SYMBOL>\"),\n                ).rstrip()))\n\n                # print legend\n                if not self.args.quiet:\n                    fmt = \"{:18s}  {:18s}  {:23s}  {:18s} {:s}\"\n                    legend = [\"hrtimer\", \"expires\", \"time_to_expired\", \"function\", \"symbol\"]\n                    self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                rb_node = read_int_from_memory(htb + self.offset_rb_root)\n                for hrtimer in self.parse_rb_node(rb_node):\n                    expires = read_int64_from_memory(hrtimer + current_arch.ptrsize * 3)\n                    function = read_int_from_memory(hrtimer + current_arch.ptrsize * 3 + 8 * 2)\n                    if is_32bit() and not is_valid_addr(function):\n                        expires = read_int64_from_memory(hrtimer + current_arch.ptrsize * 3 + 4)\n                        function = read_int_from_memory(hrtimer + current_arch.ptrsize * 3 + 4 + 8 * 2)\n                    self.out.append(\"{:#018x}  {:#018x}  {:23s}  {:#018x}{:s}\".format(\n                        hrtimer, expires,\n                        \"? (too hard to calc)\",\n                        function,\n                        Symbol.get_symbol_string(function, nosymbol_string=\" <NO_SYMBOL>\"),\n                    ).rstrip())\n        return\n\n    def dump_timer(self):\n        \"\"\"\n        struct timer_list {\n            struct hlist_node entry;\n            unsigned long expires;\n            void (*function)(struct timer_list *);\n            u32 flags;\n        #ifdef CONFIG_LOCKDEP\n            struct lockdep_map lockdep_map;\n        #endif\n        };\n        \"\"\"\n\n        jiffies = read_int_from_memory(self.jiffies)\n\n        for cpu, timer_base in enumerate(self.per_cpu_timer_bases):\n            # dump timer_list\n            for base_n in range(self.nr_bases):\n                tb = timer_base + self.roughly_sizeof_timer_base * base_n\n                self.out.append(titlify(\"cpu{:d} timer_base[{:d}]: {:#x}\".format(cpu, base_n, tb)))\n\n                # print legend\n                if not self.args.quiet:\n                    fmt = \"{:18s}  {:18s}  {:23s}  {:18s} {:s}\"\n                    legend = [\"timer_list\", \"expires\", \"time_to_expired\", \"function\", \"symbol\"]\n                    self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n                i = 0\n                while True:\n                    addr = tb + current_arch.ptrsize * i\n                    try:\n                        v = read_int_from_memory(addr)\n                    except gdb.MemoryError:\n                        self.err_add_out(\"Memory read error\")\n                        return\n\n                    if v == 0:\n                        i += 1\n                        continue\n\n                    if i < 512:\n                        if not is_valid_addr(v):\n                            i += 1\n                            continue\n                        if read_int_from_memory(v + current_arch.ptrsize) != addr:\n                            i += 1\n                            continue\n                    else:\n                        if not is_valid_addr(v):\n                            break\n                        if read_int_from_memory(v + current_arch.ptrsize) != addr:\n                            break\n\n                    timer_list = v\n                    expires = read_int_from_memory(timer_list + current_arch.ptrsize * 2)\n                    function = read_int_from_memory(timer_list + current_arch.ptrsize * 3)\n                    sym = Symbol.get_symbol_string(function, nosymbol_string=\" <NO_SYMBOL>\")\n                    tte = expires - jiffies\n                    self.out.append(\"{:#018x}  {:#018x}  {:#018x} tick  {:#018x}{:s}\".format(\n                        v, expires, tte, function, sym,\n                    ).rstrip())\n                    i += 1\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"4.8\":\n            err(\"Unsupported before v4.8\")\n            return\n        if \"6.18\" <= kversion:\n            # Read-write function pointers have been removed,\n            # so there is no longer any point in displaying them with this command.\n            err(\"Unsupported after v6.18\")\n            return\n\n        self.quiet_info(\"Wait for memory scan\")\n\n        if not self.initialize():\n            return\n\n        self.out = []\n        self.dump_timer()\n        self.dump_hrtimer()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelPciDeviceCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the PCI devices.\"\"\"\n\n    _cmdline_ = \"kpcidev\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified pcidev structure:\",\n        \"\",\n        \"+----------------+   +-pci_bus--------+\",\n        \"| pci_root_buses |-->| node.next      |-->...\",\n        \"+----------------+   | node.prev      |\",\n        \"                     | parent         |    +-pci_dev----------+\",\n        \"                     | children.next  | +->| bus_list.next    |-->...\",\n        \"                     | children.prev  | |  | bus_list.prev    |\",\n        \"                     | devices.next   |-+  | ...              |\",\n        \"                     | devices.prev   |    | vendor           |\",\n        \"                     | ...            |    | device           |\",\n        \"                     | dev            |    | subsystem_vendor |\",\n        \"                     |   kobj         |    | subsystem_device |\",\n        \"                     |     name       |    | class            |\",\n        \"                     | ...            |    | revision         |\",\n        \"                     +----------------+    | dev              |\",\n        \"                                           |   kobj           |\",\n        \"                                           |     name         |\",\n        \"                                           | ...              |\",\n        \"                                           | +-resource[0]-+  |\",\n        \"                                           | | start       |  |\",\n        \"                                           | | end         |  |\",\n        \"                                           | | name        |  |\",\n        \"                                           | | flags       |  |\",\n        \"                                           | | ...         |  |\",\n        \"                                           | +-resource[1]-+  |\",\n        \"                                           | | ...         |  |\",\n        \"                                           | +-------------+  |\",\n        \"                                           | | ...         |  |\",\n        \"                                           | +-------------+  |\",\n        \"                                           | ...              |\",\n        \"                                           +------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # pci_root_buses\n        self.pci_root_buses = KernelAddressHeuristicFinder.get_pci_root_buses()\n        if not self.pci_root_buses:\n            self.quiet_err(\"Could not find pci_root_buses (maybe, CONFIG_PCI is not set)\")\n            return False\n        self.quiet_info(\"pci_root_buses: {:#x}\".format(self.pci_root_buses))\n\n        first_root_bus = read_int_from_memory(self.pci_root_buses)\n        if self.pci_root_buses == first_root_bus:\n            warn(\"No PCI devices found\")\n            return False\n\n        # pci_bus->{node,children,devices}\n        \"\"\"\n        struct pci_bus {\n            struct list_head node;\n            struct pci_bus *parent;\n            struct list_head children;\n            struct list_head devices;\n            struct pci_dev *self;\n            struct list_head slots;\n            struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];\n            struct list_head resources;\n            struct resource busn_res;\n            struct pci_ops *ops;\n            struct msi_controller *msi;\n            void *sysdata;\n            struct proc_dir_entry *procdir;\n            unsigned char number;\n            unsigned char primary;\n            unsigned char max_bus_speed;\n            unsigned char cur_bus_speed;\n        #ifdef CONFIG_PCI_DOMAINS_GENERIC\n            int domain_nr;\n        #endif\n            char name[48];\n            unsigned short bridge_ctl;\n            pci_bus_flags_t bus_flags;\n            struct device *bridge;\n            struct device {\n                struct kobject {\n                    const char *name; <-- search for this\n                    ...\n                } kobj;\n                ...\n            } dev;\n            struct bin_attribute *legacy_io;\n            struct bin_attribute *legacy_mem;\n            unsigned int is_added:1;\n        };\n        \"\"\"\n\n        self.offset_pci_bus_node = 0\n        self.offset_pci_bus_children = current_arch.ptrsize * 3\n        self.offset_pci_bus_devices = current_arch.ptrsize * 5\n\n        # pci_bus->dev\n        for i in range(100):\n            v = read_int_from_memory(first_root_bus + current_arch.ptrsize * i)\n            if is_valid_addr(v):\n                if read_cstring_from_memory(v) == \"0000:00\":\n                    self.offset_pci_bus_dev = current_arch.ptrsize * i\n                    self.quiet_info(\"offsetof(pci_bus, dev): {:#x}\".format(self.offset_pci_bus_dev))\n                    break\n        else:\n            self.quiet_err(\"Could not find pci_bus->dev\")\n            return False\n\n        # pci_dev->{bus_list,vendor,device,subsystem_vendor,subsystem_device,class,revision}\n        \"\"\"\n        struct pci_dev {\n            struct list_head bus_list;\n            struct pci_bus *bus;\n            struct pci_bus *subordinate;\n            void *sysdata;\n            struct proc_dir_entry *procent;\n            struct pci_slot *slot;\n            unsigned int devfn;\n            unsigned short vendor;\n            unsigned short device;\n            unsigned short subsystem_vendor;\n            unsigned short subsystem_device;\n            unsigned int class;\n            u8 revision;\n            u8 hdr_type;\n            ...\n            struct device {\n                struct kobject {\n                    const char *name; <-- search for this\n                    ...\n                } kobj;\n                ...\n            } dev;\n            int cfg_size;\n            unsigned int irq;\n            struct resource resource[DEVICE_COUNT_RESOURCE];\n            ...\n        };\n        \"\"\"\n\n        self.offset_pci_dev_bus_list = 0\n        self.offset_pci_dev_vendor = current_arch.ptrsize * 7 + 4\n        self.offset_pci_dev_device = self.offset_pci_dev_vendor + 2\n        self.offset_pci_dev_subsystem_vendor = self.offset_pci_dev_device + 2\n        self.offset_pci_dev_subsystem_device = self.offset_pci_dev_subsystem_vendor + 2\n        self.offset_pci_dev_class = self.offset_pci_dev_subsystem_device + 2\n        self.offset_pci_dev_revision = self.offset_pci_dev_class + 4\n\n        # pci_dev->dev\n        first_dev = read_int_from_memory(first_root_bus + self.offset_pci_bus_devices)\n        for i in range(100):\n            v = read_int_from_memory(first_dev + current_arch.ptrsize * i)\n            if is_valid_addr(v):\n                if read_cstring_from_memory(v) == \"0000:00:00.0\":\n                    self.offset_pci_dev_dev = current_arch.ptrsize * i\n                    self.quiet_info(\"offsetof(pci_dev, dev): {:#x}\".format(self.offset_pci_dev_dev))\n                    break\n        else:\n            self.quiet_err(\"Could not find pci_dev->dev\")\n            return False\n\n        # pci_dev->resource\n        \"\"\"\n        struct resource {\n            resource_size_t start;\n            resource_size_t end;\n            const char *name;\n            unsigned long flags;\n            unsigned long desc;\n            struct resource *parent, *sibling, *child;\n        };\n        \"\"\"\n\n        ofs_base = self.offset_pci_dev_dev + current_arch.ptrsize\n        for i in range(200):\n            v = read_int_from_memory(first_dev + ofs_base + current_arch.ptrsize * i)\n            if is_valid_addr(v):\n                if read_cstring_from_memory(v) == \"0000:00:00.0\":\n                    self.offset_pci_dev_resource = ofs_base + current_arch.ptrsize * i - 0x10\n                    self.sizeof_resource = 0x10 + current_arch.ptrsize * 6\n                    self.quiet_info(\"offsetof(pci_dev, resource): {:#x}\".format(self.offset_pci_dev_resource))\n                    break\n        else:\n            self.quiet_err(\"Could not find pci_dev->resource\")\n            return False\n\n        # pci.ids\n        pci_ids_file_name = \"/usr/share/misc/pci.ids\"\n        if os.path.exists(pci_ids_file_name):\n            self.quiet_info(\"use {:s}\".format(pci_ids_file_name))\n            content = open(pci_ids_file_name).read()\n        else:\n            pci_ids_file_name = os.path.join(GEF_TEMP_DIR, \"pci.ids\")\n            if os.path.exists(pci_ids_file_name):\n                self.quiet_info(\"use {:s}\".format(pci_ids_file_name))\n                content = open(pci_ids_file_name).read()\n            else:\n                url = \"https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids\"\n                self.quiet_info(\"use {:s}\".format(url))\n                content = String.bytes2str(http_get(url) or \"\")\n                if not content:\n                    self.quiet_info(\"Connection timed out: {:s}\".format(url))\n                open(pci_ids_file_name, \"w\").write(content)\n        self.pci_ids = self.parse_pci_ids(content)\n\n        self.initialized = True\n        return True\n\n    def parse_pci_ids(self, content):\n        dic = {}\n        class_mode = False\n        for line in content.splitlines():\n            if not line or line.startswith(\"#\"):\n                continue\n\n            if class_mode is False and line.startswith(\"C\"):\n                class_mode = True\n\n            if class_mode is False:\n                # device mode\n                if not line.startswith(\"\\t\"):\n                    vendor, *desc = line.split(\"  \")\n                    vendor = int(vendor, 16)\n                    dic[vendor] = \" \".join(desc)\n                    continue\n\n                if line.startswith(\"\\t\") and not line.startswith(\"\\t\\t\"):\n                    device, *desc = line[1:].split(\"  \")\n                    device = int(device, 16)\n                    # Use the previous value for `vendor`.\n                    dic[vendor, device] = \" \".join(desc)\n                    continue\n\n                if line.startswith(\"\\t\\t\"):\n                    subsystem, *desc = line[2:].split(\"  \")\n                    subv, subd = subsystem.split()\n                    subv = int(subv, 16)\n                    subd = int(subd, 16)\n                    # Use the previous value for `vendor` and `device`.\n                    dic[vendor, device, subv, subd] = \" \".join(desc)\n                    continue\n\n            else:\n                # class mode\n                if not line.startswith(\"\\t\"):\n                    base_class, *desc = line.split(\"  \")\n                    base_class = int(base_class[2:], 16)\n                    dic[\"C\", base_class] = \" \".join(desc)\n                    continue\n\n                if line.startswith(\"\\t\") and not line.startswith(\"\\t\\t\"):\n                    sub_class, *desc = line[1:].split(\"  \")\n                    sub_class = int(sub_class, 16)\n                    # Use the previous value for `base_class`.\n                    dic[\"C\", base_class, sub_class] = \" \".join(desc)\n                    continue\n\n                if line.startswith(\"\\t\\t\"):\n                    prgif, *desc = line[2:].split(\"  \")\n                    prgif = int(prgif, 16)\n                    # Use the previous value for `base_class` and `sub_class`.\n                    dic[\"C\", base_class, sub_class, prgif] = \" \".join(desc)\n                    continue\n        return dic\n\n    def get_description(self, base_class, sub_class, prgif, vendor, device, subv, subd):\n        # The information provided by the programming interface (prgif) is too detailed,\n        # so it is not used.\n        class_str = self.pci_ids.get((\"C\", base_class, sub_class), None)\n        if class_str is None:\n            class_str = self.pci_ids.get((\"C\", base_class), None)\n        if class_str is None:\n            class_str = \"???\"\n\n        device_str = self.pci_ids.get((vendor, device, subv, subd), None)\n        if device_str is None:\n            device_str = self.pci_ids.get((vendor, device), None)\n        if device_str is None:\n            device_str = self.pci_ids.get(vendor, None)\n        if device_str is None:\n            device_str = \"???\"\n\n        qemu_monitor_out = \"\"\n        if is_qemu_system():\n            dev = \"\"\n            res = gdb.execute(\"monitor info qtree\", to_string=True)\n            target = \"pci id {:04x}:{:04x} (sub {:04x}:{:04x})\".format(vendor, device, subv, subd)\n            for line in res.splitlines():\n                m = re.search('dev: (.+), id \".*\"', line)\n                if m:\n                    dev = m.group(1)\n                    continue\n                if target in line:\n                    qemu_monitor_out = \" ({:s})\".format(Color.boldify(dev))\n                    break\n\n        return \"{:s} / {:s}\".format(class_str, device_str) + qemu_monitor_out\n\n    @staticmethod\n    def get_flags_str(flags_value):\n        flags_dic = {\n            0x80000000: \"IORESOURCE_BUSY\",\n            0x40000000: \"IORESOURCE_AUTO\",\n            0x20000000: \"IORESOURCE_UNSET\",\n            0x10000000: \"IORESOURCE_DISABLED\",\n            0x08000000: \"IORESOURCE_EXCLUSIVE\",\n            0x04000000: \"IORESOURCE_SYSRAM_MERGEABLE\",\n            0x02000000: \"IORESOURCE_SYSRAM_DRIVER_MANAGED\",\n            0x01000000: \"IORESOURCE_SYSRAM\",\n            0x00400000: \"IORESOURCE_MUXED\",\n            0x00200000: \"IORESOURCE_WINDOW\",\n            0x00100000: \"IORESOURCE_MEM_64\",\n            0x00080000: \"IORESOURCE_STARTALIGN\",\n            0x00040000: \"IORESOURCE_SIZEALIGN\",\n            0x00020000: \"IORESOURCE_SHADOWABLE\",\n            0x00010000: \"IORESOURCE_RANGELENGTH\",\n            0x00008000: \"IORESOURCE_CACHEABLE\",\n            0x00004000: \"IORESOURCE_READONLY\",\n            0x00002000: \"IORESOURCE_PREFETCH\",\n            0x00001000: \"IORESOURCE_BUS\",\n            0x00000800: \"IORESOURCE_DMA\",\n            0x00000400: \"IORESOURCE_IRQ\",\n            0x00000200: \"IORESOURCE_MEM\",\n            0x00000100: \"IORESOURCE_IO\",\n        }\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n\n        if \"IORESOURCE_IO\" in flags and \"IORESOURCE_MEM\" in flags:\n            flags.remove(\"IORESOURCE_IO\")\n            flags.remove(\"IORESOURCE_MEM\")\n            flags.append(\"IORESOURCE_REG\")\n\n        flags_str = \" | \".join(flags)\n        if flags_str == \"\":\n            flags_str = \"none\"\n        return flags_str.replace(\"IORESOURCE_\", \"\")\n\n    def search_label(self, start, end):\n        if not is_qemu_system():\n            return []\n\n        label_list = []\n        res = gdb.execute(\"monitor info mtree -f\", to_string=True)\n        for line in res.splitlines():\n            if not line.startswith(\"  \"):\n                continue\n\n            m = re.search(r\"  ([0-9a-f]+)-([0-9a-f]+)\", line)\n            if not m:\n                continue\n\n            s = int(m.group(1), 16)\n            e = int(m.group(2), 16)\n            if not (start <= s and e <= end):\n                continue\n\n            line = \"      -> \" + line.lstrip()\n            if line not in label_list:\n                label_list.append(line)\n\n        if label_list == []:\n            label_list.append(\"      -> No results found from `monitor info mtree -f`\")\n        return label_list\n\n    def walk_devices(self, dev):\n        if not self.args.quiet:\n            fmt = \"{:18s} {:12s} {:7s} {:10s} {:10s} {:3s} {:s}\"\n            legend = [\"pci_dev\", \"name\", \"class\", \"vendor:dev\", \"subsystem\", \"rev\", \"description\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if not dev:\n            return\n\n        while dev not in self.seen_dev:\n            self.seen_dev.append(dev)\n\n            # parse device info\n            dev_name = read_cstring_from_memory(read_int_from_memory(dev + self.offset_pci_dev_dev))\n            vendor = read_int16_from_memory(dev + self.offset_pci_dev_vendor)\n            device = read_int16_from_memory(dev + self.offset_pci_dev_device)\n            sub_vendor = read_int16_from_memory(dev + self.offset_pci_dev_subsystem_vendor)\n            sub_device = read_int16_from_memory(dev + self.offset_pci_dev_subsystem_device)\n            revision = read_int8_from_memory(dev + self.offset_pci_dev_revision)\n\n            # u32:class = u8:unused || u8:base_class || u8:sub_class || u8:programming-interface\n            class_val = read_int32_from_memory(dev + self.offset_pci_dev_class)\n            prgif = class_val & 0xff\n            sub_class = (class_val >> 8) & 0xff\n            base_class = (class_val >> 16) & 0xff\n\n            desc = self.get_description(base_class, sub_class, prgif, vendor, device, sub_vendor, sub_device)\n            self.out.append(\"{:#018x} {:s} {:02x}{:02x}:{:02x} {:04x}:{:04x}  {:04x}:{:04x}  {:02x}  {:s}\".format(\n                dev, dev_name, base_class, sub_class, prgif, vendor, device, sub_vendor, sub_device, revision, desc,\n            ))\n\n            if self.args.verbose:\n                # parse resource\n                i = 0\n                while True:\n                    resource_i = dev + self.offset_pci_dev_resource + self.sizeof_resource * i\n\n                    # parse resource name\n                    resource_i_name = read_int_from_memory(resource_i + 8 * 2)\n                    if not is_valid_addr(resource_i_name):\n                        break\n                    if read_cstring_from_memory(resource_i_name) != dev_name:\n                        break\n\n                    # parse resource address\n                    resource_i_start = read_int_from_memory(resource_i + 8 * 0)\n                    resource_i_end = read_int_from_memory(resource_i + 8 * 1)\n                    resource_i_size = resource_i_end - resource_i_start\n\n                    if resource_i_start != 0 and resource_i_end != 0:\n                        # parse resource flags\n                        resource_i_flags = read_int_from_memory(resource_i + 8 * 2 + current_arch.ptrsize)\n                        flag_str = KernelPciDeviceCommand.get_flags_str(resource_i_flags)\n                        if (resource_i_flags & 0x300) == 0x300:\n                            type_str = \"RegOffs\"\n                        elif resource_i_flags & 0x100:\n                            type_str = \"I/O-Mem\"\n                        elif resource_i_flags & 0x200:\n                            type_str = \"PhysMem\"\n                        else:\n                            type_str = \"???\"\n\n                        self.out.append(\"  [{:d}] {:7s}: {:#010x}-{:#010x} ({:#010x}) flags:{:#x} ({:s})\".format(\n                            i, type_str, resource_i_start, resource_i_end, resource_i_size, resource_i_flags, flag_str,\n                        ))\n\n                        # add more details\n                        ret = self.search_label(resource_i_start, resource_i_end)\n                        self.out.extend(ret)\n                    i += 1\n\n            # goto next\n            dev = read_int_from_memory(dev + self.offset_pci_dev_bus_list)\n        return\n\n    def walk_pci_bus(self, bus):\n        if not bus:\n            return\n\n        while bus not in self.seen_bus:\n            self.seen_bus.append(bus)\n            bus_name = read_cstring_from_memory(read_int_from_memory(bus + self.offset_pci_bus_dev))\n            self.out.append(titlify(\"Bus {:s}: {:#x}\".format(bus_name, bus)))\n\n            # parse device\n            self.seen_dev.append(bus + self.offset_pci_bus_devices)\n            dev = read_int_from_memory(bus + self.offset_pci_bus_devices)\n            self.walk_devices(dev)\n\n            # parse child\n            self.seen_bus.append(bus + self.offset_pci_bus_children)\n            first_child_bus = read_int_from_memory(bus + self.offset_pci_bus_children)\n            self.walk_pci_bus(first_child_bus)\n\n            # goto next\n            bus = read_int_from_memory(bus + self.offset_pci_bus_node)\n        return\n\n    def dump_pci(self):\n        first_root_bus = read_int_from_memory(self.pci_root_buses)\n        self.seen_bus = [self.pci_root_buses]\n        self.seen_dev = []\n        self.walk_pci_bus(first_root_bus)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if not self.initialize():\n            return\n\n        self.out = []\n        self.dump_pci()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelConfigCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the kernel config if available.\"\"\"\n\n    _cmdline_ = \"kconfig\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP include filter.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def get_config(self):\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.ro_base is None:\n            err(\"Not recognized .rodata\")\n            return False\n\n        if is_kgdb():\n            info(\"The config is often near the top of .rodata; once found, the search stops early.\")\n            ro_data = b\"\"\n            tqdm = GefUtil.get_tqdm(not self.args.quiet)\n            for pos in tqdm(range(0, kinfo.ro_size, 0x1000), leave=False):\n                if not is_valid_addr(kinfo.ro_base + pos):\n                    err(\"Memory read error\")\n                    return\n                ro_data += read_memory(kinfo.ro_base + pos, 0x1000)\n                if ro_data.find(b\"IKCFG_ST\") >= 0 and ro_data.find(b\"IKCFG_ED\") >= 0:\n                    break\n        else:\n            if not is_valid_addr(kinfo.ro_base):\n                err(\"Memory read error\")\n                return\n            ro_data = read_memory(kinfo.ro_base, kinfo.ro_size)\n\n        start_pos = ro_data.find(b\"IKCFG_ST\")\n        if start_pos == -1:\n            err(\"Could not find IKCFG_ST, this kernel may be built as CONFIG_IKCONFIG_PROC=n\")\n            return False\n        end_pos = ro_data.find(b\"IKCFG_ED\")\n\n        info(\"IKCFG_ST: {:#x}\".format(kinfo.ro_base + start_pos))\n        info(\"IKCFG_ED: {:#x}\".format(kinfo.ro_base + end_pos))\n        configz = ro_data[start_pos + len(\"IKCFG_ST\"):end_pos]\n\n        import gzip\n        try:\n            self.configs = String.bytes2str(gzip.decompress(configz))\n        except gzip.BadGzipFile:\n            err(\"Gzip decompress error\")\n            return False\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if not hasattr(self, \"configs\"):\n            self.configs = None\n\n        if args.rescan:\n            self.configs = None\n\n        if self.configs is None:\n            ret = self.get_config()\n            if not ret:\n                return\n\n        self.out = self.configs.splitlines()\n\n        if args.filter:\n            out = []\n            for line in self.out:\n                for filt in args.filter:\n                    if filt.search(line):\n                        out.append(line)\n                        break\n            self.out = out\n\n        self.print_output()\n        return\n\n\n@register_command\nclass KernelSearchCodePtrCommand(GenericCommand, BufferingOutput):\n    \"\"\"Search the code pointer in kernel data area.\"\"\"\n\n    _cmdline_ = \"ksearch-code-ptr\"\n    _category_ = \"06-k. Qemu-system/KGDB Cooperation - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-d\", \"--depth\", type=int, default=1, help=\"depth of reference. (default: %(default)s)\")\n    parser.add_argument(\"-r\", \"--max-range\", type=AddressUtil.parse_address, default=0,\n                        help=\"allowable offset range for each reference. (default: %(default)s)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    @Cache.cache_until_next\n    def read_int_from_memory(self, addr):\n        return read_int_from_memory(addr)\n\n    def get_permission(self, addr):\n        for vaddr, size, perm in self.kinfo.maps:\n            if vaddr <= addr and addr < vaddr + size:\n                return perm\n        return \"???\"\n\n    def search(self, backtrack_info, addr, max_range, depth):\n        if depth == 0:\n            if not (self.kinfo.text_base <= addr < self.kinfo.text_end):\n                return False\n\n            # backtrack\n            new_backtrack_info = backtrack_info + [(addr, 0)]\n            msg = []\n            for addr, offset in new_backtrack_info:\n                addr_sym = Symbol.get_symbol_string(addr + offset, nosymbol_string=\" <NO_SYMBOL>\")\n                m = \"{:#x}+{:#x}{:s} [{:s}]\".format(addr, offset, addr_sym, self.get_permission(addr + offset))\n                msg.append(m)\n\n            # create message\n            self.out.append(\"\\n  -> \".join(msg) + \"\\n\")\n            return True\n\n        valid = False\n        if depth not in self.invalid_addrs:\n            self.invalid_addrs[depth] = []\n\n        for offset in range(0, max_range + current_arch.ptrsize, current_arch.ptrsize):\n            # align to 32bit / 64bit\n            cur = AddressUtil.align_address(addr + offset)\n            # is aligned?\n            if cur & 0x7 != 0:\n                continue\n            # is kernel address?\n            # TODO: more suitable check for kernel address\n            if (cur >> (current_arch.ptrsize * 8 - 1)) == 0:\n                continue\n            # is accessible?\n            if not is_valid_addr(cur):\n                continue\n            # check result of previous recursive\n            v = self.read_int_from_memory(cur)\n            if v in self.invalid_addrs[depth]:\n                continue\n            # add to backtrack\n            new_backtrack_info = backtrack_info + [(addr, offset)]\n            # recursive\n            ret = self.search(new_backtrack_info, v, max_range, depth - 1)\n            if ret is False:\n                self.invalid_addrs[depth].append(v)\n            valid |= ret\n        return valid\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if args.max_range and args.max_range % current_arch.ptrsize:\n            err(\"The range must be a multiple of the pointer size\")\n            return\n\n        if args.depth <= 0:\n            err(\"The depth must be larger than 0\")\n            return\n\n        info(\"Wait for memory scan\")\n\n        self.kinfo = Kernel.get_kernel_layout()\n        if self.kinfo.has_none or self.kinfo.rwx:\n            err(\"Unsupported environment which has RWX data area\")\n            return\n\n        self.invalid_addrs = {}\n        self.out = []\n\n        if not is_valid_addr(self.kinfo.rw_base):\n            err(\"Memory read error\")\n            return\n        rw_data = read_memory(self.kinfo.rw_base, self.kinfo.rw_size)\n        rw_data = slice_unpack(rw_data, current_arch.ptrsize)\n\n        tqdm = GefUtil.get_tqdm()\n        for i, rw_d in tqdm(enumerate(rw_data), leave=False, total=len(rw_data)):\n            rw_addr = self.kinfo.rw_base + i * current_arch.ptrsize\n            backtrack_info = [(rw_addr, 0)]\n            self.search(backtrack_info, rw_d, args.max_range, args.depth - 1)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelDmesgCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the ring buffer of the dmesg area.\"\"\"\n\n    _cmdline_ = \"kdmesg\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"The information such as [T1] is the thread ID.\",\n        \"Originally, this information is displayed when CONFIG_PRINTK_CALLER=y.\",\n        \"However it is always displayed because it is useful.\",\n        \"\",\n        \"Simplified dmesg structure (5.10~):\",\n        \"\",\n        \"+-----+\",\n        \"| prb |--+\",\n        \"+-----+  |\",\n        \"         |\",\n        \"+--------+\",\n        \"|\",\n        \"+->+-printk_rb_static-+  +-------------------------->+-prb_desc[]----+\",\n        \"   | desc_ring        |  |                       +---| state_var     |---+\",\n        \"   |   count_bits     |  | +->+-printk_info[]-+  |   | ...           |   |\",\n        \"   |   descs          |--+ |  | seq           |  |   +---------------+   |\",\n        \"   |   infos          |----+  | ts_nsec       |  |   | state_var     |   |\",\n        \"   |   head_id        |       | text_len      |  |   | ...           |   |\",\n        \"   |   tail_id        |       | facility      |  |   +---------------+   |\",\n        \"   |   ...            |       | flags, level  |  |   | ...           |   |\",\n        \"   | text_data_ring   |       | caller_id     |  |   +---------------+<--+\",\n        \"   |   size_bits      |       | dev_info      |  |   | state_var     |\",\n        \"   |   data           |--+    +---------------+  |   | text_blk_lpos |\",\n        \"   |   head_lpos      |  |    | seq           |  |   |   begin       |(=text block start offset)\",\n        \"   |   tail_lpos      |  |    | ts_nsec       |  |   |   next        |(=text block end offset)\",\n        \"   | fail             |  |    | text_len      |  |   +---------------+\",\n        \"   +------------------+  |    | facility      |  |   | state_var     |\",\n        \"                         |    | flags, level  |  |   | text_blk_lpos |\",\n        \"+------------------------+    | caller_id     |  |   |   begin       |\",\n        \"|                             | dev_info      |  |   |   next        |\",\n        \"+->+-printk_record-+          +---------------+  |   +---------------+\",\n        \"   | info          |          | ...           |  |\",\n        \"   | text_buf      |-->text   +---------------+<-+\",\n        \"   | text_buf_size |          | seq           |\",\n        \"   +---------------+          | ...           |\",\n        \"                              +---------------+\",\n        \"* prb_desc and printk_info are accessed in two ways. One is seq number based access which is simply incremented\",\n        \"  and the other is id number based access by lower bit of state_var.\",\n        \"  1-A. (Seq-based prb_desc): Preserving entry state and entry index (=id).\",\n        \"  1-B. (Id-based prb_desc): Preserving begin and next.\",\n        \"  2-A. (Seq-based printk_info): Preserving text data length, time, thread ID, etc. for each entry.\",\n        \"  2-B. (Id-based printk_info): Preserving seq for ring buffer reuse.\",\n        \"\",\n        \"Simplified dmesg structure (~5.10):\",\n        \"\",\n        \"+-----------+\",\n        \"| __log_buf |-------->+-log_buffer-----+   ^     ^\",\n        \"+-----------+         | ts_nsec        |   |     |\",\n        \"                      | len            |-->|     |\",\n        \"                      | text_len       |   |     |\",\n        \"                      | ...            |   |     |\",\n        \"                      | text[text_len] |   |     |\",\n        \"                      +----------------+   v     |\",\n        \"+---------------+     | ...            |         |\",\n        \"| log_first_idx |---->+----------------+         |\",\n        \"+---------------+     | ts_nsec        |         |\",\n        \" =start               | len            |         |    +-------------+\",\n        \"                      | text_len       |         |<---| log_buf_len |\",\n        \"                      | ...            |         |    +-------------+\",\n        \"                      | text[text_len] |         |\",\n        \"                      +----------------+         |\",\n        \"+---------------+     | ...            |         |\",\n        \"| log_next_idx  |---->+----------------+         |\",\n        \"+---------------+     | ts_nsec        |         |\",\n        \" =end                 | len            |         |\",\n        \"                      | text_len       |         |\",\n        \"                      | ...            |         |\",\n        \"                      | text[text_len] |         |\",\n        \"                      +----------------+         v\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def dump_printk_ringbuffer(self, ring_buffer_name, ring_buffer_address):\n        \"\"\"\n        # [v5.10~]\n        struct printk_ringbuffer {\n            struct prb_desc_ring {\n                unsigned int count_bits;\n                struct prb_desc* descs;\n                struct printk_info* infos;\n                atomic_long_t head_id;\n                atomic_long_t tail_id;\n                atomic_long_t last_finalized_id; // v5.18~\n            } desc_ring;\n            struct prb_data_ring {\n                unsigned int size_bits;\n                char* data;\n                atomic_long_t head_lpos;\n                atomic_long_t tail_lpos;\n            } text_data_ring;\n            atomic_long_t fail;\n        };\n        \"\"\"\n\n        current = ring_buffer_address\n        rb = {}\n        rb[\"desc_ring\"] = {}\n        rb[\"desc_ring\"][\"count_bits\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"desc_ring\"][\"descs\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"desc_ring\"][\"infos\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"desc_ring\"][\"head_id\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"desc_ring\"][\"tail_id\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"text_data_ring\"] = {}\n        size_bits = read_int_from_memory(current)\n        if size_bits > current_arch.ptrsize * 8:\n            current += current_arch.ptrsize # last_finalized_id\n            size_bits = read_int_from_memory(current)\n        rb[\"text_data_ring\"][\"size_bits\"] = size_bits\n        current += current_arch.ptrsize\n        rb[\"text_data_ring\"][\"data\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"text_data_ring\"][\"head_lpos\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"text_data_ring\"][\"tail_lpos\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        rb[\"fail\"] = read_int_from_memory(current)\n\n        self.quiet_info(\"name: {:s}\".format(ring_buffer_name))\n        self.quiet_info(\"address: {:#x}\".format(ring_buffer_address))\n        self.quiet_info(\"desc_ring.count_bits: {:#x}\".format(rb[\"desc_ring\"][\"count_bits\"]))\n        self.quiet_info(\"desc_ring.descs: {:#x}\".format(rb[\"desc_ring\"][\"descs\"]))\n        self.quiet_info(\"desc_ring.infos: {:#x}\".format(rb[\"desc_ring\"][\"infos\"]))\n        self.quiet_info(\"desc_ring.head_id: {:#x}\".format(rb[\"desc_ring\"][\"head_id\"]))\n        self.quiet_info(\"desc_ring.tail_id: {:#x}\".format(rb[\"desc_ring\"][\"tail_id\"]))\n        self.quiet_info(\"text_data_ring.size_bits: {:#x}\".format(rb[\"text_data_ring\"][\"size_bits\"]))\n        self.quiet_info(\"text_data_ring.data: {:#x}\".format(rb[\"text_data_ring\"][\"data\"]))\n        self.quiet_info(\"text_data_ring.head_lpos: {:#x}\".format(rb[\"text_data_ring\"][\"head_lpos\"]))\n        self.quiet_info(\"text_data_ring.tail_lpos: {:#x}\".format(rb[\"text_data_ring\"][\"tail_lpos\"]))\n        self.quiet_info(\"fail: {:#x}\".format(rb[\"fail\"]))\n\n        def read_desc_i(descs_addr, seq):\n            \"\"\"\n            struct prb_desc {\n                atomic_long_t state_var;\n                struct prb_data_blk_lpos {\n                    unsigned long begin;\n                    unsigned long next;\n                } text_blk_lpos;\n            };\n            \"\"\"\n            sizeof_desc = current_arch.ptrsize * 3\n            current = descs_addr + sizeof_desc * seq\n            if not is_valid_addr(current):\n                return False\n            desc = {}\n            desc[\"state_var\"] = read_int_from_memory(current)\n            desc[\"text_blk_lpos\"] = {}\n            current += current_arch.ptrsize\n            desc[\"text_blk_lpos\"][\"begin\"] = read_int_from_memory(current)\n            current += current_arch.ptrsize\n            desc[\"text_blk_lpos\"][\"next\"] = read_int_from_memory(current)\n            current += current_arch.ptrsize\n            return desc\n\n        def read_info_i(infos_addr, seq):\n            \"\"\"\n            struct printk_info {\n                u64 seq;        /* sequence number */\n                u64 ts_nsec;    /* timestamp in nanoseconds */\n                u16 text_len;   /* length of text message */\n                u8 facility;    /* syslog facility */\n                u8 flags:5;     /* internal record flags */\n                u8 level:3;     /* syslog level */\n                u32 caller_id;  /* thread id or processor id */\n                struct dev_printk_info dev_info;\n            };\n            \"\"\"\n            sizeof_info = 8 + 8 + 2 + 1 + 1 + 4 + 16 + 48\n            current = infos_addr + sizeof_info * seq\n            if not is_valid_addr(current):\n                return False\n            info = {}\n            info[\"seq\"] = read_int64_from_memory(current)\n            current += 8\n            info[\"ts_nsec\"] = read_int64_from_memory(current)\n            current += 8\n            info[\"text_len\"] = read_int16_from_memory(current)\n            current += 2\n            info[\"facility\"] = read_int8_from_memory(current)\n            current += 1\n            info[\"flags\"] = read_int8_from_memory(current) & 0b11111\n            info[\"level\"] = (read_int8_from_memory(current) >> 5) & 0b111\n            current += 1\n            info[\"caller_id\"] = read_int32_from_memory(current)\n            current += 4\n            info[\"dev_info\"] = {}\n            info[\"dev_info\"][\"subsystem\"] = read_memory(current, 16)\n            current += 16\n            info[\"dev_info\"][\"device\"] = read_memory(current, 48)\n            current += 48\n            return info\n\n        seq_mask = (1 << rb[\"desc_ring\"][\"count_bits\"]) - 1\n        state_var_id_mask = ~(3 << (current_arch.ptrsize * 8 - 2))\n        get_desc_state = lambda sv: (sv >> (current_arch.ptrsize * 8 - 2)) & 3\n        size_bits = rb[\"text_data_ring\"][\"size_bits\"]\n        data_size_mask = (1 << size_bits) - 1\n\n        info(\"Wait for reading records...\")\n\n        seq = 0\n        while True:\n            # prb_read\n            # - Read prb_desc and printk_info based on seq number.\n            seq_based_desc = read_desc_i(rb[\"desc_ring\"][\"descs\"], seq & seq_mask)\n            seq_based_info = read_info_i(rb[\"desc_ring\"][\"infos\"], seq & seq_mask)\n\n            # desc_read_finalized_seq, desc_read\n            # - Read prb_desc and printk_info based on id number.\n            id = seq_based_desc[\"state_var\"] & state_var_id_mask\n            id_based_desc = read_desc_i(rb[\"desc_ring\"][\"descs\"], id & seq_mask)\n            id_based_info = read_info_i(rb[\"desc_ring\"][\"infos\"], id & seq_mask)\n            # - Determine whether it is the last entry based on the state and seq values.\n            if (id_based_desc[\"state_var\"] & state_var_id_mask) != id: # desc_miss\n                break\n            if get_desc_state(id_based_desc[\"state_var\"]) in [0, 1]: # desc_reserved, desc_commited\n                break\n            if id_based_info[\"seq\"] != seq:\n                if seq == 0:\n                    # ring buffer is already looping\n                    seq = id_based_info[\"seq\"]\n                else:\n                    break\n            if get_desc_state(id_based_desc[\"state_var\"]) == 2: # desc_reusable\n                if (id_based_desc[\"text_blk_lpos\"][\"begin\"], id_based_desc[\"text_blk_lpos\"][\"next\"]) == (1, 1):\n                    break\n\n            # copy_data, get_data\n            # - Calculates the start address of text data from the begin and next values.\n            begin = id_based_desc[\"text_blk_lpos\"][\"begin\"]\n            next = id_based_desc[\"text_blk_lpos\"][\"next\"]\n            if (begin >> size_bits) == (next >> size_bits) and (begin < next):\n                src = rb[\"text_data_ring\"][\"data\"] + (begin & data_size_mask)\n            elif ((begin + (1 << size_bits)) >> size_bits) == (next >> size_bits):\n                src = rb[\"text_data_ring\"][\"data\"]\n            else:\n                raise\n            size = seq_based_info[\"text_len\"]\n            src += current_arch.ptrsize\n            if size:\n                entry = String.bytes2str(read_memory(src, size))\n            else:\n                entry = \"\"\n\n            # timestamp\n            sec = seq_based_info[\"ts_nsec\"] // 1000 // 1000 // 1000\n            nsec = seq_based_info[\"ts_nsec\"] % (1000 * 1000 * 1000)\n            nsec_str = \"{:09d}\".format(nsec)[:6]\n            # thread id. This is displayed when CONFIG_PRINTK_CALLER=y, but always displayed because it is useful.\n            caller_id_str = \"T{:d}\".format(seq_based_info[\"caller_id\"])\n            # output\n            formatted_entry = \"[{:5d}.{:s}] [{:>6s}] {:s}\".format(sec, nsec_str, caller_id_str, entry)\n            self.out.append(formatted_entry)\n\n            seq += 1\n        return\n\n    def dump_printk_log_buffer(self, log_first_idx, log_end_idx, buf_start, buf_end):\n        \"\"\"\n        # [~v5.9]\n        struct printk_log {\n            u64 ts_nsec;        /* timestamp in nanoseconds */\n            u16 len;            /* length of entire record */\n            u16 text_len;       /* length of text buffer */\n            u16 dict_len;       /* length of dictionary buffer */\n            u8 facility;        /* syslog facility */\n            u8 flags:5;         /* internal record flags */\n            u8 level:3;         /* syslog level */\n        #ifdef CONFIG_PRINTK_CALLER\n            u32 caller_id;      /* thread id or processor id */\n        #endif\n        };\n        \"\"\"\n\n        CONFIG_PRINTK_CALLER = Symbol.get_ksymaddr(\"print_caller\") is not None\n        length_of_caller_id = 4 if CONFIG_PRINTK_CALLER else 0\n        sizeof_printk_log = 16 + length_of_caller_id\n\n        pos = buf_start + log_first_idx\n        log_end_pos = buf_start + log_end_idx\n\n        while pos != log_end_pos:\n            x = read_memory(pos, 16)\n            ts_nsec = u64(x[:8])\n            rec_len = u16(x[8:10])\n\n            if rec_len == 0:\n                pos = buf_start\n                continue\n\n            text_len = u16(x[10:12])\n            #dict_len = u16(x[12:14])\n            #facility = u8(x[14:15])\n            #flags = (u8(x[15:16]) >> 0) & 0b11111\n            #level = (u8(x[15:16]) >> 5) & 0b111\n            text = read_memory(pos + sizeof_printk_log, text_len)\n\n            sec = ts_nsec // 1000 // 1000 // 1000\n            nsec = ts_nsec % (1000 * 1000 * 1000)\n            nsec_str = \"{:09d}\".format(nsec)[:6]\n\n            # split from multi-line message\n            for t in String.bytes2str(text).splitlines():\n                formatted_entry = \"[{:5d}.{:s}] {:s}\".format(sec, nsec_str, t)\n                self.out.append(formatted_entry)\n\n            pos += rec_len\n            if pos >= buf_end:\n                break # something is wrong\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if args.use_cache and hasattr(self, \"cache\") and self.cache:\n            self.out = self.cache[::]\n            self.print_output()\n            return\n\n        self.out = []\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if \"5.10\" <= kversion:\n            # new structure\n            printk_rb_static = KernelAddressHeuristicFinder.get_printk_rb_static()\n            if printk_rb_static is None:\n                err(\"Could not find printk_rb_static\")\n                return\n            self.dump_printk_ringbuffer(\"printk_rb_static\", printk_rb_static)\n\n        else:\n            # old structure\n            log_first_idx_ptr = KernelAddressHeuristicFinder.get_log_first_idx()\n            if log_first_idx_ptr is None:\n                err(\"Could not find log_first_idx\")\n                return\n            self.quiet_info(\"log_first_idx: {:#x}\".format(log_first_idx_ptr))\n\n            log_next_idx_ptr = KernelAddressHeuristicFinder.get_log_next_idx()\n            if log_next_idx_ptr is None:\n                err(\"Could not find log_next_idx\")\n                return\n            self.quiet_info(\"log_next_idx: {:#x}\".format(log_next_idx_ptr))\n\n            log_buf_start = KernelAddressHeuristicFinder.get___log_buf()\n            if log_buf_start is None:\n                err(\"Could not find __log_buf\")\n                return\n            self.quiet_info(\"__log_buf: {:#x}\".format(log_buf_start))\n\n            log_buf_len_ptr = KernelAddressHeuristicFinder.get_log_buf_len()\n            if log_buf_len_ptr is None:\n                err(\"Could not find log_buf_len\")\n                return\n            self.quiet_info(\"log_buf_len: {:#x}\".format(log_buf_len_ptr))\n\n            log_first_idx = read_int32_from_memory(log_first_idx_ptr)\n            log_next_idx = read_int32_from_memory(log_next_idx_ptr)\n            log_buf_len = read_int32_from_memory(log_buf_len_ptr)\n            log_buf_end = log_buf_start + log_buf_len\n            self.quiet_info(\"*log_first_idx: {:#x}\".format(log_first_idx))\n            self.quiet_info(\"*log_next_idx: {:#x}\".format(log_next_idx))\n            self.quiet_info(\"*log_buf_len: {:#x}\".format(log_buf_len))\n            self.dump_printk_log_buffer(log_first_idx, log_next_idx, log_buf_start, log_buf_end)\n\n        self.print_output()\n        self.cache = self.out[::]\n        return\n\n\n@register_command\nclass StringsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Search ASCII string (recursively) from specific location.\"\"\"\n\n    _cmdline_ = \"strings\"\n    _category_ = \"03-a. Memory - Search\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"the start location to search for.\")\n    parser.add_argument(\"end_location\", metavar=\"END_LOCATION\", type=AddressUtil.parse_address, nargs=\"?\",\n                        help=\"the end location to search for. (default: end of region or LOCATION+0x1000)\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[], help=\"REGEXP include filter.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=re.compile, default=[], help=\"REGEXP exclude filter.\")\n    parser.add_argument(\"-d\", \"--depth\", type=int, default=0, help=\"recursive depth. (default: %(default)s)\")\n    parser.add_argument(\"-r\", \"--range\", type=AddressUtil.parse_address, default=0x40,\n                        help=\"search range for recursively. (default: %(default)s)\")\n    parser.add_argument(\"-s\", \"--skip-save\", action=\"store_true\", help=\"do not save the output.\")\n    parser.add_argument(\"-m\", \"--minlen\", type=int, default=8, help=\"minimum string length (default: %(default)s)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x00007ffffffde000 0x00007ffffffff000             # exact specification\",\n        \"{0:s} 0x00007ffffffde000                                # guess the search end location\",\n        \"{0:s} -m 10 0x00007ffffffde000 0x00007ffffffff000       # filter by length\",\n        \"{0:s} -d 1 0x00007ffffffde000 0x00007ffffffff000        # if an address is found, it will be followed up\",\n        '{0:s} -f \"GLIBC\" 0x00007ffffffde000 0x00007ffffffff000  # filter by keywords (-f, -e). need double-escape',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def strings(self, data, len_threshold):\n        strings_result = []\n        for m in re.finditer(b\"[\\x20-\\x7E]+\\x00\", data):\n            s = m.group(0).rstrip(b\"\\0\")\n            if len(s) >= len_threshold:\n                strings_result.append((m.span(0)[0], String.bytes2str(s)))\n        return strings_result\n\n    def search_ascii(self, queue):\n        seen_addr = []\n        seen_cstr = []\n\n        while queue:\n            location, search_range, depth = queue.pop(0)\n\n            # get data\n            data = b\"\"\n            try:\n                # read range\n                data += read_memory(location, search_range)\n                # read extra\n                while data and data[-1] in range(0x20, 0x7f):\n                    data += read_memory(location + len(data), 1)\n            except gdb.MemoryError:\n                pass\n\n            # search for string\n            for offset, cstr in self.strings(data, self.args.minlen):\n                address = location + offset\n\n                seen = False\n                for seen_addr_start, seen_addr_end in seen_cstr:\n                    if seen_addr_start <= address < seen_addr_end:\n                        seen = True\n                        break\n                if seen:\n                    continue\n\n                if not self.args.filter or any(filt.search(cstr) for filt in self.args.filter):\n                    if not self.args.exclude or not any(ex.search(cstr) for ex in self.args.exclude):\n                        self.out.append(\"{!s}: {:s}\".format(ProcessMap.lookup_address(address), cstr))\n                seen_cstr.append((address, address + len(cstr) + 1))\n\n            if depth == 0:\n                continue\n\n            # search for the pointer for recursive\n            aligned_data = data[current_arch.ptrsize - location % current_arch.ptrsize:]\n            if len(aligned_data) % 8:\n                aligned_data = aligned_data[:-(len(aligned_data) % current_arch.ptrsize)]\n            for addr in slice_unpack(aligned_data, current_arch.ptrsize):\n                if addr in seen_addr:\n                    continue\n                if is_valid_addr(addr):\n                    queue.append((addr, self.args.range, depth - 1))\n                    seen_addr.append(addr)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.end_location:\n            first_range = args.end_location - args.location\n        else:\n            loc = ProcessMap.lookup_address(args.location)\n            if loc.valid:\n                first_range = loc.section.page_end - args.location\n            else:\n                first_range = get_pagesize()\n\n        self.out = []\n        queue = [(args.location, first_range, args.depth)]\n        self.search_ascii(queue)\n\n        if not args.skip_save:\n            tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"strings\", suffix=\".txt\")\n            os.fdopen(tmp_fd, \"w\").write(\"\\n\".join(self.out))\n            info(\"The output is saved to {:s}\".format(tmp_path))\n\n        self.print_output()\n        return\n\n\n@register_command\nclass SyscallTableViewCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display syscall_table entries.\"\"\"\n\n    _cmdline_ = \"syscall-table-view\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n    _aliases_ = [\"kst\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[], help=\"REGEXP filter.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n        \"{0:s} --filter write\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @switch_to_intel_syntax\n    def parse_syscall_table(self, sys_call_table_addr):\n        # scan\n        cached_table = []\n        i = 0\n        while True:\n            addr = sys_call_table_addr + i * current_arch.ptrsize\n            if not is_valid_addr(addr):\n                break\n            syscall_function_addr = read_int_from_memory(addr)\n            if (is_arm32() or is_arm64()) and syscall_function_addr % 4: # should be aligned\n                break\n            if not is_valid_addr(syscall_function_addr): # if entry is valid, no error\n                break\n\n            # check symbol\n            symbol = Symbol.get_symbol_string(syscall_function_addr)\n            if symbol is None:\n                symbol = Symbol.get_ksymaddr_symbol(syscall_function_addr)\n                if symbol is None:\n                    symbol = \" <NO_SYMBOL>\"\n            elif \"+\" in symbol:\n                break\n\n            # check if valid insn or not\n            insn = get_insn(syscall_function_addr)\n            insn2 = get_insn_next(syscall_function_addr)\n            if insn is None or insn2 is None:\n                break\n\n            if is_x86():\n                # detect endbr, so slide\n                if insn.mnemonic in [\"endbr64\", \"endbr32\"]:\n                    codelen = len(insn.opcodes)\n                    insn2 = get_insn_next(insn.address + codelen)\n                    insn = get_insn(insn.address + codelen)\n\n                # detect `call non-essential-function` e.g., perf, trace, debug, ...\n                while insn and insn2 and insn.mnemonic == \"call\":\n                    codelen = len(insn.opcodes)\n                    insn2 = get_insn_next(insn.address + codelen)\n                    insn = get_insn(insn.address + codelen)\n\n            elif is_arm64():\n                # detect bti, so slide\n                if insn.mnemonic in [\"bti\"]:\n                    codelen = len(insn.opcodes)\n                    insn2 = get_insn_next(insn.address + codelen)\n                    insn = get_insn(insn.address + codelen)\n\n                # detect `bl non-essential-function` e.g., perf, trace, debug, ...\n                while insn and insn2 and insn.mnemonic == \"bl\":\n                    codelen = len(insn.opcodes)\n                    insn2 = get_insn_next(insn.address + codelen)\n                    insn = get_insn(insn.address + codelen)\n\n            elif is_arm32():\n                # detect `bl non-essential-function` e.g., perf, trace, debug, ...\n                while insn and insn2 and insn.mnemonic in [\"bl\", \"blx\"]:\n                    codelen = len(insn.opcodes)\n                    insn2 = get_insn_next(insn.address + codelen)\n                    insn = get_insn(insn.address + codelen)\n\n            # check again\n            if insn is None or insn2 is None:\n                break\n\n            # check if the target system call is disabled\n            is_valid = True\n            if is_x86():\n                if is_x86_64():\n                    err = \"0xffffffffffffffda\"\n                else:\n                    err = \"0xffffffda\"\n                if len(insn.operands) == 2 and insn.operands[-1] == err:\n                    if insn2.mnemonic == \"ret\":\n                        is_valid = False\n                    elif insn2.mnemonic == \"jmp\":\n                        try:\n                            insn3 = get_insn(AddressUtil.parse_address(insn2.operands[-1]))\n                            if insn3 and insn3.mnemonic == \"ret\":\n                                is_valid = False\n                        except (gdb.error, ValueError):\n                            pass\n            elif is_arm64():\n                if len(insn.operands) == 2 and insn.operands[-1].split(\"\\t\")[0].strip() == \"#0xffffffffffffffda\":\n                    is_valid = False\n                elif len(insn.operands) == 3 and insn.operands[-1] == \"// #-38\":\n                    is_valid = False\n\n            cached_table.append([i, addr, syscall_function_addr, symbol, is_valid])\n            i += 1\n        return cached_table\n\n    def syscall_table_view(self, orig_tag, sys_call_table_addr, syscall_list, nr_base=0):\n        if syscall_list is None:\n            self.quiet_add_out(\"{} {}\".format(Color.colorify(\"[+]\", \"bold red\"), \"Could not find the syscall table\"))\n            return\n\n        if sys_call_table_addr is None:\n            self.quiet_add_out(\"{} {}\".format(Color.colorify(\"[+]\", \"bold red\"), \"Could not find the symbol\"))\n            return\n\n        # It maintains the cache both when running with and without symbols.\n        try:\n            AddressUtil.parse_address(\"_stext\")\n            tag = \"symboled_\" + orig_tag\n        except gdb.error:\n            tag = orig_tag\n\n        # parse\n        if tag not in self.cached_table:\n            self.cached_table[tag] = self.parse_syscall_table(sys_call_table_addr)\n\n        # print legend\n        if not self.args.quiet:\n            fmt = \"{:8s} {:5s} {:7s} {:30s} {:18s} {:18s} {:s}\"\n            legend = [\"Tag\", \"Index\", \"IsValid\", \"Syscall Name\", \"Table Address\", \"Function Address\", \"Symbol\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # for duplication check\n        seen_count = {}\n        for _, _, syscall_function_addr, _, _ in self.cached_table[tag]:\n            seen_count[syscall_function_addr] = seen_count.get(syscall_function_addr, 0) + 1\n\n        # print\n        for i, addr, syscall_function_addr, symbol, is_valid in self.cached_table[tag]:\n            nr = nr_base + i\n            if nr in syscall_list.nr_table:\n                expected_name = syscall_list.nr_table[nr].name\n            else:\n                expected_name = \"<UNDEFINED_IN_THIS_ARCH>\"\n\n            fmt = \"{:8s} [{:03d}] {:7s} {:30s} {:#018x} {:#018x}{:s}\"\n            if seen_count[syscall_function_addr] == 1 and is_valid: # valid entry\n                msg = fmt.format(orig_tag, i, \"valid\", expected_name, addr, syscall_function_addr, symbol)\n            if seen_count[syscall_function_addr] > 1 or not is_valid: # invalid entry\n                msg = fmt.format(orig_tag, i, \"invalid\", expected_name, addr, syscall_function_addr, symbol)\n                msg = Color.grayify(msg)\n\n            if not self.args.filter:\n                self.out.append(msg)\n            else:\n                for re_pattern in self.args.filter:\n                    if re_pattern.search(msg):\n                        self.out.append(msg)\n        return\n\n    def dump_syscall_table(self):\n        if is_x86_32():\n            self.quiet_add_out(titlify(\"sys_call_table (x86)\"))\n            sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_x86()\n            self.syscall_table_view(\"x86\", sys_call_table_addr, get_syscall_table(\"X86\", \"N32\"))\n\n        elif is_x86_64():\n            self.quiet_add_out(titlify(\"sys_call_table (x64)\"))\n            sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_x64()\n            self.syscall_table_view(\"x86_64\", sys_call_table_addr, get_syscall_table(\"X86\", \"64\"))\n\n            kversion = Kernel.kernel_version()\n\n            self.quiet_add_out(titlify(\"ia32_sys_call_table\"))\n            if kversion < \"6.6.26\":\n                sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_x86()\n                self.syscall_table_view(\"x86_32\", sys_call_table_addr, get_syscall_table(\"X86\", \"32\"))\n            else:\n                self.quiet_add_out(\"ia32_sys_call_table is removed from 6.6.26.\")\n                self.quiet_add_out(\"each entry is embedded in `ia32_sys_call()` as call instruction.\")\n\n            self.quiet_add_out(titlify(\"x32_sys_call_table\"))\n            if kversion < \"6.6.26\":\n                sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_x32()\n                self.syscall_table_view(\"x86_x32\", sys_call_table_addr, get_syscall_table(\"X86\", \"64\"), nr_base=0x4000_0000)\n            else:\n                self.quiet_add_out(\"x32_sys_call_table is removed from 6.6.26.\")\n                self.quiet_add_out(\"each entry is embedded in `x32_sys_call()` as call instruction.\")\n\n        elif is_arm32():\n            self.quiet_add_out(titlify(\"sys_call_table (arm32)\"))\n            sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_arm32()\n            self.syscall_table_view(\"arm32\", sys_call_table_addr, get_syscall_table(\"ARM\", \"N32\"))\n\n        elif is_arm64():\n            self.quiet_add_out(titlify(\"sys_call_table (arm64)\"))\n            sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_arm64()\n            self.syscall_table_view(\"arm64\", sys_call_table_addr, get_syscall_table(\"ARM64\", \"ARM\"))\n\n            self.quiet_add_out(titlify(\"compat_sys_call_table (arm32)\"))\n            sys_call_table_addr = KernelAddressHeuristicFinder.get_sys_call_table_arm64_compat()\n            self.syscall_table_view(\"arm64_32\", sys_call_table_addr, get_syscall_table(\"ARM\", \"32\"))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if not hasattr(self, \"cached_table\"):\n            self.cached_table = {}\n\n        self.out = []\n        self.dump_syscall_table()\n        self.print_output(check_terminal_size=True)\n        return\n\n\nclass ExecAsm:\n    \"\"\"Execute embedded asm. e.g., ExecAsm(asm_op_list).exec_code().\n    WARNING: Disable `-enable-kvm` option for qemu-system; If set, this code will crash the guest OS.\"\"\"\n\n    def __init__(self, target_codes, regs=None, step=None, use_bp=False, debug=False):\n        self.regs = regs\n        self.step = step or 1\n        # Step execution often fails due to an interrupt on ARM64\n        self.use_bp = use_bp\n        # debug print enable\n        self.debug = debug\n        # output is always stdout\n        self.stdout = 1\n\n        codes = []\n        if target_codes:\n            # to stop another thread\n            codes += [current_arch.infloop_insn]\n            if current_arch.has_delay_slot:\n                codes += [current_arch.nop_insn]\n            codes += target_codes\n\n        # list to bytes\n        if Endian.is_big_endian():\n            self.code = b\"\".join(code[::-1] for code in codes)\n        else:\n            self.code = b\"\".join(codes)\n        return\n\n    def get_state(self):\n        d = {}\n\n        # pc\n        # This value is used to point to the code location. It is not used to restore registers.\n        d[\"pc\"] = current_arch.pc\n        if is_arm32() or is_arm32_cortex_m():\n            if current_arch.is_thumb():\n                d[\"pc\"] -= 1\n\n        # code\n        d[\"code\"] = read_memory(d[\"pc\"], len(self.code))\n\n        # reg\n        d[\"reg\"] = {}\n        for reg in current_arch.all_registers:\n            d[\"reg\"][reg] = get_register(reg)\n        return d\n\n    def revert_state(self, d):\n        # code\n        write_memory(d[\"pc\"], d[\"code\"])\n\n        # reg\n        for reg, v in d[\"reg\"].items():\n            if get_register(reg) == v:\n                continue\n            if (is_hppa32() or is_hppa64()) and reg == \"$pc\":\n                continue\n            if is_sh4() and reg in [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\"]:\n                reg = reg + \"b0\" # since r0-r7 cannot be changed directly, use bank 0\n            try:\n                gdb.execute(\"set {:s} = {:#x}\".format(reg, v), to_string=True)\n            except gdb.error as e:\n                if str(e).startswith(\"Cannot access memory at address\"):\n                    pass\n                else:\n                    info(\"set {:s} = {:#x} is failed\".format(reg, v))\n        return\n\n    def close_stdout(self):\n        if self.debug:\n            return\n\n        self.stdout_bak = os.dup(self.stdout)\n        f = open(\"/dev/null\")\n        os.dup2(f.fileno(), self.stdout)\n        f.close()\n        EventHooking.gef_on_stop_unhook(EventHandler.hook_stop_handler)\n        return\n\n    def revert_stdout(self):\n        if self.debug:\n            return\n        EventHooking.gef_on_stop_hook(EventHandler.hook_stop_handler)\n        os.dup2(self.stdout_bak, self.stdout)\n        os.close(self.stdout_bak)\n        return\n\n    def modify_regs(self):\n        if not self.regs:\n            return\n\n        for reg, v in self.regs.items():\n            if get_register(reg) == v:\n                continue\n            try:\n                gdb.execute(\"set {:s} = {:#x}\".format(reg, v), to_string=True)\n            except gdb.error as e:\n                if str(e).startswith(\"Cannot access memory at address\"):\n                    pass\n                else:\n                    info(\"set {:s} = {:#x} is failed\".format(reg, v))\n        return\n\n    def exec_code(self):\n        # backup\n        d = self.get_state()\n\n        # modify code, regs\n        self.modify_regs()\n        write_memory(d[\"pc\"], self.code)\n        if self.debug:\n            gdb.execute(\"context\")\n\n        # skip infloop\n        if self.code:\n            dst = d[\"pc\"] + len(current_arch.infloop_insn)\n            if current_arch.has_delay_slot:\n                dst += len(current_arch.nop_insn)\n            if is_hppa32() or is_hppa64():\n                gdb.execute(\"set $pcoqh = {:#x}\".format(dst), to_string=True)\n                dst2 = dst + len(current_arch.syscall_insn)\n                gdb.execute(\"set $pcoqt = {:#x}\".format(dst2), to_string=True)\n            elif is_sparc32() or is_sparc32plus() or is_sparc64():\n                gdb.execute(\"set $pc = {:#x}\".format(dst), to_string=True)\n                dst2 = dst + len(current_arch.syscall_insn)\n                gdb.execute(\"set $npc = {:#x}\".format(dst2), to_string=True)\n            else:\n                gdb.execute(\"set $pc = {:#x}\".format(dst), to_string=True)\n\n        # exec\n        self.close_stdout()\n        if self.debug:\n            gdb.execute(\"context\")\n        if self.use_bp:\n            bp = None\n            try:\n                bp_addr = current_arch.pc\n                for _ in range(self.step):\n                    bp_addr += get_insn(bp_addr).size\n                bp = gdb.Breakpoint(\"*{:#x}\".format(bp_addr))\n                gdb.execute(\"continue\", to_string=True)\n            except gdb.error:\n                pass\n            finally:\n                if bp:\n                    bp.delete()\n        else:\n            try:\n                gdb.execute(\"stepi {:d}\".format(self.step), to_string=True)\n            except gdb.MemoryError:\n                pass\n        if self.debug:\n            gdb.execute(\"context\")\n        self.revert_stdout()\n\n        # get result\n        ret = self.get_state()\n\n        # revert\n        self.revert_state(d)\n        return ret\n\n\nclass ExecSyscall(ExecAsm):\n    \"\"\"Execute embedded asm for syscall. e.g., ExecSyscall(nr, args).exec_code().\n    WARNING: Disable `-enable-kvm` option for qemu-system; If set, this code will crash the guest OS.\"\"\"\n\n    def __init__(self, nr, args, debug=False, use_bp=False):\n        self.syscall_nr = nr\n        self.syscall_args = args\n        # Step execution often fails due to an interrupt on ARM64\n        self.use_bp = use_bp\n        # debug print enable\n        self.debug = debug\n        # output is always stdout\n        self.stdout = 1\n\n        if is_hppa32() or is_hppa64():\n            self.step = 3 # syscall, delay slot, trampoline\n        else:\n            self.step = 1\n\n        codes = []\n\n        # to stop another thread\n        codes += [current_arch.infloop_insn]\n        if current_arch.has_delay_slot:\n            codes += [current_arch.nop_insn]\n\n        # syscall opcodes\n        syscall_insn = current_arch.syscall_insn\n        if is_s390x() and nr <= 127:\n            syscall_insn = syscall_insn[:-1] + bytes([nr])\n\n        codes += [syscall_insn]\n        # Stepping through a syscall instruction may continue execution to the next instruction.\n        # Depending on gdb version, this occurs even on architectures without delay slots, requiring a nop.\n        codes += [current_arch.nop_insn]\n\n        # list to bytes\n        if Endian.is_big_endian():\n            self.code = b\"\".join(code[::-1] for code in codes)\n        else:\n            self.code = b\"\".join(codes)\n        return\n\n    def get_state(self):\n        d = super().get_state()\n\n        # mem\n        if is_mips32():\n            d[\"mem\"] = {}\n            for offset in [0x10, 0x14, 0x18, 0x1c]:\n                d[\"mem\"][offset] = read_memory(current_arch.sp + offset, 4)\n        if is_cris():\n            d[\"mem\"] = {}\n            for offset in [0x1c]:\n                d[\"mem\"][offset] = read_memory(current_arch.sp + offset, 4)\n        return d\n\n    def revert_state(self, d):\n        super().revert_state(d)\n\n        # mem\n        if is_mips32():\n            for offset in [0x10, 0x14, 0x18, 0x1c]:\n                if read_memory(current_arch.sp + offset, 4) == d[\"mem\"][offset]:\n                    continue\n                write_memory(current_arch.sp + offset, d[\"mem\"][offset])\n        if is_cris():\n            for offset in [0x1c]:\n                if read_memory(current_arch.sp + offset, 4) == d[\"mem\"][offset]:\n                    continue\n                write_memory(current_arch.sp + offset, d[\"mem\"][offset])\n        return\n\n    def modify_regs(self):\n        # modify syscall args\n        if is_mips32():\n            syscall_parameters = current_arch.syscall_parameters_o32\n        else:\n            syscall_parameters = current_arch.syscall_parameters\n        for reg, val in zip(syscall_parameters, self.syscall_args):\n            if is_mips32() and \"+\" in reg:\n                reg, off = reg.split(\"+\")\n                write_memory(get_register(reg) + int(off, 16), p32(val))\n            else:\n                if is_sh4() and reg in [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\"]:\n                    reg = reg + \"b0\" # since r0-r7 cannot be changed directly, use bank 0\n                gdb.execute(\"set {:s} = {:#x}\".format(reg, val), to_string=True)\n\n        # modify syscall register\n        if is_s390x():\n            if self.syscall_nr > 127: # embedded in instruction\n                reg = current_arch.syscall_register[1]\n                gdb.execute(\"set {:s} = {:#x}\".format(reg, self.syscall_nr), to_string=True)\n        else:\n            reg = current_arch.syscall_register\n            if is_sh4() and reg in [\"$r0\", \"$r1\", \"$r2\", \"$r3\", \"$r4\", \"$r5\", \"$r6\", \"$r7\"]:\n                reg = reg + \"b0\" # since r0-r7 cannot be changed directly, use bank 0\n            gdb.execute(\"set {:s} = {:#x}\".format(reg, self.syscall_nr), to_string=True)\n        return\n\n\n@register_command\nclass TlsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display TLS base address. Requires glibc.\"\"\"\n\n    _cmdline_ = \"tls\"\n    _category_ = \"02-b. Process Information - Base Address\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--all\", action=\"store_true\", help=\"show all TLS address.\")\n    parser.add_argument(\"-i\", \"--thread-id\", type=AddressUtil.parse_address, help=\"show specific TLS address.\")\n    parser.add_argument(\"-s\", \"--symbol-hint\", action=\"store_true\", help=\"show hints if symbol is available (x64/x86 only).\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"count\", default=1, help=\"show more entries (+16).\")\n    parser.add_argument(\"-V\", \"--more-verbose\", action=\"count\", default=0, help=\"show more entries (+256).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -vvv  # repeat `-v` to display more lines\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @staticmethod\n    def get_direction():\n        if is_x86() or is_sparc64() or is_s390x():\n            direction = -1\n        else:\n            direction = 1\n        return direction\n\n    def get_specific_tls(self, thread_id):\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        threads = [th for th in threads if th.num == thread_id]\n\n        if len(threads) != 1:\n            err(\"Could not find the target thread\")\n            return\n\n        try:\n            threads[0].switch()\n            tls = current_arch.get_tls()\n        except Exception:\n            tls = None\n\n        orig_thread.switch() # revert\n        orig_frame.select()\n        return tls\n\n    def print_all_tls(self):\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        threads = sorted(threads, key=lambda th: th.num)\n\n        if not threads:\n            err(\"No thread is detected\")\n            return\n\n        for thread in threads:\n            msg = \"Thread Id:{:d}\".format(thread.num)\n            try:\n                thread.switch()\n            except gdb.error:\n                msg += \" - Failed to switch to this thread\"\n                continue\n            tls = current_arch.get_tls()\n            msg += \" - {:#x}\".format(tls)\n            gef_print(msg)\n\n        orig_thread.switch() # revert\n        orig_frame.select()\n        return\n\n    def get_varnames(self):\n        tp = GefUtil.cached_lookup_type(\"tcbhead_t\")\n        if tp is None:\n            return \"\"\n\n        aligned_members = []\n        for name, field in tp.items():\n            if field.bitpos % 8:\n                continue\n            if (field.bitpos // 8) % current_arch.ptrsize:\n                continue\n            aligned_members.append([(field.bitpos // 8) // current_arch.ptrsize, name])\n\n        args_string = \" \".join([\"-t {:d} {:s}\".format(i, n) for i, n in aligned_members])\n        return args_string\n\n    def dump_tls(self, tls):\n        self.out.append(\"$tls = {:#x}\".format(tls))\n        gdb.execute(\"p $tls = {:#x}\".format(tls), to_string=True)\n\n        n_entries = (16 * self.args.verbose) + (256 * self.args.more_verbose)\n\n        self.out.append(titlify(\"TLS-{:#x}\".format(current_arch.ptrsize * n_entries)))\n        r = gdb.execute(\"dereference $tls-{:#x} {:d} --no-pager\".format(\n            current_arch.ptrsize * n_entries, n_entries,\n        ), to_string=True)\n        self.out.extend(r.rstrip().splitlines())\n\n        self.out.append(titlify(\"TLS\"))\n        if self.args.symbol_hint and is_x86():\n            args_string = self.get_varnames()\n            r = gdb.execute(\"dereference $tls {:d} --no-pager {}\".format(n_entries, args_string), to_string=True)\n        else:\n            r = gdb.execute(\"dereference $tls {:d} --no-pager\".format(n_entries), to_string=True)\n        self.out.extend(r.rstrip().splitlines())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        if not current_arch.tls_supported:\n            warn(\"This command is not supported on this architecture\")\n            return\n\n        if args.all:\n            self.print_all_tls()\n            return\n\n        if args.thread_id:\n            tls = self.get_specific_tls(args.thread_id)\n        else:\n            tls = current_arch.get_tls()\n        if tls is None:\n            err(\"Failed to get TLS address\")\n            return\n\n        if not is_valid_addr(tls):\n            err(\"Cannot access memory at address {:#x}\".format(tls))\n            return\n\n        self.out = []\n        self.dump_tls(tls)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass FsbaseCommand(GenericCommand):\n    \"\"\"Display fsbase address.\"\"\"\n\n    _cmdline_ = \"fsbase\"\n    _category_ = \"02-b. Process Information - Base Address\"\n    _aliases_ = [\"fs\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command overwrites original \\\"fs (=tui focus)\\\" command.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @exclude_specific_gdb_mode(mode=(\"qiling\", \"kgdb\"))\n    def do_invoke(self, args):\n        fsbase = current_arch.get_fs()\n        if fsbase is not None:\n            gef_print(\"$fs_base: {:#x}\".format(fsbase))\n        return\n\n\n@register_command\nclass GsbaseCommand(GenericCommand):\n    \"\"\"Display gsbase address.\"\"\"\n\n    _cmdline_ = \"gsbase\"\n    _category_ = \"02-b. Process Information - Base Address\"\n    _aliases_ = [\"gs\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qiling\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        gsbase = current_arch.get_gs()\n        if gsbase is not None:\n            gef_print(\"$gs_base: {:#x}\".format(gsbase))\n        return\n\n\n@register_command\nclass GdtInfoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Print GDT/LDT entries. If user-land, show sample entries.\"\"\"\n\n    _cmdline_ = \"gdtinfo\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--only-gdt\", action=\"store_true\", help=\"show only GDT entries (qemu-system only).\")\n    parser.add_argument(\"--only-ldt\", action=\"store_true\", help=\"show only LDT entries (qemu-system only).\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"also display bit information of gdt entries.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command is intended to dump the GDTR and LDTR when working with qemu-system.\",\n        \"When you're debugging a normal userland app you can't read the GDTR or LDTR,\",\n        \"so this is just to show you an example of what information is stored there.\",\n        \"However, the segment registers show the correct (real) values.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    # arch/x86/include/asm/segment.h\n    SEGMENT_DESCRIPTION_64 = {\n        0: \"NULL\",\n        1: \"KERNEL32_CS\",\n        2: \"KERNEL_CS\",\n        3: \"KERNEL_DS\",\n        4: \"DEFAULT_USER32_CS\",\n        5: \"DEFAULT_USER_DS\",\n        6: \"DEFAULT_USER_CS\",\n        7: \"???\",\n        8: \"TSS-part1\",\n        9: \"TSS-part2\",\n        10: \"LDT-part1\",\n        11: \"LDT-part2\",\n        12: \"TLS_#1\",\n        13: \"TLS_#2\",\n        14: \"TLS_#3\",\n        15: \"CPUNODE\",\n    }\n    SEGMENT_DESCRIPTION_32 = {\n        0: \"NULL\",\n        1: \"RESERVED\",\n        2: \"RESERVED\",\n        3: \"RESERVED\",\n        4: \"UNUSED\",\n        5: \"UNUSED\",\n        6: \"TLS_#1\",\n        7: \"TLS_#2\",\n        8: \"TLS_#3\",\n        9: \"RESERVED\",\n        10: \"RESERVED\",\n        11: \"RESERVED\",\n        12: \"KERNEL_CS\",\n        13: \"KERNEL_DS\",\n        14: \"DEFAULT_USER_CS\",\n        15: \"DEFAULT_USER_DS\",\n        16: \"TSS\",\n        17: \"LDT\",\n        18: \"PNPBIOS_CS32\",\n        19: \"PNPBIOS_CS16\",\n        20: \"PNPBIOS_DS\",\n        21: \"PNPBIOS_TS1\",\n        22: \"PNPBIOS_TS2\",\n        23: \"APMBIOS_BASE\",\n        24: \"APMBIOS\",\n        25: \"APMBIOS\",\n        26: \"ESPFIX_SS\",\n        27: \"PERCPU\",\n        28: \"STACK_CANARY\",\n        29: \"UNUSED\",\n        30: \"UNUSED\",\n        31: \"DOUBLEFAULT_TSS\",\n    }\n\n    def print_seg_info(self):\n        if not is_alive():\n            return\n        self.out.append(titlify(\"Current register values\"))\n        for k in [\"cs\", \"ds\", \"es\", \"fs\", \"gs\", \"ss\"]:\n            v = get_register(k)\n            rpl = v & 0b11\n            ti = (v >> 2) & 0b1\n            index = (v >> 3)\n            red_k = Color.colorify(\"{:4s}\".format(k), \"bold red\")\n            self.out.append(\"{:s}: {:#4x} (=rpl:{:d}, ti:{:d}, index:{:d})\".format(red_k, v, rpl, ti, index))\n        self.out.append(\" * rpl: Requested Privilege Level (0:Ring0, 3:Ring3)\")\n        self.out.append(\" * ti: Table Indicator (0:GDT, 1:LDT)\")\n        self.out.append(\" * index: Index of GDT/LDT\")\n        self.out.append(\" * segment register value = (index << 3) | (ti << 2) | rpl\")\n        self.out.append(\" * commonly used cs values:\")\n        self.out.append(\"   * x64 code: 0x33\")\n        self.out.append(\"   * x86 code (on x64): 0x23\")\n        self.out.append(\"   * x86 code (native): 0x73\")\n        return\n\n    def entry_unpack(self, vals):\n        if isinstance(vals, list):\n            val = vals[0] # for 64bit SYSTEM segment\n        else:\n            val = vals\n\n        # parse\n        entry = {}\n        entry[\"value\"] = val\n\n        entry[\"type_bytes\"] = (val >> 40) & 0b1111\n        entry[\"p\"] = (val >> 47) & 0b1\n        entry[\"dpl\"] = (val >> 45) & 0b11\n\n        entry[\"s\"] = (val >> 44) & 0b1\n        entry[\"s_s\"] = [\"SYSTEM\", \"CODE/DATA\"][entry[\"s\"]]\n\n        if entry[\"s\"] == 0:\n            # SYSTEM segment\n            entry[\"type_bytes_s\"] = Color.boldify({\n                0b0000: [\"Reserved\", \"Reserved\"],\n                0b0001: [\"Available 16bit TSS\", \"Reserved\"],\n                0b0010: [\"LDT\", \"LDT\"],\n                0b0011: [\"Busy 16bit TSS\", \"Reserved\"],\n                0b0100: [\"16bit call gate\", \"Reserved\"],\n                0b0101: [\"16/32bit task gate\", \"Reserved\"],\n                0b0110: [\"16bit interrupt gate\", \"Reserved\"],\n                0b0111: [\"16bit trap gate\", \"Reserved\"],\n                0b1000: [\"Reserved\", \"Reserved\"],\n                0b1001: [\"Available 32bit TSS\", \"64bit TSS\"],\n                0b1010: [\"Reserved\", \"Reserved\"],\n                0b1011: [\"Busy 32bit TSS\", \"Busy 64bit TSS\"],\n                0b1100: [\"32bit call gate\", \"64bit call gate\"],\n                0b1101: [\"Reserved\", \"Reserved\"],\n                0b1110: [\"32bit interrupt gate\", \"64bit interrupt gate\"],\n                0b1111: [\"32bit trap gate\", \"64bit trap gate\"],\n            }[entry[\"type_bytes\"]][is_x86_64()])\n\n        if entry[\"s\"] == 0 and entry[\"type_bytes\"] == 0b1100:\n            # SYSTEM segment (call gate)\n            entry[\"offseg0\"] = val & 0xffff\n            entry[\"segsel\"] = (val >> 16) & 0xffff\n            entry[\"offseg1\"] = (val >> 48) & 0xffff\n            entry[\"offseg\"] = (entry[\"offseg1\"] << 16) | entry[\"offseg0\"]\n\n            if isinstance(vals, list):\n                # for 64bit SYSTEM segment (call gate)\n                entry[\"value\"] = vals[1] # overwrite\n                entry[\"offseg2\"] = vals[1] & 0xffff_ffff\n                entry[\"offseg\"] |= entry[\"offseg2\"] << 32\n\n        else:\n            # CODE/DATA segment or SYSTEM segment (not call gate)\n            entry[\"g\"] = (val >> 54) & 0x01\n            grsize = {0: 1, 1: 4096}[entry[\"g\"]]\n\n            entry[\"limit0\"] = val & 0xffff\n            entry[\"base0\"] = (val >> 16) & 0xffff\n            entry[\"base1\"] = (val >> 32) & 0xff\n            entry[\"limit1\"] = (val >> 48) & 0x0f\n            entry[\"base2\"] = (val >> 56) & 0xff\n\n            entry[\"limit\"] = ((entry[\"limit1\"] << 16) | entry[\"limit0\"]) * grsize\n            entry[\"base\"] = (entry[\"base2\"] << 24) | (entry[\"base1\"] << 16) | entry[\"base0\"]\n\n            if isinstance(vals, list):\n                # for 64bit SYSTEM segment (not call gate)\n                entry[\"value\"] = vals[1] # overwrite\n                entry[\"base3\"] = vals[1] & 0xffff_ffff\n                entry[\"base\"] |= entry[\"base3\"] << 32\n\n            if entry[\"s\"] == 1:\n                # CODE/DATA segment\n                entry[\"db\"] = (val >> 53) & 0x01\n                entry[\"l\"] = (val >> 52) & 0x01\n                dbl = (entry[\"db\"] << 1) | entry[\"l\"]\n                entry[\"dbl\"] = \"{:d}\".format(dbl)\n                entry[\"dbl_s\"] = [\"16bit\", \"64bit\", \"32bit\", \"(N/A)\"][dbl]\n\n                entry[\"avl\"] = (val >> 51) & 0x01\n\n                entry[\"e\"] = (val >> 43) & 0x01\n                entry[\"dc\"] = (val >> 42) & 0x01\n                entry[\"rw\"] = (val >> 41) & 0x01\n                entry[\"ac\"] = (val >> 40) & 0x01\n                if entry[\"e\"] == 0:\n                    # DATA segment\n                    entry[\"e_s\"] = Color.boldify(\"DATA\")\n                    entry[\"rw_s\"] = [\"RO\", \"RW\"][entry[\"rw\"]]\n                    entry[\"dc_s\"] = [\"EXPAND-UP\", \"EXPAND-DOWN\"][entry[\"dc\"]]\n                else:\n                    # CODE segment\n                    entry[\"e_s\"] = Color.boldify(\"CODE\")\n                    entry[\"rw_s\"] = [\"RO\", \"RX\"][entry[\"rw\"]]\n                    entry[\"dc_s\"] = [\"NON-CONFORMING\", \"CONFORMING\"][entry[\"dc\"]]\n                entry[\"ac_s\"] = [\"NotAccessed\", \"Accessed\"][entry[\"ac\"]]\n\n        Entry = collections.namedtuple(\"Entry\", entry.keys())\n        return Entry(*entry.values())\n\n    def entry2str(self, value, value_only=False):\n        if value_only:\n            return \"{:#018x}\".format(value)\n\n        if value == 0: # and not list\n            return \"{:#018x}\".format(value)\n\n        entry = self.entry_unpack(value)\n        out = \"\"\n        out += \"{:#018x} \".format(entry.value)\n        if entry.s == 0 and entry.type_bytes == 0b1100: # SYSTEM - call gate\n            out += \"{:#018x} \".format(entry.segsel)\n            out += \"{:#010x} \".format(entry.offseg)\n            out += \"{:15s}\".format(\"\")\n\n            out += \"{:<1d} \".format(entry.p)\n            out += \"{:<3d} \".format(entry.dpl)\n            out += \"{:<1d}{:11s} \".format(entry.s, \"({:s})\".format(entry.s_s))\n\n            out += \"{:#06b}({:s})\".format(entry.type_bytes, entry.type_bytes_s)\n\n        else:\n            out += \"{:#018x} \".format(entry.base)\n            out += \"{:#010x} \".format(entry.limit)\n            out += \"{:<1d} \".format(entry.g)\n\n            if entry.s == 0: # SYSTEM - Other\n                out += \"{:13s}\".format(\"\")\n            else: # CODE/DATA\n                out += \"{:<1s}({:5s}) \".format(entry.dbl, entry.dbl_s)\n                out += \"{:<3d} \".format(entry.avl)\n\n            out += \"{:<1d} \".format(entry.p)\n            out += \"{:<3d} \".format(entry.dpl)\n            out += \"{:<1d}{:11s} \".format(entry.s, \"({:s})\".format(entry.s_s))\n\n            if entry.s == 0: # SYSTEM - Other\n                out += \"{:#06b}({:s})\".format(entry.type_bytes, entry.type_bytes_s)\n            else: # CODE/DATA\n                type_bytes_s = []\n                type_bytes_s.append(entry.e_s)\n                type_bytes_s.append(entry.dc_s)\n                type_bytes_s.append(entry.rw_s)\n                type_bytes_s.append(entry.ac_s)\n                type_bytes_s = \",\".join(type_bytes_s)\n                out += \"{:#06b}({:s})\".format(entry.type_bytes, type_bytes_s)\n        return out\n\n    def get_segreg_list(self):\n        regs = {}\n        if is_alive():\n            for k in [\"cs\", \"ds\", \"es\", \"fs\", \"gs\", \"ss\"]:\n                v = get_register(k)\n                ti = (v >> 2) & 0b1\n                index = int(v >> 3)\n                if v != 0 and ti == 0:\n                    regs[index] = regs.get(index, []) + [k]\n        return regs\n\n    def print_entries(self, entries, segm_desc=None, skip_null=False):\n        regs = self.get_segreg_list()\n\n        # print legend\n        fmt = \"{:2s} {:20s} {:18s} {:18s} {:10s} {:1s} {:8s} {:3s} {:1s} {:3s} {:12s} {:s}\"\n        legend = [\"#\", \"SegmentName\", \"Value\", \"BASE\", \"LIMIT\", \"G\", \"D/B,L\", \"AVL\", \"P\", \"DPL\", \"S\", \"TYPE\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # print entry\n        i = 0\n        concat_prev = False\n        while i < len(entries):\n            # check null entry\n            if entries[i] == 0 and skip_null:\n                if not concat_prev:\n                    i += 1\n                    continue\n\n            # segment name\n            if segm_desc:\n                segname = segm_desc.get(i, \"Undefined\")\n            else:\n                segname = \"???\"\n\n            # parse and make string\n            entry = self.entry_unpack(entries[i])\n            if concat_prev:\n                # lower half of 64bit SYSTEM entries\n                estr = self.entry2str([entries[i - 1], entries[i]])\n                concat_prev = False\n\n                if not segname.endswith(\"-part2\"):\n                    segname += \"-part2\"\n\n            elif entry.s == 0 and entry.type_bytes != 0 and (is_x86_64() or is_emulated32()):\n                # upper half of 64bit SYSTEM entries\n                estr = self.entry2str(entries[i], value_only=True)\n                concat_prev = True\n\n                if not segname.endswith(\"-part1\"):\n                    segname += \"-part1\"\n\n            else:\n                # CODE/DATA segment or 16/32bit SYSTEM entries\n                estr = self.entry2str(entries[i])\n                concat_prev = False\n\n            # extra info\n            reglist = regs.get(i, [])\n            if reglist:\n                regstr = Color.colorify(\n                    \" <- {:s}\".format(\" ,\".join(reglist)),\n                    Config.get_gef_setting(\"theme.dereference_register_value\"),\n                )\n            else:\n                regstr = \"\"\n\n            # print\n            self.out.append(\"{:<2d} {:20s} {:s} {:s}\".format(i, segname, estr, regstr))\n\n            i += 1\n        return\n\n    def print_gdt_example(self):\n        # print title\n        if is_x86_64() or is_emulated32():\n            self.out.append(titlify(\"GDT Entry (x64 sample)\"))\n            segm_desc = self.SEGMENT_DESCRIPTION_64\n        else:\n            self.out.append(titlify(\"GDT Entry (x86 sample)\"))\n            segm_desc = self.SEGMENT_DESCRIPTION_32\n\n        # print legend\n        self.info_add_out(\"*** This is an {:s} ***\".format(Color.boldify(\"EXAMPLE\")))\n\n        # print entry\n        if is_x86_64() or is_emulated32():\n            entries = [\n                0x0000_0000_0000_0000,\n                0x00cf_9b00_0000_ffff,\n                0x00af_9b00_0000_ffff,\n                0x00cf_9300_0000_ffff,\n                0x00cf_fb00_0000_ffff,\n                0x00cf_f300_0000_ffff,\n                0x00af_fb00_0000_ffff,\n                0x0000_0000_0000_0000,\n                0x0000_8b00_0000_206f,\n                0x0000_0000_ffff_fe00,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0040_f500_0000_0000,\n            ]\n        else:\n            entries = [\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x00cf_9a00_0000_ffff,\n                0x00cf_9300_0000_ffff,\n                0x00cf_fa00_0000_ffff,\n                0x00cf_f300_0000_ffff,\n                0xff00_8b80_4000_206b,\n                0x0000_0000_0000_0000,\n                0x0040_9a00_0000_ffff,\n                0x0000_9a00_0000_ffff,\n                0x0000_9200_0000_ffff,\n                0x0000_9200_0000_0000,\n                0x0000_9200_0000_0000,\n                0x0040_9a00_0000_ffff,\n                0x0000_9a00_0000_ffff,\n                0x0040_9200_0000_ffff,\n                0x00cf_9200_0000_ffff,\n                0x038f_9370_8000_ffff,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0x0000_0000_0000_0000,\n                0xc400_8970_6000_206b,\n            ]\n\n        if is_x86_64():\n            segm_desc = self.SEGMENT_DESCRIPTION_64\n        else:\n            segm_desc = self.SEGMENT_DESCRIPTION_32\n        self.print_entries(entries, segm_desc)\n        return\n\n    def print_gdt_real(self):\n        # parse real value\n        if is_qemu_system():\n            res = gdb.execute(\"monitor info registers\", to_string=True)\n            r = re.search(r\"GDT\\s*=\\s*(\\S+) (\\S+)\", res)\n        elif is_vmware():\n            res = gdb.execute(\"monitor r gdtr\", to_string=True)\n            r = re.search(r\"gdtr base=(\\S+) limit=(\\S+)\", res)\n\n        if not r:\n            self.err_add_out(\"Could not find GDTR\")\n            return\n\n        base = int(r.group(1), 16)\n        limit = int(r.group(2), 16)\n\n        # print title\n        self.out.append(titlify(\"GDT Entry: base:{:#x} / limit:{:#x}\".format(base, limit)))\n\n        # check initialized or not\n        if (base == 0x0 and limit == 0xffff) or limit == 0x0:\n            self.err_add_out(\"GDT is uninitialized\")\n            return\n\n        try:\n            gdt_data = read_memory(base, limit + 1)\n        except gdb.MemoryError:\n            self.err_add_out(\"Memory read error\")\n            return\n        entries = slice_unpack(gdt_data, 8)\n\n        if is_x86_64():\n            segm_desc = self.SEGMENT_DESCRIPTION_64\n        else:\n            segm_desc = self.SEGMENT_DESCRIPTION_32\n        self.print_entries(entries, segm_desc)\n        return\n\n    def print_ldt_real(self):\n        # parse real value\n        if is_qemu_system():\n            res = gdb.execute(\"monitor info registers\", to_string=True)\n            r = re.search(r\"LDT=\\S+ (\\S+) (\\S+)\", res)\n        elif is_vmware():\n            res = gdb.execute(\"monitor r ldtr\", to_string=True)\n            r = re.search(r\"ldtr base=(\\S+) limit=(\\S+)\", res)\n\n        if not r:\n            self.err_add_out(\"Could not find LDTR\")\n            return\n\n        base = int(r.group(1), 16)\n        limit = int(r.group(2), 16)\n\n        # print title\n        self.out.append(titlify(\"LDT Entry: base:{:#x} / limit:{:#x}\".format(base, limit)))\n\n        # check initialized or not\n        if (base == 0x0 and limit == 0xffff_ffff) or limit == 0x0:\n            self.err_add_out(\"LDT is uninitialized\")\n            return\n\n        try:\n            ldt_data = read_memory(base, limit + 1)\n        except gdb.MemoryError:\n            self.err_add_out(\"Memory read error\")\n            return\n        entries = slice_unpack(ldt_data, 8)\n\n        self.print_entries(entries, skip_null=True)\n        return\n\n    def print_gdt_entry_legend(self):\n        self.out.append(titlify(\"legend (GDT/LDT entry for S=1)\"))\n        self.out.append(\"              <Flag bytes->        <----- Access bytes----->\")\n        self.out.append(\"                                          <---Type bytes--->\")\n        self.out.append(\" 31            23 22 21 20 19       15 14  12   11 10 9  8  7            0bit\")\n        self.out.append(\"-------------------------------------------------------------------------- 8byte\")\n        self.out.append(\"|             |  |D |  |A |        |  |   |    |  |D |R |A |             |\")\n        self.out.append(\"| BASE2 31:24 |G |/ |L |V | LIMIT1 |P |DPL|S(1)|E |  |  |  | BASE1 23:16 |\")\n        self.out.append(\"|             |  |B |  |L | 19:16  |  |   |    |  |C |W |C |             |\")\n        self.out.append(\"-------------------------------------------------------------------------- 4byte\")\n        self.out.append(\"|            BASE0 15:0            |             LIMIT0 15:0             |\")\n        self.out.append(\"-------------------------------------------------------------------------- 0byte\")\n        self.out.append(\" * BASE                 : Start address\")\n        self.out.append(\" * LIMIT                : Segment size (4KB unit if G=1)\")\n        self.out.append(\" * Flag bytes\")\n        self.out.append(\"   * G                  : Granularity flag (0:SegLimitAsByte, 1:SegLimitAs4KB)\")\n        self.out.append(\"   * D/B                : Segment flag (0:16bitSeg, 1:32bitSeg)\")\n        self.out.append(\"   * L (if code seg)    : 64-bit code segment flag (0:32bitSeg, 1:64bitSeg)\")\n        self.out.append(\"   * L (if data seg)    : Reserved (0)\")\n        self.out.append(\"   * AVL                : Used by system software\")\n        self.out.append(\" * Access bytes\")\n        self.out.append(\"   * P                  : Segment present flag (0:SegmentNotInMemory, 1:SegmentInMemory)\")\n        self.out.append(\"   * DPL                : Descriptor privilege level (0:Ring0, 3:Ring3)\")\n        self.out.append(\"   * S                  : Descriptor type flag (0:SystemSegment, 1:Code/DataSegment)\")\n        self.out.append(\"   * Type bytes (if S=1)\")\n        self.out.append(\"     * E                : Executable bit (0:Unexecutable/DataSegment, 1:Executable/CodeSegment)\")\n        self.out.append(\"     * DC (if code seg) : Conforming bit (0:NoConforming, 1:Conforming)\")\n        self.out.append(\"     * DC (if data seg) : Direction bit (0:ExpandUp, 1:ExpandDown)\")\n        self.out.append(\"     * RW (if code seg) : Read/Exec bit (0:ExecOnly, 1:Read/Exec)\")\n        self.out.append(\"     * RW (if data seg) : Read/Write bit (0:ReadOnly, 1:Read/Write)\")\n        self.out.append(\"     * AC               : Access bit (0:NotAccessed, 1:Accessed)\")\n        self.out.append(titlify(\"legend (GDT/LDT entry for S=0, not call gate)\"))\n        self.out.append(\"                                          <---Type bytes--->\")\n        self.out.append(\" 31            23 22       19       15 14  12   11          7            0bit\")\n        self.out.append(\"-------------------------------------------------------------------------- 16byte\")\n        self.out.append(\"|                             ZERO1 (x64 only)                           |\")\n        self.out.append(\"-------------------------------------------------------------------------- 12byte\")\n        self.out.append(\"|                          BASE3 47:32 (x64 only)                        |\")\n        self.out.append(\"-------------------------------------------------------------------------- 8byte\")\n        self.out.append(\"|             |  |        |        |  |   |    |           |             |\")\n        self.out.append(\"| BASE2 31:24 |G | ZERO0  | LIMIT1 |P |DPL|S(0)|   type    | BASE1 23:16 |\")\n        self.out.append(\"|             |  |        | 19:16  |  |   |    |           |             |\")\n        self.out.append(\"-------------------------------------------------------------------------- 4byte\")\n        self.out.append(\"|            BASE0 15:0            |             LIMIT0 15:0             |\")\n        self.out.append(\"-------------------------------------------------------------------------- 0byte\")\n        self.out.append(\" * LIMIT (if TSS Entry) : __KERNEL_TSS_LIMIT\")\n        self.out.append(\" * LIMIT (if LDT Entry) : (LDT entries * 8) - 1\")\n        self.out.append(\" * Access bytes\")\n        self.out.append(\"   * Type bytes (if S=0)  16bit/32bit          / 64bit\")\n        self.out.append(\"     * 0000             : Reserved             / Reserved\")\n        self.out.append(\"     * 0001             : Available 16bit TSS  / Reserved\")\n        self.out.append(\"     * 0010             : LDT                  / LDT\")\n        self.out.append(\"     * 0011             : Busy 16bit TSS       / Reserved\")\n        self.out.append(\"     * 0100             : 16bit call gate      / Reserved\")\n        self.out.append(\"     * 0101             : 16/32bit task gate   / Reserved\")\n        self.out.append(\"     * 0110             : 16bit interrupt gate / Reserved\")\n        self.out.append(\"     * 0111             : 16bit trap gate      / Reserved\")\n        self.out.append(\"     * 1000             : Reserved             / Reserved\")\n        self.out.append(\"     * 1001             : Available 32bit TSS  / 64bit TSS\")\n        self.out.append(\"     * 1010             : Reserved             / Reserved\")\n        self.out.append(\"     * 1011             : Busy 32bit TSS       / Busy 64bit TSS\")\n        self.out.append(\"     * 1100             : 32bit call gate      / 64bit call gate\")\n        self.out.append(\"     * 1101             : Reserved             / Reserved\")\n        self.out.append(\"     * 1110             : 32bit interrupt gate / 64bit interrupt gate\")\n        self.out.append(\"     * 1111             : 32bit trap gate      / 64bit trap gate\")\n        self.out.append(titlify(\"legend (GDT/LDT entry for S=0, call gate)\"))\n        self.out.append(\"                                          <---Type bytes--->\")\n        self.out.append(\" 31                        19       15 14  12   11          7      4     0bit\")\n        self.out.append(\"-------------------------------------------------------------------------- 16byte\")\n        self.out.append(\"|                              ZERO (x64 only)                           |\")\n        self.out.append(\"-------------------------------------------------------------------------- 12byte\")\n        self.out.append(\"|                   OffsetInSegment2 63:32 (x64 only)                    |\")\n        self.out.append(\"-------------------------------------------------------------------------- 8byte\")\n        self.out.append(\"|                                  |  |   |    |           |      |      |\")\n        self.out.append(\"|      OffsetInSegment1 31:16      |P |DPL|S(0)|   type    |0 0 0 |Param |\")\n        self.out.append(\"|                                  |  |   |    | (1 1 0 0) |      |Count |\")\n        self.out.append(\"-------------------------------------------------------------------------- 4byte\")\n        self.out.append(\"|       SegmentSelector 15:0       |        OffsetInSegment0 15:0        |\")\n        self.out.append(\"-------------------------------------------------------------------------- 0byte\")\n        return\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"x86_16\"))\n    def do_invoke(self, args):\n        self.out = []\n\n        if not args.quiet:\n            self.print_seg_info()\n\n        if is_qemu_system() or is_vmware():\n            if not args.only_ldt:\n                self.print_gdt_real()\n            if not args.only_gdt:\n                self.print_ldt_real()\n        else:\n            self.print_gdt_example()\n\n        if args.verbose:\n            self.print_gdt_entry_legend()\n        else:\n            self.quiet_info_add_out(\"for flags description, use `-v`\")\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass IdtInfoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Print IDT entries. If user-land, show sample entries.\"\"\"\n\n    _cmdline_ = \"idtinfo\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"also display bit information of idt entries.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command is intended to dump the IDTR when working with qemu-system.\",\n        \"When you're debugging a normal userland app you can't read the IDTR,\",\n        \"so this is just to show you an example of what information is stored there.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    # arch/x86/include/asm/trapnr.h\n    INTERRUPT_DESCRIPTION = {\n        0: \"#DE: Divide-by-zero\",\n        1: \"#DB: Debug\",\n        2: \"#NMI: Non-maskable Interrupt\",\n        3: \"#BP: Breakpoint\",\n        4: \"#OF: Overflow\" ,\n        5: \"#BR: BOUND Range Exceeded\",\n        6: \"#UD: Invalid Opcode\",\n        7: \"#NM: Device Not Available\",\n        8: \"#DF: Double Fault\",\n        9: \"#OLD_MF: Coprocessor Segment Overrun\",\n        10: \"#TS: Invalid TSS\",\n        11: \"#NP: Segment Not Present\",\n        12: \"#SS: Stack Segment Fault\",\n        13: \"#GP: General Protection Fault\",\n        14: \"#PF: Page Fault\",\n        15: \"#SPRIOUS: Sprious Interrupt\",\n        16: \"#MF: x87 Floating-Point Exception\",\n        17: \"#AC: Alignment Check\",\n        18: \"#MC: Machine-Check\",\n        19: \"#XF: SIMD Floating-Point Exception\",\n        20: \"#VE: Virtualization Exception\",\n        21: \"#CP: Control Protection Exception\",\n        29: \"#VC: VMM Communication Exception\",\n        32: \"#IRET: IRET Exception\",\n    }\n\n    @staticmethod\n    def idt_unpack(val):\n        idt = {}\n        idt[\"value\"] = val\n\n        idt[\"offset\"] = val & 0xffff\n        idt[\"offset\"] = idt[\"offset\"] | ((val >> 32) & (0xffff_0000))\n        idt[\"offset\"] = ((val >> 32) & (0xffff_ffff_0000_0000)) | idt[\"offset\"]\n        idt[\"segment\"] = (val >> 16) & 0xffff\n        idt[\"ist\"] = (val >> 32) & 0b111 # codespell:ignore\n        idt[\"gate_type\"] = (val >> 40) & (0b1111)\n        idt[\"dpl\"] = (val >> 45) & (0b11)\n        idt[\"present\"] = (val >> 47) & (0b1)\n\n        Idt = collections.namedtuple(\"Idt\", idt.keys())\n        return Idt(*idt.values())\n\n    @staticmethod\n    def idtval2str(value):\n        val_width = current_arch.ptrsize * 4 + 2\n        ofs_width = current_arch.ptrsize * 2 + 2\n\n        idt = IdtInfoCommand.idt_unpack(value)\n        if idt.present == 0:\n            return \"(none)\"\n\n        out = \"\"\n        out += \"{:#0{:d}x} \".format(idt.value, val_width)\n        out += \"{:#03x} \".format(idt.gate_type)\n        out += \"{:#03x} \".format(idt.ist) # codespell:ignore\n        out += \"{:#03x} \".format(idt.dpl)\n        out += \"{:#03x} \".format(idt.present)\n        out += \"{:#06x}:{:#0{:d}x}\".format(idt.segment, idt.offset, ofs_width)\n        return out\n\n    @staticmethod\n    def idtval2str_legend():\n        val_width = current_arch.ptrsize * 4 + 2\n        ofs_width = current_arch.ptrsize * 2 + 2\n        return \"{:3s} {:36s} {:{:d}s} {:3s} {:3s} {:3s} {:3s} {:6s}:{:{:d}s}\".format(\n            \"#\", \"name\", \"value\", val_width, \"typ\",\n            \"ist\", \"dpl\", \"p\", \"segm\", \"offset\", ofs_width, # codespell:ignore\n        )\n\n    def print_idt_example(self):\n        # print title\n        if is_x86_64() or is_emulated32():\n            self.out.append(titlify(\"IDT Entry (x64 sample)\"))\n        else:\n            self.out.append(titlify(\"IDT Entry (x86 sample)\"))\n\n        # print legend\n        self.info_add_out(\"*** This is an {:s} ***\".format(Color.boldify(\"EXAMPLE\")))\n        self.out.append(GefUtil.make_legend(self.idtval2str_legend()))\n\n        # print entry\n        if is_x86_64() or is_emulated32():\n            entries = [\n                # idx, value\n                [0,    0x00_0000_0000_ffff_ffff_8160_8e00_0010_0c30],\n                [1,    0x00_0000_0000_ffff_ffff_8160_8e03_0010_0f00],\n                [2,    0x00_0000_0000_ffff_ffff_8160_8e02_0010_12f0],\n                [3,    0x00_0000_0000_ffff_ffff_8160_ee00_0010_0f60],\n                [4,    0x00_0000_0000_ffff_ffff_8160_ee00_0010_0c60],\n                [5,    0x00_0000_0000_ffff_ffff_8160_8e00_0010_0c90],\n                [6,    0x00_0000_0000_ffff_ffff_8160_8e00_0010_0cc0],\n                [7,    0x00_0000_0000_ffff_ffff_8160_8e00_0010_0cf0],\n                [8,    0x00_0000_0000_ffff_ffff_8160_8e01_0010_0d20],\n                [9,    0x00_0000_0000_ffff_ffff_8160_8e00_0010_0d50],\n                [10,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0d80],\n                [11,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0db0],\n                [12,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0fb0],\n                [13,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0fe0],\n                [14,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_1010],\n                [15,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0de0],\n                [16,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0e10],\n                [17,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0e40],\n                [18,   0x00_0000_0000_ffff_ffff_8160_8e04_0010_1090],\n                [19,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0e70],\n                [20,   0x00_0000_0000_ffff_ffff_81c9_8e00_0010_f0b4],\n                [21,   0x00_0000_0000_ffff_ffff_81c9_8e00_0010_f0bd],\n                [29,   0x00_0000_0000_ffff_ffff_81c9_8e00_0010_f105],\n                [32,   0x00_0000_0000_ffff_ffff_8160_8e00_0010_0b90],\n            ]\n        else:\n            entries = [\n                # idx, value\n                [0,    0x00_c378_8e00_0060_5974],\n                [1,    0x00_c378_8e00_0060_5c4c],\n                [2,    0x00_c378_8e00_0060_5c5c],\n                [3,    0x00_c378_ee00_0060_5ef8],\n                [4,    0x00_c378_ee00_0060_58f4],\n                [5,    0x00_c378_8e00_0060_5904],\n                [6,    0x00_c378_8e00_0060_5914],\n                [7,    0x00_c378_8e00_0060_58e0],\n                [8,    0x00_0000_8500_00f8_0000],\n                [9,    0x00_c378_8e00_0060_5924],\n                [10,   0x00_c378_8e00_0060_5934],\n                [11,   0x00_c378_8e00_0060_5944],\n                [12,   0x00_c378_8e00_0060_5954],\n                [13,   0x00_c378_8e00_0060_5ffc],\n                [14,   0x00_c378_8e00_0060_59a4],\n                [15,   0x00_c378_8e00_0060_5994],\n                [16,   0x00_c378_8e00_0060_58c0],\n                [17,   0x00_c378_8e00_0060_5964],\n                [18,   0x00_c378_8e00_0060_5984],\n                [19,   0x00_c378_8e00_0060_58d0],\n                [20,   0x00_c395_8e00_0060_30bc],\n                [21,   0x00_c395_8e00_0060_30c5],\n                [29,   0x00_c395_8e00_0060_310d],\n                [32,   0x00_c378_8e00_0060_4b90],\n            ]\n\n        for i, value in entries:\n            if value != 0:\n                int_name = self.INTERRUPT_DESCRIPTION.get(i, \"User defined Interrupt {:#x}\".format(i))\n                self.out.append(\"{:<3d} {:36s} {:s}\".format(i, int_name, self.idtval2str(value)))\n        return\n\n    def print_idt_real(self):\n        # parse real value\n        if is_qemu_system():\n            res = gdb.execute(\"monitor info registers\", to_string=True)\n            r = re.search(r\"IDT\\s*=\\s*(\\S+) (\\S+)\", res)\n        elif is_vmware():\n            res = gdb.execute(\"monitor r idtr\", to_string=True)\n            r = re.search(r\"idtr base=(\\S+) limit=(\\S+)\", res)\n\n        if not r:\n            self.err_add_out(\"Could not find IDTR\")\n            return\n\n        base = int(r.group(1), 16)\n        limit = int(r.group(2), 16)\n\n        # print title\n        self.out.append(titlify(\"IDT Entry: base:{:#x} / limit:{:#x}\".format(base, limit)))\n\n        # print legend\n        self.out.append(GefUtil.make_legend(self.idtval2str_legend()))\n\n        # check initialized or not\n        if (base == 0x0 and limit == 0xffff) or limit == 0x0:\n            self.err_add_out(\"IDT is uninitialized\")\n            return\n\n        try:\n            idt_data = read_memory(base, min(limit + 1, current_arch.ptrsize * 2 * 256))\n        except gdb.MemoryError:\n            self.err_add_out(\"Memory read error\")\n            return\n        entries = slice_unpack(idt_data, current_arch.ptrsize * 2)\n\n        # print entry\n        for i, b in enumerate(entries):\n            int_name = self.INTERRUPT_DESCRIPTION.get(i, \"User defined Interrupt {:#x}\".format(i))\n            valstr = self.idtval2str(b)\n            sym = Symbol.get_symbol_string(self.idt_unpack(b).offset, nosymbol_string=\" <NO_SYMBOL>\")\n            self.out.append(\"{:<3d} {:36s} {:s}{:s}\".format(i, int_name, valstr, sym))\n        return\n\n    def print_idt_entry_legend(self):\n        self.out.append(titlify(\"legend (Normal IDT entry)\"))\n        self.out.append(\" 31                                 15  14    13  12     8       3     0bit\")\n        self.out.append(\"------------------------------------------------------------------------\")\n        self.out.append(\"|                              RESERVED                                | 12byte\")\n        self.out.append(\"------------------------------------------------------------------------\")\n        self.out.append(\"|                            OFFSET2 63:32                             | 8byte\")\n        self.out.append(\"------------------------------------------------------------------------\")\n        self.out.append(\"|         OFFSET1 31:16            | P | DPL | 0 | Type | 00000 | IST  | 4byte\") # codespell:ignore\n        self.out.append(\"------------------------------------------------------------------------\")\n        self.out.append(\"|         Segment Selector         |           OFFSET0 15:0            | 0byte\")\n        self.out.append(\"------------------------------------------------------------------------\")\n        self.out.append(\" * segment selector : Segment selector for destination code segment\")\n        self.out.append(\" * offset           : Offset to handler procedure entry point\")\n        self.out.append(\" * ist              : Interrupt stack table\") # codespell:ignore\n        self.out.append(\" * type             : One of following\")\n        self.out.append(\"                        0x5: Task gate\")\n        self.out.append(\"                        0xC: Call gate\")\n        self.out.append(\"                        0xE: 32/64-bit interrupt gate\")\n        self.out.append(\"                        0xF: 32/64-bit trap gate\")\n        self.out.append(\" * dpl              : Descriptor privilege level\")\n        self.out.append(\" * p                : Segment present flag\")\n        return\n\n    @parse_args\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"x86_16\"))\n    def do_invoke(self, args):\n        self.out = []\n\n        if is_qemu_system() or is_vmware():\n            self.print_idt_real()\n        else:\n            self.print_idt_example()\n\n        if args.verbose:\n            self.print_idt_entry_legend()\n        else:\n            self.quiet_info_add_out(\"for flags description, use `-v`\")\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass MemoryCompareCommand(GenericCommand, BufferingOutput):\n    \"\"\"Compare the memory contents of two locations.\"\"\"\n\n    _cmdline_ = \"memcmp\"\n    _category_ = \"03-c. Memory - Compare\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys1\", action=\"store_true\", help=\"treat LOCATION1 as a physical address.\")\n    parser.add_argument(\"location1\", metavar=\"LOCATION1\", type=AddressUtil.parse_address,\n                        help=\"first address for comparison.\")\n    parser.add_argument(\"--phys2\", action=\"store_true\", help=\"treat LOCATION2 as a physical address.\")\n    parser.add_argument(\"location2\", metavar=\"LOCATION2\", type=AddressUtil.parse_address,\n                        help=\"second address for comparison.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"the size for comparison.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\", help=\"display the same line without omitting.\")\n    parser.add_argument(\"-t\", \"--telescope-like\", action=\"store_true\", help=\"compare the output like telescope.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def read_data(self, from1, from2, size):\n        try:\n            if self.args.phys1:\n                from1data = read_physmem(from1, size)\n            else:\n                from1data = read_memory(from1, size)\n        except (gdb.MemoryError, ValueError, OverflowError, MemoryError):\n            err(\"Read error {:#x}\".format(from1))\n            return None\n\n        try:\n            if self.args.phys2:\n                from2data = read_physmem(from2, size)\n            else:\n                from2data = read_memory(from2, size)\n        except (gdb.MemoryError, ValueError, OverflowError, MemoryError):\n            err(\"Read error {:#x}\".format(from2))\n            return None\n\n        return from1data, from2data\n\n    def memcmp_telescope_like(self, from1data, from2data):\n        unpack = {2:u16, 4:u32, 8:u64}[current_arch.ptrsize]\n        diff_found = False\n        asterisk = False\n\n        for pos in range(0, self.args.size, current_arch.ptrsize):\n            f1_bin = from1data[pos : pos + current_arch.ptrsize]\n            f2_bin = from2data[pos : pos + current_arch.ptrsize]\n\n            if not self.args.full:\n                if f1_bin == f2_bin:\n                    if asterisk is False:\n                        self.out.append(\"*\")\n                        asterisk = True\n                    continue\n\n            diff_found = True\n            asterisk = False\n\n            f1_hex = ProcessMap.lookup_address(unpack(f1_bin))\n            f2_hex = ProcessMap.lookup_address(unpack(f2_bin))\n\n            addr1 = ProcessMap.lookup_address(self.args.location1 + pos)\n            addr2 = ProcessMap.lookup_address(self.args.location2 + pos)\n            self.out.append(\"{!s}|{:+#07x}|{:+04d}: {:s}  |  {!s}|{:+#07x}|{:+04d}: {:s}\".format(\n                addr1, pos, pos // current_arch.ptrsize, f1_hex.long_fmt(),\n                addr2, pos, pos // current_arch.ptrsize, f2_hex.long_fmt(),\n            ))\n\n        if diff_found is False:\n            self.info_add_out(\"No difference\")\n        return\n\n    def memcmp(self, from1data, from2data):\n        diff_found = False\n        asterisk = False\n\n        hex_pad_len = {\n            1: 37,\n            2: 35,\n            3: 32,\n            4: 30,\n            5: 27,\n            6: 25,\n            7: 22,\n            8: 20,\n            9: 17,\n            10: 15,\n            11: 12,\n            12: 9,\n            13: 7,\n            14: 5,\n            15: 2,\n            16: 0,\n        }\n\n        for pos in range(0, self.args.size, 16):\n            # determining continuity\n            f1_bin = from1data[pos : pos + 16]\n            f2_bin = from2data[pos : pos + 16]\n            if not self.args.full:\n                if f1_bin == f2_bin:\n                    if asterisk is False:\n                        self.out.append(\"*\")\n                        asterisk = True\n                    continue\n\n            diff_found = True\n            asterisk = False\n\n            # coloring\n            f1_hex = []\n            f2_hex = []\n            f1_ascii = []\n            f2_ascii = []\n            for i in range(min(len(f1_bin), 16)):\n                if f1_bin[i] == f2_bin[i]:\n                    color_func = lambda x: x\n                else:\n                    color_func = Color.boldify\n                f1_hex.append(color_func(\"{:02x}\".format(f1_bin[i])))\n                f2_hex.append(color_func(\"{:02x}\".format(f2_bin[i])))\n                f1_ascii.append(color_func(chr(f1_bin[i]) if 0x20 <= f1_bin[i] < 0x7f else \".\"))\n                f2_ascii.append(color_func(chr(f2_bin[i]) if 0x20 <= f2_bin[i] < 0x7f else \".\"))\n\n            # formatting\n            # [\"00\", \"00\", \"00\" \"00\", ...] -> [\"0000\", \"0000\", ...]\n            f1_hex2 = [\"\".join(x) for x in slicer(f1_hex, 2)]\n            f2_hex2 = [\"\".join(x) for x in slicer(f2_hex, 2)]\n\n            # padding\n            # [\"0000\", \"0000\", ...] -> \"0000 0000 ...\"\n            f1_hex_s = \" \".join(f1_hex2) + \" \" * hex_pad_len[len(f1_hex)]\n            f2_hex_s = \" \".join(f2_hex2) + \" \" * hex_pad_len[len(f2_hex)]\n            # [\".\", \".\", ...] -> \"................\"\n            f1_ascii_s = \"\".join(f1_ascii) + \" \" * (16 - len(f1_ascii))\n            f2_ascii_s = \"\".join(f2_ascii) + \" \" * (16 - len(f2_ascii))\n\n            # make line\n            addr1 = ProcessMap.lookup_address(self.args.location1 + pos)\n            addr2 = ProcessMap.lookup_address(self.args.location2 + pos)\n            self.out.append(\"{!s}: {:s} |{:s}| {!s}: {:s} |{:s}|\".format(\n                addr1, f1_hex_s, f1_ascii_s,\n                addr2, f2_hex_s, f2_ascii_s,\n            ))\n\n        if diff_found is False:\n            self.info_add_out(\"No difference\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys1 or args.phys2:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size == 0:\n            self.info_add_out(\"The size is zero, maybe wrong\")\n\n        ret = self.read_data(args.location1, args.location2, args.size)\n        if ret is None:\n            return\n\n        self.out = []\n        from1data, from2data = ret\n        if args.telescope_like:\n            if current_arch is None:\n                err(\"current_arch is None\")\n                return\n            if args.size % current_arch.ptrsize != 0:\n                err(\"The size must be aligned {:#x}\".format(current_arch.ptrsize))\n                return\n            self.memcmp_telescope_like(from1data, from2data)\n        else:\n            self.memcmp(from1data, from2data)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass MemorySetCommand(GenericCommand):\n    \"\"\"Set the value to the memory range.\"\"\"\n\n    _cmdline_ = \"memset\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\", help=\"treat TO_ADDRESS as a physical address.\")\n    parser.add_argument(\"to_addr\", metavar=\"TO_ADDRESS\", type=AddressUtil.parse_address, help=\"destination of memset.\")\n    parser.add_argument(\"value\", metavar=\"VALUE\", type=AddressUtil.parse_address, help=\"the value to write.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"the size for memset.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0xff 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"If you want to specify a large value for `VALUE`, use the `patch string` command.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def memset(self, to_phys, to_addr, value, size):\n        data = bytes([value]) * size\n\n        try:\n            PatchCommand.PatchInfo(to_addr, data, length=size, phys=to_phys).patch()\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Write error {:#x}\".format(to_addr))\n            return\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size == 0:\n            info(\"The size is zero, maybe wrong\")\n\n        if args.value < 0 or 256 <= args.value:\n            err(\"Wrong value (it must be 0x00-0xff)\")\n            return\n\n        self.memset(args.phys, args.to_addr, args.value, args.size)\n        return\n\n\n@register_command\nclass MemoryCopyCommand(GenericCommand):\n    \"\"\"Copy the contents of one memory to another.\"\"\"\n\n    _cmdline_ = \"memcpy\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys1\", action=\"store_true\", help=\"treat TO_ADDRESS as a physical address.\")\n    parser.add_argument(\"to_addr\", metavar=\"TO_ADDRESS\", type=AddressUtil.parse_address, help=\"destination of memcpy.\")\n    parser.add_argument(\"--phys2\", action=\"store_true\", help=\"treat FROM_ADDRESS as a physical address.\")\n    parser.add_argument(\"from_addr\", metavar=\"FROM_ADDRESS\", type=AddressUtil.parse_address, help=\"source of memcpy.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"the size for memcpy.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"memcpy dst src 8\",\n        \"                                 <--size-->\",\n        \"            dst                   src\",\n        \"  Before: [ AAAAAAAA | BBBBBBBB | CCCCCCCC ]\",\n        \"  After : [ CCCCCCCC | BBBBBBBB | CCCCCCCC ]\",\n        \"\",\n        \"memswap dst src 8\",\n        \"                                 <--size-->\",\n        \"            dst                   src\",\n        \"  Before: [ AAAAAAAA | BBBBBBBB | CCCCCCCC ]\",\n        \"  After : [ CCCCCCCC | BBBBBBBB | AAAAAAAA ]\",\n        \"\",\n        \"meminsert dst src 16 8\",\n        \"           <-------size1-------> <--size2->\",\n        \"            dst                   src\",\n        \"  Before: [ AAAAAAAA | BBBBBBBB | CCCCCCCC ]\",\n        \"  After : [ CCCCCCCC | AAAAAAAA | BBBBBBBB ]\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @staticmethod\n    def get_data(from_phys, from_addr, size):\n        try:\n            if from_phys:\n                data = read_physmem(from_addr, size)\n            else:\n                data = read_memory(from_addr, size)\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Read error {:#x}\".format(from_addr))\n            return None\n\n        info(\"Read count: {:#x}\".format(len(data)))\n        return data\n\n    def memcpy(self, to_phys, to_addr, from_phys, from_addr, size):\n        data = MemoryCopyCommand.get_data(from_phys, from_addr, size)\n        if data is None:\n            return\n\n        try:\n            PatchCommand.PatchInfo(to_addr, data, length=size, phys=to_phys).patch()\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Write error {:#x}\".format(to_addr))\n            return\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys1 or args.phys2:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size == 0:\n            info(\"The size is zero, maybe wrong\")\n\n        self.memcpy(args.phys1, args.to_addr, args.phys2, args.from_addr, args.size)\n        return\n\n\n@register_command\nclass MemorySwapCommand(GenericCommand):\n    \"\"\"Swap the contents of one memory to another.\"\"\"\n\n    _cmdline_ = \"memswap\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys1\", action=\"store_true\", help=\"treat SWAP_ADDRESS1 as a physical address.\")\n    parser.add_argument(\"swap_addr1\", metavar=\"SWAP_ADDRESS1\", type=AddressUtil.parse_address,\n                        help=\"swap target address.\")\n    parser.add_argument(\"--phys2\", action=\"store_true\", help=\"treat SWAP_ADDRESS2 as a physical address.\")\n    parser.add_argument(\"swap_addr2\", metavar=\"SWAP_ADDRESS2\", type=AddressUtil.parse_address,\n                        help=\"another swap target address.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"the size for memory swap.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = MemoryCopyCommand._note_\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def memswap(self, phys1, addr1, phys2, addr2, size):\n        data1 = MemoryCopyCommand.get_data(phys1, addr1, size)\n        if data1 is None:\n            return\n        data2 = MemoryCopyCommand.get_data(phys2, addr2, size)\n        if data2 is None:\n            return\n\n        tag = PatchCommand.PatchInfo.get_unique_tag()\n        try:\n            PatchCommand.PatchInfo(addr1, data2, length=size, phys=phys1, tag=tag).patch()\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Write error {:#x}\".format(addr1))\n            return\n        try:\n            PatchCommand.PatchInfo(addr2, data1, length=size, phys=phys2, tag=tag).patch()\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Write error {:#x}\".format(addr2))\n            return\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys1 or args.phys2:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size == 0:\n            info(\"The size is zero, maybe wrong\")\n\n        self.memswap(args.phys1, args.swap_addr1, args.phys2, args.swap_addr2, args.size)\n        return\n\n\n@register_command\nclass MemoryInsertCommand(GenericCommand):\n    \"\"\"Insert the contents of one memory to another.\"\"\"\n\n    _cmdline_ = \"meminsert\"\n    _category_ = \"03-d. Memory - Patch\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys1\", action=\"store_true\", help=\"treat TO_ADDRESS as a physical address.\")\n    parser.add_argument(\"to_addr\", metavar=\"TO_ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"destination of meminsert.\")\n    parser.add_argument(\"--phys2\", action=\"store_true\", help=\"treat FROM_ADDRESS as a physical address.\")\n    parser.add_argument(\"from_addr\", metavar=\"FROM_ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"source of meminsert.\")\n    parser.add_argument(\"size1\", metavar=\"SIZE1\", type=AddressUtil.parse_address,\n                        help=\"the pushed back size for meminsert.\")\n    parser.add_argument(\"size2\", metavar=\"SIZE2\", type=AddressUtil.parse_address,\n                        help=\"the inserted(slided) size for meminsert.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = MemoryCopyCommand._note_\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def meminsert(self, phys1, addr1, size1, phys2, addr2, size2):\n        data1 = MemoryCopyCommand.get_data(phys1, addr1, size1)\n        if data1 is None:\n            return\n        data2 = MemoryCopyCommand.get_data(phys2, addr2, size2)\n        if data2 is None:\n            return\n\n        to_write_data = data2 + data1\n\n        try:\n            PatchCommand.PatchInfo(addr1, to_write_data, phys=phys1).patch()\n        except (gdb.MemoryError, ValueError, OverflowError):\n            err(\"Write error {:#x}\".format(addr1))\n            return\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys1 or args.phys2:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size2 == 0:\n            info(\"The size2 is zero, maybe wrong\")\n\n        self.meminsert(args.phys1, args.to_addr, args.size1, args.phys2, args.from_addr, args.size2)\n        return\n\n\nclass Hash:\n    class SHA512TruncBase:\n        block_size = 128\n        digest_size = None\n\n        # SHA-512 round constants\n        K = (\n            0x428a_2f98_d728_ae22, 0x7137_4491_23ef_65cd, 0xb5c0_fbcf_ec4d_3b2f, 0xe9b5_dba5_8189_dbbc,\n            0x3956_c25b_f348_b538, 0x59f1_11f1_b605_d019, 0x923f_82a4_af19_4f9b, 0xab1c_5ed5_da6d_8118,\n            0xd807_aa98_a303_0242, 0x1283_5b01_4570_6fbe, 0x2431_85be_4ee4_b28c, 0x550c_7dc3_d5ff_b4e2,\n            0x72be_5d74_f27b_896f, 0x80de_b1fe_3b16_96b1, 0x9bdc_06a7_25c7_1235, 0xc19b_f174_cf69_2694,\n            0xe49b_69c1_9ef1_4ad2, 0xefbe_4786_384f_25e3, 0x0fc1_9dc6_8b8c_d5b5, 0x240c_a1cc_77ac_9c65,\n            0x2de9_2c6f_592b_0275, 0x4a74_84aa_6ea6_e483, 0x5cb0_a9dc_bd41_fbd4, 0x76f9_88da_8311_53b5,\n            0x983e_5152_ee66_dfab, 0xa831_c66d_2db4_3210, 0xb003_27c8_98fb_213f, 0xbf59_7fc7_beef_0ee4,\n            0xc6e0_0bf3_3da8_8fc2, 0xd5a7_9147_930a_a725, 0x06ca_6351_e003_826f, 0x1429_2967_0a0e_6e70,\n            0x27b7_0a85_46d2_2ffc, 0x2e1b_2138_5c26_c926, 0x4d2c_6dfc_5ac4_2aed, 0x5338_0d13_9d95_b3df,\n            0x650a_7354_8baf_63de, 0x766a_0abb_3c77_b2a8, 0x81c2_c92e_47ed_aee6, 0x9272_2c85_1482_353b,\n            0xa2bf_e8a1_4cf1_0364, 0xa81a_664b_bc42_3001, 0xc24b_8b70_d0f8_9791, 0xc76c_51a3_0654_be30,\n            0xd192_e819_d6ef_5218, 0xd699_0624_5565_a910, 0xf40e_3585_5771_202a, 0x106a_a070_32bb_d1b8,\n            0x19a4_c116_b8d2_d0c8, 0x1e37_6c08_5141_ab53, 0x2748_774c_df8e_eb99, 0x34b0_bcb5_e19b_48a8,\n            0x391c_0cb3_c5c9_5a63, 0x4ed8_aa4a_e341_8acb, 0x5b9c_ca4f_7763_e373, 0x682e_6ff3_d6b2_b8a3,\n            0x748f_82ee_5def_b2fc, 0x78a5_636f_4317_2f60, 0x84c8_7814_a1f0_ab72, 0x8cc7_0208_1a64_39ec,\n            0x90be_fffa_2363_1e28, 0xa450_6ceb_de82_bde9, 0xbef9_a3f7_b2c6_7915, 0xc671_78f2_e372_532b,\n            0xca27_3ece_ea26_619c, 0xd186_b8c7_21c0_c207, 0xeada_7dd6_cde0_eb1e, 0xf57d_4f7f_ee6e_d178,\n            0x06f0_67aa_7217_6fba, 0x0a63_7dc5_a2c8_98a6, 0x113f_9804_bef9_0dae, 0x1b71_0b35_131c_471b,\n            0x28db_77f5_2304_7d84, 0x32ca_ab7b_40c7_2493, 0x3c9e_be0a_15c9_bebc, 0x431d_67c4_9c10_0d4c,\n            0x4cc5_d4be_cb3e_42b6, 0x597f_299c_fc65_7e2a, 0x5fcb_6fab_3ad6_faec, 0x6c44_198c_4a47_5817,\n        )\n\n        def __init__(self, data=b\"\"):\n            if self.digest_size is None:\n                raise ValueError(\"digest_size must be set in subclass\")\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n\n            self.h0 = self.initial_state[0]\n            self.h1 = self.initial_state[1]\n            self.h2 = self.initial_state[2]\n            self.h3 = self.initial_state[3]\n            self.h4 = self.initial_state[4]\n            self.h5 = self.initial_state[5]\n            self.h6 = self.initial_state[6]\n            self.h7 = self.initial_state[7]\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h0 = self.h0\n            other.h1 = self.h1\n            other.h2 = self.h2\n            other.h3 = self.h3\n            other.h4 = self.h4\n            other.h5 = self.h5\n            other.h6 = self.h6\n            other.h7 = self.h7\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 128:\n                block = bytes(self.buf[:128])\n                del self.buf[:128]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            full = struct.pack(\">8Q\", c.h0, c.h1, c.h2, c.h3, c.h4, c.h5, c.h6, c.h7)\n            return full[: self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # Padding: append 0x80, then 0x00* until length ≡ 112 (mod 128),\n            # then append message length in bits as 128-bit big-endian.\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n            while (len(self.buf) % 128) != 112:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\">QQ\", (bit_len >> 64) & 0xffff_ffff_ffff_ffff, bit_len & 0xffff_ffff_ffff_ffff))\n            while len(self.buf) >= 128:\n                block = bytes(self.buf[:128])\n                del self.buf[:128]\n                self.compress(block)\n            return\n\n        def rotr64(self, x, n):\n            x &= 0xffff_ffff_ffff_ffff\n            n &= 63\n            if n == 0:\n                return x\n            return ((x >> n) | (x << (64 - n))) & 0xffff_ffff_ffff_ffff\n\n        def shr64(self, x, n):\n            x &= 0xffff_ffff_ffff_ffff\n            return (x >> n) & 0xffff_ffff_ffff_ffff\n\n        def ch(self, x, y, z):\n            return (x & y) ^ ((~x) & z)\n\n        def maj(self, x, y, z):\n            return (x & y) ^ (x & z) ^ (y & z)\n\n        def big_sigma0(self, x):\n            return self.rotr64(x, 28) ^ self.rotr64(x, 34) ^ self.rotr64(x, 39)\n\n        def big_sigma1(self, x):\n            return self.rotr64(x, 14) ^ self.rotr64(x, 18) ^ self.rotr64(x, 41)\n\n        def small_sigma0(self, x):\n            return self.rotr64(x, 1) ^ self.rotr64(x, 8) ^ self.shr64(x, 7)\n\n        def small_sigma1(self, x):\n            return self.rotr64(x, 19) ^ self.rotr64(x, 61) ^ self.shr64(x, 6)\n\n        def compress(self, block):\n            w = list(struct.unpack(\">16Q\", block))\n            for i in range(16, 80):\n                v = (self.small_sigma1(w[i - 2]) + w[i - 7] + self.small_sigma0(w[i - 15]) + w[i - 16]) & 0xffff_ffff_ffff_ffff\n                w.append(v)\n\n            a = self.h0\n            b = self.h1\n            c = self.h2\n            d = self.h3\n            e = self.h4\n            f = self.h5\n            g = self.h6\n            h = self.h7\n\n            for i in range(80):\n                t1 = (h + self.big_sigma1(e) + self.ch(e, f, g) + self.K[i] + w[i]) & 0xffff_ffff_ffff_ffff\n                t2 = (self.big_sigma0(a) + self.maj(a, b, c)) & 0xffff_ffff_ffff_ffff\n                h = g\n                g = f\n                f = e\n                e = (d + t1) & 0xffff_ffff_ffff_ffff\n                d = c\n                c = b\n                b = a\n                a = (t1 + t2) & 0xffff_ffff_ffff_ffff\n\n            self.h0 = (self.h0 + a) & 0xffff_ffff_ffff_ffff\n            self.h1 = (self.h1 + b) & 0xffff_ffff_ffff_ffff\n            self.h2 = (self.h2 + c) & 0xffff_ffff_ffff_ffff\n            self.h3 = (self.h3 + d) & 0xffff_ffff_ffff_ffff\n            self.h4 = (self.h4 + e) & 0xffff_ffff_ffff_ffff\n            self.h5 = (self.h5 + f) & 0xffff_ffff_ffff_ffff\n            self.h6 = (self.h6 + g) & 0xffff_ffff_ffff_ffff\n            self.h7 = (self.h7 + h) & 0xffff_ffff_ffff_ffff\n            return\n\n    class SHA512_224(SHA512TruncBase):\n        digest_size = 28\n        initial_state = (\n            0x8c3d_37c8_1954_4da2, 0x73e1_9966_89dc_d4d6, 0x1dfa_b7ae_32ff_9c82, 0x679d_d514_582f_9fcf,\n            0x0f6d_2b69_7bd4_4da8, 0x77e3_6f73_04c4_8942, 0x3f9d_85a8_6a1d_36c8, 0x1112_e6ad_91d6_92a1,\n        )\n\n    class SHA512_256(SHA512TruncBase):\n        digest_size = 32\n        initial_state = (\n            0x2231_2194_fc2b_f72c, 0x9f55_5fa3_c84c_64c2, 0x2393_b86b_6f53_b151, 0x9638_7719_5940_eabd,\n            0x9628_3ee2_a88e_ffe3, 0xbe5e_1e25_5386_3992, 0x2b01_99fc_2c85_b8aa, 0x0eb7_2ddc_81c5_2ca2,\n        )\n\n    class KeccakBase:\n        # Keccak-f[1600] parameters\n        lanes = 25\n        rounds = 24\n        # Rho offsets (index = x + 5*y)\n        rho = (\n            0x00, 0x01, 0x3e, 0x1c, 0x1b, 0x24, 0x2c, 0x06, 0x37, 0x14, 0x03, 0x0a, 0x2b, 0x19, 0x27,\n            0x29, 0x2d, 0x0f, 0x15, 0x08, 0x12, 0x02, 0x3d, 0x38, 0x0e,\n        )\n        # Round constants\n        rc = (\n            0x0000_0000_0000_0001, 0x0000_0000_0000_8082, 0x8000_0000_0000_808a, 0x8000_0000_8000_8000,\n            0x0000_0000_0000_808b, 0x0000_0000_8000_0001, 0x8000_0000_8000_8081, 0x8000_0000_0000_8009,\n            0x0000_0000_0000_008a, 0x0000_0000_0000_0088, 0x0000_0000_8000_8009, 0x0000_0000_8000_000a,\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n\n        def __init__(self, data=b\"\"):\n            self.block_size = self.rate_bytes\n            self.state = [0] * 25\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n\n            while len(self.buf) >= self.rate_bytes:\n                block = bytes(self.buf[:self.rate_bytes])\n                del self.buf[:self.rate_bytes]\n                self.absorb(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = c.squeeze(self.digest_size)\n            return out\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # Keccak padding: pad10*1 with domain separation 0x01 (Keccak, not SHA3)\n            self.buf.append(0x01)\n            while (len(self.buf) % self.rate_bytes) != (self.rate_bytes - 1):\n                self.buf.append(0x00)\n            self.buf.append(0x80)\n\n            while len(self.buf) >= self.rate_bytes:\n                block = bytes(self.buf[:self.rate_bytes])\n                del self.buf[:self.rate_bytes]\n                self.absorb(block)\n            return\n\n        def absorb(self, block):\n            # XOR block into the first rate_bytes of the state (little-endian lanes)\n            lanes = self.rate_bytes // 8\n            for i in range(lanes):\n                v = struct.unpack_from(\"<Q\", block, i * 8)[0]\n                self.state[i] ^= v\n                self.state[i] &= 0xffff_ffff_ffff_ffff\n            self.permute(self.state)\n            return\n\n        def squeeze(self, out_len):\n            out = bytearray()\n            while len(out) < out_len:\n                block = self.state_bytes(self.rate_bytes)\n                need = out_len - len(out)\n                out.extend(block[:need])\n                if len(out) < out_len:\n                    self.permute(self.state)\n            return bytes(out)\n\n        def state_bytes(self, nbytes):\n            # Serialize the first nbytes of the state (little-endian lanes)\n            out = bytearray()\n            lanes = (nbytes + 7) // 8\n            for i in range(lanes):\n                out.extend(struct.pack(\"<Q\", self.state[i] & 0xffff_ffff_ffff_ffff))\n            return bytes(out[:nbytes])\n\n        def permute(self, a):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            for rnd in range(24):\n                # Theta\n                c = [0] * 5\n                for x in range(5):\n                    c[x] = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20]\n                d = [0] * 5\n                for x in range(5):\n                    d[x] = c[(x - 1) % 5] ^ rol64(c[(x + 1) % 5], 1)\n                for y in range(5):\n                    for x in range(5):\n                        a[x + 5 * y] ^= d[x]\n\n                # Rho + Pi\n                b = [0] * 25\n                for y in range(5):\n                    for x in range(5):\n                        idx = x + 5 * y\n                        rot = self.rho[idx]\n                        v = rol64(a[idx], rot)\n                        x2 = y\n                        y2 = (2 * x + 3 * y) % 5\n                        b[x2 + 5 * y2] = v\n\n                # Chi\n                for y in range(5):\n                    row = [b[x + 5 * y] for x in range(5)]\n                    for x in range(5):\n                        a[x + 5 * y] = row[x] ^ ((~row[(x + 1) % 5]) & row[(x + 2) % 5])\n\n                # Iota\n                a[0] ^= self.rc[rnd]\n\n            return\n\n    class Keccak224(KeccakBase):\n        rate_bytes = 144\n        digest_size = 28\n\n    class Keccak256(KeccakBase):\n        rate_bytes = 136\n        digest_size = 32\n\n    class Keccak384(KeccakBase):\n        rate_bytes = 104\n        digest_size = 48\n\n    class Keccak512(KeccakBase):\n        rate_bytes = 72\n        digest_size = 64\n\n    class TurboShakeBase:\n        # Keccak-p[1600,12] with little-endian 64-bit lanes\n        rounds = 12\n        domain = 0x1f\n        rho = (\n            0x00, 0x01, 0x3e, 0x1c, 0x1b, 0x24, 0x2c, 0x06, 0x37, 0x14, 0x03, 0x0a, 0x2b, 0x19, 0x27,\n            0x29, 0x2d, 0x0f, 0x15, 0x08, 0x12, 0x02, 0x3d, 0x38, 0x0e,\n        )\n        # Keccak-f[1600] round constants; Keccak-p[1600,12] uses the last 12 of these.\n        rc_last12 = (\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n\n        def __init__(self, data=b\"\", digest_bits=128):\n            self.digest_size = digest_bits // 8\n            self.block_size = self.rate_bytes\n            self.state = [0] * 25\n            self.buf = bytearray()\n            self.msg_len = 0\n\n            lane_count = self.rate_bytes // 8\n            self.lane_unpack = struct.Struct(\"<\" + (\"Q\" * lane_count))\n            self.lane_pack = struct.Struct(\"<\" + (\"Q\" * lane_count))\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(digest_bits=self.digest_size * 8)\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            mv = memoryview(data)\n            self.msg_len += len(mv)\n\n            # First, fill the partial block if any.\n            if self.buf:\n                need = self.rate_bytes - len(self.buf)\n                if len(mv) < need:\n                    self.buf.extend(mv)\n                    return self\n\n                self.buf.extend(mv[:need])\n                self.absorb(self.buf)\n                self.buf.clear()\n                mv = mv[need:]\n\n            # Process full blocks directly from input without copying/deleting from the front.\n            full_len = (len(mv) // self.rate_bytes) * self.rate_bytes\n            for off in range(0, full_len, self.rate_bytes):\n                self.absorb(mv[off:off + self.rate_bytes])\n\n            # Keep only the tail.\n            if full_len != len(mv):\n                self.buf.extend(mv[full_len:])\n\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = c.squeeze(self.digest_size)\n            return out\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # update() invariant: self.buf length is always < rate_bytes.\n            self.buf.append(self.domain)\n\n            rem = len(self.buf) % self.rate_bytes\n            if rem != 0:\n                self.buf.extend(b\"\\x00\" * (self.rate_bytes - rem))\n\n            self.buf[-1] ^= 0x80\n\n            # Exactly one block should exist here.\n            self.absorb(self.buf)\n            self.buf.clear()\n            return\n\n        def absorb(self, block):\n            values = self.lane_unpack.unpack_from(block)\n            state = self.state\n\n            for i, v in enumerate(values):\n                state[i] = (state[i] ^ v) & 0xffff_ffff_ffff_ffff\n\n            self.keccak_p1600_12(state)\n            return\n\n        def squeeze(self, out_len):\n            out = bytearray()\n            while len(out) < out_len:\n                out.extend(self.state_bytes(self.rate_bytes))\n                if len(out) < out_len:\n                    self.keccak_p1600_12(self.state)\n            return bytes(out[:out_len])\n\n        def state_bytes(self, nbytes):\n            lane_count = self.rate_bytes // 8\n            packed = self.lane_pack.pack(*[\n                self.state[i] & 0xffff_ffff_ffff_ffff\n                for i in range(lane_count)\n            ])\n            return packed[:nbytes]\n\n        def keccak_p1600_12(self, a):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            for rnd in range(12):\n                # Theta\n                c = [0] * 5\n                for x in range(5):\n                    c[x] = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20]\n                d = [0] * 5\n                for x in range(5):\n                    d[x] = c[(x - 1) % 5] ^ rol64(c[(x + 1) % 5], 1)\n                for y in range(5):\n                    for x in range(5):\n                        a[x + 5 * y] ^= d[x]\n\n                # Rho + Pi\n                b = [0] * 25\n                for y in range(5):\n                    for x in range(5):\n                        idx = x + 5 * y\n                        rot = self.rho[idx]\n                        v = rol64(a[idx], rot)\n                        x2 = y\n                        y2 = (2 * x + 3 * y) % 5\n                        b[x2 + 5 * y2] = v\n\n                # Chi\n                for y in range(5):\n                    row = [b[x + 5 * y] for x in range(5)]\n                    for x in range(5):\n                        a[x + 5 * y] = row[x] ^ ((~row[(x + 1) % 5]) & row[(x + 2) % 5])\n\n                # Iota\n                a[0] ^= self.rc_last12[rnd]\n            return\n\n    class TurboShake128(TurboShakeBase):\n        rate_bytes = 168  # 1344 bits\n\n    class TurboShake256(TurboShakeBase):\n        rate_bytes = 136  # 1088 bits\n\n    class KangarooTwelveBase:\n        # Keccak-p[1600,12] parameters\n        rho = (\n            0x00, 0x01, 0x3e, 0x1c, 0x1b, 0x24, 0x2c, 0x06, 0x37, 0x14, 0x03, 0x0a, 0x2b, 0x19, 0x27,\n            0x29, 0x2d, 0x0f, 0x15, 0x08, 0x12, 0x02, 0x3d, 0x38, 0x0e,\n        )\n        # Round constants\n        rc_last12 = (\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n        # K12 chunk size (bytes)\n        chunk_size = 8192\n\n        def __init__(self, data=b\"\", custom=b\"\", digest_bits=128):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(custom, (bytes, bytearray, memoryview)):\n                raise TypeError(\"custom must be bytes-like\")\n            self.digest_size = digest_bits // 8\n            self.block_size = self.chunk_size\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            self.custom = custom\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", custom=self.custom, digest_bits=self.digest_size * 8)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.result\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            m = bytes(self.buf)\n            self.result = self.k12(m, self.custom, self.digest_size)\n            return\n\n        def k12(self, m, custom, out_len):\n            s = m + custom + self.length_encode(len(custom))\n\n            if len(s) <= self.chunk_size:\n                out = self.turbo_shake(s, 7, out_len)\n                return out\n\n            chunks = []\n            for i in range(0, len(s), self.chunk_size):\n                chunks.append(s[i:i + self.chunk_size])\n\n            n = len(chunks)\n\n            final_node = bytearray()\n            final_node.extend(chunks[0])\n            final_node.extend(b\"\\x03\" + (b\"\\x00\" * 7))\n\n            for i in range(1, n):\n                cv = self.turbo_shake(chunks[i], 11, self.cv_len)\n                final_node.extend(cv)\n\n            final_node.extend(self.length_encode(n - 1))\n            final_node.extend(b\"\\xff\\xff\")\n\n            out = self.turbo_shake(bytes(final_node), 6, out_len)\n            return out\n\n        def length_encode(self, x):\n            if x < 0:\n                raise ValueError(\"x must be non-negative\")\n            s = bytearray()\n            while x > 0:\n                s.insert(0, x & 0xff)\n                x //= 256\n            s.append(len(s) & 0xff)\n            return bytes(s)\n\n        def turbo_shake(self, m, d, out_len):\n            if not isinstance(m, (bytes, bytearray, memoryview)):\n                raise TypeError(\"m must be bytes-like\")\n            if not (1 <= d <= 127):\n                raise ValueError(\"domain byte d must be in [0x01..0x7f]\")\n            if out_len <= 0:\n                raise ValueError(\"out_len must be positive\")\n\n            mp = bytearray(m)\n            mp.append(d)\n\n            rem = len(mp) % self.rate_bytes\n            if rem != 0:\n                mp.extend(b\"\\x00\" * (self.rate_bytes - rem))\n\n            mp[-1] ^= 0x80\n\n            a = [0] * 25\n            lanes = self.rate_bytes // 8\n\n            for off in range(0, len(mp), self.rate_bytes):\n                block = mp[off:off + self.rate_bytes]\n                for i in range(lanes):\n                    v = struct.unpack_from(\"<Q\", block, i * 8)[0]\n                    a[i] ^= v\n                self.keccak_p1600_12(a)\n\n            out = bytearray()\n            while len(out) < out_len:\n                out.extend(self.state_bytes(a, self.rate_bytes))\n                if len(out) < out_len:\n                    self.keccak_p1600_12(a)\n\n            return bytes(out[:out_len])\n\n        def state_bytes(self, a, nbytes):\n            out = bytearray()\n            lanes = (nbytes + 7) // 8\n            for i in range(lanes):\n                out.extend(struct.pack(\"<Q\", a[i] & 0xffff_ffff_ffff_ffff))\n            return bytes(out[:nbytes])\n\n        def keccak_p1600_12(self, a):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            for rnd in range(12):\n                # Theta\n                c = [0] * 5\n                for x in range(5):\n                    c[x] = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20]\n                d = [0] * 5\n                for x in range(5):\n                    d[x] = c[(x - 1) % 5] ^ rol64(c[(x + 1) % 5], 1)\n                for y in range(5):\n                    for x in range(5):\n                        a[x + 5 * y] ^= d[x]\n\n                # Rho + Pi\n                b = [0] * 25\n                for y in range(5):\n                    for x in range(5):\n                        idx = x + 5 * y\n                        rot = self.rho[idx]\n                        v = rol64(a[idx], rot)\n                        x2 = y\n                        y2 = (2 * x + 3 * y) % 5\n                        b[x2 + 5 * y2] = v\n\n                # Chi\n                for y in range(5):\n                    row = [b[x + 5 * y] for x in range(5)]\n                    for x in range(5):\n                        a[x + 5 * y] = row[x] ^ ((~row[(x + 1) % 5]) & row[(x + 2) % 5])\n\n                # Iota\n                a[0] ^= self.rc_last12[rnd]\n            return\n\n    class KangarooTwelve128(KangarooTwelveBase):\n        rate_bytes = 168  # TurboSHAKE128 rate\n        cv_len = 32  # KT128 chaining value length\n\n    class KangarooTwelve256(KangarooTwelveBase):\n        rate_bytes = 136  # TurboSHAKE256 rate\n        cv_len = 64  # KT256 chaining value length\n\n    class KMACBase:\n        rho = (\n            0x00, 0x01, 0x3e, 0x1c, 0x1b, 0x24, 0x2c, 0x06, 0x37, 0x14, 0x03, 0x0a, 0x2b, 0x19, 0x27,\n            0x29, 0x2d, 0x0f, 0x15, 0x08, 0x12, 0x02, 0x3d, 0x38, 0x0e,\n        )\n        rc = (\n            0x0000_0000_0000_0001, 0x0000_0000_0000_8082, 0x8000_0000_0000_808a, 0x8000_0000_8000_8000,\n            0x0000_0000_0000_808b, 0x0000_0000_8000_0001, 0x8000_0000_8000_8081, 0x8000_0000_0000_8009,\n            0x0000_0000_0000_008a, 0x0000_0000_0000_0088, 0x0000_0000_8000_8009, 0x0000_0000_8000_000a,\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n\n        def __init__(self, key=b\"\", data=b\"\", custom=b\"\", digest_bits=None):\n            if not isinstance(key, (bytes, bytearray, memoryview)):\n                raise TypeError(\"key must be bytes-like\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(custom, (bytes, bytearray, memoryview)):\n                raise TypeError(\"custom must be bytes-like\")\n            key = bytes(key)\n            data = bytes(data)\n            custom = bytes(custom)\n\n            if digest_bits is not None:\n                digest_size = digest_bits // 8\n                if digest_size < 1:\n                    raise ValueError(\"digest_size must be a positive integer\")\n                self.digest_size = digest_size\n\n            self.key = key\n            self.custom = custom\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(self.key, b\"\", self.custom, self.digest_size * 8)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def finalize(self):\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.kmac(self.key, bytes(c.buf), c.digest_size * 8, c.custom)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def left_encode(self, x):\n            if not isinstance(x, int) or x < 0:\n                raise ValueError(\"x must be a non-negative integer\")\n            n = 1\n            while (x >> (8 * n)) != 0:\n                n += 1\n            out = bytes([n]) + x.to_bytes(n, \"big\")\n            return out\n\n        def right_encode(self, x):\n            if not isinstance(x, int) or x < 0:\n                raise ValueError(\"x must be a non-negative integer\")\n            n = 1\n            while (x >> (8 * n)) != 0:\n                n += 1\n            out = x.to_bytes(n, \"big\") + bytes([n])\n            return out\n\n        def encode_string(self, s):\n            if not isinstance(s, (bytes, bytearray, memoryview)):\n                raise TypeError(\"s must be bytes-like\")\n            s = bytes(s)\n            out = self.left_encode(len(s) * 8) + s\n            return out\n\n        def bytepad(self, x, w):\n            if not isinstance(x, (bytes, bytearray, memoryview)):\n                raise TypeError(\"x must be bytes-like\")\n            if not isinstance(w, int) or w <= 0:\n                raise ValueError(\"w must be a positive integer\")\n            x = bytes(x)\n            z = self.left_encode(w) + x\n            pad_len = (-len(z)) % w\n            out = z + (b\"\\x00\" * pad_len)\n            return out\n\n        def keccak_f1600(self, a):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            for rnd in range(24):\n                # Theta\n                c = [0] * 5\n                for x in range(5):\n                    c[x] = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20]\n                d = [0] * 5\n                for x in range(5):\n                    d[x] = c[(x - 1) % 5] ^ rol64(c[(x + 1) % 5], 1)\n                for y in range(5):\n                    for x in range(5):\n                        a[x + 5 * y] ^= d[x]\n\n                # Rho + Pi\n                b = [0] * 25\n                for y in range(5):\n                    for x in range(5):\n                        idx = x + 5 * y\n                        rot = self.rho[idx]\n                        v = rol64(a[idx], rot)\n                        x2 = y\n                        y2 = (2 * x + 3 * y) % 5\n                        b[x2 + 5 * y2] = v\n\n                # Chi\n                for y in range(5):\n                    row = [b[x + 5 * y] for x in range(5)]\n                    for x in range(5):\n                        a[x + 5 * y] = row[x] ^ ((~row[(x + 1) % 5]) & row[(x + 2) % 5])\n\n                # Iota\n                a[0] ^= self.rc[rnd]\n            return\n\n        def sponge(self, data, outlen, rate, suffix):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(outlen, int) or outlen < 0:\n                raise ValueError(\"outlen must be a non-negative integer\")\n            if not isinstance(rate, int) or rate <= 0:\n                raise ValueError(\"rate must be a positive integer\")\n            if not isinstance(suffix, int) or not (0 <= suffix <= 255):\n                raise ValueError(\"suffix must be a byte\")\n\n            data = bytes(data)\n            msg = bytearray(data)\n            msg.append(suffix)\n            while (len(msg) % rate) != (rate - 1):\n                msg.append(0)\n            msg.append(0x80)\n\n            s = [0] * 25\n            rate_words = rate // 8\n\n            off = 0\n            while off < len(msg):\n                block = msg[off:off + rate]\n                for i in range(rate_words):\n                    lane = int.from_bytes(block[i * 8:(i + 1) * 8], \"little\")\n                    s[i] ^= lane\n                self.keccak_f1600(s)\n                off += rate\n\n            out = bytearray()\n            while len(out) < outlen:\n                chunk = bytearray()\n                for i in range(rate_words):\n                    chunk.extend(s[i].to_bytes(8, \"little\"))\n                take = min(outlen - len(out), rate)\n                out.extend(chunk[:take])\n                if len(out) < outlen:\n                    self.keccak_f1600(s)\n\n            return bytes(out)\n\n        def cshake(self, x, outlen_bytes, n, s):\n            if not isinstance(x, (bytes, bytearray, memoryview)):\n                raise TypeError(\"x must be bytes-like\")\n            if not isinstance(n, (bytes, bytearray, memoryview)):\n                raise TypeError(\"n must be bytes-like\")\n            if not isinstance(s, (bytes, bytearray, memoryview)):\n                raise TypeError(\"s must be bytes-like\")\n            x = bytes(x)\n            n = bytes(n)\n            s = bytes(s)\n\n            if n == b\"\" and s == b\"\":\n                return self.sponge(x, outlen_bytes, self.block_size, 31)\n\n            prefix = self.bytepad(self.encode_string(n) + self.encode_string(s), self.block_size)\n            return self.sponge(prefix + x, outlen_bytes, self.block_size, 4)\n\n        def kmac(self, key, x, l_bits, custom):\n            if not isinstance(key, (bytes, bytearray, memoryview)):\n                raise TypeError(\"key must be bytes-like\")\n            if not isinstance(x, (bytes, bytearray, memoryview)):\n                raise TypeError(\"x must be bytes-like\")\n            if not isinstance(custom, (bytes, bytearray, memoryview)):\n                raise TypeError(\"custom must be bytes-like\")\n            if not isinstance(l_bits, int) or l_bits < 0:\n                raise ValueError(\"l_bits must be a non-negative integer\")\n            if (l_bits % 8) != 0:\n                raise ValueError(\"l_bits must be a multiple of 8\")\n\n            key = bytes(key)\n            x = bytes(x)\n            custom = bytes(custom)\n\n            new_x = self.bytepad(self.encode_string(key), self.block_size) + x + self.right_encode(l_bits)\n            outlen_bytes = l_bits // 8\n            return self.cshake(new_x, outlen_bytes, b\"KMAC\", custom)\n\n    class KMAC128(KMACBase):\n        block_size = 168  # rate for cshake_128/kmac_128\n        digest_size = 32  # 256 bits\n\n    class KMAC256(KMACBase):\n        block_size = 136  # rate for cshake_256/kmac_256\n        digest_size = 64  # 512 bits\n\n    class TupleHashBase:\n        rho = (\n            0x00, 0x01, 0x3e, 0x1c, 0x1b, 0x24, 0x2c, 0x06, 0x37, 0x14, 0x03, 0x0a, 0x2b, 0x19, 0x27,\n            0x29, 0x2d, 0x0f, 0x15, 0x08, 0x12, 0x02, 0x3d, 0x38, 0x0e,\n        )\n        rc = (\n            0x0000_0000_0000_0001, 0x0000_0000_0000_8082, 0x8000_0000_0000_808a, 0x8000_0000_8000_8000,\n            0x0000_0000_0000_808b, 0x0000_0000_8000_0001, 0x8000_0000_8000_8081, 0x8000_0000_0000_8009,\n            0x0000_0000_0000_008a, 0x0000_0000_0000_0088, 0x0000_0000_8000_8009, 0x0000_0000_8000_000a,\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n\n        def __init__(self, data=b\"\", custom=b\"\", digest_bits=None):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(custom, (bytes, bytearray, memoryview)):\n                raise TypeError(\"custom must be bytes-like\")\n\n            self.suffix = 0x04  # cSHAKE domain separation suffix\n            self.output_bits = digest_bits\n\n            if digest_bits is not None:\n                self.digest_size = digest_bits // 8\n\n            self.state = [0] * 25  # 25 lanes of 64-bit\n            self.buf = bytearray()\n            self.finalized = False\n\n            self.custom = bytes(custom)\n\n            # cSHAKE init: absorb bytepad(encode_string(N) || encode_string(S), rate)\n            n = b\"TupleHash\"\n            init = self.bytepad(self.encode_string(n) + self.encode_string(self.custom), self.rate)\n            self.absorb(init)\n\n            if data:\n                self.update(bytes(data))\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.custom)\n            other.rate = self.rate\n            other.suffix = self.suffix\n            other.output_bits = self.output_bits\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"cannot update after finalize\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n\n            # TupleHash input is a tuple of strings: update(data) == append one element\n            self.absorb(self.encode_string(data))\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = c.squeeze(self.digest_size)\n            return out\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            # Append right_encode(L) where L is output length in bits\n            self.absorb(self.right_encode(self.output_bits))\n\n            # Apply cSHAKE padding and switch to squeezing\n            self.pad_and_permute()\n            self.finalized = True\n            return\n\n        def keccak_f1600(self, a):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            for rnd in range(24):\n                # Theta\n                c = [0] * 5\n                for x in range(5):\n                    c[x] = a[x] ^ a[x + 5] ^ a[x + 10] ^ a[x + 15] ^ a[x + 20]\n                d = [0] * 5\n                for x in range(5):\n                    d[x] = c[(x - 1) % 5] ^ rol64(c[(x + 1) % 5], 1)\n                for y in range(5):\n                    for x in range(5):\n                        a[x + 5 * y] ^= d[x]\n\n                # Rho + Pi\n                b = [0] * 25\n                for y in range(5):\n                    for x in range(5):\n                        idx = x + 5 * y\n                        rot = self.rho[idx]\n                        v = rol64(a[idx], rot)\n                        x2 = y\n                        y2 = (2 * x + 3 * y) % 5\n                        b[x2 + 5 * y2] = v\n\n                # Chi\n                for y in range(5):\n                    row = [b[x + 5 * y] for x in range(5)]\n                    for x in range(5):\n                        a[x + 5 * y] = row[x] ^ ((~row[(x + 1) % 5]) & row[(x + 2) % 5])\n\n                # Iota\n                a[0] ^= self.rc[rnd]\n            return\n\n        def absorb(self, data):\n            if self.finalized:\n                raise ValueError(\"cannot absorb after finalize\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n\n            self.buf.extend(data)\n            while len(self.buf) >= self.rate:\n                block = bytes(self.buf[:self.rate])\n                del self.buf[:self.rate]\n                self.xor_into_state(block)\n                self.keccak_f1600(self.state)\n            return\n\n        def xor_into_state(self, block):\n            # XOR block into state lanes (little-endian)\n            lanes = self.rate // 8\n            for i in range(lanes):\n                v = int.from_bytes(block[i * 8:(i + 1) * 8], \"little\")\n                self.state[i] ^= v\n            return\n\n        def pad_and_permute(self):\n            # pad10*1 with domain suffix (cSHAKE uses 0x04)\n            self.buf.append(self.suffix)\n\n            if len(self.buf) > self.rate:\n                # should not happen, but keep strict\n                raise ValueError(\"internal buffer overflow\")\n\n            if len(self.buf) == self.rate:\n                # last byte already present; set MSB and absorb\n                self.buf[self.rate - 1] |= 0x80\n                block = bytes(self.buf)\n                self.buf.clear()\n                self.xor_into_state(block)\n                self.keccak_f1600(self.state)\n                return\n\n            while len(self.buf) < self.rate:\n                self.buf.append(0x00)\n\n            self.buf[self.rate - 1] |= 0x80\n            block = bytes(self.buf)\n            self.buf.clear()\n            self.xor_into_state(block)\n            self.keccak_f1600(self.state)\n            return\n\n        def squeezeblock(self):\n            # Extract rate bytes from state (little-endian)\n            out = bytearray()\n            lanes = self.rate // 8\n            for i in range(lanes):\n                out.extend(self.state[i].to_bytes(8, \"little\"))\n            return bytes(out)\n\n        def squeeze(self, outlen):\n            if not self.finalized:\n                raise ValueError(\"must finalize before squeeze\")\n            if outlen < 0:\n                raise ValueError(\"outlen must be non-negative\")\n\n            out = bytearray()\n            while len(out) < outlen:\n                block = self.squeezeblock()\n                take = min(outlen - len(out), self.rate)\n                out.extend(block[:take])\n                if len(out) < outlen:\n                    self.keccak_f1600(self.state)\n            return bytes(out)\n\n        def left_encode(self, x):\n            if x < 0:\n                raise ValueError(\"x must be non-negative\")\n            n = 1\n            t = x\n            while t > 0xff:\n                n += 1\n                t >>= 8\n            return bytes([n]) + x.to_bytes(n, \"big\")\n\n        def right_encode(self, x):\n            if x < 0:\n                raise ValueError(\"x must be non-negative\")\n            n = 1\n            t = x\n            while t > 0xff:\n                n += 1\n                t >>= 8\n            return x.to_bytes(n, \"big\") + bytes([n])\n\n        def encode_string(self, s):\n            if not isinstance(s, (bytes, bytearray, memoryview)):\n                raise TypeError(\"s must be bytes-like\")\n            s = bytes(s)\n            return self.left_encode(len(s) * 8) + s\n\n        def bytepad(self, x, w):\n            if w <= 0:\n                raise ValueError(\"w must be positive\")\n            if not isinstance(x, (bytes, bytearray, memoryview)):\n                raise TypeError(\"x must be bytes-like\")\n            x = bytes(x)\n\n            z = bytearray()\n            z.extend(self.left_encode(w))\n            z.extend(x)\n            while (len(z) % w) != 0:\n                z.append(0x00)\n            return bytes(z)\n\n    class TupleHash128(TupleHashBase):\n        # TupleHash128 = cSHAKE128 with N=\"TupleHash\"\n        block_size = 168  # rate in bytes (Keccak[1600], r=1344)\n        digest_size = 16  # 128 bits\n        rate = 168\n\n    class TupleHash256(TupleHashBase):\n        # TupleHash256 = cSHAKE256 with N=\"TupleHash\"\n        block_size = 136  # rate in bytes (Keccak[1600], r=1088)\n        digest_size = 32  # 256 bits\n        rate = 136\n\n    class TIGER:\n        block_size = 64\n\n        sbox1 = (\n            0x02aa_b17c_f7e9_0c5e, 0xac42_4b03_e243_a8ec, 0x72cd_5be3_0dd5_fcd3, 0x6d01_9b93_f6f9_7f3a,\n            0xcd99_78ff_d21f_9193, 0x7573_a1c9_7080_29e2, 0xb164_326b_922a_83c3, 0x4688_3eee_0491_5870,\n            0xeaac_e305_7103_ece6, 0xc541_69b8_08a3_535c, 0x4ce7_5491_8dde_c47c, 0x0aa2_f4df_dc0d_f40c,\n            0x10b7_6f18_a74d_befa, 0xc6cc_b623_5ad1_ab6a, 0x1372_6121_572f_e2ff, 0x1a48_8c6f_199d_921e,\n            0x4bc9_f9f4_da00_07ca, 0x26f5_e6f6_e852_41c7, 0x8590_79db_ea59_47b6, 0x4f18_85c5_c99e_8c92,\n            0xd78e_761e_a96f_864b, 0x8e36_428c_52b5_c17d, 0x69cf_6827_3730_63c1, 0xb607_c93d_9bb4_c56e,\n            0x7d82_0e76_0e76_b5ea, 0x645c_9cc6_f07f_dc42, 0xbf38_a078_2433_42e0, 0x5f6b_343c_9d2e_7d04,\n            0xf2c2_8aeb_600b_0ec6, 0x6c0e_d85f_7254_bcac, 0x7159_2281_a4db_4fe5, 0x1967_fa69_ce0f_ed9f,\n            0xfd52_93f8_b965_45db, 0xc879_e9d7_f2a7_600b, 0x8602_4892_0193_194e, 0xa4f9_533b_2d9c_c0b3,\n            0x9053_836c_1595_7613, 0xdb6d_cf8a_fc35_7bf1, 0x18be_ea7a_7a37_0f57, 0x0371_17ca_50b9_9066,\n            0x6ab3_0a97_7442_4a35, 0xf4e9_2f02_e325_249b, 0x7739_db07_061c_cae1, 0xd8f3_b49c_eca4_2a05,\n            0xbd56_be3f_5138_2f73, 0x45fa_ed58_43b0_bb28, 0x1c81_3d5c_11bf_1f83, 0x8af0_e4b6_d75f_a169,\n            0x33ee_18a4_87ad_9999, 0x3c26_e8ea_b1c9_4410, 0xb510_102b_c0a8_22f9, 0x141e_ef31_0ce6_123b,\n            0xfc65_b900_59dd_b154, 0xe015_8640_c5e0_e607, 0x884e_0798_26c3_a3cf, 0x930d_0d95_23c5_35fd,\n            0x3563_8d75_4e9a_2b00, 0x4085_fccf_4046_9dd5, 0xc4b1_7ad2_8be2_3a4c, 0xcab2_f0fc_6a3e_6a2e,\n            0x2860_971a_6b94_3fcd, 0x3dde_6ee2_12e3_0446, 0x6222_f32a_e017_65ae, 0x5d55_0bb5_4783_08fe,\n            0xa9ef_a98d_a0ed_a22a, 0xc351_a716_86c4_0da7, 0x1105_586d_9c86_7c84, 0xdcff_ee85_fda2_2853,\n            0xccfb_d026_2c5e_ef76, 0xbaf2_94cb_8990_d201, 0xe694_64f5_2afa_d975, 0x94b0_13af_df13_3e14,\n            0x06a7_d1a3_2823_c958, 0x6f95_fe51_30f6_1119, 0xd92a_b34e_462c_06c0, 0xed7b_de33_887c_71d2,\n            0x7974_6d6e_6518_393e, 0x5ba4_1938_5d71_3329, 0x7c1b_a6b9_48a9_7564, 0x3198_7c19_7bfd_ac67,\n            0xde6c_23c4_4b05_3d02, 0x581c_49fe_d002_d64d, 0xdd47_4d63_3826_1571, 0xaa45_46c3_e473_d062,\n            0x928f_ce34_9455_f860, 0x4816_1bba_caab_94d9, 0x6391_2430_770e_6f68, 0x6ec8_a5e6_02c6_641c,\n            0x8728_2515_337d_dd2b, 0x2cda_6b42_034b_701b, 0xb03d_37c1_81cb_096d, 0xe108_4382_66c7_1c6f,\n            0x2b31_80c7_eb51_b255, 0xdf92_b82f_96c0_8bbc, 0x5c68_c8c0_a632_f3ba, 0x5504_cc86_1c3d_0556,\n            0xabbf_a4e5_5fb2_6b8f, 0x4184_8b0a_b3ba_ceb4, 0xb334_a273_aa44_5d32, 0xbca6_96f0_a85a_d881,\n            0x24f6_ec65_b528_d56c, 0x0ce1_512e_90f4_524a, 0x4e9d_d79d_5506_d35a, 0x2589_05fa_c6ce_9779,\n            0x2019_295b_3e10_9b33, 0xf8a9_478b_73a0_54cc, 0x2924_f2f9_3441_7eb0, 0x3993_357d_536d_1bc4,\n            0x38a8_1ac2_1db6_ff8b, 0x47c4_fbf1_7d60_16bf, 0x1e0f_aadd_7667_e3f5, 0x7abc_ff62_938b_eb96,\n            0xa78d_ad94_8fc1_79c9, 0x8f1f_98b7_2911_e50d, 0x61e4_8eae_2712_1a91, 0x4d62_f7ad_3185_9808,\n            0xeceb_a345_ef5c_eaeb, 0xf5ce_b25e_bc96_84ce, 0xf633_e20c_b7f7_6221, 0xa32c_df06_ab82_93e4,\n            0x985a_202c_a5ee_2ca4, 0xcf0b_8447_cc8a_8fb1, 0x9f76_5244_9798_59a3, 0xa8d5_16b1_a124_0017,\n            0x0bd7_ba3e_bb5d_c726, 0xe54b_ca55_b86a_db39, 0x1d7a_3afd_6c47_8063, 0x519e_c608_e766_9edd,\n            0x0e57_15a2_d149_aa23, 0x177d_4571_848f_f194, 0xeeb5_5f32_4101_4c22, 0x0f5e_5ca1_3a6e_2ec2,\n            0x8029_927b_75f5_c361, 0xad13_9fab_c3d6_e436, 0x0d5d_f1a9_4ccf_402f, 0x3e8b_d948_bea5_dfc8,\n            0xa5a0_d357_bd3f_f77e, 0xa2d1_2e25_1f74_f645, 0x66fd_9e52_5e81_a082, 0x2e0c_90ce_7f68_7a49,\n            0xc2e8_bcbe_ba97_3bc5, 0x0000_01bc_e509_745f, 0x4237_77bb_e6da_b3d6, 0xd166_1c7e_aef0_6eb5,\n            0xa178_1f35_4daa_cfd8, 0x2d11_284a_2b16_affc, 0xf1fc_4f67_fa89_1d1f, 0x73ec_c25d_cb92_0ada,\n            0xae61_0c22_c2a1_2651, 0x96e0_a810_d356_b78a, 0x5a9a_381f_2fe7_870f, 0xd5ad_62ed_e94e_5530,\n            0xd225_e5e8_368d_1427, 0x6597_7b70_c7af_4631, 0x99f8_89b2_de39_d74f, 0x233f_30bf_54e1_d143,\n            0x9a96_75d3_d9a6_3c97, 0x5470_554f_f334_f9a8, 0x166a_cb74_4a4f_5688, 0x70c7_4caa_b2e4_aead,\n            0xf0d0_9164_6f29_4d12, 0x57b8_2a89_6840_31d1, 0xefd9_5a5a_61be_0b6b, 0x2fbd_12e9_69f2_f29a,\n            0x9bd3_7013_feff_9fe8, 0x3f9b_0404_d608_5a06, 0x4940_c1f3_166c_fe15, 0x0954_2c4d_cdf3_defb,\n            0xb4c5_2183_85cd_5ce3, 0xc935_b7dc_4462_a641, 0x3417_f8a6_8ed3_b63f, 0xb809_5929_5b21_5b40,\n            0xf99c_daef_3b8c_8572, 0x018c_0614_f8fc_b95d, 0x1b14_accd_1a3a_cdf3, 0x84d4_71f2_00bb_732d,\n            0xc1a3_110e_95e8_da16, 0x430a_7220_bf1a_82b8, 0xb77e_090d_39df_210e, 0x5ef4_bd9f_3cd0_5e9d,\n            0x9d4f_f6da_7e57_a444, 0xda1d_60e1_83d4_a5f8, 0xb287_c384_1799_8e47, 0xfe3e_dc12_1bb3_1886,\n            0xc7fe_3ccc_980c_cbef, 0xe46f_b590_189b_fd03, 0x3732_fd46_9a4c_57dc, 0x7ef7_00a0_7cf1_ad65,\n            0x59c6_4468_a31d_8859, 0x762f_b0b4_d45b_61f6, 0x155b_aed0_9904_7718, 0x6875_5e4c_3d50_baa6,\n            0xe921_4e7f_22d8_b4df, 0x2add_bf53_2eac_95f4, 0x32ae_3909_b4bd_0109, 0x834d_f537_b08e_3450,\n            0xfa20_9da8_4220_728d, 0x9e69_1d9b_9efe_23f7, 0x0446_d288_c4ae_8d7f, 0x7b4c_c524_e169_785b,\n            0x21d8_7f01_35ca_1385, 0xcebb_400f_137b_8aa5, 0x272e_2b66_5807_96be, 0x3612_2641_25c2_b0de,\n            0x0577_02bd_ad1e_fbb2, 0xd4ba_bb8e_acf8_4be9, 0x9158_3139_641b_c67b, 0x8bdc_2de0_8036_e024,\n            0x603c_8156_f49f_68ed, 0xf7d2_36f7_dbef_5111, 0x9727_c459_8ad2_1e80, 0xa08a_0896_670a_5fd7,\n            0xcb4a_8f43_09eb_a9cb, 0x81af_564b_0f70_36a1, 0xc0b9_9aa7_7819_9abd, 0x959f_1ec8_3fc8_e952,\n            0x8c50_5077_794a_81b9, 0x3aca_af8f_0563_38f0, 0x07b4_3f50_627a_6778, 0x4a44_ab49_f5ec_cc77,\n            0x3bc3_d6e4_b679_ee98, 0x9cc0_d4d1_cf14_108c, 0x4406_c00b_206b_c8a0, 0x82a1_8854_c8d7_2d89,\n            0x67e3_66b3_5c3c_432c, 0xb923_dd61_102b_37f2, 0x56ab_2779_d884_271d, 0xbe83_e1b0_ff15_25af,\n            0xfb7c_65d4_217e_49a9, 0x6bdb_e0e7_6d48_e7d4, 0x08df_8287_45d9_179e, 0x22ea_6a9a_dd53_bd34,\n            0xe36e_141c_5622_200a, 0x7f80_5d1b_8cb7_50ee, 0xafe5_c7a5_9f58_e837, 0xe27f_996a_4fb1_c23c,\n            0xd386_7dfb_0775_f0d0, 0xd0e6_73de_6e88_891a, 0x123a_eb9e_afb8_6c25, 0x30f1_d5d5_c145_b895,\n            0xbb43_4a2d_ee72_69e7, 0x78cb_67ec_f931_fa38, 0xf33b_0372_323b_bf9c, 0x52d6_6336_fb27_9c74,\n            0x505f_33ac_0afb_4eaa, 0xe8a5_cd99_a2cc_e187, 0x5349_7480_1e2d_30bb, 0x8d2d_5711_d587_6d90,\n            0x1f1a_4128_91bc_038e, 0xd6e2_e71d_82e5_6648, 0x7403_6c3a_4977_32b7, 0x89b6_7ed9_6361_f5ab,\n            0xffed_95d8_f1ea_02a2, 0xe72b_3bd6_1464_d43d, 0xa630_0f17_0bdc_4820, 0xebc1_8760_ed78_a77a,\n        )\n        sbox2 = (\n            0xe6a6_be5a_05a1_2138, 0xb5a1_22a5_b4f8_7c98, 0x563c_6089_140b_6990, 0x4c46_cb2e_391f_5dd5,\n            0xd932_addb_c9b7_9434, 0x08ea_70e4_2015_aff5, 0xd765_a667_3e47_8cf1, 0xc4fb_757e_ab27_8d99,\n            0xdf11_c686_2d6e_0692, 0xddeb_84f1_0d7f_3b16, 0x6f2e_f604_a665_ea04, 0x4a8e_0f0f_f0e0_dfb3,\n            0xa5ed_eef8_3dbc_ba51, 0xfc4f_0a2a_0ea4_371e, 0xe83e_1da8_5cb3_8429, 0xdc8f_f882_ba1b_1ce2,\n            0xcd45_505e_8353_e80d, 0x18d1_9a00_d4db_0717, 0x34a0_cfed_a5f3_8101, 0x0be7_7e51_8887_caf2,\n            0x1e34_1438_b3c4_5136, 0xe057_97f4_9089_ccf9, 0xffd2_3f9d_f259_1d14, 0x543d_da22_8595_c5cd,\n            0x661f_81fd_9905_2a33, 0x8736_e641_db0f_7b76, 0x1522_7725_418e_5307, 0xe25f_7f46_162e_b2fa,\n            0x48a8_b212_6c13_d9fe, 0xafdc_5417_92e7_6eea, 0x03d9_12bf_c6d1_898f, 0x31b1_aafa_1b83_f51b,\n            0xf1ac_2796_e42a_b7d9, 0x40a3_a7d7_fcd2_ebac, 0x1056_136d_0afb_bcc5, 0x7889_e1dd_9a6d_0c85,\n            0xd335_2578_2a79_74aa, 0xa7e2_5d09_078a_c09b, 0xbd41_38b3_eac6_edd0, 0x920a_bfbe_71eb_9e70,\n            0xa2a5_d0f5_4fc2_625c, 0xc054_e36b_0b12_90a3, 0xf6dd_59ff_62fe_932b, 0x3537_3545_11a8_ac7d,\n            0xca84_5e91_72fa_dcd4, 0x84f8_2b60_329d_20dc, 0x79c6_2ce1_cd67_2f18, 0x8b09_a2ad_d124_642c,\n            0xd0c1_e96a_19d9_e726, 0x5a78_6a9b_4ba9_500c, 0x0e02_0336_634c_43f3, 0xc17b_474a_eb66_d822,\n            0x6a73_1ae3_ec9b_aac2, 0x8226_667a_e084_0258, 0x67d4_5676_91ca_eca5, 0x1d94_155c_4875_adb5,\n            0x6d00_fd98_5b81_3fdf, 0x5128_6efc_b774_cd06, 0x5e88_3447_1fa7_44af, 0xf72c_a0ae_e761_ae2e,\n            0xbe40_e4cd_aee8_e09a, 0xe997_0bbb_5118_f665, 0x726e_4beb_33df_1964, 0x703b_0007_2919_9762,\n            0x4631_d816_f5ef_30a7, 0xb880_b5b5_1504_a6be, 0x6417_93c3_7ed8_4b6c, 0x7b21_ed77_f6e9_7d96,\n            0x7763_0631_2ef9_6b73, 0xae52_8948_e86f_f3f4, 0x53db_d7f2_86a3_f8f8, 0x16ca_dce7_4cfc_1063,\n            0x005c_19bd_fa52_c6dd, 0x6886_8f5d_64d4_6ad3, 0x3a9d_512c_cf1e_186a, 0x367e_62c2_3856_60ae,\n            0xe359_e7ea_77dc_b1d7, 0x526c_0773_749a_be6e, 0x735a_e5f9_d09f_734b, 0x493f_c7cc_8a55_8ba8,\n            0xb0b9_c153_3041_ab45, 0x3219_58ba_470a_59bd, 0x852d_b00b_5f46_c393, 0x9120_9b2b_d336_b0e5,\n            0x6e60_4f7d_659e_f19f, 0xb99a_8ae2_782c_cb24, 0xccf5_2ab6_c814_c4c7, 0x4727_d9af_be11_727b,\n            0x7e95_0d0c_0121_b34d, 0x756f_4356_70ad_471f, 0xf5ad_d442_615a_6849, 0x4e87_e099_80b9_957a,\n            0x2acf_a1df_50ae_e355, 0xd898_263a_fd2f_d556, 0xc8f4_924d_d80c_8fd6, 0xcf99_ca3d_754a_173a,\n            0xfe47_7bac_af91_bf3c, 0xed53_71f6_d690_c12d, 0x831a_5c28_5e68_7094, 0xc5d3_c90a_3708_a0a4,\n            0x0f7f_9037_17d0_6580, 0x19f9_bb13_b8fd_f27f, 0xb1bd_6f1b_4d50_2843, 0x1c76_1ba3_8fff_4012,\n            0x0d15_30c4_e2e2_1f3b, 0x8943_ce69_a737_2c8a, 0xe518_4e11_feb5_ce66, 0x618b_db80_bd73_6621,\n            0x7d29_bad6_8b57_4d0b, 0x81bb_613e_25e6_fe5b, 0x071c_9c10_bc07_913f, 0xc7be_eb79_09ac_2d97,\n            0xc3e5_8d35_3bc5_d757, 0xeb01_7892_f38f_61e8, 0xd4ef_fb9c_9b1c_c21a, 0x9972_7d26_f494_f7ab,\n            0xa3e0_63a2_956b_3e03, 0x9d4a_8b9a_4aa0_9c30, 0x3f6a_b7d5_0009_0fb4, 0x9cc0_f2a0_5726_8ac0,\n            0x3dee_9d2d_edbf_42d1, 0x330f_49c8_7960_a972, 0xc6b2_7202_8742_1b41, 0x0ac5_9ec0_7c00_369c,\n            0xef4e_ac49_cb35_3425, 0xf450_244e_ef01_29d8, 0x8acc_46e5_caf4_deb6, 0x2ffe_ab63_9892_63f7,\n            0x8f7c_b9fe_5d7a_4578, 0x5bd8_f764_4e63_4635, 0x427a_7315_bf2d_c900, 0x17d0_c4aa_2125_261c,\n            0x3992_486c_9351_8e50, 0xb4cb_fee0_a2d7_d4c3, 0x7c75_d620_2c5d_dd8d, 0xdbc2_95d8_e35b_6c61,\n            0x60b3_69d3_0203_2b19, 0xce42_685f_dce4_4132, 0x06f3_ddb9_ddf6_5610, 0x8ea4_d21d_b5e1_48f0,\n            0x20b0_fce6_2fcd_496f, 0x2c1b_9123_58b0_ee31, 0xb283_17b8_18f5_a308, 0xa89c_1e18_9ca6_d2cf,\n            0x0c6b_1857_6aaa_dbc8, 0xb65d_eaa9_1299_fae3, 0xfb2b_794b_7f10_27e7, 0x04e4_317f_443b_5beb,\n            0x4b85_2d32_5939_d0a6, 0xd5ae_6bee_fb20_7ffc, 0x3096_82b2_81c7_d374, 0xbae3_09a1_94c3_b475,\n            0x8cc3_f97b_13b4_9f05, 0x98a9_422f_f829_3967, 0x244b_16b0_1076_ff7c, 0xf8bf_571c_663d_67ee,\n            0x1f0d_6758_eee3_0da1, 0xc9b6_11d9_7ade_b9b7, 0xb7af_d588_7b6c_57a2, 0x6290_ae84_6b98_4fe1,\n            0x94df_4cde_acc1_a5fd, 0x058a_5bd1_c548_3aff, 0x6316_6cc1_42ba_3c37, 0x8db8_526e_b2f7_6f40,\n            0xe108_8003_6f0d_6d4e, 0x9e05_23c9_971d_311d, 0x45ec_2824_cc7c_d691, 0x575b_8359_e623_82c9,\n            0xfa9e_400d_c488_9995, 0xd182_3ecb_4572_1568, 0xdafd_983b_8206_082f, 0xaa7d_2908_2386_a8cb,\n            0x269f_cd44_03b8_7588, 0x1b91_f5f7_28bd_d1e0, 0xe466_9f39_0402_01f6, 0x7a1d_7c21_8cf0_4ade,\n            0x6562_3c29_d79c_e5ce, 0x2368_4490_96c0_0bb1, 0xab9b_f187_9da5_03ba, 0xbc23_ecb1_a458_058e,\n            0x9a58_df01_bb40_1ecc, 0xa070_e868_a85f_143d, 0x4ff1_8830_7df2_239e, 0x14d5_65b4_1a64_1183,\n            0xee13_3374_5270_1602, 0x950e_3dcf_3f28_5e09, 0x5993_0254_b9c8_0953, 0x3bf2_9940_8930_da6d,\n            0xa955_943f_5369_1387, 0xa15e_deca_a9cb_8784, 0x2914_2127_352b_e9a0, 0x76f0_371f_ff4e_7afb,\n            0x0239_f450_274f_2228, 0xbb07_3af0_1d5e_868b, 0xbfc8_0571_c10e_96c1, 0xd267_0885_6822_2e23,\n            0x9671_a3d4_8e80_b5b0, 0x55b5_d38a_e193_bb81, 0x693a_e2d0_a18b_04b8, 0x5c48_b4ec_add5_335f,\n            0xfd74_3b19_4916_a1ca, 0x2577_0181_34be_98c4, 0xe779_87e8_3c54_a4ad, 0x28e1_1014_da33_e1b9,\n            0x270c_c59e_226a_a213, 0x7149_5f75_6d1a_5f60, 0x9be8_53fb_60af_ef77, 0xadc7_86a7_f744_3dbf,\n            0x0904_4561_73b2_9a82, 0x58bc_7a66_c232_bd5e, 0xf306_558c_673a_c8b2, 0x41f6_39c6_b6c9_772a,\n            0x216d_efe9_9fda_35da, 0x1164_0cc7_1c7b_e615, 0x93c4_3694_565c_5527, 0xea03_8e62_4677_7839,\n            0xf9ab_f3ce_5a3e_2469, 0x741e_768d_0fd3_12d2, 0x0144_b883_ced6_52c6, 0xc20b_5a5b_a33f_8552,\n            0x1ae6_9633_c343_5a9d, 0x97a2_8ca4_088c_fdec, 0x8824_a43c_1e96_f420, 0x3761_2fa6_6eee_a746,\n            0x6b4c_b165_f9cf_0e5a, 0x43aa_1c06_a0ab_fb4a, 0x7f4d_c26f_f162_796b, 0x6cba_cc8e_54ed_9b0f,\n            0xa6b7_ffef_d2bb_253e, 0x2e25_bc95_b0a2_9d4f, 0x86d6_a58b_def1_388c, 0xded7_4ac5_76b6_f054,\n            0x8030_bdbc_2b45_805d, 0x3c81_af70_e94d_9289, 0x3eff_6dda_9e31_00db, 0xb38d_c39f_dfcc_8847,\n            0x1238_8552_8d17_b87e, 0xf2da_0ed2_40b1_b642, 0x44ce_fadc_d54b_f9a9, 0x1312_200e_433c_7ee6,\n            0x9ffc_c84f_3a78_c748, 0xf0cd_1f72_2485_76bb, 0xec69_7405_3638_cfe4, 0x2ba7_b67c_0cec_4e4c,\n            0xac2f_4df3_e5ce_32ed, 0xcb33_d143_26ea_4c11, 0xa4e9_044c_c77e_58bc, 0x5f51_3293_d934_fcef,\n            0x5dc9_6455_06e5_5444, 0x50de_418f_317d_e40a, 0x388c_b31a_69dd_e259, 0x2db4_a834_5582_0a86,\n            0x9010_a91e_8471_1ae9, 0x4df7_f0b7_b149_8371, 0xd62a_2eab_c097_7179, 0x22fa_c097_aa8d_5c0e,\n        )\n        sbox3 = (\n            0xf49f_cc2f_f1da_f39b, 0x487f_d5c6_6ff2_9281, 0xe8a3_0667_fcdc_a83f, 0x2c9b_4be3_d2fc_ce63,\n            0xda3f_f74b_93fb_bbc2, 0x2fa1_65d2_fe70_ba66, 0xa103_e279_970e_93d4, 0xbecd_ec77_b0e4_5e71,\n            0xcfb4_1e72_3985_e497, 0xb70a_aa02_5ef7_5017, 0xd423_09f0_3840_b8e0, 0x8efc_1ad0_3589_8579,\n            0x96c6_920b_e2b2_abc5, 0x66af_4163_375a_9172, 0x2174_abdc_ca71_27fb, 0xb33c_cea6_4a72_ff41,\n            0xf04a_4933_0830_66a5, 0x8d97_0acd_d728_9af5, 0x8f96_e8e0_31c8_c25e, 0xf3fe_c022_7687_5d47,\n            0xec7b_f310_0561_90dd, 0xf5ad_b0ae_bb0f_1491, 0x9b50_f885_0fd5_8892, 0x4975_4883_58b7_4de8,\n            0xa335_4ff6_9153_1c61, 0x0702_bbe4_81d2_c6ee, 0x89fb_2405_7ded_ed98, 0xac30_7513_8596_e902,\n            0x1d2d_3580_1727_72ed, 0xeb73_8fc2_8e6b_c30d, 0x5854_ef8f_6304_4326, 0x9e5c_5232_5add_3bbe,\n            0x90aa_53cf_325c_4623, 0xc1d2_4d51_349d_d067, 0x2051_cfee_a69e_a624, 0x1322_0f0a_862e_7e4f,\n            0xce39_3994_04e0_4864, 0xd9c4_2ca4_7086_fcb7, 0x685a_d223_8a03_e7cc, 0x0664_84b2_ab2f_f1db,\n            0xfe9d_5d70_efbf_79ec, 0x5b13_b9dd_9c48_1854, 0x15f0_d475_ed15_09ad, 0x0beb_cd06_0ec7_9851,\n            0xd58c_6791_183a_b7f8, 0xd118_7c50_52f3_eee4, 0xc95d_1192_e54e_82ff, 0x86ee_a14c_b9ac_6ca2,\n            0x3485_beb1_5367_7d5d, 0xdd19_1d78_1f8c_492a, 0xf608_66ba_a784_ebf9, 0x518f_643b_a2d0_8c74,\n            0x8852_e956_e108_7c22, 0xa768_cb8d_c410_ae8d, 0x3804_7726_bfec_8e1a, 0xa677_38b4_cd3b_45aa,\n            0xad16_691c_ec0d_de19, 0xc6d4_3193_8046_2e07, 0xc5a5_876d_0ba6_1938, 0x16b9_fa1f_a58f_d840,\n            0x188a_b117_3ca7_4f18, 0xabda_2f98_c99c_021f, 0x3e05_80ab_134a_e816, 0x5f3b_05b7_7364_5abb,\n            0x2501_a2be_5575_f2f6, 0x1b2f_7400_4e7e_8ba9, 0x1cd7_5803_71e8_d953, 0x7f6e_d895_6276_4e30,\n            0xb159_26ff_596f_003d, 0x9f65_293d_a8c5_d6b9, 0x6ece_f04d_d690_f84c, 0x4782_275f_ff33_af88,\n            0xe414_3308_3f82_0801, 0xfd0d_fe40_9a1a_f9b5, 0x4325_a334_2cdb_396b, 0x8ae7_7e62_b301_b252,\n            0xc36f_9e9f_6655_615a, 0x8545_5a2d_92d3_2c09, 0xf2c7_dea9_4947_7485, 0x63cf_b4c1_33a3_9eba,\n            0x83b0_40cc_6ebc_5462, 0x3b94_54c8_fdb3_26b0, 0x56f5_6a9e_87ff_d78c, 0x2dc2_940d_99f4_2bc6,\n            0x98f7_df09_6b09_6e2d, 0x19a6_e01e_3ad8_52bf, 0x42a9_9ccb_dbd4_b40b, 0xa599_98af_45e9_c559,\n            0x3662_95e8_07d9_3186, 0x6b48_181b_faa1_f773, 0x1fec_57e2_157a_0a1d, 0x4667_446a_f620_1ad5,\n            0xe615_ebca_cfb0_f075, 0xb8f3_1f4f_6829_0778, 0x2271_3ed6_ce22_d11e, 0x3057_c1a7_2ec3_c93b,\n            0xcb46_acc3_7c3f_1f2f, 0xdbb8_93fd_02aa_f50e, 0x331f_d92e_600b_9fcf, 0xa498_f961_48ea_3ad6,\n            0xa8d8_426e_8b6a_83ea, 0xa089_b274_b773_5cdc, 0x87f6_b373_1e52_4a11, 0x1188_08e5_cbc9_6749,\n            0x9906_e4c7_b19b_d394, 0xafed_7f7e_9b24_a20c, 0x6509_eade_eb36_44a7, 0x6c1e_f1d3_e8ef_0ede,\n            0xb9c9_7d43_e979_8fb4, 0xa2f2_d784_740c_28a3, 0x7b84_9647_6197_566f, 0x7a5b_e3e6_b65f_069d,\n            0xf963_30ed_78be_6f10, 0xeee6_0de7_7a07_6a15, 0x2b4b_ee4a_a08b_9bd0, 0x6a56_a63e_c7b8_894e,\n            0x0212_1359_ba34_fef4, 0x4cbf_99f8_2837_03fc, 0x3980_7135_0caf_30c8, 0xd0a7_7a89_f017_687a,\n            0xf1c1_a9eb_9e42_3569, 0x8c79_7628_2dee_8199, 0x5d17_37a5_dd1f_7abd, 0x4f53_433c_09a9_fa80,\n            0xfa8b_0c53_df7c_a1d9, 0x3fd9_dcbc_886c_cb77, 0xc040_917c_a91b_4720, 0x7dd0_0142_f9d1_dcdf,\n            0x8476_fc1d_4f38_7b58, 0x23f8_e7c5_f331_6503, 0x032a_2244_e7e3_7339, 0x5c87_a5d7_50f5_a74b,\n            0x082b_4cc4_3698_992e, 0xdf91_7bec_b858_f63c, 0x3270_b8fc_5bf8_6dda, 0x10ae_72bb_29b5_dd76,\n            0x576a_c94e_7700_362b, 0x1ad1_12da_c61e_fb8f, 0x691b_c30e_c5fa_a427, 0xff24_6311_cc32_7143,\n            0x3142_368e_30e5_3206, 0x7138_0e31_e02c_a396, 0x958d_5c96_0aad_76f1, 0xf8d6_f430_c16d_a536,\n            0xc8ff_d13f_1be7_e1d2, 0x7578_ae66_004d_dbe1, 0x0583_3f01_067b_e646, 0xbb34_b5ad_3bfe_586d,\n            0x095f_34c9_a12b_97f0, 0x247a_b645_25d6_0ca8, 0xdcdb_c6f3_0174_77d1, 0x4a2e_14d4_deca_d24d,\n            0xbdb5_e6d9_be0a_1eeb, 0x2a7e_70f7_7943_01ab, 0xdef4_2d8a_2705_40fd, 0x0107_8ec0_a34c_22c1,\n            0xe5de_511a_f4c1_6387, 0x7ebb_3a52_bd9a_330a, 0x7769_7857_aa7d_6435, 0x004e_8316_03ae_4c32,\n            0xe7a2_1020_ad78_e312, 0x9d41_a70c_6ab4_20f2, 0x28e0_6c18_ea11_41e6, 0xd2b2_8cbd_984f_6b28,\n            0x26b7_5f6c_446e_9d83, 0xba47_568c_4d41_8d7f, 0xd80b_adbf_e618_3d8e, 0x0e20_6d7f_5f16_6044,\n            0xe258_a439_11cb_ca3e, 0x723a_1746_b21d_c0bc, 0xc7ca_a854_f5d7_cdd3, 0x7cac_3288_3d26_1d9c,\n            0x7690_c264_23ba_942c, 0x17e5_5524_4780_42b8, 0xe0be_4776_56a2_389f, 0x4d28_9b5e_67ab_2da0,\n            0x4486_2b9c_8fbb_fd31, 0xb47c_c804_9d14_1365, 0x822c_1b36_2b91_c793, 0x4eb1_4655_fb13_dfd8,\n            0x1ecb_ba07_14e2_a97b, 0x6143_459d_5cde_5f14, 0x53a8_fbf1_d5f0_ac89, 0x97ea_04d8_1c5e_5b00,\n            0x6221_81a8_d4fd_b3f3, 0xe9bc_d341_572a_1208, 0x1411_2586_43cc_e58a, 0x9144_c5fe_a4c6_e0a4,\n            0x0d33_d065_65cf_620f, 0x54a4_8d48_9f21_9ca1, 0xc43e_5eac_6d63_c821, 0xa972_8b3a_7277_0daf,\n            0xd793_4e7b_20df_87ef, 0xe355_03b6_1a3e_86e5, 0xcae3_21fb_c819_d504, 0x129a_50b3_ac60_bfa6,\n            0xcd5e_68ea_7e9f_b6c3, 0xb01c_9019_9483_b1c7, 0x3de9_3cd5_c295_376c, 0xaed5_2edf_2ab9_ad13,\n            0x2e60_f512_c0a0_7884, 0xbc3d_86a3_e362_10c9, 0x3526_9d9b_1639_51ce, 0x0c7d_6e2a_d0cd_b5fa,\n            0x59e8_6297_d87f_5733, 0x298e_f221_898d_b0e7, 0x5500_0029_d1a5_aa7e, 0x8bc0_8ae1_b506_1b45,\n            0xc2c3_1c2b_6c92_703a, 0x94cc_596b_af25_ef42, 0x0a1d_73db_2254_0456, 0x04b6_a0f9_d9c4_179a,\n            0xeffd_afa2_ae3d_3c60, 0xf7c8_075b_b494_96c4, 0x9cc5_c714_1d1c_d4e3, 0x78bd_1638_218e_5534,\n            0xb2f1_1568_f850_246a, 0xedfa_bcfa_9502_bc29, 0x796c_e5f2_da23_051b, 0xaae1_28b0_dc93_537c,\n            0x3a49_3da0_ee4b_29ae, 0xb5df_6b2c_4168_95d7, 0xfcab_bd25_122d_7f37, 0x7081_0b58_105d_c4b1,\n            0xe10f_dd37_f788_2a90, 0x524d_cab5_518a_3f5c, 0x3c9e_8587_8451_255b, 0x4029_8281_19bd_34e2,\n            0x74a0_5b6f_5d3c_eccb, 0xb610_0215_42e1_3eca, 0x0ff9_79d1_2f59_e2ac, 0x6037_da27_e4f9_cc50,\n            0x5e92_975a_0df1_847d, 0xd66d_e190_d3e6_23fe, 0x5032_d6b8_7b56_8048, 0x9a36_b7ce_8235_216e,\n            0x8027_2a7a_24f6_4b4a, 0x93ef_ed8b_8c69_16f7, 0x37dd_bff4_4cce_1555, 0x4b95_db5d_4b99_bd25,\n            0x92d3_fda1_6981_2fc0, 0xfb1a_4a9a_9066_0bb6, 0x730c_1969_46a4_b9b2, 0x81e2_89aa_7f49_da68,\n            0x6466_9a0f_83b1_a05f, 0x27b3_ff7d_9644_f48b, 0xcc6b_615c_8db6_75b3, 0x674f_20b9_bceb_be95,\n            0x6f31_2382_7565_5982, 0x5ae4_8871_3e45_cf05, 0xbf61_9f99_54c2_1157, 0xeaba_c460_40a8_eae9,\n            0x454c_6fe9_f2c0_c1cd, 0x419c_f649_6412_691c, 0xd3dc_3bef_265b_0f70, 0x6d0e_60f5_c357_8a9e,\n        )\n        sbox4 = (\n            0x5b0e_6085_2632_3c55, 0x1a46_c1a9_fa1b_59f5, 0xa9e2_45a1_7c4c_8ffa, 0x65ca_5159_db29_55d7,\n            0x05db_0a76_ce35_afc2, 0x81ea_c77e_a911_3d45, 0x528e_f88a_b6ac_0a0d, 0xa09e_a253_597b_e3ff,\n            0x430d_dfb3_ac48_cd56, 0xc4b3_a67a_f45c_e46f, 0x4ece_cfd8_fbe2_d05e, 0x3ef5_6f10_b399_35f0,\n            0x0b22_d682_9cd6_19c6, 0x17fd_460a_74df_2069, 0x6cf8_cc8e_8510_ed40, 0xd6c8_24bf_3a6e_caa7,\n            0x6124_3d58_1a81_7049, 0x048b_acb6_bbc1_63a2, 0xd9a3_8ac2_7d44_cc32, 0x7fdd_ff5b_aaf4_10ab,\n            0xad6d_495a_a804_824b, 0xe1a6_a74f_2d8c_9f94, 0xd4f7_8512_35de_e8e3, 0xfd4b_7f88_6540_d893,\n            0x247c_2004_2aa4_bfda, 0x096e_a1c5_17d1_327c, 0xd569_66b4_361a_6685, 0x277d_a5c3_1221_057d,\n            0x94d5_9893_a43a_cff7, 0x64f0_c51c_cdc0_2281, 0x3d33_bcc4_ff61_89db, 0xe005_cb18_4ce6_6af1,\n            0xff5c_cd1d_1db9_9bea, 0xb0b8_54a7_fe42_980f, 0x7bd4_6a6a_718d_4b9f, 0xd10f_a8cc_22a5_fd8c,\n            0xd314_8495_2be4_bd31, 0xc7fa_975f_cb24_3847, 0x4886_ed1e_5846_c407, 0x28cd_db79_1eb7_0b04,\n            0xc2b0_0be2_f573_417f, 0x5c95_9045_2180_f877, 0x7a6b_ddff_f370_eb00, 0xce50_9e38_d6d9_d6a4,\n            0xebeb_0f00_647f_a702, 0x1dcc_06cf_7660_6f06, 0xe4d9_f28b_a286_ff0a, 0xd85a_305d_c918_c262,\n            0x475b_1d87_3222_5f54, 0x2d4f_b516_68cc_b5fe, 0xa679_b9d9_d72b_ba20, 0x5384_1c0d_912d_43a5,\n            0x3b7e_aa48_bf12_a4e8, 0x781e_0e47_f22f_1ddf, 0xeff2_0ce6_0ab5_0973, 0x20d2_61d1_9dff_b742,\n            0x16a1_2b03_062a_2e39, 0x1960_eb22_3965_0495, 0x251c_16fe_d50e_b8b8, 0x9ac0_c330_f826_016e,\n            0xed15_2665_953e_7671, 0x02d6_3194_a636_9570, 0x5074_f083_94b1_c987, 0x70ba_598c_90b2_5ce1,\n            0x794a_1581_0b97_42f6, 0x0d59_25e9_fcaf_8c6c, 0x3067_716c_d868_744e, 0x910a_b077_e8d7_731b,\n            0x6a61_bbdb_5ac4_2f61, 0x9351_3efb_f085_1567, 0xf494_724b_9e83_e9d5, 0xe887_e198_5c09_648d,\n            0x34b1_d3c6_7537_0cfd, 0xdc35_e433_bc0d_255d, 0xd0aa_b842_3413_1be0, 0x0804_2a50_b48b_7eaf,\n            0x9997_c4ee_44a3_ab35, 0x829a_7b49_2017_99d0, 0x263b_8307_b7c5_4441, 0x752f_95f4_fd6a_6ca6,\n            0x9272_1740_2c08_c6e5, 0x2a8a_b754_a795_d9ee, 0xa442_f755_2f72_943d, 0x2c31_334e_1978_1208,\n            0x4fa9_8d7c_eaee_6291, 0x55c3_862f_665d_b309, 0xbd06_1017_5d53_b1f3, 0x46fe_6cb8_4041_3f27,\n            0x3fe0_3792_df0c_fa59, 0xcfe7_0037_2eb8_5e8f, 0xa7be_29e7_adbc_e118, 0xe544_ee5c_de84_31dd,\n            0x8a78_1b1b_41f1_873e, 0xa5c9_4c78_a0d2_f0e7, 0x3941_2e28_77b6_0728, 0xa126_5ef3_afc9_a62c,\n            0xbcc2_770c_6a25_06c5, 0x3ab6_6dd5_dce1_ce12, 0xe654_99d0_4a67_5b37, 0x7d8f_5234_81bf_d216,\n            0x0f6f_64fc_ec15_f389, 0x74ef_be61_8b5b_13c8, 0xacdc_82b7_1427_3e1d, 0xdd40_bfe0_0319_9d17,\n            0x37e9_9257_e7e0_61f8, 0xfa52_6269_0477_5aaa, 0x8bbb_f63a_463d_56f9, 0xf001_3f15_43a2_6e64,\n            0xa830_7e9f_879e_c898, 0xcc4c_27a4_1501_77cc, 0x1b43_2f2c_ca1d_3348, 0xde1d_1f8f_9f6f_a013,\n            0x6066_02a0_47a7_ddd6, 0xd237_ab64_cc1c_b2c7, 0x9b93_8e72_25fc_d1d3, 0xec4e_0370_8e0f_f476,\n            0xfeb2_fbda_3d03_c12d, 0xae0b_ced2_ee43_889a, 0x22cb_8923_ebfb_4f43, 0x6936_0d01_3cf7_396d,\n            0x855e_3602_d2d4_e022, 0x0738_05ba_d01f_784c, 0x33e1_7a13_3852_f546, 0xdf48_7405_8ac7_b638,\n            0xba92_b29c_678a_a14a, 0x0ce8_9fc7_6cfa_adcd, 0x5f9d_4e09_0833_9e34, 0xf1af_e929_1f59_23b9,\n            0x6e34_80f6_0f4a_265f, 0xeebf_3a2a_b29b_841c, 0xe219_38a8_8f91_b4ad, 0x57df_eff8_45c6_d3c3,\n            0x2f00_6b0b_f62c_aaf2, 0x62f4_79ef_6f75_ee78, 0x11a5_5ad4_1c89_16a9, 0xf229_d290_84fe_d453,\n            0x42f1_c27b_16b0_00e6, 0x2b1f_7674_9823_c074, 0x4b76_eca3_c274_5360, 0x8c98_f463_b916_91bd,\n            0x14bc_c93c_f1ad_e66a, 0x8885_213e_6d45_8397, 0x8e17_7df0_274d_4711, 0xb49b_73b5_503f_2951,\n            0x1016_8168_c3f9_6b6b, 0x0e3d_963b_63ca_b0ae, 0x8dfc_4b56_55a1_db14, 0xf789_f135_6e14_de5c,\n            0x683e_68af_4e51_dac1, 0xc9a8_4f9d_8d4b_0fd9, 0x3691_e03f_52a0_f9d1, 0x5ed8_6e46_e187_8e80,\n            0x3c71_1a0e_99d0_7150, 0x5a08_65b2_0c4e_9310, 0x56fb_fc1f_e4f0_682e, 0xea8d_5de3_105e_df9b,\n            0x71ab_fdb1_2379_187a, 0x2eb9_9de1_bee7_7b9c, 0x21ec_c0ea_33cf_4523, 0x59a4_d752_1805_c7a1,\n            0x3896_f5eb_56ae_7c72, 0xaa63_8f3d_b18f_75dc, 0x9f39_358d_abe9_808e, 0xb7de_fa91_c00b_72ac,\n            0x6b55_41fd_6249_2d92, 0x6dc6_dee8_f92e_4d5b, 0x353f_57ab_c4be_ea7e, 0x7357_69d6_da56_90ce,\n            0x0a23_4aa6_4239_1484, 0xf6f9_5080_28f8_0d9d, 0xb8e3_19a2_7ab3_f215, 0x31ad_9c11_5134_1a4d,\n            0x773c_22a5_7bef_5805, 0x45c7_561a_0796_8633, 0xf913_da9e_249d_be36, 0xda65_2d9b_78a6_4c68,\n            0x4c27_a97f_3bc3_34ef, 0x7662_1220_e66b_17f4, 0x9677_4389_9acd_7d0b, 0xf3ee_5bca_e0ed_6782,\n            0x409f_7536_00c8_79fc, 0x06d0_9a39_b592_6db6, 0x6f83_aeb0_317a_c588, 0x01e6_ca4a_8638_1f21,\n            0x66ff_3462_d19f_3025, 0x7220_7c24_ddfd_3bfb, 0x4af6_b6d3_e2ec_e2eb, 0x9c99_4dbe_c7ea_08de,\n            0x49ac_e597_b09a_8bc4, 0xb38c_4766_cf07_97ba, 0x131b_9373_c57c_2a75, 0xb182_2cce_6193_1e58,\n            0x9d75_55b9_09ba_1c0c, 0x127f_afdd_937d_11d2, 0x29da_3bad_c66d_92e4, 0xa2c1_d571_54c2_ecbc,\n            0x58c5_134d_82f6_fe24, 0x1c3a_e351_5b62_274f, 0xe907_c82e_01cb_8126, 0xf8ed_0919_13e3_7fcb,\n            0x3249_d8f9_c800_46c9, 0x80cf_9bed_e388_fb63, 0x1881_539a_116c_f19e, 0x5103_f3f7_6bd5_2457,\n            0x15b7_e6f5_ae47_f7a8, 0xdbd7_c6de_d47e_9ccf, 0x44e5_5c41_0228_bb1a, 0xb647_d425_5edb_4e99,\n            0x5d11_882b_b8aa_fc30, 0xf509_8bbb_29d3_212a, 0x8fb5_ea14_e902_96b3, 0x677b_9421_57dd_025a,\n            0xfb58_e7c0_a390_acb5, 0x89d3_674c_83bd_4a01, 0x9e2d_a4df_4bf3_b93b, 0xfcc4_1e32_8cab_4829,\n            0x03f3_8c96_ba58_2c52, 0xcad1_bdbd_7fd8_5db2, 0xbbb4_42c1_6082_ae83, 0xb95f_e86b_a5da_9ab0,\n            0xb22e_0467_3771_a93f, 0x8453_58c9_4931_52d8, 0xbe2a_4886_97b4_541e, 0x95a2_dc2d_d38e_6966,\n            0xc02c_11ac_923c_852b, 0x2388_b199_0df2_a87b, 0x7c80_08fa_1b4f_37be, 0x1f70_d0c8_4d54_e503,\n            0x5490_adec_7ece_57d4, 0x002b_3c27_d906_3a3a, 0x7eae_a384_8030_a2bf, 0xc602_326d_ed20_03c0,\n            0x83a7_287d_69a9_4086, 0xc57a_5fcb_30f5_7a8a, 0xb568_44e4_79eb_e779, 0xa373_b40f_05dc_bce9,\n            0xd71a_786e_8857_0ee2, 0x879c_bacd_bde8_f6a0, 0x976a_d1bc_c164_a32f, 0xab21_e25e_9666_d78b,\n            0x9010_63aa_e5e5_c33c, 0x9818_b344_4869_8d90, 0xe364_87ae_3e1e_8abb, 0xafbd_f931_893b_dcb4,\n            0x6345_a0dc_5fbb_d519, 0x8628_fe26_9b94_65ca, 0x1e5d_0160_3f9c_51ec, 0x4de4_4006_a150_49b7,\n            0xbf6c_70e5_f776_cbb1, 0x4112_18f2_ef55_2bed, 0xcb0c_0708_705a_36a3, 0xe74d_1475_4f98_6044,\n            0xcd56_d943_0ea8_280e, 0xc125_91d7_535f_5065, 0xc832_23f1_720a_ef96, 0xc3a0_396f_7363_a51f,\n        )\n\n        def __init__(self, data=b\"\", digest_bits=128, passes=3, version=1):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.a = 0x0123_4567_89ab_cdef\n            self.b = 0xfedc_ba98_7654_3210\n            self.c = 0xf096_a5b4_c3b2_e187\n            self.digest_size = digest_bits // 8\n            self.passes = passes\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            self.version = version\n            if data:\n                self.update(bytes(data))\n            return\n\n        def copy(self):\n            other = self.__class__(digest_bits=self.digest_size * 8, passes=self.passes, version=self.version)\n            other.a = self.a\n            other.b = self.b\n            other.c = self.c\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = struct.pack(\"<3Q\", c.a, c.b, c.c)\n            return out[: self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            if self.version == 1:\n                self.buf.append(0x01)\n            else:\n                self.buf.append(0x80)\n            while (len(self.buf) % 64) != 56:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\"<Q\", bit_len))\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return\n\n        def u64(self, x):\n            return x & 0xffff_ffff_ffff_ffff\n\n        def round(self, a, b, c, x, mul):\n            s1 = self.__class__.sbox1\n            s2 = self.__class__.sbox2\n            s3 = self.__class__.sbox3\n            s4 = self.__class__.sbox4\n            c = self.u64(c ^ x)\n            a = self.u64(a - (s1[(c >> 0) & 0xff] ^ s2[(c >> 16) & 0xff] ^ s3[(c >> 32) & 0xff] ^ s4[(c >> 48) & 0xff]))\n            b = self.u64(b + (s4[(c >> 8) & 0xff] ^ s3[(c >> 24) & 0xff] ^ s2[(c >> 40) & 0xff] ^ s1[(c >> 56) & 0xff]))\n            b = self.u64(b * mul)\n            return a, b, c\n\n        def key_schedule(self, x):\n            x[0] = self.u64(x[0] - (x[7] ^ 0xa5a5_a5a5_a5a5_a5a5))\n            x[1] = self.u64(x[1] ^ x[0])\n            x[2] = self.u64(x[2] + x[1])\n            x[3] = self.u64(x[3] - (x[2] ^ (self.u64(~x[1]) << 19)))\n            x[4] = self.u64(x[4] ^ x[3])\n            x[5] = self.u64(x[5] + x[4])\n            x[6] = self.u64(x[6] - (x[5] ^ (self.u64(~x[4]) >> 23)))\n            x[7] = self.u64(x[7] ^ x[6])\n            x[0] = self.u64(x[0] + x[7])\n            x[1] = self.u64(x[1] - (x[0] ^ (self.u64(~x[7]) << 19)))\n            x[2] = self.u64(x[2] ^ x[1])\n            x[3] = self.u64(x[3] + x[2])\n            x[4] = self.u64(x[4] - (x[3] ^ (self.u64(~x[2]) >> 23)))\n            x[5] = self.u64(x[5] ^ x[4])\n            x[6] = self.u64(x[6] + x[5])\n            x[7] = self.u64(x[7] - (x[6] ^ 0x0123_4567_89ab_cdef))\n            return\n\n        def do_pass(self, a, b, c, x, mul):\n            a, b, c = self.round(a, b, c, x[0], mul)\n            b, c, a = self.round(b, c, a, x[1], mul)\n            c, a, b = self.round(c, a, b, x[2], mul)\n            a, b, c = self.round(a, b, c, x[3], mul)\n            b, c, a = self.round(b, c, a, x[4], mul)\n            c, a, b = self.round(c, a, b, x[5], mul)\n            a, b, c = self.round(a, b, c, x[6], mul)\n            b, c, a = self.round(b, c, a, x[7], mul)\n            return a, b, c\n\n        def compress(self, block):\n            if not isinstance(block, (bytes, bytearray, memoryview)) or len(block) != 64:\n                raise ValueError(\"block must be 64 bytes\")\n\n            x = list(struct.unpack(\"<8Q\", block))\n\n            aa = self.a\n            bb = self.b\n            cc = self.c\n\n            # passes: 3 or 4\n            if self.passes == 3:\n                # PASS(a,b,c,5); KS; PASS(c,a,b,7); KS; PASS(b,c,a,9)\n                a, b, c = self.do_pass(self.a, self.b, self.c, x, 5)\n                self.key_schedule(x)\n                c, a, b = self.do_pass(c, a, b, x, 7)\n                self.key_schedule(x)\n                b, c, a = self.do_pass(b, c, a, x, 9)\n                self.a, self.b, self.c = a, b, c\n            elif self.passes == 4:\n                a, b, c = self.do_pass(self.a, self.b, self.c, x, 5)\n                self.key_schedule(x)\n                c, a, b = self.do_pass(c, a, b, x, 7)\n                self.key_schedule(x)\n                b, c, a = self.do_pass(b, c, a, x, 9)\n                self.key_schedule(x)\n                b, c, a = self.do_pass(a, b, c, x, 9)\n                self.a, self.b, self.c = a, b, c\n            else:\n                raise ValueError(\"passes must be 3 or 4\")\n\n            # feed-forward\n            self.a = self.u64(self.a ^ aa)\n            self.b = self.u64(self.b - bb)\n            self.c = self.u64(self.c + cc)\n            return\n\n    class SHA0:\n        block_size = 64\n        digest_size = 20\n\n        def __init__(self, data=b\"\"):\n            # Initial values are the same as SHA-1\n            self.h0 = 0x674_52301\n            self.h1 = 0xefc_dab89\n            self.h2 = 0x98b_adcfe\n            self.h3 = 0x103_25476\n            self.h4 = 0xc3d_2e1f0\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h0 = self.h0\n            other.h1 = self.h1\n            other.h2 = self.h2\n            other.h3 = self.h3\n            other.h4 = self.h4\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return struct.pack(\">5I\", c.h0, c.h1, c.h2, c.h3, c.h4)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # Padding: append 0x80, then 0x00* until length ≡ 56 (mod 64),\n            # then append message length in bits as 64-bit big-endian.\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n            while (len(self.buf) % 64) != 56:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\">Q\", bit_len))\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return\n\n        def compress(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            # Prepare message schedule W[0..79]\n            W = list(struct.unpack(\">16I\", block))\n            for t in range(16, 80):\n                # SHA-0: no rotation here (this is the key difference from SHA-1)\n                W.append((W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]) & 0xffff_ffff)\n\n            a = self.h0\n            b = self.h1\n            c = self.h2\n            d = self.h3\n            e = self.h4\n\n            for t in range(80):\n                if 0 <= t <= 19:\n                    f = (b & c) | ((~b) & d)\n                    k = 0x5a82_7999\n                elif 20 <= t <= 39:\n                    f = b ^ c ^ d\n                    k = 0x6ed9_eba1\n                elif 40 <= t <= 59:\n                    f = (b & c) | (b & d) | (c & d)\n                    k = 0x8f1b_bcdc\n                else:\n                    f = b ^ c ^ d\n                    k = 0xca62_c1d6\n\n                temp = (rol32(a, 5) + f + e + k + W[t]) & 0xffff_ffff\n                e = d\n                d = c\n                c = rol32(b, 30)\n                b = a\n                a = temp\n\n            self.h0 = (self.h0 + a) & 0xffff_ffff\n            self.h1 = (self.h1 + b) & 0xffff_ffff\n            self.h2 = (self.h2 + c) & 0xffff_ffff\n            self.h3 = (self.h3 + d) & 0xffff_ffff\n            self.h4 = (self.h4 + e) & 0xffff_ffff\n            return\n\n    class WhirlpoolBase:\n        block_size = 64\n        digest_size = 64\n\n        def __init__(self, data=b\"\"):\n            self.ensure_tables()\n            self.h = [0] * 8\n            self.buf = b\"\"\n            self.count = 0  # total bytes processed\n            if data != b\"\":\n                self.update(data)\n            return\n\n        def gf_mul(self, a, b):\n            # GF(2^8) with p(x)=x^8+x^4+x^3+x^2+1 (0x11d)\n            a &= 0xff\n            b &= 0xff\n            res = 0\n            for _ in range(8):\n                if b & 1:\n                    res ^= a\n                b >>= 1\n                carry = a & 0x80\n                a = (a << 1) & 0xff\n                if carry:\n                    # reduce by 0x11d; after shift xor with low 8 bits 0x1d\n                    a ^= 0x1d\n            res &= 0xff\n            return res\n\n        def ensure_tables(self):\n            if hasattr(self, \"t_table\") and hasattr(self, \"rc_table\"):\n                return\n            if not hasattr(self, \"sbox\") or not hasattr(self, \"mds_row0\"):\n                raise ValueError(\"sbox/mds_row0 must be set in subclass\")\n            if len(self.sbox) != 256:\n                raise ValueError(\"sbox must have length 256\")\n            if len(self.mds_row0) != 8:\n                raise ValueError(\"mds_row0 must have length 8\")\n\n            # t[x] = pack8( mds_row0[i] * sbox[x] ) as u64 big-endian\n            t = [0] * 256\n            for x in range(256):\n                s = self.sbox[x] & 0xff\n                w = 0\n                for i in range(8):\n                    w = (w << 8) | self.gf_mul(self.mds_row0[i], s)\n                t[x] = w & 0xffff_ffff_ffff_ffff\n            self.t_table = t\n\n            # rc[r] = pack8( sbox[8*r : 8*r+8] ) as u64 big-endian\n            rc = [0] * 10\n            for r in range(10):\n                w = 0\n                base = 8 * r\n                for i in range(8):\n                    w = (w << 8) | (self.sbox[base + i] & 0xff)\n                rc[r] = w & 0xffff_ffff_ffff_ffff\n            self.rc_table = rc\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = self.h[:]\n            other.buf = self.buf\n            other.count = self.count\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.count += len(data)\n            self.buf += data\n            while len(self.buf) >= 64:\n                block = self.buf[:64]\n                self.buf = self.buf[64:]\n                self.process_block(block)\n            return self\n\n        def rho(self, a, n, c):\n\n            def ror64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                return ((x >> n) | (x << (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            n0 = n & 7\n            t = self.t_table\n            b = t[(a[n0] >> 56) & 0xff]\n            b ^= ror64(t[(a[(n0 + 7) & 7] >> 48) & 0xff], 8)\n            b ^= ror64(t[(a[(n0 + 6) & 7] >> 40) & 0xff], 16)\n            b ^= ror64(t[(a[(n0 + 5) & 7] >> 32) & 0xff], 24)\n            b ^= ror64(t[(a[(n0 + 4) & 7] >> 24) & 0xff], 32)\n            b ^= ror64(t[(a[(n0 + 3) & 7] >> 16) & 0xff], 40)\n            b ^= ror64(t[(a[(n0 + 2) & 7] >> 8) & 0xff], 48)\n            b ^= ror64(t[(a[(n0 + 1) & 7] >> 0) & 0xff], 56)\n            return b ^ c\n\n        def process_block(self, block):\n            x = list(struct.unpack(\">8Q\", block))\n            state = [x[i] ^ self.h[i] for i in range(8)]\n            k = self.h[:]\n\n            rc = self.rc_table\n\n            for r in range(10):\n                l = [0] * 8  # noqa: E741\n                for i in range(8):\n                    l[i] = self.rho(k, i, 0)\n                l[0] ^= rc[r]\n                k = l\n\n                l2 = [0] * 8\n                for i in range(8):\n                    l2[i] = self.rho(state, i, k[i])\n                state = l2\n\n            for i in range(8):\n                self.h[i] ^= state[i] ^ x[i]\n            return\n\n        def finalize(self):\n            bit_len = self.count * 8\n            if bit_len < 0 or bit_len >= (1 << 256):\n                raise ValueError(\"message too long\")\n\n            buf = self.buf + b\"\\x80\"\n            pad_len = (32 - (len(buf) % 64)) % 64\n            buf += b\"\\x00\" * pad_len\n            buf += bit_len.to_bytes(32, \"big\")\n\n            for off in range(0, len(buf), 64):\n                self.process_block(buf[off:off + 64])\n            self.buf = b\"\"\n            return\n\n        def digest(self):\n            tmp = self.copy()\n            tmp.finalize()\n            out = b\"\".join(struct.pack(\">Q\", w & 0xffff_ffff_ffff_ffff) for w in tmp.h)\n            return out\n\n        def hexdigest(self):\n            out = self.digest().hex()\n            return out\n\n    class Whirlpool(WhirlpoolBase):\n        # new sbox\n        sbox = (\n            0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52,\n            0x60, 0xbc, 0x9b, 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, 0xfe, 0x57,\n            0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85,\n            0xbd, 0x5d, 0x10, 0xf4, 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, 0xd8,\n            0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33,\n            0x63, 0x02, 0xaa, 0x71, 0xc8, 0x19, 0x49, 0xd9, 0xf2, 0xe3, 0x5b, 0x88, 0x9a, 0x26, 0x32, 0xb0,\n            0xe9, 0x0f, 0xd5, 0x80, 0xbe, 0xcd, 0x34, 0x48, 0xff, 0x7a, 0x90, 0x5f, 0x20, 0x68, 0x1a, 0xae,\n            0xb4, 0x54, 0x93, 0x22, 0x64, 0xf1, 0x73, 0x12, 0x40, 0x08, 0xc3, 0xec, 0xdb, 0xa1, 0x8d, 0x3d,\n            0x97, 0x00, 0xcf, 0x2b, 0x76, 0x82, 0xd6, 0x1b, 0xb5, 0xaf, 0x6a, 0x50, 0x45, 0xf3, 0x30, 0xef,\n            0x3f, 0x55, 0xa2, 0xea, 0x65, 0xba, 0x2f, 0xc0, 0xde, 0x1c, 0xfd, 0x4d, 0x92, 0x75, 0x06, 0x8a,\n            0xb2, 0xe6, 0x0e, 0x1f, 0x62, 0xd4, 0xa8, 0x96, 0xf9, 0xc5, 0x25, 0x59, 0x84, 0x72, 0x39, 0x4c,\n            0x5e, 0x78, 0x38, 0x8c, 0xd1, 0xa5, 0xe2, 0x61, 0xb3, 0x21, 0x9c, 0x1e, 0x43, 0xc7, 0xfc, 0x04,\n            0x51, 0x99, 0x6d, 0x0d, 0xfa, 0xdf, 0x7e, 0x24, 0x3b, 0xab, 0xce, 0x11, 0x8f, 0x4e, 0xb7, 0xeb,\n            0x3c, 0x81, 0x94, 0xf7, 0xb9, 0x13, 0x2c, 0xd3, 0xe7, 0x6e, 0xc4, 0x03, 0x56, 0x44, 0x7f, 0xa9,\n            0x2a, 0xbb, 0xc1, 0x53, 0xdc, 0x0b, 0x9d, 0x6c, 0x31, 0x74, 0xf6, 0x46, 0xac, 0x89, 0x14, 0xe1,\n            0x16, 0x3a, 0x69, 0x09, 0x70, 0xb6, 0xd0, 0xed, 0xcc, 0x42, 0x98, 0xa4, 0x28, 0x5c, 0xf8, 0x86,\n        )\n        # new mixrows\n        mds_row0 = (0x01, 0x01, 0x04, 0x01, 0x08, 0x05, 0x02, 0x09)\n\n    class WhirlpoolT(Whirlpool):\n        # old mixrows\n        mds_row0 = (0x01, 0x01, 0x03, 0x01, 0x05, 0x08, 0x09, 0x05)\n\n    class Whirlpool0(WhirlpoolBase):\n        # old sbox\n        sbox = (\n            0x68, 0xd0, 0xeb, 0x2b, 0x48, 0x9d, 0x6a, 0xe4, 0xe3, 0xa3, 0x56, 0x81, 0x7d, 0xf1, 0x85, 0x9e,\n            0x2c, 0x8e, 0x78, 0xca, 0x17, 0xa9, 0x61, 0xd5, 0x5d, 0x0b, 0x8c, 0x3c, 0x77, 0x51, 0x22, 0x42,\n            0x3f, 0x54, 0x41, 0x80, 0xcc, 0x86, 0xb3, 0x18, 0x2e, 0x57, 0x06, 0x62, 0xf4, 0x36, 0xd1, 0x6b,\n            0x1b, 0x65, 0x75, 0x10, 0xda, 0x49, 0x26, 0xf9, 0xcb, 0x66, 0xe7, 0xba, 0xae, 0x50, 0x52, 0xab,\n            0x05, 0xf0, 0x0d, 0x73, 0x3b, 0x04, 0x20, 0xfe, 0xdd, 0xf5, 0xb4, 0x5f, 0x0a, 0xb5, 0xc0, 0xa0,\n            0x71, 0xa5, 0x2d, 0x60, 0x72, 0x93, 0x39, 0x08, 0x83, 0x21, 0x5c, 0x87, 0xb1, 0xe0, 0x00, 0xc3,\n            0x12, 0x91, 0x8a, 0x02, 0x1c, 0xe6, 0x45, 0xc2, 0xc4, 0xfd, 0xbf, 0x44, 0xa1, 0x4c, 0x33, 0xc5,\n            0x84, 0x23, 0x7c, 0xb0, 0x25, 0x15, 0x35, 0x69, 0xff, 0x94, 0x4d, 0x70, 0xa2, 0xaf, 0xcd, 0xd6,\n            0x6c, 0xb7, 0xf8, 0x09, 0xf3, 0x67, 0xa4, 0xea, 0xec, 0xb6, 0xd4, 0xd2, 0x14, 0x1e, 0xe1, 0x24,\n            0x38, 0xc6, 0xdb, 0x4b, 0x7a, 0x3a, 0xde, 0x5e, 0xdf, 0x95, 0xfc, 0xaa, 0xd7, 0xce, 0x07, 0x0f,\n            0x3d, 0x58, 0x9a, 0x98, 0x9c, 0xf2, 0xa7, 0x11, 0x7e, 0x8b, 0x43, 0x03, 0xe2, 0xdc, 0xe5, 0xb2,\n            0x4e, 0xc7, 0x6d, 0xe9, 0x27, 0x40, 0xd8, 0x37, 0x92, 0x8f, 0x01, 0x1d, 0x53, 0x3e, 0x59, 0xc1,\n            0x4f, 0x32, 0x16, 0xfa, 0x74, 0xfb, 0x63, 0x9f, 0x34, 0x1a, 0x2a, 0x5a, 0x8d, 0xc9, 0xcf, 0xf6,\n            0x90, 0x28, 0x88, 0x9b, 0x31, 0x0e, 0xbd, 0x4a, 0xe8, 0x96, 0xa6, 0x0c, 0xc8, 0x79, 0xbc, 0xbe,\n            0xef, 0x6e, 0x46, 0x97, 0x5b, 0xed, 0x19, 0xd9, 0xac, 0x99, 0xa8, 0x29, 0x64, 0x1f, 0xad, 0x55,\n            0x13, 0xbb, 0xf7, 0x6f, 0xb9, 0x47, 0x2f, 0xee, 0xb8, 0x7b, 0x89, 0x30, 0xd3, 0x7f, 0x76, 0x82,\n        )\n        # old mixrows row0\n        mds_row0 = (0x01, 0x01, 0x03, 0x01, 0x05, 0x08, 0x09, 0x05)\n\n    class HASHxN:\n        def __init__(self, name, N, data=b\"\", use_hex=False):\n            self.name = name\n            self.N = N\n            self.hash = self.get_hash_func(name)\n            self.digest_size = self.hash.digest_size\n            self.use_hex = use_hex\n            if data:\n                self.update(data)\n            return\n\n        def get_hash_func(self, name):\n            import hashlib\n            return hashlib.new(name)\n\n        def update(self, data):\n            self.hash.update(data)\n            return\n\n        def digest(self):\n            digest = self.hash.digest()\n            for _ in range(self.N - 1):\n                next_hash_obj = self.get_hash_func(self.name)\n                if self.use_hex:\n                    next_hash_obj.update(digest.hex().encode())\n                else:\n                    next_hash_obj.update(digest)\n                digest = next_hash_obj.digest()\n            return digest\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class MD2:\n        block_size = 16\n        digest_size = 16\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes (kept for consistency)\n            self.state = [0] * 48\n            self.checksum = [0] * 16\n            self.S = [\n                0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,\n                0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,\n                0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,\n                0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,\n                0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,\n                0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,\n                0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,\n                0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,\n                0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,\n                0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,\n                0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,\n                0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,\n                0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,\n                0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,\n                0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,\n                0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14,\n            ]\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.state = list(self.state)\n            other.checksum = list(self.checksum)\n            other.S = list(self.S)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 16:\n                block = bytes(self.buf[:16])\n                del self.buf[:16]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytes(c.state[0:16])\n            return out\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            pad_len = 16 - (len(self.buf) % 16)\n            pad = bytes([pad_len]) * pad_len\n            padded = bytes(self.buf) + pad\n            self.buf.clear()\n            for i in range(0, len(padded), 16):\n                self.compress(padded[i:i + 16])\n            checksum_block = bytes(self.checksum)\n            self.compress(checksum_block)\n            return\n\n        def compress(self, block):\n            m = list(block)\n            for i in range(16):\n                self.state[16 + i] = m[i]\n                self.state[32 + i] = self.state[i] ^ m[i]\n            t = 0\n            for i in range(18):\n                for j in range(48):\n                    self.state[j] ^= self.S[t]\n                    t = self.state[j] & 0xff\n                t = (t + i) & 0xff\n            l = self.checksum[15]  # noqa: E741\n            for i in range(16):\n                c = m[i]\n                self.checksum[i] ^= self.S[c ^ l]\n                l = self.checksum[i] & 0xff  # noqa: E741\n            return\n\n    class MD4:\n        block_size = 64\n        digest_size = 16\n\n        def __init__(self, data=b\"\"):\n            self.a = 0x6745_2301\n            self.b = 0xefcd_ab89\n            self.c = 0x98ba_dcfe\n            self.d = 0x1032_5476\n            self.buf = bytearray()\n            self.msg_len = 0  # bytes processed\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.a, other.b, other.c, other.d = self.a, self.b, self.c, self.d\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def f(self, x, y, z):\n            return (x & y) | (~x & z)\n\n        def g(self, x, y, z):\n            return (x & y) | (x & z) | (y & z)\n\n        def h(self, x, y, z):\n            return x ^ y ^ z\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            # MD4 output is little-endian A,B,C,D\n            return struct.pack(\"<4I\", c.a, c.b, c.c, c.d)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n            while (len(self.buf) % 64) != 56:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\"<Q\", bit_len))\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return\n\n        def compress(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            x = list(struct.unpack(\"<16I\", block))\n            a, b, c, d = self.a, self.b, self.c, self.d\n            m = 0xffff_ffff\n\n            # round 1\n            a = rol32(a + self.f(b, c, d) + x[0], 3)\n            d = rol32(d + self.f(a, b, c) + x[1], 7)\n            c = rol32(c + self.f(d, a, b) + x[2], 11)\n            b = rol32(b + self.f(c, d, a) + x[3], 19)\n\n            a = rol32(a + self.f(b, c, d) + x[4], 3)\n            d = rol32(d + self.f(a, b, c) + x[5], 7)\n            c = rol32(c + self.f(d, a, b) + x[6], 11)\n            b = rol32(b + self.f(c, d, a) + x[7], 19)\n\n            a = rol32(a + self.f(b, c, d) + x[8], 3)\n            d = rol32(d + self.f(a, b, c) + x[9], 7)\n            c = rol32(c + self.f(d, a, b) + x[10], 11)\n            b = rol32(b + self.f(c, d, a) + x[11], 19)\n\n            a = rol32(a + self.f(b, c, d) + x[12], 3)\n            d = rol32(d + self.f(a, b, c) + x[13], 7)\n            c = rol32(c + self.f(d, a, b) + x[14], 11)\n            b = rol32(b + self.f(c, d, a) + x[15], 19)\n\n            # round 2\n            k2 = 0x5a82_7999\n            a = rol32(a + self.g(b, c, d) + x[0] + k2, 3)\n            d = rol32(d + self.g(a, b, c) + x[4] + k2, 5)\n            c = rol32(c + self.g(d, a, b) + x[8] + k2, 9)\n            b = rol32(b + self.g(c, d, a) + x[12] + k2, 13)\n\n            a = rol32(a + self.g(b, c, d) + x[1] + k2, 3)\n            d = rol32(d + self.g(a, b, c) + x[5] + k2, 5)\n            c = rol32(c + self.g(d, a, b) + x[9] + k2, 9)\n            b = rol32(b + self.g(c, d, a) + x[13] + k2, 13)\n\n            a = rol32(a + self.g(b, c, d) + x[2] + k2, 3)\n            d = rol32(d + self.g(a, b, c) + x[6] + k2, 5)\n            c = rol32(c + self.g(d, a, b) + x[10] + k2, 9)\n            b = rol32(b + self.g(c, d, a) + x[14] + k2, 13)\n\n            a = rol32(a + self.g(b, c, d) + x[3] + k2, 3)\n            d = rol32(d + self.g(a, b, c) + x[7] + k2, 5)\n            c = rol32(c + self.g(d, a, b) + x[11] + k2, 9)\n            b = rol32(b + self.g(c, d, a) + x[15] + k2, 13)\n\n            # round 3\n            k3 = 0x6ed9_eba1\n            a = rol32(a + self.h(b, c, d) + x[0] + k3, 3)\n            d = rol32(d + self.h(a, b, c) + x[8] + k3, 9)\n            c = rol32(c + self.h(d, a, b) + x[4] + k3, 11)\n            b = rol32(b + self.h(c, d, a) + x[12] + k3, 15)\n\n            a = rol32(a + self.h(b, c, d) + x[2] + k3, 3)\n            d = rol32(d + self.h(a, b, c) + x[10] + k3, 9)\n            c = rol32(c + self.h(d, a, b) + x[6] + k3, 11)\n            b = rol32(b + self.h(c, d, a) + x[14] + k3, 15)\n\n            a = rol32(a + self.h(b, c, d) + x[1] + k3, 3)\n            d = rol32(d + self.h(a, b, c) + x[9] + k3, 9)\n            c = rol32(c + self.h(d, a, b) + x[5] + k3, 11)\n            b = rol32(b + self.h(c, d, a) + x[13] + k3, 15)\n\n            a = rol32(a + self.h(b, c, d) + x[3] + k3, 3)\n            d = rol32(d + self.h(a, b, c) + x[11] + k3, 9)\n            c = rol32(c + self.h(d, a, b) + x[7] + k3, 11)\n            b = rol32(b + self.h(c, d, a) + x[15] + k3, 15)\n\n            self.a = (self.a + a) & m\n            self.b = (self.b + b) & m\n            self.c = (self.c + c) & m\n            self.d = (self.d + d) & m\n            return\n\n    class NTLM:\n        # NT hash: MD4(UTF-16LE(password))\n        digest_size = 32\n\n        def __init__(self, data=b\"\"):\n            self.md4 = Hash.MD4()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.md4 = self.md4.copy()\n            return other\n\n        def update(self, password, skip_utf16le=False):\n            if isinstance(password, str):\n                if skip_utf16le:\n                    data = password.encode()\n                else:\n                    data = password.encode(\"utf-16le\")\n            elif isinstance(password, (bytes, bytearray, memoryview)):\n                if skip_utf16le:\n                    data = bytes(password)\n                else:\n                    data = String.bytes2str(password).encode(\"utf-16le\")\n            else:\n                raise TypeError(\"password must be str or bytes-like\")\n            self.md4.update(data)\n            return self\n\n        def digest(self):\n            return self.md4.digest()\n\n        def hexdigest(self):\n            return self.md4.hexdigest()\n\n    class MD6:\n        def __init__(self, d=256, key=b\"\", L=64, r=None):\n            if not (1 <= int(d) <= 512):\n                raise ValueError(\"d must be in [1, 512]\")\n            if not (0 <= len(key) <= 64):\n                raise ValueError(\"key length must be in [0, 64] bytes\")\n            if int(L) < 0:\n                raise ValueError(\"L must be non-negative\")\n\n            self.d = int(d)\n            self.digest_size = self.d // 8\n            self.key = bytes(key)\n            self.L = int(L)\n\n            if r is None:\n                base = 40 + ((self.d + 3) // 4)  # 40 + ceil(d/4)\n                if len(self.key) != 0:\n                    self.r = max(80, base)\n                else:\n                    self.r = base\n            else:\n                if int(r) < 0:\n                    raise ValueError(\"r must be non-negative\")\n                self.r = int(r)\n\n            self.buffer = b\"\"\n\n            self.w = 64\n            self.n = 89\n            self.c = 16\n            self.b = 64\n            self.mask64 = 0xffff_ffff_ffff_ffff\n\n            self.t0 = 0x11\n            self.t1 = 0x12\n            self.t2 = 0x15\n            self.t3 = 0x1f\n            self.t4 = 0x43\n\n            self.rshift = (\n                0x0a, 0x05, 0x0d, 0x0a, 0x0b, 0x0c, 0x02, 0x07, 0x0e, 0x0f, 0x07, 0x0d, 0x0b, 0x07, 0x06, 0x0c,\n            )\n            self.lshift = (\n                0x0b, 0x18, 0x09, 0x10, 0x0f, 0x09, 0x1b, 0x0f, 0x06, 0x02, 0x1d, 0x08, 0x0f, 0x05, 0x1f, 0x09,\n            )\n            self.Q = [\n                0x7311_c281_2425_cfa0, 0x6432_2864_34aa_c8e7, 0xb604_50e9_ef68_b7c1, 0xe8fb_2390_8d9f_06f1,\n                0xdd2e_76cb_a691_e5bf, 0x0cd0_d63b_2c30_bc41, 0x1f8c_cf68_2305_8f8a, 0x54e5_ed5b_88e3_775d,\n                0x4ad1_2aae_0a6d_6031, 0x3e7f_16bb_8822_2e0d, 0x8af8_671d_3fb5_0c2c, 0x995a_d117_8bd2_5c31,\n                0xc878_c1dd_04c4_b633, 0x3b72_066c_7a15_52ac, 0x0d6f_3522_631e_ffcb,\n            ]\n\n            self.S0 = 0x0123_4567_89ab_cdef\n            self.Sstar = 0x7311_c281_2425_cfa0\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buffer += bytes(data)\n            return self\n\n        def copy(self):\n            other = self.__class__(d=self.d, key=self.key, L=self.L, r=self.r)\n            other.buffer = self.buffer\n            return other\n\n        def digest(self):\n            return self.hash(self.buffer)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def rol64(self, x, n):\n            n &= 63\n            x &= self.mask64\n            return ((x << n) & self.mask64) | (x >> (64 - n))\n\n        def pack_control(self, r, L, z, p, keylen, d):\n            # Control word V layout (high-order 4 bits are zero):\n            # [0:4][r:12][L:8][z:4][p:16][keylen:8][d:12]\n            # r at bits 48..59, L at 40..47, z at 36..39, p at 20..35, keylen at 12..19, d at 0..11\n            r &= (1 << 12) - 1\n            L &= (1 << 8) - 1\n            z &= (1 << 4) - 1\n            p &= (1 << 16) - 1\n            keylen &= (1 << 8) - 1\n            d &= (1 << 12) - 1\n            return ((r << 48) | (L << 40) | (z << 36) | (p << 20) | (keylen << 12) | d) & self.mask64\n\n        def pack_node_id(self, ell, i):\n            # Unique node ID U layout:\n            # high-order byte is ell, remaining 7 bytes is index i\n            return (((ell & 0xff) << 56) | (i & ((1 << 56) - 1))) & self.mask64\n\n        def bytes_to_words_be(self, data, count):\n            out = []\n            need = count * 8\n            if len(data) < need:\n                data = data + b\"\\x00\" * (need - len(data))\n            for j in range(count):\n                out.append(int.from_bytes(data[j * 8:(j + 1) * 8], \"big\"))\n            return out\n\n        def words_to_bytes_be(self, words):\n            return b\"\".join((w & self.mask64).to_bytes(8, \"big\") for w in words)\n\n        def make_key_words(self):\n            kp = self.key + b\"\\x00\" * (64 - len(self.key))\n            return self.bytes_to_words_be(kp, 8)\n\n        def make_round_constants(self, r):\n            # S'_0 = S0\n            # S'_{j+1} = (S'_j <<< 1) xor (S'_j & S*)\n            # Use rotate-left by 1 (<<<).\n            S = []\n            x = self.S0 & self.mask64\n            for _ in range(r):\n                S.append(x)\n                x = self.rol64(x, 1) ^ (x & self.Sstar)\n                x &= self.mask64\n            return S\n\n        def compress(self, N_words, r):\n            # N_words length must be 89 (15 Q + 8 K + 1 U + 1 V + 64 B)\n            if len(N_words) != self.n:\n                raise ValueError(\"N_words must be length 89\")\n\n            t = 16 * r\n            A = list(N_words)\n\n            Sround = self.make_round_constants(r)\n\n            for i in range(self.n, self.n + t):\n                step = i - self.n  # 0..t-1\n                ridx = step & 0x0f\n                round_idx = step >> 4\n\n                x = Sround[round_idx]\n                x ^= A[i - self.n]\n                x ^= A[i - self.t0]\n                x ^= (A[i - self.t1] & A[i - self.t2])\n                x ^= (A[i - self.t3] & A[i - self.t4])\n                x &= self.mask64\n\n                x ^= (x >> self.rshift[ridx])\n                x &= self.mask64\n\n                y = x ^ ((x << self.lshift[ridx]) & self.mask64)\n                y &= self.mask64\n\n                A.append(y)\n\n            # Output last 16 words\n            return A[-self.c:]\n\n        def par(self, M_bytes, ell):\n            # PAR operator (Figure 2.5): input message at level ell-1 -> output message at level ell\n            block_bytes = 512  # 64 words\n            m_bits = len(M_bytes) * 8\n\n            j = (len(M_bytes) + block_bytes - 1) // block_bytes\n            if j < 1:\n                j = 1\n\n            total_bytes = j * block_bytes\n            pad_bits = total_bytes * 8 - m_bits  # 0..4096*? (here <= 4096-8)\n            if pad_bits < 0:\n                raise RuntimeError(\"internal padding error\")\n\n            Mp = M_bytes + b\"\\x00\" * (total_bytes - len(M_bytes))\n\n            K_words = self.make_key_words()\n            keylen = len(self.key)\n            z_all = 1 if j == 1 else 0\n\n            out_chunks = []\n            for i in range(j):\n                Bi = Mp[i * block_bytes:(i + 1) * block_bytes]\n                B_words = self.bytes_to_words_be(Bi, 64)\n\n                p = pad_bits if (i == j - 1) else 0\n                V = self.pack_control(self.r, self.L, z_all, p, keylen, self.d)\n                U = self.pack_node_id(ell, i)\n\n                N = self.Q + K_words + [U, V] + B_words\n                Ci = self.compress(N, self.r)\n                out_chunks.append(Ci)\n\n            # Concatenate C0||C1||... as bytes\n            out_words = []\n            for Ci in out_chunks:\n                out_words.extend(Ci)\n            return self.words_to_bytes_be(out_words)\n\n        def seq(self, M_bytes):\n            # SEQ operator (Figure 2.6): sequential MD-like; returns d-bit hash\n            block_words = 48\n            block_bytes = block_words * 8  # 384 bytes\n\n            m_bits = len(M_bytes) * 8\n\n            j = (len(M_bytes) + block_bytes - 1) // block_bytes\n            if j < 1:\n                j = 1\n\n            total_bytes = j * block_bytes\n            pad_bits = total_bytes * 8 - m_bits  # 0..3072\n            Mp = M_bytes + b\"\\x00\" * (total_bytes - len(M_bytes))\n\n            K_words = self.make_key_words()\n            keylen = len(self.key)\n\n            C_prev = [0x00] * self.c  # 16-word IV of zeros\n\n            ell = self.L + 1\n            for i in range(j):\n                Bi = Mp[i * block_bytes:(i + 1) * block_bytes]\n                Bi_words = self.bytes_to_words_be(Bi, block_words)\n\n                z = 1 if (i == j - 1) else 0\n                p = pad_bits if (i == j - 1) else 0\n\n                V = self.pack_control(self.r, self.L, z, p, keylen, self.d)\n                U = self.pack_node_id(ell, i)\n\n                # B is 64 words = C_{i-1} (16) || B_i (48)\n                B_words = list(C_prev) + Bi_words\n                N = self.Q + K_words + [U, V] + B_words\n                C_prev = self.compress(N, self.r)\n\n            # Return last d bits of C_{j-1}\n            full = self.words_to_bytes_be(C_prev)  # 128 bytes (1024 bits)\n            return self.last_bits(full, self.d)\n\n        def last_bits(self, data, d_bits):\n            # Return the last d_bits of data (data is a big-endian bitstring).\n            if d_bits == 0:\n                return b\"\"\n            total_bits = len(data) * 8\n            if d_bits > total_bits:\n                raise ValueError(\"d_bits larger than available bits\")\n\n            # Fast path for byte-aligned\n            if (d_bits & 7) == 0:\n                return data[-(d_bits // 8):]\n\n            # Bit-level extraction\n            keep_bytes = (d_bits + 7) // 8\n            tail = data[-keep_bytes:]\n            excess = (keep_bytes * 8) - d_bits  # 1..7\n            # We need the lowest (8-excess) bits of the first byte\n            first = tail[0] & ((1 << (8 - excess)) - 1)\n            return bytes([first]) + tail[1:]\n\n        def hash(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            M = bytes(data)\n\n            # Main level-by-level loop (Figure 2.4):\n            # ell starts at 0, then increments; if ell == L+1 -> SEQ on previous\n            ell = 0\n            M_ell_minus_1 = M\n\n            while True:\n                ell += 1\n                if ell == self.L + 1:\n                    return self.seq(M_ell_minus_1)\n\n                M_ell = self.par(M_ell_minus_1, ell)\n\n                # If M_ell is exactly c words (16 words) long, return last d bits of M_ell\n                if len(M_ell) == self.c * 8:\n                    return self.last_bits(M_ell, self.d)\n\n                M_ell_minus_1 = M_ell\n            raise\n\n    class RIPEMDBase:\n        block_size = 64\n        digest_size = None  # bytes\n        init_state_words = None  # little-endian words\n        rounds = None  # 4 for 128/160/256, 5 for 320\n\n        # RIPEMD message word order and rotation amounts (base tables; 128/160/256 use first 64, 320 uses full 80)\n        r = (\n            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n            0x07, 0x04, 0x0d, 0x01, 0x0a, 0x06, 0x0f, 0x03, 0x0c, 0x00, 0x09, 0x05, 0x02, 0x0e, 0x0b, 0x08,\n            0x03, 0x0a, 0x0e, 0x04, 0x09, 0x0f, 0x08, 0x01, 0x02, 0x07, 0x00, 0x06, 0x0d, 0x0b, 0x05, 0x0c,\n            0x01, 0x09, 0x0b, 0x0a, 0x00, 0x08, 0x0c, 0x04, 0x0d, 0x03, 0x07, 0x0f, 0x0e, 0x05, 0x06, 0x02,\n            0x04, 0x00, 0x05, 0x09, 0x07, 0x0c, 0x02, 0x0a, 0x0e, 0x01, 0x03, 0x08, 0x0b, 0x06, 0x0f, 0x0d,\n        )\n        rp = (\n            0x05, 0x0e, 0x07, 0x00, 0x09, 0x02, 0x0b, 0x04, 0x0d, 0x06, 0x0f, 0x08, 0x01, 0x0a, 0x03, 0x0c,\n            0x06, 0x0b, 0x03, 0x07, 0x00, 0x0d, 0x05, 0x0a, 0x0e, 0x0f, 0x08, 0x0c, 0x04, 0x09, 0x01, 0x02,\n            0x0f, 0x05, 0x01, 0x03, 0x07, 0x0e, 0x06, 0x09, 0x0b, 0x08, 0x0c, 0x02, 0x0a, 0x00, 0x04, 0x0d,\n            0x08, 0x06, 0x04, 0x01, 0x03, 0x0b, 0x0f, 0x00, 0x05, 0x0c, 0x02, 0x0d, 0x09, 0x07, 0x0a, 0x0e,\n            0x0c, 0x0f, 0x0a, 0x04, 0x01, 0x05, 0x08, 0x07, 0x06, 0x02, 0x0d, 0x0e, 0x00, 0x03, 0x09, 0x0b,\n        )\n        s = (\n            0x0b, 0x0e, 0x0f, 0x0c, 0x05, 0x08, 0x07, 0x09, 0x0b, 0x0d, 0x0e, 0x0f, 0x06, 0x07, 0x09, 0x08,\n            0x07, 0x06, 0x08, 0x0d, 0x0b, 0x09, 0x07, 0x0f, 0x07, 0x0c, 0x0f, 0x09, 0x0b, 0x07, 0x0d, 0x0c,\n            0x0b, 0x0d, 0x06, 0x07, 0x0e, 0x09, 0x0d, 0x0f, 0x0e, 0x08, 0x0d, 0x06, 0x05, 0x0c, 0x07, 0x05,\n            0x0b, 0x0c, 0x0e, 0x0f, 0x0e, 0x0f, 0x09, 0x08, 0x09, 0x0e, 0x05, 0x06, 0x08, 0x06, 0x05, 0x0c,\n            0x09, 0x0f, 0x05, 0x0b, 0x06, 0x08, 0x0d, 0x0c, 0x05, 0x0c, 0x0d, 0x0e, 0x0b, 0x08, 0x05, 0x06,\n        )\n        sp = (\n            0x08, 0x09, 0x09, 0x0b, 0x0d, 0x0f, 0x0f, 0x05, 0x07, 0x07, 0x08, 0x0b, 0x0e, 0x0e, 0x0c, 0x06,\n            0x09, 0x0d, 0x0f, 0x07, 0x0c, 0x08, 0x09, 0x0b, 0x07, 0x07, 0x0c, 0x07, 0x06, 0x0f, 0x0d, 0x0b,\n            0x09, 0x07, 0x0f, 0x0b, 0x08, 0x06, 0x06, 0x0e, 0x0c, 0x0d, 0x05, 0x0e, 0x0d, 0x0d, 0x07, 0x05,\n            0x0f, 0x05, 0x08, 0x0b, 0x0e, 0x0e, 0x06, 0x0e, 0x06, 0x09, 0x0c, 0x09, 0x0c, 0x05, 0x0f, 0x08,\n            0x08, 0x05, 0x0c, 0x09, 0x0c, 0x05, 0x0e, 0x06, 0x08, 0x0d, 0x06, 0x05, 0x0f, 0x0d, 0x0b, 0x0b,\n        )\n\n        # constants for rounds (left line / right line)\n        K4 = (0x0000_0000, 0x5a82_7999, 0x6ed9_eba1, 0x8f1b_bcdc)\n        K4p = (0x50a2_8be6, 0x5c4d_d124, 0x6d70_3ef3, 0x0000_0000)\n\n        K5 = (0x0000_0000, 0x5a82_7999, 0x6ed9_eba1, 0x8f1b_bcdc, 0xa953_fd4e)\n        K5p = (0x50a2_8be6, 0x5c4d_d124, 0x6d70_3ef3, 0x7a6d_76e9, 0x0000_0000)\n\n        def __init__(self, data=b\"\"):\n            self.h = self.init_state_words[:]\n            self.buf = b\"\"\n            self.total = 0\n            if data:\n                self.update(data)\n            return\n\n        def f(self, j, x, y, z):\n            # j: 0..4 (uses first 4 for 128/160/256)\n            if j == 0:\n                return x ^ y ^ z\n            if j == 1:\n                return (x & y) | ((~x) & z)\n            if j == 2:\n                return (x | (~y)) ^ z\n            if j == 3:\n                return (x & z) | (y & (~z))\n            return x ^ (y | (~z))\n\n        def fp(self, j, x, y, z):\n            # parallel line order: for 4-round: I,H,G,F\n            # for 5-round: J,I,H,G,F (i.e. f4,f3,f2,f1,f0)\n            if self.rounds == 4:\n                if j == 0:\n                    return (x & z) | (y & (~z))  # I\n                if j == 1:\n                    return (x | (~y)) ^ z        # H\n                if j == 2:\n                    return (x & y) | ((~x) & z)  # G\n                return x ^ y ^ z                 # F\n            else:\n                # 0..4 maps to f4,f3,f2,f1,f0\n                if j == 0:\n                    return x ^ (y | (~z))        # J\n                if j == 1:\n                    return (x & z) | (y & (~z))  # I\n                if j == 2:\n                    return (x | (~y)) ^ z        # H\n                if j == 3:\n                    return (x & y) | ((~x) & z)  # G\n                return x ^ y ^ z                 # F\n\n        def update(self, data):\n            if not data:\n                return self\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.total += len(data)\n            self.buf += bytes(data)\n            while len(self.buf) >= 64:\n                block = self.buf[:64]\n                self.buf = self.buf[64:]\n                self.transform(block)\n            return self\n\n        def pad(self):\n            bit_len = self.total * 8\n            pad = b\"\\x80\"\n            pad_len = (56 - (self.total + 1) % 64) % 64\n            pad += b\"\\x00\" * pad_len\n            pad += (bit_len & 0xffff_ffff_ffff_ffff).to_bytes(8, \"little\")\n            return pad\n\n        def digest(self):\n            clone = self.__class__()\n            clone.h = self.h[:]\n            clone.buf = self.buf\n            clone.total = self.total\n            clone.update(clone.pad())\n            out = b\"\".join((w & 0xffff_ffff).to_bytes(4, \"little\") for w in clone.h)\n            return out[: self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class RIPEMD128(RIPEMDBase):\n        digest_size = 16\n        init_state_words = (\n            0x6745_2301, 0xefcd_ab89, 0x98ba_dcfe, 0x1032_5476,\n        )\n        rounds = 4\n\n        def transform(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            X = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n            h0, h1, h2, h3 = self.h\n\n            a, b, c, d = h0, h1, h2, h3\n            aa, bb, cc, dd = h0, h1, h2, h3\n\n            for j in range(64):\n                rj = self.r[j]\n                sj = self.s[j]\n                round_idx = j // 16\n                t = (a + self.f(round_idx, b, c, d) + X[rj] + self.K4[round_idx]) & 0xffff_ffff\n                t = rol32(t, sj)\n                a, d, c, b = d, c, b, t\n\n                rpj = self.rp[j]\n                spj = self.sp[j]\n                pround = j // 16\n                tp = (aa + self.fp(pround, bb, cc, dd) + X[rpj] + self.K4p[pround]) & 0xffff_ffff\n                tp = rol32(tp, spj)\n                aa, dd, cc, bb = dd, cc, bb, tp\n\n            self.h = [\n                (h1 + c + dd) & 0xffff_ffff,\n                (h2 + d + aa) & 0xffff_ffff,\n                (h3 + a + bb) & 0xffff_ffff,\n                (h0 + b + cc) & 0xffff_ffff,\n            ]\n            return\n\n    class RIPEMD160(RIPEMDBase):\n        digest_size = 20\n        init_state_words = (\n            0x6745_2301, 0xefcd_ab89, 0x98ba_dcfe, 0x1032_5476, 0xc3d2_e1f0,\n        )\n        rounds = 5\n\n        def transform(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            X = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n            h0, h1, h2, h3, h4 = self.h\n\n            a, b, c, d, e = h0, h1, h2, h3, h4\n            aa, bb, cc, dd, ee = h0, h1, h2, h3, h4\n\n            for j in range(80):\n                round_idx = j // 16\n\n                t = (a + self.f(round_idx, b, c, d) + X[self.r[j]] + self.K5[round_idx]) & 0xffff_ffff\n                t = rol32(t, self.s[j])\n                t = (t + e) & 0xffff_ffff\n                a, e, d, c, b = e, d, rol32(c, 0x0a), b, t  # c <<< 10\n\n                tp = (aa + self.fp(round_idx, bb, cc, dd) + X[self.rp[j]] + self.K5p[round_idx]) & 0xffff_ffff\n                tp = rol32(tp, self.sp[j])\n                tp = (tp + ee) & 0xffff_ffff\n                aa, ee, dd, cc, bb = ee, dd, rol32(cc, 0x0a), bb, tp  # cc <<< 10\n\n            self.h = [\n                (h1 + c + dd) & 0xffff_ffff,\n                (h2 + d + ee) & 0xffff_ffff,\n                (h3 + e + aa) & 0xffff_ffff,\n                (h4 + a + bb) & 0xffff_ffff,\n                (h0 + b + cc) & 0xffff_ffff,\n            ]\n            return\n\n    class RIPEMD256(RIPEMDBase):\n        digest_size = 32\n        init_state_words = (\n            0x6745_2301, 0xefcd_ab89, 0x98ba_dcfe, 0x1032_5476, 0x7654_3210, 0xfedc_ba98, 0x89ab_cdef, 0x0123_4567,\n        )\n        rounds = 4\n\n        def transform(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            X = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n            h0, h1, h2, h3, h4, h5, h6, h7 = self.h\n\n            a, b, c, d = h0, h1, h2, h3\n            aa, bb, cc, dd = h4, h5, h6, h7\n\n            for j in range(64):\n                round_idx = j // 16\n\n                t = (a + self.f(round_idx, b, c, d) + X[self.r[j]] + self.K4[round_idx]) & 0xffff_ffff\n                t = rol32(t, self.s[j])\n                a, d, c, b = d, c, b, t\n\n                tp = (aa + self.fp(round_idx, bb, cc, dd) + X[self.rp[j]] + self.K4p[round_idx]) & 0xffff_ffff\n                tp = rol32(tp, self.sp[j])\n                aa, dd, cc, bb = dd, cc, bb, tp\n\n                # swaps after each 16-step round (RIPEMD-256)\n                if (j & 0x0f) == 0x0f:\n                    if round_idx == 0:\n                        a, aa = aa, a\n                    elif round_idx == 1:\n                        b, bb = bb, b\n                    elif round_idx == 2:\n                        c, cc = cc, c\n                    else:\n                        d, dd = dd, d\n\n            self.h = [\n                (h0 + a) & 0xffff_ffff,\n                (h1 + b) & 0xffff_ffff,\n                (h2 + c) & 0xffff_ffff,\n                (h3 + d) & 0xffff_ffff,\n                (h4 + aa) & 0xffff_ffff,\n                (h5 + bb) & 0xffff_ffff,\n                (h6 + cc) & 0xffff_ffff,\n                (h7 + dd) & 0xffff_ffff,\n            ]\n            return\n\n    class RIPEMD320(RIPEMD256):\n        digest_size = 40\n        init_state_words = (\n            0x6745_2301, 0xefcd_ab89, 0x98ba_dcfe, 0x1032_5476, 0xc3d2_e1f0,\n            0x7654_3210, 0xfedc_ba98, 0x89ab_cdef, 0x0123_4567, 0x3c2d_1e0f,\n        )\n        rounds = 5\n\n        def transform(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            X = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n            h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 = self.h\n\n            a, b, c, d, e = h0, h1, h2, h3, h4\n            aa, bb, cc, dd, ee = h5, h6, h7, h8, h9\n\n            for j in range(80):\n                round_idx = j // 16\n\n                t = (a + self.f(round_idx, b, c, d) + X[self.r[j]] + self.K5[round_idx]) & 0xffff_ffff\n                t = rol32(t, self.s[j])\n                t = (t + e) & 0xffff_ffff\n                a, e, d, c, b = e, d, rol32(c, 0x0a), b, t  # rotate (c left by 10)\n\n                tp = (aa + self.fp(round_idx, bb, cc, dd) + X[self.rp[j]] + self.K5p[round_idx]) & 0xffff_ffff\n                tp = rol32(tp, self.sp[j])\n                tp = (tp + ee) & 0xffff_ffff\n                aa, ee, dd, cc, bb = ee, dd, rol32(cc, 0x0a), bb, tp\n\n                # swaps after each 16-step round (RIPEMD-320)\n                if (j & 0x0f) == 0x0f:\n                    if round_idx == 0:\n                        b, bb = bb, b\n                    elif round_idx == 1:\n                        d, dd = dd, d\n                    elif round_idx == 2:\n                        a, aa = aa, a\n                    elif round_idx == 3:\n                        c, cc = cc, c\n                    else:\n                        e, ee = ee, e\n\n            self.h = [\n                (h0 + a) & 0xffff_ffff,\n                (h1 + b) & 0xffff_ffff,\n                (h2 + c) & 0xffff_ffff,\n                (h3 + d) & 0xffff_ffff,\n                (h4 + e) & 0xffff_ffff,\n                (h5 + aa) & 0xffff_ffff,\n                (h6 + bb) & 0xffff_ffff,\n                (h7 + cc) & 0xffff_ffff,\n                (h8 + dd) & 0xffff_ffff,\n                (h9 + ee) & 0xffff_ffff,\n            ]\n            return\n\n    class BLAKEBase:\n        sigma = (\n            (0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f),\n            (0x0e, 0x0a, 0x04, 0x08, 0x09, 0x0f, 0x0d, 0x06, 0x01, 0x0c, 0x00, 0x02, 0x0b, 0x07, 0x05, 0x03),\n            (0x0b, 0x08, 0x0c, 0x00, 0x05, 0x02, 0x0f, 0x0d, 0x0a, 0x0e, 0x03, 0x06, 0x07, 0x01, 0x09, 0x04),\n            (0x07, 0x09, 0x03, 0x01, 0x0d, 0x0c, 0x0b, 0x0e, 0x02, 0x06, 0x05, 0x0a, 0x04, 0x00, 0x0f, 0x08),\n            (0x09, 0x00, 0x05, 0x07, 0x02, 0x04, 0x0a, 0x0f, 0x0e, 0x01, 0x0b, 0x0c, 0x06, 0x08, 0x03, 0x0d),\n            (0x02, 0x0c, 0x06, 0x0a, 0x00, 0x0b, 0x08, 0x03, 0x04, 0x0d, 0x07, 0x05, 0x0f, 0x0e, 0x01, 0x09),\n            (0x0c, 0x05, 0x01, 0x0f, 0x0e, 0x0d, 0x04, 0x0a, 0x00, 0x07, 0x06, 0x03, 0x09, 0x02, 0x08, 0x0b),\n            (0x0d, 0x0b, 0x07, 0x0e, 0x0c, 0x01, 0x03, 0x09, 0x05, 0x00, 0x0f, 0x04, 0x08, 0x06, 0x02, 0x0a),\n            (0x06, 0x0f, 0x0e, 0x09, 0x0b, 0x03, 0x00, 0x08, 0x0c, 0x02, 0x0d, 0x07, 0x01, 0x04, 0x0a, 0x05),\n            (0x0a, 0x02, 0x08, 0x04, 0x07, 0x06, 0x01, 0x05, 0x0f, 0x0b, 0x09, 0x0e, 0x03, 0x0c, 0x0d, 0x00),\n        )\n\n        def __init__(self, data=b\"\"):\n            self.h = list(self.iv)\n            self.buf = b\"\"\n            self.total = 0\n            self.processed = 0\n            self.mask = (1 << self.word_bits) - 1\n            self.word_bytes = self.word_bits // 8\n            if self.word_bits == 32:\n                self.rot = (16, 12, 8, 7)\n            else:\n                self.rot = (32, 25, 16, 11)\n            if data:\n                self.update(data)\n            return\n\n        def rol(self, x, n):\n            x &= self.mask\n            return ((x << n) | (x >> (self.word_bits - n))) & self.mask\n\n        def ror(self, x, n):\n            x &= self.mask\n            return ((x >> n) | (x << (self.word_bits - n))) & self.mask\n\n        def add(self, x, y):\n            return (x + y) & self.mask\n\n        def parse_block_words(self, block):\n            return [\n                int.from_bytes(block[i:i + self.word_bytes], \"big\")\n                for i in range(0, self.block_size, self.word_bytes)\n            ]\n\n        def split_counter(self, counter_bits):\n            if self.word_bits == 32:\n                t = counter_bits & 0xffff_ffff_ffff_ffff\n                t0 = t & 0xffff_ffff\n                t1 = (t >> 32) & 0xffff_ffff\n                return t0, t1\n            t = counter_bits & ((1 << 128) - 1)\n            t0 = t & 0xffff_ffff_ffff_ffff\n            t1 = (t >> 64) & 0xffff_ffff_ffff_ffff\n            return t0, t1\n\n        def g(self, v, a, b, c, d, m, r, i):\n            s = self.sigma[r % 10]\n            x = s[2 * i]\n            y = s[2 * i + 1]\n            cx = self.c[x]\n            cy = self.c[y]\n            r0, r1, r2, r3 = self.rot\n\n            va = (v[a] + v[b] + (m[x] ^ cy)) & self.mask\n            vd = self.ror(v[d] ^ va, r0)\n            vc = (v[c] + vd) & self.mask\n            vb = self.ror(v[b] ^ vc, r1)\n\n            va = (va + vb + (m[y] ^ cx)) & self.mask\n            vd = self.ror(vd ^ va, r2)\n            vc = (vc + vd) & self.mask\n            vb = self.ror(vb ^ vc, r3)\n\n            v[a] = va\n            v[b] = vb\n            v[c] = vc\n            v[d] = vd\n            return\n\n        def compress(self, block, counter_bits):\n            m = self.parse_block_words(block)\n            t0, t1 = self.split_counter(counter_bits)\n\n            v = self.h[:] + [\n                self.c[0],\n                self.c[1],\n                self.c[2],\n                self.c[3],\n                t0 ^ self.c[4],\n                t0 ^ self.c[5],\n                t1 ^ self.c[6],\n                t1 ^ self.c[7],\n            ]\n\n            for r in range(self.rounds):\n                self.g(v, 0, 4, 8, 12, m, r, 0)\n                self.g(v, 1, 5, 9, 13, m, r, 1)\n                self.g(v, 2, 6, 10, 14, m, r, 2)\n                self.g(v, 3, 7, 11, 15, m, r, 3)\n                self.g(v, 0, 5, 10, 15, m, r, 4)\n                self.g(v, 1, 6, 11, 12, m, r, 5)\n                self.g(v, 2, 7, 8, 13, m, r, 6)\n                self.g(v, 3, 4, 9, 14, m, r, 7)\n\n            h0, h1, h2, h3, h4, h5, h6, h7 = self.h\n            h0 = (h0 ^ v[0] ^ v[8]) & self.mask\n            h1 = (h1 ^ v[1] ^ v[9]) & self.mask\n            h2 = (h2 ^ v[2] ^ v[10]) & self.mask\n            h3 = (h3 ^ v[3] ^ v[11]) & self.mask\n            h4 = (h4 ^ v[4] ^ v[12]) & self.mask\n            h5 = (h5 ^ v[5] ^ v[13]) & self.mask\n            h6 = (h6 ^ v[6] ^ v[14]) & self.mask\n            h7 = (h7 ^ v[7] ^ v[15]) & self.mask\n            self.h = [h0, h1, h2, h3, h4, h5, h6, h7]\n            return\n\n        def update(self, data):\n            if not data:\n                return self\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            mv = memoryview(data)\n            self.total += len(mv)\n\n            if self.buf:\n                need = self.block_size - len(self.buf)\n                if len(mv) < need:\n                    self.buf += mv.tobytes()\n                    return self\n                block = self.buf + mv[:need].tobytes()\n                self.processed += self.block_size\n                self.compress(block, self.processed * 8)\n                self.buf = b\"\"\n                mv = mv[need:]\n\n            end = len(mv) - (len(mv) % self.block_size)\n            for off in range(0, end, self.block_size):\n                block = mv[off:off + self.block_size]\n                self.processed += self.block_size\n                self.compress(block, self.processed * 8)\n\n            self.buf = mv[end:].tobytes()\n            return self\n\n        def make_padding(self):\n            msg_bits = self.total * 8\n            buf_len = len(self.buf)\n            pad_zero_len = (\n                self.block_size - ((buf_len + 1 + 1 + self.length_bytes) % self.block_size)\n            ) % self.block_size\n            pad = (\n                b\"\\x80\"\n                + (b\"\\x00\" * pad_zero_len)\n                + bytes([self.pad_delim])\n                + msg_bits.to_bytes(self.length_bytes, \"big\")\n            )\n            return pad\n\n        def finalize(self):\n            msg_bits = self.total * 8\n            final_data = self.buf + self.make_padding()\n\n            if len(final_data) % self.block_size != 0:\n                raise ValueError(\"internal padding error\")\n\n            first_counter = msg_bits if (self.total % self.block_size) != 0 else 0\n\n            for off in range(0, len(final_data), self.block_size):\n                block = final_data[off:off + self.block_size]\n                counter_bits = first_counter if off == 0 else 0\n                self.compress(block, counter_bits)\n            return\n\n        def digest(self):\n            clone = self.__class__()\n            clone.h = self.h[:]\n            clone.buf = self.buf\n            clone.total = self.total\n            clone.processed = self.processed\n            clone.finalize()\n\n            out = b\"\".join(\n                (w & clone.mask).to_bytes(clone.word_bytes, \"big\")\n                for w in clone.h\n            )\n            return out[:self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class BLAKE224(BLAKEBase):\n        block_size = 64\n        digest_size = 28\n        word_bits = 32\n        rounds = 14\n        pad_delim = 0x00\n        length_bytes = 8\n\n        iv = (\n            0xc105_9ed8, 0x367c_d507, 0x3070_dd17, 0xf70e_5939, 0xffc0_0b31, 0x6858_1511, 0x64f9_8fa7, 0xbefa_4fa4,\n        )\n        c = (\n            0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e, 0x0370_7344, 0xa409_3822, 0x299f_31d0, 0x082e_fa98, 0xec4e_6c89,\n            0x4528_21e6, 0x38d0_1377, 0xbe54_66cf, 0x34e9_0c6c, 0xc0ac_29b7, 0xc97c_50dd, 0x3f84_d5b5, 0xb547_0917,\n        )\n\n    class BLAKE256(BLAKEBase):\n        block_size = 64\n        digest_size = 32\n        word_bits = 32\n        rounds = 14\n        pad_delim = 0x01\n        length_bytes = 8\n\n        iv = (\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a, 0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        )\n        c = (\n            0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e, 0x0370_7344, 0xa409_3822, 0x299f_31d0, 0x082e_fa98, 0xec4e_6c89,\n            0x4528_21e6, 0x38d0_1377, 0xbe54_66cf, 0x34e9_0c6c, 0xc0ac_29b7, 0xc97c_50dd, 0x3f84_d5b5, 0xb547_0917,\n        )\n\n    class BLAKE384(BLAKEBase):\n        block_size = 128\n        digest_size = 48\n        word_bits = 64\n        rounds = 16\n        pad_delim = 0x00\n        length_bytes = 16\n\n        iv = (\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x8eb4_4a87_6858_1511, 0xdb0c_2e0d_64f9_8fa7, 0x47b5_481d_befa_4fa4,\n        )\n        c = (\n            0x243f_6a88_85a3_08d3, 0x1319_8a2e_0370_7344, 0xa409_3822_299f_31d0, 0x082e_fa98_ec4e_6c89,\n            0x4528_21e6_38d0_1377, 0xbe54_66cf_34e9_0c6c, 0xc0ac_29b7_c97c_50dd, 0x3f84_d5b5_b547_0917,\n            0x9216_d5d9_8979_fb1b, 0xd131_0ba6_98df_b5ac, 0x2ffd_72db_d01a_dfb7, 0xb8e1_afed_6a26_7e96,\n            0xba7c_9045_f12c_7f99, 0x24a1_9947_b391_6cf7, 0x0801_f2e2_858e_fc16, 0x6369_20d8_7157_4e69,\n        )\n\n    class BLAKE512(BLAKEBase):\n        block_size = 128\n        digest_size = 64\n        word_bits = 64\n        rounds = 16\n        pad_delim = 0x01\n        length_bytes = 16\n\n        iv = (\n            0x6a09_e667_f3bc_c908, 0xbb67_ae85_84ca_a73b, 0x3c6e_f372_fe94_f82b, 0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1, 0x9b05_688c_2b3e_6c1f, 0x1f83_d9ab_fb41_bd6b, 0x5be0_cd19_137e_2179,\n        )\n        c = (\n            0x243f_6a88_85a3_08d3, 0x1319_8a2e_0370_7344, 0xa409_3822_299f_31d0, 0x082e_fa98_ec4e_6c89,\n            0x4528_21e6_38d0_1377, 0xbe54_66cf_34e9_0c6c, 0xc0ac_29b7_c97c_50dd, 0x3f84_d5b5_b547_0917,\n            0x9216_d5d9_8979_fb1b, 0xd131_0ba6_98df_b5ac, 0x2ffd_72db_d01a_dfb7, 0xb8e1_afed_6a26_7e96,\n            0xba7c_9045_f12c_7f99, 0x24a1_9947_b391_6cf7, 0x0801_f2e2_858e_fc16, 0x6369_20d8_7157_4e69,\n        )\n\n    class BLAKE2pBase:\n        block_size = 0x0200\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.block_index = 0\n            self.finalized = False\n            self.final_digest = None\n            self.leaves = [self.create_leaf(i) for i in range(self.parallelism)]\n            if data:\n                self.update(data)\n            return\n\n        def create_leaf(self, node_offset):\n            return self.blake2_func(\n                digest_size=self.digest_size,\n                fanout=self.parallelism,\n                depth=2,\n                leaf_size=0,\n                node_offset=node_offset,\n                node_depth=0,\n                inner_size=self.inner_size,\n                last_node=(node_offset == self.parallelism - 1),\n            )\n\n        def create_root(self):\n            return self.blake2_func(\n                digest_size=self.digest_size,\n                fanout=self.parallelism,\n                depth=2,\n                leaf_size=0,\n                node_offset=0,\n                node_depth=1,\n                inner_size=self.inner_size,\n                last_node=True,\n            )\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.block_index = self.block_index\n            other.finalized = self.finalized\n            other.final_digest = None if self.final_digest is None else bytes(self.final_digest)\n            other.leaves = [h.copy() for h in self.leaves]\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n\n            bs = self.leaf_block_size\n            while len(self.buf) >= bs:\n                block = bytes(self.buf[:bs])\n                del self.buf[:bs]\n                lane = self.block_index % self.parallelism\n                self.leaves[lane].update(block)\n                self.block_index += 0x01\n            return self\n\n        def finalize(self):\n            if self.finalized:\n                return\n            if self.buf:\n                lane = self.block_index % self.parallelism\n                self.leaves[lane].update(bytes(self.buf))\n                self.buf.clear()\n\n            root = self.create_root()\n            for h in self.leaves:\n                root.update(h.digest())\n\n            self.final_digest = root.digest()\n            self.finalized = True\n            return\n\n        def digest(self):\n            if self.finalized:\n                return bytes(self.final_digest)\n            c = self.copy()\n            c.finalize()\n            return bytes(c.final_digest)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class BLAKE2sp(BLAKE2pBase):\n        parallelism = 0x08\n        leaf_block_size = 0x40\n        digest_size = 0x20\n        inner_size = 0x20\n        blake2_func = hashlib.blake2s\n\n    class BLAKE2bp(BLAKE2pBase):\n        parallelism = 0x04\n        leaf_block_size = 0x80\n        digest_size = 0x40\n        inner_size = 0x40\n        blake2_func = hashlib.blake2b\n\n    class BLAKE3:\n        # BLAKE3 (default, unkeyed) / 256-bit output by default\n        block_size = 64\n        digest_size = 32\n        block_len = 64\n        chunk_len = 1024\n\n        # flags\n        chunk_start = 0x01\n        chunk_end = 0x02\n        parent = 0x04\n        root = 0x08\n\n        # IV == BLAKE2s IV (BLAKE3 also uses this)\n        iv = (\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a, 0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        )\n\n        msg_perm = (\n            0x02, 0x06, 0x03, 0x0a, 0x07, 0x00, 0x04, 0x0d, 0x01, 0x0b, 0x0c, 0x05, 0x09, 0x0e, 0x0f, 0x08,\n        )\n\n        def __init__(self, data=b\"\", digest_bits=256):\n            self.key_words = list(self.iv)  # default unkeyed hash uses IV as key\n            self.flags = 0\n            self.chunk_counter = 0\n            self.cv_stack = []  # list of chaining values (each is 8 words)\n            self.cs_cv = self.key_words[:]\n            self.cs_block = bytearray()\n            self.cs_blocks_compressed = 0  # number of full 64-byte blocks already compressed in this chunk (0..15)\n            self.digest_size = digest_bits // 8  # It can also be specified when issuing a digest\n            if data:\n                self.update(data)\n            return\n\n        def g(self, v, a, b, c, d, x, y):\n\n            def rotr32(x, n):\n                x &= 0xffff_ffff\n                return ((x >> n) | (x << (32 - n))) & 0xffff_ffff\n\n            v[a] = (v[a] + v[b] + x) & 0xffff_ffff\n            v[d] = rotr32(v[d] ^ v[a], 16)\n            v[c] = (v[c] + v[d]) & 0xffff_ffff\n            v[b] = rotr32(v[b] ^ v[c], 12)\n            v[a] = (v[a] + v[b] + y) & 0xffff_ffff\n            v[d] = rotr32(v[d] ^ v[a], 8)\n            v[c] = (v[c] + v[d]) & 0xffff_ffff\n            v[b] = rotr32(v[b] ^ v[c], 7)\n            return\n\n        def compress(self, cv, block_words, counter, block_len, flags):\n            # cv: 8 words, block_words: 16 words\n            v = [0] * 16\n            v[0:8] = [w & 0xffff_ffff for w in cv]\n            v[8:16] = self.iv[:]\n\n            v[12] = counter & 0xffff_ffff\n            v[13] = (counter >> 32) & 0xffff_ffff\n            v[14] = block_len & 0xffff_ffff\n            v[15] = flags & 0xffff_ffff\n\n            m = [w & 0xffff_ffff for w in block_words]\n\n            for _round in range(7):\n                # columns\n                self.g(v, 0, 4, 8, 12, m[0], m[1])\n                self.g(v, 1, 5, 9, 13, m[2], m[3])\n                self.g(v, 2, 6, 10, 14, m[4], m[5])\n                self.g(v, 3, 7, 11, 15, m[6], m[7])\n                # diagonals\n                self.g(v, 0, 5, 10, 15, m[8], m[9])\n                self.g(v, 1, 6, 11, 12, m[10], m[11])\n                self.g(v, 2, 7, 8, 13, m[12], m[13])\n                self.g(v, 3, 4, 9, 14, m[14], m[15])\n\n                # permute message words for next round\n                mp = [0] * 16\n                for i in range(16):\n                    mp[i] = m[self.msg_perm[i]]\n                m = mp\n\n            out = [0] * 16\n            for i in range(8):\n                out[i] = v[i] ^ v[i + 8]\n            for i in range(8):\n                out[i + 8] = v[i + 8] ^ cv[i]\n            return out\n\n        def chunk_state_len(self):\n            return self.cs_blocks_compressed * self.block_len + len(self.cs_block)\n\n        def chunk_output(self):\n            # returns an \"output descriptor\": (cv, block_words16, counter, block_len, flags)\n            block_len = len(self.cs_block)\n            block = bytes(self.cs_block)\n            if block_len < self.block_len:\n                block = block + b\"\\x00\" * (self.block_len - block_len)\n            block_words = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n            flags = self.flags | self.chunk_end\n            if self.cs_blocks_compressed == 0:\n                flags |= self.chunk_start\n            return (self.cs_cv[:], block_words, self.chunk_counter, block_len, flags)\n\n        def output_chaining_value(self, outdesc):\n            cv, block_words, counter, block_len, flags = outdesc\n            return self.compress(cv, block_words, counter, block_len, flags)[0:8]\n\n        def parent_outdesc(self, left_cv, right_cv):\n            block_words = [(w & 0xffff_ffff) for w in (left_cv + right_cv)]\n            return (self.key_words[:], block_words, 0, self.block_len, self.flags | self.parent)\n\n        def add_chunk_cv(self, chunk_cv):\n            # stack merge by chunk index (standard Merkle stacking)\n            i = self.chunk_counter  # current chunk index (0-based) just completed\n            cv = chunk_cv\n            while (i & 1) == 1:\n                left = self.cv_stack.pop()\n                cv = self.output_chaining_value(self.parent_outdesc(left, cv))\n                i >>= 1\n            self.cv_stack.append(cv)\n            return\n\n        def update(self, data):\n            if not data:\n                return self\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            mv = memoryview(data)\n            off = 0\n            n = len(mv)\n\n            while off < n:\n                # If the chunk is already full (1024 bytes) and we still have input left,\n                # finalize the current chunk and move to the next one.\n                if self.chunk_state_len() == self.chunk_len:\n                    # Reaching here is only valid when we have compressed 15 blocks and\n                    # have exactly one final full 64-byte block buffered.\n                    if not (self.cs_blocks_compressed == 15 and len(self.cs_block) == self.block_len):\n                        raise RuntimeError(\"invalid chunk state (chunk_len reached)\")\n                    outdesc = self.chunk_output()\n                    chunk_cv = self.output_chaining_value(outdesc)\n                    self.add_chunk_cv(chunk_cv)\n\n                    self.chunk_counter += 1\n                    self.cs_cv = self.key_words[:]\n                    self.cs_block = bytearray()\n                    self.cs_blocks_compressed = 0\n                    continue\n\n                # Consume as much as fits into the remaining space of the current chunk.\n                # This must always make progress (take > 0).\n                chunk_pos = self.chunk_state_len()\n                want = self.chunk_len - chunk_pos\n                take = want if want < (n - off) else (n - off)\n                if take <= 0:\n                    raise RuntimeError(\"internal error: take <= 0\")\n\n                self.cs_block.extend(mv[off:off + take])\n                off += take\n\n                # Compress full 64-byte blocks as long as we have them, but do not compress\n                # the last block of the chunk here (so at most 15 blocks are compressed).\n                while len(self.cs_block) >= self.block_len and self.cs_blocks_compressed < 15:\n                    block = bytes(self.cs_block[:self.block_len])\n                    del self.cs_block[:self.block_len]\n\n                    block_words = [int.from_bytes(block[i:i + 4], \"little\") for i in range(0, 64, 4)]\n                    flags = self.flags\n                    if self.cs_blocks_compressed == 0:\n                        flags |= self.chunk_start\n\n                    out = self.compress(self.cs_cv, block_words, self.chunk_counter, self.block_len, flags)\n                    self.cs_cv = out[0:8]\n                    self.cs_blocks_compressed += 1\n\n                # If the chunk is exactly full (15 blocks compressed + 1 full block buffered)\n                # and there is still input remaining, finalize now and advance to the next chunk.\n                if self.cs_blocks_compressed == 15 and len(self.cs_block) == self.block_len and off < n:\n                    outdesc = self.chunk_output()\n                    chunk_cv = self.output_chaining_value(outdesc)\n                    self.add_chunk_cv(chunk_cv)\n\n                    self.chunk_counter += 1\n                    self.cs_cv = self.key_words[:]\n                    self.cs_block = bytearray()\n                    self.cs_blocks_compressed = 0\n            return self\n\n        def final_root_outdesc(self):\n            # finalize current chunk, fold stack into parents, mark ROOT\n            outdesc = self.chunk_output()\n            cv = self.output_chaining_value(outdesc)\n\n            # fold stack from right to left: parent(left_subtree, current)\n            while self.cv_stack:\n                left = self.cv_stack.pop()\n                outdesc = self.parent_outdesc(left, cv)\n                cv = self.output_chaining_value(outdesc)\n\n            # mark root\n            cv0, bw, ctr, bl, fl = outdesc\n            outdesc = (cv0, bw, ctr, bl, fl | self.root)\n            return outdesc\n\n        def digest(self, length=None):\n            if length is None:\n                length = self.digest_size\n            if not isinstance(length, int) or length < 0:\n                raise ValueError(\"length must be a non-negative int\")\n\n            # clone state\n            clone = self.__class__()\n            clone.key_words = self.key_words[:]\n            clone.flags = self.flags\n            clone.chunk_counter = self.chunk_counter\n            clone.cv_stack = [cv[:] for cv in self.cv_stack]\n            clone.cs_cv = self.cs_cv[:]\n            clone.cs_block = bytearray(self.cs_block)\n            clone.cs_blocks_compressed = self.cs_blocks_compressed\n\n            outdesc = clone.final_root_outdesc()\n            cv, block_words, counter, block_len, flags = outdesc\n\n            # XOF output: produce 64-byte output blocks indexed by output_counter\n            out = bytearray()\n            out_counter = 0\n            while len(out) < length:\n                words16 = clone.compress(cv, block_words, out_counter, block_len, flags)\n                block = b\"\".join((w & 0xffff_ffff).to_bytes(4, \"little\") for w in words16)\n                out.extend(block)\n                out_counter += 1\n            return bytes(out[:length])\n\n        def hexdigest(self, length=None):\n            return self.digest(length).hex()\n\n    class JHBase:\n        block_size = 64\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        static const uint8_t sbox0[16] = {\n            0x9, 0x0, 0x4, 0xb, 0xd, 0xc, 0x3, 0xf, 0x1, 0xa, 0x2, 0x6, 0x7, 0x5, 0x8, 0xe,\n        };\n\n        static const uint8_t sbox1[16] = {\n            0x3, 0xc, 0x6, 0xd, 0x5, 0x7, 0x1, 0x9, 0xf, 0x2, 0x0, 0x4, 0xb, 0xa, 0xe, 0x8,\n        };\n\n        static const uint8_t round_constant_init[64] = {\n            0x6, 0xa, 0x0, 0x9, 0xe, 0x6, 0x6, 0x7, 0xf, 0x3, 0xb, 0xc, 0xc, 0x9, 0x0, 0x8,\n            0xb, 0x2, 0xf, 0xb, 0x1, 0x3, 0x6, 0x6, 0xe, 0xa, 0x9, 0x5, 0x7, 0xd, 0x3, 0xe,\n            0x3, 0xa, 0xd, 0xe, 0xc, 0x1, 0x7, 0x5, 0x1, 0x2, 0x7, 0x7, 0x5, 0x0, 0x9, 0x9,\n            0xd, 0xa, 0x2, 0xf, 0x5, 0x9, 0x0, 0xb, 0x0, 0x6, 0x6, 0x7, 0x3, 0x2, 0x2, 0xa,\n        };\n\n        static const uint8_t inv_perm[256] = {\n            0x00, 0x03, 0x04, 0x07, 0x08, 0x0b, 0x0c, 0x0f, 0x10, 0x13, 0x14, 0x17, 0x18, 0x1b, 0x1c, 0x1f,\n            0x20, 0x23, 0x24, 0x27, 0x28, 0x2b, 0x2c, 0x2f, 0x30, 0x33, 0x34, 0x37, 0x38, 0x3b, 0x3c, 0x3f,\n            0x40, 0x43, 0x44, 0x47, 0x48, 0x4b, 0x4c, 0x4f, 0x50, 0x53, 0x54, 0x57, 0x58, 0x5b, 0x5c, 0x5f,\n            0x60, 0x63, 0x64, 0x67, 0x68, 0x6b, 0x6c, 0x6f, 0x70, 0x73, 0x74, 0x77, 0x78, 0x7b, 0x7c, 0x7f,\n            0x80, 0x83, 0x84, 0x87, 0x88, 0x8b, 0x8c, 0x8f, 0x90, 0x93, 0x94, 0x97, 0x98, 0x9b, 0x9c, 0x9f,\n            0xa0, 0xa3, 0xa4, 0xa7, 0xa8, 0xab, 0xac, 0xaf, 0xb0, 0xb3, 0xb4, 0xb7, 0xb8, 0xbb, 0xbc, 0xbf,\n            0xc0, 0xc3, 0xc4, 0xc7, 0xc8, 0xcb, 0xcc, 0xcf, 0xd0, 0xd3, 0xd4, 0xd7, 0xd8, 0xdb, 0xdc, 0xdf,\n            0xe0, 0xe3, 0xe4, 0xe7, 0xe8, 0xeb, 0xec, 0xef, 0xf0, 0xf3, 0xf4, 0xf7, 0xf8, 0xfb, 0xfc, 0xff,\n            0x02, 0x01, 0x06, 0x05, 0x0a, 0x09, 0x0e, 0x0d, 0x12, 0x11, 0x16, 0x15, 0x1a, 0x19, 0x1e, 0x1d,\n            0x22, 0x21, 0x26, 0x25, 0x2a, 0x29, 0x2e, 0x2d, 0x32, 0x31, 0x36, 0x35, 0x3a, 0x39, 0x3e, 0x3d,\n            0x42, 0x41, 0x46, 0x45, 0x4a, 0x49, 0x4e, 0x4d, 0x52, 0x51, 0x56, 0x55, 0x5a, 0x59, 0x5e, 0x5d,\n            0x62, 0x61, 0x66, 0x65, 0x6a, 0x69, 0x6e, 0x6d, 0x72, 0x71, 0x76, 0x75, 0x7a, 0x79, 0x7e, 0x7d,\n            0x82, 0x81, 0x86, 0x85, 0x8a, 0x89, 0x8e, 0x8d, 0x92, 0x91, 0x96, 0x95, 0x9a, 0x99, 0x9e, 0x9d,\n            0xa2, 0xa1, 0xa6, 0xa5, 0xaa, 0xa9, 0xae, 0xad, 0xb2, 0xb1, 0xb6, 0xb5, 0xba, 0xb9, 0xbe, 0xbd,\n            0xc2, 0xc1, 0xc6, 0xc5, 0xca, 0xc9, 0xce, 0xcd, 0xd2, 0xd1, 0xd6, 0xd5, 0xda, 0xd9, 0xde, 0xdd,\n            0xe2, 0xe1, 0xe6, 0xe5, 0xea, 0xe9, 0xee, 0xed, 0xf2, 0xf1, 0xf6, 0xf5, 0xfa, 0xf9, 0xfe, 0xfd,\n        };\n\n        static void l_transform_pair(uint8_t a, uint8_t b, uint8_t *ta, uint8_t *tb)\n        {\n            uint8_t tb_local = 0;\n            uint8_t ta_local = 0;\n\n            tb_local = (uint8_t)(b ^ ((((a << 1) ^ (a >> 3) ^ ((a >> 2) & 0x2)) & 0x0f)));\n            ta_local = (uint8_t)(a ^ ((((tb_local << 1) ^ (tb_local >> 3) ^ ((tb_local >> 2) & 0x2)) & 0x0f)));\n\n            *ta = (uint8_t)(ta_local & 0x0f);\n            *tb = (uint8_t)(tb_local & 0x0f);\n        }\n\n        static void update_round_constant(uint8_t *rc)\n        {\n            uint8_t tem[64];\n            uint8_t new_rc[64];\n            int i = 0;\n\n            for (i = 0; i < 64; i++) {\n                tem[i] = sbox0[rc[i]];\n            }\n\n            for (i = 0; i < 64; i += 2) {\n                l_transform_pair(tem[i], tem[i + 1], &tem[i], &tem[i + 1]);\n            }\n\n            for (i = 0; i < 64; i += 4) {\n                uint8_t t = tem[i + 2];\n                tem[i + 2] = tem[i + 3];\n                tem[i + 3] = t;\n            }\n\n            for (i = 0; i < 32; i++) {\n                new_rc[i] = tem[i << 1];\n                new_rc[i + 32] = tem[(i << 1) + 1];\n            }\n\n            for (i = 32; i < 64; i += 2) {\n                uint8_t t = new_rc[i];\n                new_rc[i] = new_rc[i + 1];\n                new_rc[i + 1] = t;\n            }\n\n            for (i = 0; i < 64; i++) {\n                rc[i] = new_rc[i];\n            }\n        }\n\n        static void e8_initialgroup(const uint8_t *h, uint8_t *a)\n        {\n            int i = 0;\n\n            for (i = 0; i < 128; i++) {\n                int sh = 7 - (i & 7);\n                int b = i >> 3;\n                int b2 = (i + 128) >> 3;\n\n                a[i * 2] = (uint8_t)(\n                    (((h[b] >> sh) & 1) << 3) |\n                    (((h[b + 32] >> sh) & 1) << 2) |\n                    (((h[b + 64] >> sh) & 1) << 1) |\n                    ((h[b + 96] >> sh) & 1)\n                );\n\n                a[(i * 2) + 1] = (uint8_t)(\n                    (((h[b2] >> sh) & 1) << 3) |\n                    (((h[b2 + 32] >> sh) & 1) << 2) |\n                    (((h[b2 + 64] >> sh) & 1) << 1) |\n                    ((h[b2 + 96] >> sh) & 1)\n                );\n            }\n        }\n\n        static void e8_finaldegroup(uint8_t *h, const uint8_t *a)\n        {\n            int i = 0;\n\n            for (i = 0; i < 128; i++) {\n                h[i] = 0;\n            }\n\n            for (i = 0; i < 128; i++) {\n                uint8_t v0 = a[i << 1];\n                uint8_t v1 = a[(i << 1) + 1];\n                int sh = 7 - (i & 7);\n                int b = i >> 3;\n                int b2 = (i + 128) >> 3;\n\n                h[b] |= (uint8_t)(((v0 >> 3) & 1) << sh);\n                h[b + 32] |= (uint8_t)(((v0 >> 2) & 1) << sh);\n                h[b + 64] |= (uint8_t)(((v0 >> 1) & 1) << sh);\n                h[b + 96] |= (uint8_t)((v0 & 1) << sh);\n\n                h[b2] |= (uint8_t)(((v1 >> 3) & 1) << sh);\n                h[b2 + 32] |= (uint8_t)(((v1 >> 2) & 1) << sh);\n                h[b2 + 64] |= (uint8_t)(((v1 >> 1) & 1) << sh);\n                h[b2 + 96] |= (uint8_t)((v1 & 1) << sh);\n            }\n        }\n\n        static void e8_core(uint8_t *h)\n        {\n            uint8_t a[256];\n            uint8_t tem[256];\n            uint8_t new_a[256];\n            uint8_t rc[64];\n            int rnd = 0;\n            int i = 0;\n\n            e8_initialgroup(h, a);\n\n            for (i = 0; i < 64; i++) {\n                rc[i] = round_constant_init[i];\n            }\n\n            for (rnd = 0; rnd < 42; rnd++) {\n                for (i = 0; i < 256; i++) {\n                    int rc_bit = (rc[i >> 2] >> (3 - (i & 3))) & 1;\n                    tem[i] = rc_bit ? sbox1[a[i]] : sbox0[a[i]];\n                }\n\n                for (i = 0; i < 256; i += 2) {\n                    l_transform_pair(tem[i], tem[i + 1], &tem[i], &tem[i + 1]);\n                }\n\n                for (i = 0; i < 256; i++) {\n                    new_a[i] = tem[inv_perm[i]];\n                }\n\n                for (i = 0; i < 256; i++) {\n                    a[i] = new_a[i];\n                }\n\n                update_round_constant(rc);\n            }\n\n            e8_finaldegroup(h, a);\n        }\n\n        void f8(uint8_t *h, const uint8_t *block)\n        {\n            int i = 0;\n\n            for (i = 0; i < 64; i++) {\n                h[i] ^= block[i];\n            }\n\n            e8_core(h);\n\n            for (i = 0; i < 64; i++) {\n                h[i + 64] ^= block[i];\n            }\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void f8(uint8_t *h, const uint8_t *block);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.JHBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            try:\n                with warnings.catch_warnings():\n                    warnings.filterwarnings(\n                        \"ignore\",\n                        message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                        category=UserWarning,\n                        module=r\"cffi\\.vengine_cpy\",\n                    )\n                    ffi = cffi.FFI()\n                    ffi.cdef(base_class.DEF_TEMPLATE)\n                    lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib\")(\n                ffi, lib,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def ensure_table(cls):\n            if hasattr(Hash.JHBase, \"SBOX_RND\"):\n                return\n\n            L = [[0] * 16 for _ in range(16)]\n            for a in range(16):\n                for b in range(16):\n                    tb = b ^ (((a << 1) ^ (a >> 3) ^ (((a >> 2) & 0x2))) & 0xf)\n                    ta = a ^ (((tb << 1) ^ (tb >> 3) ^ (((tb >> 2) & 0x2))) & 0xf)\n                    L[a][b] = (ta, tb)\n            Hash.JHBase.L_TRANSF = tuple(tuple(row) for row in L)\n\n            P = [0] * 256\n            for i in range(256):\n                swapped_i = i ^ 1 if (i & 2) else i\n                if swapped_i % 2 == 0:\n                    k = swapped_i // 2\n                    final_idx = k\n                else:\n                    k = swapped_i // 2\n                    final_idx = 128 + k\n                if final_idx >= 128:\n                    final_idx ^= 1\n                P[i] = final_idx\n            INV_P = [0] * 256\n            for i in range(256):\n                INV_P[P[i]] = i\n            Hash.JHBase.INV_P = tuple(INV_P)\n\n            sbox0 = [\n                0x9, 0x0, 0x4, 0xb, 0xd, 0xc, 0x3, 0xf, 0x1, 0xa, 0x2, 0x6, 0x7, 0x5, 0x8, 0xe,\n            ]\n            sbox1 = [\n                0x3, 0xc, 0x6, 0xd, 0x5, 0x7, 0x1, 0x9, 0xf, 0x2, 0x0, 0x4, 0xb, 0xa, 0xe, 0x8,\n            ]\n            rc = [\n                0x6, 0xa, 0x0, 0x9, 0xe, 0x6, 0x6, 0x7, 0xf, 0x3, 0xb, 0xc, 0xc, 0x9, 0x0, 0x8,\n                0xb, 0x2, 0xf, 0xb, 0x1, 0x3, 0x6, 0x6, 0xe, 0xa, 0x9, 0x5, 0x7, 0xd, 0x3, 0xe,\n                0x3, 0xa, 0xd, 0xe, 0xc, 0x1, 0x7, 0x5, 0x1, 0x2, 0x7, 0x7, 0x5, 0x0, 0x9, 0x9,\n                0xd, 0xa, 0x2, 0xf, 0x5, 0x9, 0x0, 0xb, 0x0, 0x6, 0x6, 0x7, 0x3, 0x2, 0x2, 0xa,\n            ]\n\n            SBOX_RND = []\n            for _rnd in range(42):\n                sboxes = []\n                for i in range(256):\n                    rc_bit = (rc[i >> 2] >> (3 - (i & 3))) & 1\n                    sboxes.append(tuple(sbox1) if rc_bit else tuple(sbox0))\n                SBOX_RND.append(tuple(sboxes))\n\n                tem = [0] * 64\n                for i in range(64):\n                    tem[i] = sbox0[rc[i]]\n                for i in range(0, 64, 2):\n                    tem[i], tem[i + 1] = L[tem[i]][tem[i + 1]]\n                for i in range(0, 64, 4):\n                    tem[i + 2], tem[i + 3] = tem[i + 3], tem[i + 2]\n                new_rc = [0] * 64\n                for i in range(32):\n                    new_rc[i] = tem[i << 1]\n                    new_rc[i + 32] = tem[(i << 1) + 1]\n                for i in range(32, 64, 2):\n                    new_rc[i], new_rc[i + 1] = new_rc[i + 1], new_rc[i]\n                rc = new_rc\n\n            Hash.JHBase.SBOX_RND = tuple(SBOX_RND)\n            return\n\n        def __init__(self, data=b\"\"):\n            if self.digest_size is None:\n                raise ValueError(\"digest_size must be set in subclass\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.databitlen = 0\n            self.datasize_in_buffer = 0  # bits\n            self.H = bytearray(128)\n            self.A = [0] * 256\n            self.roundconstant = [0] * 64\n            self.buffer = bytearray(64)\n            hashbitlen = self.digest_size * 8\n            self.H[0] = (hashbitlen >> 8) & 0xff\n            self.H[1] = hashbitlen & 0xff\n            self.ensure_table()\n            self.init_cffi_backend()\n            self.f8()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.databitlen = self.databitlen\n            other.datasize_in_buffer = self.datasize_in_buffer\n            other.H = bytearray(self.H)\n            other.A = list(self.A)\n            other.roundconstant = list(self.roundconstant)\n            other.buffer = bytearray(self.buffer)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.databitlen += len(data) * 8\n            off = 0\n            while off < len(data):\n                buf_bytes = self.datasize_in_buffer // 8\n                take = min(64 - buf_bytes, len(data) - off)\n                self.buffer[buf_bytes:buf_bytes + take] = data[off:off + take]\n                self.datasize_in_buffer += take * 8\n                off += take\n                if self.datasize_in_buffer == 512:\n                    self.f8()\n                    self.datasize_in_buffer = 0\n                    for i in range(64):\n                        self.buffer[i] = 0\n            return self\n\n        def finalize(self):\n            if (self.databitlen & 0x1_ff) == 0:\n                for i in range(64):\n                    self.buffer[i] = 0\n                self.buffer[0] = 0x80\n                x = self.databitlen & 0xffff_ffff_ffff_ffff\n                self.buffer[63] = x & 0xff\n                self.buffer[62] = (x >> 8) & 0xff\n                self.buffer[61] = (x >> 16) & 0xff\n                self.buffer[60] = (x >> 24) & 0xff\n                self.buffer[59] = (x >> 32) & 0xff\n                self.buffer[58] = (x >> 40) & 0xff\n                self.buffer[57] = (x >> 48) & 0xff\n                self.buffer[56] = (x >> 56) & 0xff\n                self.f8()\n                self.datasize_in_buffer = 0\n                return\n\n            if (self.datasize_in_buffer & 7) != 0:\n                raise ValueError(\"internal error: datasize_in_buffer not multiple of 8\")\n            bytepos = ((self.databitlen & 0x1_ff) >> 3)\n            for i in range(bytepos, 64):\n                self.buffer[i] = 0\n            self.buffer[bytepos] |= 1 << (7 - (self.databitlen & 7))\n            self.f8()\n            for i in range(64):\n                self.buffer[i] = 0\n            x = self.databitlen & 0xffff_ffff_ffff_ffff\n            self.buffer[63] = x & 0xff\n            self.buffer[62] = (x >> 8) & 0xff\n            self.buffer[61] = (x >> 16) & 0xff\n            self.buffer[60] = (x >> 24) & 0xff\n            self.buffer[59] = (x >> 32) & 0xff\n            self.buffer[58] = (x >> 40) & 0xff\n            self.buffer[57] = (x >> 48) & 0xff\n            self.buffer[56] = (x >> 56) & 0xff\n            self.f8()\n            self.datasize_in_buffer = 0\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return bytes(c.H[128 - self.digest_size:])\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def f8(self):\n            if self.USE_CFFI:\n                h_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(self.H))\n                block_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(self.buffer))\n                self.cffi.lib.f8(h_buf, block_buf)\n                self.H = bytearray(self.cffi.ffi.buffer(h_buf, 128)[:])\n                return\n\n            def e8_initialgroup():\n                A = self.A\n                H = self.H\n                for i in range(128):\n                    sh = 7 - (i & 7)\n                    b = i >> 3\n                    A[i * 2] = ((H[b] >> sh) & 1) << 3 | \\\n                               ((H[b + 32] >> sh) & 1) << 2 | \\\n                               ((H[b + 64] >> sh) & 1) << 1 | \\\n                               ((H[b + 96] >> sh) & 1)\n                    b2 = (i + 128) >> 3\n                    A[i * 2 + 1] = ((H[b2] >> sh) & 1) << 3 | \\\n                                   ((H[b2 + 32] >> sh) & 1) << 2 | \\\n                                   ((H[b2 + 64] >> sh) & 1) << 1 | \\\n                                   ((H[b2 + 96] >> sh) & 1)\n                return A\n\n            def e8_finaldegroup():\n                A = self.A\n                H = bytearray(128)\n                for i in range(128):\n                    v0 = A[i << 1]\n                    v1 = A[(i << 1) + 1]\n                    sh = 7 - (i & 7)\n                    b = i >> 3\n                    H[b] |= ((v0 >> 3) & 1) << sh\n                    H[b + 32] |= ((v0 >> 2) & 1) << sh\n                    H[b + 64] |= ((v0 >> 1) & 1) << sh\n                    H[b + 96] |= (v0 & 1) << sh\n\n                    b2 = (i + 128) >> 3\n                    H[b2] |= ((v1 >> 3) & 1) << sh\n                    H[b2 + 32] |= ((v1 >> 2) & 1) << sh\n                    H[b2 + 64] |= ((v1 >> 1) & 1) << sh\n                    H[b2 + 96] |= (v1 & 1) << sh\n                self.H = H\n                return\n\n            def e8():\n                e8_initialgroup()\n                A = self.A\n                L = self.L_TRANSF\n                INV = self.INV_P\n                for rnd in range(42):\n                    sboxes = self.SBOX_RND[rnd]\n                    tem = [s[a] for s, a in zip(sboxes, A)]\n                    for i in range(0, 256, 2):\n                        tem[i], tem[i + 1] = L[tem[i]][tem[i + 1]]\n                    A = [tem[i] for i in INV]\n                self.A = A\n                e8_finaldegroup()\n                return\n\n            for i in range(64):\n                self.H[i] ^= self.buffer[i]\n            e8()\n            for i in range(64):\n                self.H[i + 64] ^= self.buffer[i]\n            return\n\n    class JH224(JHBase):\n        digest_size = 28\n\n    class JH256(JHBase):\n        digest_size = 32\n\n    class JH384(JHBase):\n        digest_size = 48\n\n    class JH512(JHBase):\n        digest_size = 64\n\n    class GroestlBase:\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        @classmethod\n        def ensure_table(cls):\n            if hasattr(Hash.GroestlBase, \"mul2\"):\n                return\n\n            def gf_mul(a, b):\n                res = 0\n                for _ in range(8):\n                    if b & 1:\n                        res ^= a\n                    hi = a & 0x80\n                    a = (a << 1) & 0xff\n                    if hi:\n                        a ^= 0x1b\n                    b >>= 1\n                return res\n\n            m2, m3, m4, m5, m7 = [], [], [], [], []\n            for i in range(256):\n                m2.append(gf_mul(i, 2))\n                m3.append(gf_mul(i, 3))\n                m4.append(gf_mul(i, 4))\n                m5.append(gf_mul(i, 5))\n                m7.append(gf_mul(i, 7))\n\n            Hash.GroestlBase.mul2 = tuple(m2)\n            Hash.GroestlBase.mul3 = tuple(m3)\n            Hash.GroestlBase.mul4 = tuple(m4)\n            Hash.GroestlBase.mul5 = tuple(m5)\n            Hash.GroestlBase.mul7 = tuple(m7)\n            return\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.ensure_table()\n            self.h = self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def init_state(self):\n            iv = bytearray(self.block_size)\n            size = self.digest_size * 8\n            p = len(iv) - 1\n            while size > 0:\n                iv[p] = size & 0xff\n                size >>= 8\n                p -= 1\n            return self.bytes_to_state(bytes(iv))\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.h = [row[:] for row in self.h]\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bs = self.block_size\n            ml = self.msg_len\n            zeros_pad = (-(ml + 1 + 8)) % bs\n            total_blocks = (ml + 1 + zeros_pad + 8) // bs\n            self.buf.append(0x80)\n            self.buf.extend(b\"\\x00\" * zeros_pad)\n            self.buf.extend(struct.pack(\">Q\", total_blocks))\n            while len(self.buf) >= bs:\n                block = bytes(self.buf[:bs])\n                del self.buf[:bs]\n                self.compress(block)\n            return\n\n        def output(self):\n            hp = self.permutation([row[:] for row in self.h], \"P\")\n            res = self.xor_state(hp, self.h)\n            out = self.state_to_bytes(res)\n            return out[-self.digest_size:]\n\n        def compress(self, block):\n            m = self.bytes_to_state(block)\n            pside = self.permutation(self.xor_state(self.h, m), \"P\")\n            qside = self.permutation([row[:] for row in m], \"Q\")\n            self.h = self.xor_state(self.xor_state(pside, qside), self.h)\n            return\n\n        def permutation(self, state, which):\n            for rnd in range(self.rounds):\n                self.add_round_constant(state, which, rnd)\n                self.sub_bytes(state)\n                self.shift_bytes(state, which)\n                self.mix_bytes(state)\n            return state\n\n        def add_round_constant(self, state, which, rnd):\n            cols = self.block_size // 8\n            if which == \"P\":\n                for c in range(cols):\n                    state[0][c] ^= ((c << 4) ^ rnd) & 0xff\n            else:\n                for r in range(8):\n                    for c in range(cols):\n                        if r == 7:\n                            state[r][c] ^= (((0xff - ((c << 4) & 0xff)) & 0xff) ^ rnd) & 0xff\n                        else:\n                            state[r][c] ^= 0xff\n            return\n\n        def sub_bytes(self, state):\n            s = self.sbox\n            for r in range(8):\n                state[r] = [s[x] for x in state[r]]\n            return\n\n        def shift_bytes(self, state, which):\n            cols = self.block_size // 8\n            sigma = self.sigma_p if which == \"P\" else self.sigma_q\n            for r in range(8):\n                sh = sigma[r] % cols\n                if sh:\n                    row = state[r]\n                    state[r] = row[sh:] + row[:sh]\n            return\n\n        def mix_bytes(self, state):\n            cols = self.block_size // 8\n            m2, m3, m4, m5, m7 = self.mul2, self.mul3, self.mul4, self.mul5, self.mul7\n            for c in range(cols):\n                s0, s1, s2, s3, s4, s5, s6, s7 = (state[r][c] for r in range(8))\n                state[0][c] = m2[s0] ^ m2[s1] ^ m3[s2] ^ m4[s3] ^ m5[s4] ^ m3[s5] ^ m5[s6] ^ m7[s7]\n                state[1][c] = m7[s0] ^ m2[s1] ^ m2[s2] ^ m3[s3] ^ m4[s4] ^ m5[s5] ^ m3[s6] ^ m5[s7]\n                state[2][c] = m5[s0] ^ m7[s1] ^ m2[s2] ^ m2[s3] ^ m3[s4] ^ m4[s5] ^ m5[s6] ^ m3[s7]\n                state[3][c] = m3[s0] ^ m5[s1] ^ m7[s2] ^ m2[s3] ^ m2[s4] ^ m3[s5] ^ m4[s6] ^ m5[s7]\n                state[4][c] = m5[s0] ^ m3[s1] ^ m5[s2] ^ m7[s3] ^ m2[s4] ^ m2[s5] ^ m3[s6] ^ m4[s7]\n                state[5][c] = m4[s0] ^ m5[s1] ^ m3[s2] ^ m5[s3] ^ m7[s4] ^ m2[s5] ^ m2[s6] ^ m3[s7]\n                state[6][c] = m3[s0] ^ m4[s1] ^ m5[s2] ^ m3[s3] ^ m5[s4] ^ m7[s5] ^ m2[s6] ^ m2[s7]\n                state[7][c] = m2[s0] ^ m3[s1] ^ m4[s2] ^ m5[s3] ^ m3[s4] ^ m5[s5] ^ m7[s6] ^ m2[s7]\n            return\n\n        def bytes_to_state(self, block):\n            cols = self.block_size // 8\n            return [[block[c * 8 + r] for c in range(cols)] for r in range(8)]\n\n        def state_to_bytes(self, state):\n            cols = self.block_size // 8\n            out = bytearray(self.block_size)\n            for r in range(8):\n                row = state[r]\n                for c in range(cols):\n                    out[c * 8 + r] = row[c]\n            return bytes(out)\n\n        def xor_state(self, a, b):\n            return [[x ^ y for x, y in zip(ra, rb)] for ra, rb in zip(a, b)]\n\n    class Groestl224(GroestlBase):\n        block_size = 64\n        digest_size = 28\n        rounds = 10\n        sigma_p = (0, 1, 2, 3, 4, 5, 6, 7)\n        sigma_q = (1, 3, 5, 7, 0, 2, 4, 6)\n\n    class Groestl256(GroestlBase):\n        block_size = 64\n        digest_size = 32\n        rounds = 10\n        sigma_p = (0, 1, 2, 3, 4, 5, 6, 7)\n        sigma_q = (1, 3, 5, 7, 0, 2, 4, 6)\n\n    class Groestl384(GroestlBase):\n        block_size = 128\n        digest_size = 48\n        rounds = 14\n        sigma_p = (0, 1, 2, 3, 4, 5, 6, 11)\n        sigma_q = (1, 3, 5, 11, 0, 2, 4, 6)\n\n    class Groestl512(GroestlBase):\n        block_size = 128\n        digest_size = 64\n        rounds = 14\n        sigma_p = (0, 1, 2, 3, 4, 5, 6, 11)\n        sigma_q = (1, 3, 5, 11, 0, 2, 4, 6)\n\n    class SkeinBBase:\n        type_cfg = 0x04\n        type_msg = 0x30\n        type_out = 0x3f\n        flag_first = 0x4000_0000_0000_0000\n        flag_final = 0x8000_0000_0000_0000\n        c240 = 0x1bd1_1bda_a9fc_1a22\n\n        def __init__(self, data=b\"\", digest_bits=None):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if digest_bits is None:\n                digest_bits = self.block_size * 8\n            if digest_bits not in (0x100, 0x200, 0x400):\n                raise ValueError(\"digest_bits must be 256, 512, or 1024\")\n            self.digest_bits = int(digest_bits)\n            self.digest_size = self.digest_bits // 8\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.pos = 0\n            self.is_first = True\n            self.state = self.make_initial_state(self.digest_bits)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", digest_bits=self.digest_bits)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.pos = self.pos\n            other.is_first = self.is_first\n            other.state = list(self.state)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) > self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.pos += self.block_size\n                self.state = self.ubi_compress_words(self.state, block, self.pos, self.type_msg, self.is_first, False)\n                self.is_first = False\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output_digest()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            nm = self.msg_len\n            if nm == 0:\n                block = b\"\\x00\" * self.block_size\n                self.state = self.ubi_compress_words(self.state, block, 0, self.type_msg, True, True)\n                self.pos = 0\n                self.is_first = False\n                self.buf = bytearray()\n                return\n            if len(self.buf) > self.block_size:\n                raise ValueError(\"internal error: buffer larger than block size\")\n            block = bytes(self.buf) + b\"\\x00\" * (self.block_size - len(self.buf))\n            self.state = self.ubi_compress_words(self.state, block, nm, self.type_msg, self.is_first, True)\n            self.pos = nm\n            self.is_first = False\n            self.buf = bytearray()\n            return\n\n        def output_digest(self):\n            out = bytearray()\n            need = self.digest_size\n            counter = 0\n            while len(out) < need:\n                block = struct.pack(\"<Q\", counter) + b\"\\x00\" * (self.block_size - 8)\n                words = self.ubi_compress_words(self.state, block, 8, self.type_out, True, True)\n                out.extend(struct.pack(\"<{}Q\".format(self.word_count), *[x & 0xffff_ffff_ffff_ffff for x in words]))\n                counter += 1\n            return bytes(out[:need])\n\n        def make_initial_state(self, digest_bits):\n            g0 = [0] * self.word_count\n            cfg = self.configuration_string(digest_bits)\n            g1 = self.ubi(g0, cfg, self.type_cfg)\n            return g1\n\n        def configuration_string(self, digest_bits):\n            s = bytearray()\n            s.extend(b\"SHA3\\x01\\x00\\x00\\x00\")\n            s.extend(struct.pack(\"<Q\", digest_bits))\n            s.extend(b\"\\x00\" * 16)\n            if len(s) != 32:\n                raise ValueError(\"internal error: config size\")\n            return bytes(s)\n\n        def ubi(self, g_words, m_bytes, type_value):\n            if not isinstance(m_bytes, (bytes, bytearray, memoryview)):\n                raise TypeError(\"m_bytes must be bytes-like\")\n            nm = len(m_bytes)\n            if nm == 0:\n                padded = b\"\\x00\" * self.block_size\n                blocks = [padded]\n            else:\n                pad = (-nm) % self.block_size\n                padded = m_bytes + (b\"\\x00\" * pad)\n                blocks = [padded[i:i + self.block_size] for i in range(0, len(padded), self.block_size)]\n            h = list(g_words)\n            for i, block in enumerate(blocks):\n                first = (i == 0)\n                final = (i == len(blocks) - 1)\n                pos = min(nm, (i + 1) * self.block_size)\n                h = self.ubi_compress_words(h, block, pos, type_value, first, final)\n            return h\n\n        def ubi_compress_words(self, g_words, block_bytes, position, type_value, first, final):\n            t0 = position\n            t1 = ((type_value & 0x3f) << 56) & 0xffff_ffff_ffff_ffff\n            if first:\n                t1 |= self.flag_first\n            if final:\n                t1 |= self.flag_final\n            pt_words = list(struct.unpack(\"<{}Q\".format(self.word_count), block_bytes))\n            ct_words = self.threefish_encrypt(g_words, t0, t1, pt_words)\n            out_words = [ct_words[i] ^ pt_words[i] for i in range(self.word_count)]\n            return out_words\n\n        def threefish_encrypt(self, key_words, tweak0, tweak1, pt_words):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 0x3f\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            n = self.word_count\n            nr = self.rounds\n\n            k = list(key_words)\n            parity = self.c240\n            for x in k:\n                parity ^= x\n            k.append(parity)\n\n            t = [tweak0, tweak1, tweak0 ^ tweak1]\n\n            v = pt_words[:]\n            for d in range(nr):\n                if (d & 0x03) == 0:\n                    sub = self.threefish_subkey(k, t, d >> 2)\n                    for i in range(n):\n                        v[i] = (v[i] + sub[i]) & 0xffff_ffff_ffff_ffff\n                f = [0] * n\n                rset = self.rotation[d & 0x07]\n                for j in range(n // 2):\n                    x0 = v[2 * j]\n                    x1 = v[2 * j + 1]\n                    y0 = (x0 + x1) & 0xffff_ffff_ffff_ffff\n                    y1 = rol64(x1, rset[j]) ^ y0\n                    f[2 * j] = y0\n                    f[2 * j + 1] = y1\n                v = [f[self.perm[i]] for i in range(n)]\n            sub = self.threefish_subkey(k, t, nr >> 2)\n            for i in range(n):\n                v[i] = (v[i] + sub[i]) & 0xffff_ffff_ffff_ffff\n            return v\n\n        def threefish_subkey(self, k_ext, t_ext, s):\n            n = self.word_count\n            sub = [0] * n\n            for i in range(n):\n                sub[i] = k_ext[(s + i) % (n + 1)]\n            sub[n - 3] = (sub[n - 3] + t_ext[s % 3]) & 0xffff_ffff_ffff_ffff\n            sub[n - 2] = (sub[n - 2] + t_ext[(s + 1) % 3]) & 0xffff_ffff_ffff_ffff\n            sub[n - 1] = (sub[n - 1] + (s & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            return sub\n\n    class Skein256(SkeinBBase):\n        block_size = 0x20\n        word_count = 0x04\n        rounds = 0x48\n        rotation = (\n            (0x0e, 0x10),\n            (0x34, 0x39),\n            (0x17, 0x28),\n            (0x05, 0x25),\n            (0x19, 0x21),\n            (0x2e, 0x0c),\n            (0x3a, 0x16),\n            (0x20, 0x20),\n        )\n        perm = (0x00, 0x03, 0x02, 0x01)\n\n    class Skein512(SkeinBBase):\n        block_size = 0x40\n        word_count = 0x08\n        rounds = 0x48\n        rotation = (\n            (0x2e, 0x24, 0x13, 0x25),\n            (0x21, 0x1b, 0x0e, 0x2a),\n            (0x11, 0x31, 0x24, 0x27),\n            (0x2c, 0x09, 0x36, 0x38),\n            (0x27, 0x1e, 0x22, 0x18),\n            (0x0d, 0x32, 0x0a, 0x11),\n            (0x19, 0x1d, 0x27, 0x2b),\n            (0x08, 0x23, 0x38, 0x16),\n        )\n        perm = (0x02, 0x01, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03)\n\n    class Skein1024(SkeinBBase):\n        block_size = 0x80\n        word_count = 0x10\n        rounds = 0x50\n        rotation = (\n            (0x18, 0x0d, 0x08, 0x2f, 0x08, 0x11, 0x16, 0x25),\n            (0x26, 0x13, 0x0a, 0x37, 0x31, 0x12, 0x17, 0x34),\n            (0x21, 0x04, 0x33, 0x0d, 0x22, 0x29, 0x3b, 0x11),\n            (0x05, 0x14, 0x30, 0x29, 0x2f, 0x1c, 0x10, 0x19),\n            (0x29, 0x09, 0x25, 0x1f, 0x0c, 0x2f, 0x2c, 0x1e),\n            (0x10, 0x22, 0x38, 0x33, 0x04, 0x35, 0x2a, 0x29),\n            (0x1f, 0x2c, 0x2f, 0x2e, 0x13, 0x2a, 0x2c, 0x19),\n            (0x09, 0x30, 0x23, 0x34, 0x17, 0x1f, 0x25, 0x14),\n        )\n        perm = (0x00, 0x09, 0x02, 0x0d, 0x06, 0x0b, 0x04, 0x0f, 0x0a, 0x07, 0x0c, 0x03, 0x0e, 0x05, 0x08, 0x01)\n\n    class ShabalBBase:\n        block_size = 64\n        digest_size = None\n\n        shabal_block_words = 16\n        shabal_param_r = 12\n        shabal_param_p = 3\n        shabal_param_e = 3\n        o1 = 13\n        o2 = 9\n        o3 = 6\n\n        def __init__(self, data=b\"\"):\n            if self.digest_size is None:\n                raise ValueError(\"digest_size must be set in derived class\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.a = [0] * self.shabal_param_r\n            self.b = [0] * self.shabal_block_words\n            self.c = [0] * self.shabal_block_words\n            self.wlow = 0xffff_ffff\n            self.whigh = 0xffff_ffff\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.a = self.a[:]\n            other.b = self.b[:]\n            other.c = self.c[:]\n            other.wlow = self.wlow\n            other.whigh = self.whigh\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.process_block(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            words = c.digest_size * 8 // 32\n            start = self.shabal_block_words - words\n            out = bytearray()\n            for i in range(start, self.shabal_block_words):\n                out.extend(struct.pack(\"<I\", c.b[i] & 0xffff_ffff))\n            return bytes(out)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.process_block(block)\n\n            self.buf.append(0x80)\n            while len(self.buf) < self.block_size:\n                self.buf.append(0x00)\n\n            m = self.decode_block(bytes(self.buf[:self.block_size]))\n            self.buf = bytearray()\n\n            self.input_block_add(m)\n            self.xor_counter()\n            self.apply_perm(m)\n\n            for _ in range(self.shabal_param_e):\n                self.swap_bc()\n                self.xor_counter()\n                self.apply_perm(m)\n            return\n\n        def init_state(self):\n            hashbitlen = self.digest_size * 8\n            m = [0] * self.shabal_block_words\n            for j in range(0, 2 * self.shabal_block_words, self.shabal_block_words):\n                for i in range(self.shabal_block_words):\n                    m[i] = hashbitlen + j + i\n                self.input_block_add(m)\n                self.xor_counter()\n                self.apply_perm(m)\n                self.input_block_sub(m)\n                self.swap_bc()\n                self.incr_counter()\n            return\n\n        def swap_bc(self):\n            self.b, self.c = self.c, self.b\n            return\n\n        def decode_block(self, block):\n            if len(block) != self.block_size:\n                raise ValueError(\"block must be 64 bytes\")\n            return list(struct.unpack(\"<16I\", block))\n\n        def input_block_add(self, m):\n            for i in range(self.shabal_block_words):\n                self.b[i] = (self.b[i] + m[i]) & 0xffff_ffff\n            return\n\n        def input_block_sub(self, m):\n            for i in range(self.shabal_block_words):\n                self.c[i] = (self.c[i] - m[i]) & 0xffff_ffff\n            return\n\n        def xor_counter(self):\n            self.a[0] ^= self.wlow\n            self.a[1] ^= self.whigh\n            return\n\n        def incr_counter(self):\n            self.wlow = (self.wlow + 1) & 0xffff_ffff\n            if self.wlow == 0:\n                self.whigh = (self.whigh + 1) & 0xffff_ffff\n            return\n\n        def apply_perm(self, m):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            for i in range(self.shabal_block_words):\n                t = self.b[i]\n                self.b[i] = ((t << 17) | (t >> 15)) & 0xffff_ffff\n\n            for j in range(self.shabal_param_p):\n                for i in range(self.shabal_block_words):\n                    idx_a = (i + self.shabal_block_words * j) % self.shabal_param_r\n                    idx_am1 = (i + self.shabal_block_words * j + (self.shabal_param_r - 1)) % self.shabal_param_r\n\n                    xa = self.a[idx_a]\n                    xam1 = self.a[idx_am1]\n\n                    rot15 = ((xam1 << 15) | (xam1 >> 17)) & 0xffff_ffff\n                    v = (5 * rot15) & 0xffff_ffff\n                    u_in = xa ^ v ^ self.c[(8 + self.shabal_block_words - i) % self.shabal_block_words]\n                    u = (3 * u_in) & 0xffff_ffff\n\n                    x_new = u ^ self.b[(i + self.o1) % self.shabal_block_words]\n                    x_new ^= self.b[(i + self.o2) % self.shabal_block_words] & \\\n                            (~self.b[(i + self.o3) % self.shabal_block_words]) & 0xffff_ffff\n                    self.a[idx_a] = x_new ^ m[i]\n\n                    tb = self.b[i]\n                    self.b[i] = (rol32(tb, 1) ^ ((~self.a[idx_a]) & 0xffff_ffff)) & 0xffff_ffff\n\n            for j in range(3 * self.shabal_param_r):\n                idx_a = (3 * self.shabal_param_r - 1 - j) % self.shabal_param_r\n                idx_c = (3 * self.shabal_param_r * self.shabal_block_words + 6 - j) % self.shabal_block_words\n                self.a[idx_a] = (self.a[idx_a] + self.c[idx_c]) & 0xffff_ffff\n            return\n\n        def process_block(self, block):\n            m = self.decode_block(block)\n            self.input_block_add(m)\n            self.xor_counter()\n            self.apply_perm(m)\n            self.input_block_sub(m)\n            self.swap_bc()\n            self.incr_counter()\n            return\n\n    class Shabal192(ShabalBBase):\n        digest_size = 24\n\n    class Shabal224(ShabalBBase):\n        digest_size = 28\n\n    class Shabal256(ShabalBBase):\n        digest_size = 32\n\n    class Shabal384(ShabalBBase):\n        digest_size = 48\n\n    class Shabal512(ShabalBBase):\n        digest_size = 64\n\n    class XXHashBase:\n        prime32_1 = 0x9e37_79b1\n        prime32_2 = 0x85eb_ca77\n        prime32_3 = 0xc2b2_ae3d\n        prime32_4 = 0x27d4_eb2f\n        prime32_5 = 0x1656_67b1\n\n        prime64_1 = 0x9e37_79b1_85eb_ca87\n        prime64_2 = 0xc2b2_ae3d_27d4_eb4f\n        prime64_3 = 0x1656_67b1_9e37_79f9\n        prime64_4 = 0x85eb_ca77_c2b2_ae63\n        prime64_5 = 0x27d4_eb2f_1656_67c5\n\n        prime_mx1 = 0x1656_6791_9e37_79f9\n        prime_mx2 = 0x9fb2_1c65_1e98_df25\n\n        default_secret = bytes([\n            0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,\n            0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,\n            0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,\n            0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,\n            0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,\n            0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,\n            0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,\n            0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,\n            0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,\n            0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,\n            0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,\n            0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,\n        ])\n\n        def __init__(self, seed=0):\n            self.seed = seed & 0xffff_ffff_ffff_ffff\n            self.buf = b\"\"\n            self.total = 0\n            return\n\n        def update(self, data):\n            if not data:\n                return self\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            b = bytes(data)\n            self.buf += b\n            self.total += len(b)\n            return self\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def rol32(self, x, r):\n            x &= 0xffff_ffff\n            r &= 31\n            return ((x << r) | (x >> (32 - r))) & 0xffff_ffff\n\n        def rol64(self, x, r):\n            x &= 0xffff_ffff_ffff_ffff\n            r &= 63\n            return ((x << r) | (x >> (64 - r))) & 0xffff_ffff_ffff_ffff\n\n        def bswap32(self, x):\n            x &= 0xffff_ffff\n            return int.from_bytes(x.to_bytes(4, \"little\"), \"big\")\n\n        def bswap64(self, x):\n            x &= 0xffff_ffff_ffff_ffff\n            return int.from_bytes(x.to_bytes(8, \"little\"), \"big\")\n\n        def u32le(self, b, off):\n            return int.from_bytes(b[off:off + 4], \"little\")\n\n        def u64le(self, b, off):\n            return int.from_bytes(b[off:off + 8], \"little\")\n\n        def lower32(self, x):\n            return x & 0xffff_ffff\n\n        def higher32(self, x):\n            return (x >> 32) & 0xffff_ffff\n\n        def lower64(self, x):\n            return x & 0xffff_ffff_ffff_ffff\n\n        def higher64(self, x):\n            return (x >> 64) & 0xffff_ffff_ffff_ffff\n\n        def round32(self, acc, lane):\n            acc = (acc + lane * self.prime32_2) & 0xffff_ffff\n            acc = self.rol32(acc, 13)\n            return (acc * self.prime32_1) & 0xffff_ffff\n\n        def round64(self, acc, lane):\n            acc = (acc + lane * self.prime64_2) & 0xffff_ffff_ffff_ffff\n            acc = self.rol64(acc, 31)\n            return (acc * self.prime64_1) & 0xffff_ffff_ffff_ffff\n\n    class XXH32(XXHashBase):\n        digest_size = 4\n\n        def avalanche32(self, h):\n            h &= 0xffff_ffff\n            h ^= (h >> 15)\n            h = (h * self.prime32_2) & 0xffff_ffff\n            h ^= (h >> 13)\n            h = (h * self.prime32_3) & 0xffff_ffff\n            h ^= (h >> 16)\n            return h\n\n        def digest(self):\n            data = self.buf\n            seed32 = self.seed & 0xffff_ffff\n            n = len(data)\n            p = 0\n\n            if n >= 16:\n                acc1 = (seed32 + self.prime32_1 + self.prime32_2) & 0xffff_ffff\n                acc2 = (seed32 + self.prime32_2) & 0xffff_ffff\n                acc3 = (seed32 + 0) & 0xffff_ffff\n                acc4 = (seed32 - self.prime32_1) & 0xffff_ffff\n\n                limit = n - 16\n                while p <= limit:\n                    acc1 = self.round32(acc1, self.u32le(data, p))\n                    p += 4\n                    acc2 = self.round32(acc2, self.u32le(data, p))\n                    p += 4\n                    acc3 = self.round32(acc3, self.u32le(data, p))\n                    p += 4\n                    acc4 = self.round32(acc4, self.u32le(data, p))\n                    p += 4\n\n                h32 = (\n                    self.rol32(acc1, 1) + self.rol32(acc2, 7) + self.rol32(acc3, 12) + self.rol32(acc4, 18)\n                ) & 0xffff_ffff\n            else:\n                h32 = (seed32 + self.prime32_5) & 0xffff_ffff\n\n            h32 = (h32 + n) & 0xffff_ffff\n\n            while p + 4 <= n:\n                h32 = (h32 + self.u32le(data, p) * self.prime32_3) & 0xffff_ffff\n                h32 = self.rol32(h32, 17)\n                h32 = (h32 * self.prime32_4) & 0xffff_ffff\n                p += 4\n\n            while p < n:\n                h32 = (h32 + data[p] * self.prime32_5) & 0xffff_ffff\n                h32 = self.rol32(h32, 11)\n                h32 = (h32 * self.prime32_1) & 0xffff_ffff\n                p += 1\n            return self.avalanche32(h32).to_bytes(4, \"big\")\n\n    class XXH64(XXHashBase):\n        digest_size = 8\n\n        def avalanche_xxh64(self, x):\n            x &= 0xffff_ffff_ffff_ffff\n            x ^= (x >> 33)\n            x = (x * self.prime64_2) & 0xffff_ffff_ffff_ffff\n            x ^= (x >> 29)\n            x = (x * self.prime64_3) & 0xffff_ffff_ffff_ffff\n            x ^= (x >> 32)\n            return x\n\n        def digest(self):\n            data = self.buf\n            seed = self.seed\n            n = len(data)\n            p = 0\n\n            if n >= 32:\n                acc1 = (seed + self.prime64_1 + self.prime64_2) & 0xffff_ffff_ffff_ffff\n                acc2 = (seed + self.prime64_2) & 0xffff_ffff_ffff_ffff\n                acc3 = (seed + 0) & 0xffff_ffff_ffff_ffff\n                acc4 = (seed - self.prime64_1) & 0xffff_ffff_ffff_ffff\n\n                limit = n - 32\n                while p <= limit:\n                    acc1 = self.round64(acc1, self.u64le(data, p))\n                    p += 8\n                    acc2 = self.round64(acc2, self.u64le(data, p))\n                    p += 8\n                    acc3 = self.round64(acc3, self.u64le(data, p))\n                    p += 8\n                    acc4 = self.round64(acc4, self.u64le(data, p))\n                    p += 8\n\n                h64 = (\n                    self.rol64(acc1, 1) + self.rol64(acc2, 7) + self.rol64(acc3, 12) + self.rol64(acc4, 18)\n                ) & 0xffff_ffff_ffff_ffff\n\n                h64 ^= self.round64(0, acc1)\n                h64 = (h64 * self.prime64_1 + self.prime64_4) & 0xffff_ffff_ffff_ffff\n                h64 ^= self.round64(0, acc2)\n                h64 = (h64 * self.prime64_1 + self.prime64_4) & 0xffff_ffff_ffff_ffff\n                h64 ^= self.round64(0, acc3)\n                h64 = (h64 * self.prime64_1 + self.prime64_4) & 0xffff_ffff_ffff_ffff\n                h64 ^= self.round64(0, acc4)\n                h64 = (h64 * self.prime64_1 + self.prime64_4) & 0xffff_ffff_ffff_ffff\n            else:\n                h64 = (seed + self.prime64_5) & 0xffff_ffff_ffff_ffff\n\n            h64 = (h64 + n) & 0xffff_ffff_ffff_ffff\n            while p + 8 <= n:\n                h64 ^= self.round64(0, self.u64le(data, p))\n                h64 = (self.rol64(h64, 27) * self.prime64_1 + self.prime64_4) & 0xffff_ffff_ffff_ffff\n                p += 8\n            if p + 4 <= n:\n                h64 ^= (self.u32le(data, p) * self.prime64_1) & 0xffff_ffff_ffff_ffff\n                h64 = (self.rol64(h64, 23) * self.prime64_2 + self.prime64_3) & 0xffff_ffff_ffff_ffff\n                p += 4\n            while p < n:\n                h64 ^= (data[p] * self.prime64_5) & 0xffff_ffff_ffff_ffff\n                h64 = (self.rol64(h64, 11) * self.prime64_1) & 0xffff_ffff_ffff_ffff\n                p += 1\n            return self.avalanche_xxh64(h64).to_bytes(8, \"big\")\n\n    class XXH3Base(XXH64):\n        def derive_secret(self, seed):\n            seed &= 0xffff_ffff_ffff_ffff\n            words = [self.u64le(self.default_secret, i * 8) for i in range(24)]\n            for i in range(12):\n                words[i * 2] = (words[i * 2] + seed) & 0xffff_ffff_ffff_ffff\n                words[i * 2 + 1] = (words[i * 2 + 1] - seed) & 0xffff_ffff_ffff_ffff\n            return b\"\".join(w.to_bytes(8, \"little\") for w in words)\n\n        def secret_for_length(self, n):\n            if n > 240 and self.seed != 0:\n                return self.derive_secret(self.seed)\n            return self.default_secret\n\n        def mix_step(self, data16, secret, secret_offset, seed):\n            dw0 = self.u64le(data16, 0)\n            dw1 = self.u64le(data16, 8)\n            sw0 = self.u64le(secret, secret_offset)\n            sw1 = self.u64le(secret, secret_offset + 8)\n            add = (sw0 + seed) & 0xffff_ffff_ffff_ffff\n            sub = (sw1 - seed) & 0xffff_ffff_ffff_ffff\n            mul = (dw0 ^ add) * (dw1 ^ sub)\n            return self.lower64(mul) ^ self.higher64(mul)\n\n        def accumulate_stripe(self, acc, stripe64bytes, secret, secret_offset):\n            secret_words = [self.u64le(secret, secret_offset + i * 8) for i in range(8)]\n            stripe_words = [self.u64le(stripe64bytes, i * 8) for i in range(8)]\n            for i in range(8):\n                value = stripe_words[i] ^ secret_words[i]\n                acc[i ^ 1] = (acc[i ^ 1] + stripe_words[i]) & 0xffff_ffff_ffff_ffff\n                prod = self.lower32(value) * self.higher32(value)\n                acc[i] = (acc[i] + prod) & 0xffff_ffff_ffff_ffff\n            return acc\n\n        def scramble_acc(self, acc, secret):\n            secret_len = len(secret)\n            tail = secret[secret_len - 64:secret_len]\n            secret_words = [self.u64le(tail, i * 8) for i in range(8)]\n            for i in range(8):\n                v = acc[i]\n                v ^= (v >> 47)\n                v ^= secret_words[i]\n                acc[i] = (v * self.prime32_1) & 0xffff_ffff_ffff_ffff\n            return acc\n\n        def avalanche_xxh3(self, x):\n            x &= 0xffff_ffff_ffff_ffff\n            x ^= (x >> 37)\n            x = (x * self.prime_mx1) & 0xffff_ffff_ffff_ffff\n            x ^= (x >> 32)\n            return x\n\n        def final_merge(self, acc, secret, init_value, secret_offset):\n            secret_words = [self.u64le(secret, secret_offset + i * 8) for i in range(8)]\n            result = init_value & 0xffff_ffff_ffff_ffff\n            for i in range(4):\n                a = (acc[i * 2] ^ secret_words[i * 2]) & 0xffff_ffff_ffff_ffff\n                b = (acc[i * 2 + 1] ^ secret_words[i * 2 + 1]) & 0xffff_ffff_ffff_ffff\n                mul = a * b\n                result = (result + (self.lower64(mul) ^ self.higher64(mul))) & 0xffff_ffff_ffff_ffff\n            return self.avalanche_xxh3(result)\n\n    class XXH3_64(XXH3Base):\n        digest_size = 8\n\n        def digest(self):\n            data = self.buf\n            n = len(data)\n            seed = self.seed\n            secret = self.secret_for_length(n)\n\n            if n == 0:\n                sw0 = self.u64le(secret, 56)\n                sw1 = self.u64le(secret, 64)\n                value = seed ^ sw0 ^ sw1\n                return self.avalanche_xxh64(value).to_bytes(8, \"big\")\n\n            if n <= 3:\n                combined = data[n - 1] | (n << 8) | (data[0] << 16) | (data[n >> 1] << 24)\n                s0 = self.u32le(secret, 0)\n                s1 = self.u32le(secret, 4)\n                value = (((s0 ^ s1) + seed) & 0xffff_ffff_ffff_ffff) ^ combined\n                return self.avalanche_xxh64(value).to_bytes(8, \"big\")\n\n            if n <= 8:\n                input_first = self.u32le(data, 0)\n                input_last = self.u32le(data, n - 4)\n                modified_seed = seed ^ (self.bswap32(seed) << 32)\n                sw0 = self.u64le(secret, 8)\n                sw1 = self.u64le(secret, 16)\n                combined = (input_last | (input_first << 32)) & 0xffff_ffff_ffff_ffff\n                value = (((sw0 ^ sw1) - modified_seed) & 0xffff_ffff_ffff_ffff) ^ combined\n                value ^= self.rol64(value, 49) ^ self.rol64(value, 24)\n                value = (value * self.prime_mx2) & 0xffff_ffff_ffff_ffff\n                value ^= ((value >> 35) + n) & 0xffff_ffff_ffff_ffff\n                value = (value * self.prime_mx2) & 0xffff_ffff_ffff_ffff\n                value ^= (value >> 28)\n                return value.to_bytes(8, \"big\")\n\n            if n <= 16:\n                input_first = self.u64le(data, 0)\n                input_last = self.u64le(data, n - 8)\n                sw0 = self.u64le(secret, 24)\n                sw1 = self.u64le(secret, 32)\n                sw2 = self.u64le(secret, 40)\n                sw3 = self.u64le(secret, 48)\n                low = (((sw0 ^ sw1) + seed) & 0xffff_ffff_ffff_ffff) ^ input_first\n                high = (((sw2 ^ sw3) - seed) & 0xffff_ffff_ffff_ffff) ^ input_last\n                mul = low * high\n                value = n + self.bswap64(low) + high + (self.lower64(mul) ^ self.higher64(mul))\n                return self.avalanche_xxh3(value).to_bytes(8, \"big\")\n\n            if n <= 128:\n                acc = (n * self.prime64_1) & 0xffff_ffff_ffff_ffff\n                num_rounds = ((n - 1) >> 5) + 1\n                for i in range(num_rounds - 1, -1, -1):\n                    off_start = i * 16\n                    off_end = n - i * 16 - 16\n                    ms1 = self.mix_step(data[off_start:off_start + 16], secret, i * 32, seed)\n                    ms2 = self.mix_step(data[off_end:off_end + 16], secret, i * 32 + 16, seed)\n                    acc = (acc + ms1) & 0xffff_ffff_ffff_ffff\n                    acc = (acc + ms2) & 0xffff_ffff_ffff_ffff\n                return self.avalanche_xxh3(acc).to_bytes(8, \"big\")\n\n            if n <= 240:\n                acc = (n * self.prime64_1) & 0xffff_ffff_ffff_ffff\n                num_chunks = n >> 4\n                for i in range(8):\n                    ms = self.mix_step(data[i * 16:i * 16 + 16], secret, i * 16, seed)\n                    acc = (acc + ms) & 0xffff_ffff_ffff_ffff\n                acc = self.avalanche_xxh3(acc)\n                for i in range(8, num_chunks):\n                    ms = self.mix_step(data[i * 16:i * 16 + 16], secret, (i - 8) * 16 + 3, seed)\n                    acc = (acc + ms) & 0xffff_ffff_ffff_ffff\n                ms = self.mix_step(data[n - 16:n], secret, 119, seed)\n                return self.avalanche_xxh3(acc + ms).to_bytes(8, \"big\")\n\n            # large\n            secret_len = len(secret)\n            stripes_per_block = (secret_len - 64) // 8\n            block_size = 64 * stripes_per_block\n\n            acc = [\n                self.prime32_3, self.prime64_1, self.prime64_2, self.prime64_3,\n                self.prime64_4, self.prime32_2, self.prime64_5, self.prime32_1,\n            ]\n\n            p = 0\n            while n - p > block_size:\n                block = data[p:p + block_size]\n                for stripe_index in range(stripes_per_block):\n                    stripe = block[stripe_index * 64:stripe_index * 64 + 64]\n                    acc = self.accumulate_stripe(acc, stripe, secret, stripe_index * 8)\n                acc = self.scramble_acc(acc, secret)\n                p += block_size\n\n            # last round\n            last = data[p:]\n            last_len = len(last)\n            n_full = (last_len - 1) // 64\n            for stripe_index in range(n_full):\n                stripe = last[stripe_index * 64:stripe_index * 64 + 64]\n                acc = self.accumulate_stripe(acc, stripe, secret, stripe_index * 8)\n            last_stripe = data[n - 64:n]\n            acc = self.accumulate_stripe(acc, last_stripe, secret, secret_len - 71)\n\n            return self.final_merge(acc, secret, n * self.prime64_1, 11).to_bytes(8, \"big\")\n\n    class XXH3_128(XXH3Base):\n        digest_size = 16\n\n        def digest(self):\n            data = self.buf\n            n = len(data)\n            seed = self.seed\n            secret = self.secret_for_length(n)\n\n            def pack128(low, high):\n                return high.to_bytes(8, \"big\") + low.to_bytes(8, \"big\")\n\n            if n == 0:\n                sw0 = self.u64le(secret, 64)\n                sw1 = self.u64le(secret, 72)\n                sw2 = self.u64le(secret, 80)\n                sw3 = self.u64le(secret, 88)\n                low = self.avalanche_xxh64(seed ^ sw0 ^ sw1)\n                high = self.avalanche_xxh64(seed ^ sw2 ^ sw3)\n                return pack128(low, high)\n\n            if n <= 3:\n                combined = data[n - 1] | (n << 8) | (data[0] << 16) | (data[n >> 1] << 24)\n                s0 = self.u32le(secret, 0)\n                s1 = self.u32le(secret, 4)\n                s2 = self.u32le(secret, 8)\n                s3 = self.u32le(secret, 12)\n                low = (((s0 ^ s1) + seed) & 0xffff_ffff_ffff_ffff) ^ combined\n                rot = self.rol32(self.bswap32(combined), 13)\n                high = (((s2 ^ s3) - seed) & 0xffff_ffff_ffff_ffff) ^ rot\n                low = self.avalanche_xxh64(low)\n                high = self.avalanche_xxh64(high)\n                return pack128(low, high)\n\n            if n <= 8:\n                input_first = self.u32le(data, 0)\n                input_last = self.u32le(data, n - 4)\n                modified_seed = seed ^ (self.bswap32(seed) << 32)\n                sw0 = self.u64le(secret, 16)\n                sw1 = self.u64le(secret, 24)\n                combined = (input_first | (input_last << 32)) & 0xffff_ffff_ffff_ffff\n                value = (((sw0 ^ sw1) + modified_seed) & 0xffff_ffff_ffff_ffff) ^ combined\n                mul = (value & 0xffff_ffff_ffff_ffff) * ((self.prime64_1 + (n << 2)) & 0xffff_ffff_ffff_ffff)\n                high = self.higher64(mul)\n                low = self.lower64(mul)\n                high = (high + (low << 1)) & 0xffff_ffff_ffff_ffff\n                low ^= (high >> 3)\n                low ^= (low >> 35)\n                low = (low * self.prime_mx2) & 0xffff_ffff_ffff_ffff\n                low ^= (low >> 28)\n                high = self.avalanche_xxh3(high)\n                return pack128(low, high)\n\n            if n <= 16:\n                input_first = self.u64le(data, 0)\n                input_last = self.u64le(data, n - 8)\n                sw0 = self.u64le(secret, 32)\n                sw1 = self.u64le(secret, 40)\n                sw2 = self.u64le(secret, 48)\n                sw3 = self.u64le(secret, 56)\n                val1 = (((sw0 ^ sw1) - seed) & 0xffff_ffff_ffff_ffff) ^ input_first ^ input_last\n                val2 = (((sw2 ^ sw3) + seed) & 0xffff_ffff_ffff_ffff) ^ input_last\n                mul1 = (val1 & 0xffff_ffff_ffff_ffff) * self.prime64_1\n                low = (self.lower64(mul1) + ((n - 1) << 54)) & 0xffff_ffff_ffff_ffff\n                high = (\n                    self.higher64(mul1) + (self.higher32(val2) << 32) + self.lower32(val2) * self.prime32_2\n                ) & 0xffff_ffff_ffff_ffff\n                low ^= self.bswap64(high)\n                mul2 = (low & 0xffff_ffff_ffff_ffff) * self.prime64_2\n                low2 = self.lower64(mul2)\n                high2 = (self.higher64(mul2) + high * self.prime64_2) & 0xffff_ffff_ffff_ffff\n                low_out = self.avalanche_xxh3(low2)\n                high_out = self.avalanche_xxh3(high2)\n                return pack128(low_out, high_out)\n\n            # medium\n            if n <= 240:\n                acc0 = (n * self.prime64_1) & 0xffff_ffff_ffff_ffff\n                acc1 = 0\n\n                if n <= 128:\n                    num_rounds = ((n - 1) >> 5) + 1\n                    for i in range(num_rounds - 1, -1, -1):\n                        off_start = i * 16\n                        off_end = n - i * 16 - 16\n                        d1 = data[off_start:off_start + 16]\n                        d2 = data[off_end:off_end + 16]\n                        acc0 = (acc0 + self.mix_step(d1, secret, i * 32, seed)) & 0xffff_ffff_ffff_ffff\n                        acc1 = (acc1 + self.mix_step(d2, secret, i * 32 + 16, seed)) & 0xffff_ffff_ffff_ffff\n                        dw1_0 = self.u64le(d1, 0)\n                        dw1_1 = self.u64le(d1, 8)\n                        dw2_0 = self.u64le(d2, 0)\n                        dw2_1 = self.u64le(d2, 8)\n                        acc0 ^= (dw2_0 + dw2_1) & 0xffff_ffff_ffff_ffff\n                        acc1 ^= (dw1_0 + dw1_1) & 0xffff_ffff_ffff_ffff\n                else:\n                    num_chunks = n >> 5\n                    for i in range(4):\n                        base = i * 32\n                        d1 = data[base:base + 16]\n                        d2 = data[base + 16:base + 32]\n                        acc0 = (acc0 + self.mix_step(d1, secret, i * 32, seed)) & 0xffff_ffff_ffff_ffff\n                        acc1 = (acc1 + self.mix_step(d2, secret, i * 32 + 16, seed)) & 0xffff_ffff_ffff_ffff\n                        dw1_0 = self.u64le(d1, 0)\n                        dw1_1 = self.u64le(d1, 8)\n                        dw2_0 = self.u64le(d2, 0)\n                        dw2_1 = self.u64le(d2, 8)\n                        acc0 ^= (dw2_0 + dw2_1) & 0xffff_ffff_ffff_ffff\n                        acc1 ^= (dw1_0 + dw1_1) & 0xffff_ffff_ffff_ffff\n\n                    acc0 = self.avalanche_xxh3(acc0)\n                    acc1 = self.avalanche_xxh3(acc1)\n\n                    for i in range(4, num_chunks):\n                        base = i * 32\n                        d1 = data[base:base + 16]\n                        d2 = data[base + 16:base + 32]\n                        off = (i - 4) * 32 + 3\n                        acc0 = (acc0 + self.mix_step(d1, secret, off, seed)) & 0xffff_ffff_ffff_ffff\n                        acc1 = (acc1 + self.mix_step(d2, secret, off + 16, seed)) & 0xffff_ffff_ffff_ffff\n                        dw1_0 = self.u64le(d1, 0)\n                        dw1_1 = self.u64le(d1, 8)\n                        dw2_0 = self.u64le(d2, 0)\n                        dw2_1 = self.u64le(d2, 8)\n                        acc0 ^= (dw2_0 + dw2_1) & 0xffff_ffff_ffff_ffff\n                        acc1 ^= (dw1_0 + dw1_1) & 0xffff_ffff_ffff_ffff\n\n                    # last mixed: note different half-order and seed negation\n                    d1 = data[n - 16:n]\n                    d2 = data[n - 32:n - 16]\n                    neg_seed = (0 - seed) & 0xffff_ffff_ffff_ffff\n                    acc0 = (acc0 + self.mix_step(d1, secret, 103, neg_seed)) & 0xffff_ffff_ffff_ffff\n                    acc1 = (acc1 + self.mix_step(d2, secret, 103 + 16, neg_seed)) & 0xffff_ffff_ffff_ffff\n                    dw1_0 = self.u64le(d1, 0)\n                    dw1_1 = self.u64le(d1, 8)\n                    dw2_0 = self.u64le(d2, 0)\n                    dw2_1 = self.u64le(d2, 8)\n                    acc0 ^= (dw2_0 + dw2_1) & 0xffff_ffff_ffff_ffff\n                    acc1 ^= (dw1_0 + dw1_1) & 0xffff_ffff_ffff_ffff\n\n                low = (acc0 + acc1) & 0xffff_ffff_ffff_ffff\n                high = (\n                    (acc0 * self.prime64_1) + \\\n                    (acc1 * self.prime64_4) + \\\n                    (((n - seed) & 0xffff_ffff_ffff_ffff) * self.prime64_2)\n                ) & 0xffff_ffff_ffff_ffff\n                low_out = self.avalanche_xxh3(low)\n                high_out = (0 - self.avalanche_xxh3(high)) & 0xffff_ffff_ffff_ffff\n                return pack128(low_out, high_out)\n\n            # large\n            secret_len = len(secret)\n            stripes_per_block = (secret_len - 64) // 8\n            block_size = 64 * stripes_per_block\n\n            acc = [\n                self.prime32_3, self.prime64_1, self.prime64_2, self.prime64_3,\n                self.prime64_4, self.prime32_2, self.prime64_5, self.prime32_1,\n            ]\n\n            p = 0\n            while n - p > block_size:\n                block = data[p:p + block_size]\n                for stripe_index in range(stripes_per_block):\n                    stripe = block[stripe_index * 64:stripe_index * 64 + 64]\n                    acc = self.accumulate_stripe(acc, stripe, secret, stripe_index * 8)\n                acc = self.scramble_acc(acc, secret)\n                p += block_size\n\n            last = data[p:]\n            last_len = len(last)\n            n_full = (last_len - 1) // 64\n            for stripe_index in range(n_full):\n                stripe = last[stripe_index * 64:stripe_index * 64 + 64]\n                acc = self.accumulate_stripe(acc, stripe, secret, stripe_index * 8)\n\n            last_stripe = data[n - 64:n]\n            acc = self.accumulate_stripe(acc, last_stripe, secret, secret_len - 71)\n\n            low = self.final_merge(acc, secret, (n * self.prime64_1) & 0xffff_ffff_ffff_ffff, 11)\n            high = self.final_merge(acc, secret, (~(n * self.prime64_2)) & 0xffff_ffff_ffff_ffff, secret_len - 75)\n            return pack128(low, high)\n\n    class FNVBase:\n        bits = None\n        fnv_prime = None\n        offset_basis = None\n        variant = None  # \"fnv0\", \"fnv0a\", \"fnv1\", \"fnv1a\"\n\n        def __init__(self, data=b\"\", basis=None, variant=\"fnv1\"):\n            if self.bits is None or self.fnv_prime is None or self.offset_basis is None:\n                raise ValueError(\"FNVBase must be subclassed with constants\")\n            self.variant = variant\n            self.mask = (1 << self.bits) - 1\n            if basis is None:\n                if variant in [\"fnv0\", \"fnv0a\"]:\n                    self.h = 0\n                else:\n                    self.h = self.offset_basis & self.mask\n            else:\n                self.h = int(basis) & self.mask\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not data:\n                return self\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            b = bytes(data)\n\n            if self.variant in [\"fnv0\", \"fnv1\"]:\n                for byte in b:\n                    self.h = (self.h * self.fnv_prime) & self.mask\n                    self.h ^= byte\n            else:\n                # fnv0a, fnv1a\n                for byte in b:\n                    self.h ^= byte\n                    self.h = (self.h * self.fnv_prime) & self.mask\n            return self\n\n        def digest(self):\n            out_len = self.bits // 8\n            return int(self.h & self.mask).to_bytes(out_len, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class FNV_32(FNVBase):\n        bits = 32\n        digest_size = 4\n        fnv_prime = 0x0100_0193\n        offset_basis = 0x811c_9dc5\n\n    class FNV_64(FNVBase):\n        bits = 64\n        digest_size = 8\n        fnv_prime = 0x0000_0100_0000_01b3\n        offset_basis = 0xcbf2_9ce4_8422_2325\n\n    class FNV_128(FNVBase):\n        bits = 128\n        digest_size = 16\n        fnv_prime = 0x0000_0000_0100_0000_0000_0000_0000_013b\n        offset_basis = 0x6c62_272e_07bb_0142_62b8_2175_6295_c58d\n\n    class FNV_256(FNVBase):\n        bits = 256\n        digest_size = 32\n        fnv_prime = 0x0000_0000_0000_0000_0000_0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0163\n        offset_basis = 0xdd26_8dbc_aac5_5036_2d98_c384_c4e5_76cc_c8b1_5368_47b6_bbb3_1023_b4c8_caee_0535\n\n    class FNV_512(FNVBase):\n        bits = 512\n        digest_size = 64\n        fnv_prime = (\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 3)) | \\\n            (0x0000_0000_0100_0000_0000_0000_0000_0000 << (128 * 2)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 1)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0157 << (128 * 0))\n        )\n        offset_basis = (\n            (0xb86d_b0b1_171f_4416_dca1_e50f_3099_90ac << (128 * 3)) | \\\n            (0xac87_d059_c900_0000_0000_0000_0000_0d21 << (128 * 2)) | \\\n            (0xe948_f68a_34c1_92f6_2ea7_9bc9_42db_e7ce << (128 * 1)) | \\\n            (0x1820_3641_5f56_e34b_ac98_2aac_4afe_9fd9 << (128 * 0))\n        )\n\n    class FNV_1024(FNVBase):\n        bits = 1024\n        digest_size = 128\n        fnv_prime = (\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 7)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 6)) | \\\n            (0x0000_0000_0000_0000_0000_0100_0000_0000 << (128 * 5)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 4)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 3)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 2)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 1)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_018d << (128 * 0))\n        )\n        offset_basis = (\n            (0x0000_0000_0000_0000_005f_7a76_758e_cc4d << (128 * 7)) | \\\n            (0x32e5_6d5a_5910_28b7_4b29_fc42_23fd_ada1 << (128 * 6)) | \\\n            (0x6c3b_f34e_da36_74da_9a21_d900_0000_0000 << (128 * 5)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 4)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0000_0000 << (128 * 3)) | \\\n            (0x0000_0000_0000_0000_0000_0000_0004_c6d7 << (128 * 2)) | \\\n            (0xeb6e_7380_2734_510a_555f_256c_c005_ae55 << (128 * 1)) | \\\n            (0x6bde_8cc9_c6a9_3b21_aff4_b16c_71ee_90b3 << (128 * 0))\n        )\n\n    class HAVAL:\n        block_size = 128  # bytes (1024 bits)\n        version = 0x01\n\n        # Table 1 word processing orders\n        ord1 = (\n            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,\n        )\n        ord2 = (\n            0x05, 0x0e, 0x1a, 0x12, 0x0b, 0x1c, 0x07, 0x10, 0x00, 0x17, 0x14, 0x16, 0x01, 0x0a, 0x04, 0x08,\n            0x1e, 0x03, 0x15, 0x09, 0x11, 0x18, 0x1d, 0x06, 0x13, 0x0c, 0x0f, 0x0d, 0x02, 0x19, 0x1f, 0x1b,\n        )\n        ord3 = (\n            0x13, 0x09, 0x04, 0x14, 0x1c, 0x11, 0x08, 0x16, 0x1d, 0x0e, 0x19, 0x0c, 0x18, 0x1e, 0x10, 0x1a,\n            0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x12, 0x1b, 0x0d, 0x06, 0x15, 0x0a, 0x17, 0x0b, 0x05, 0x02,\n        )\n        ord4 = (\n            0x18, 0x04, 0x00, 0x0e, 0x02, 0x07, 0x1c, 0x17, 0x1a, 0x06, 0x1e, 0x14, 0x12, 0x19, 0x13, 0x03,\n            0x16, 0x0b, 0x1f, 0x15, 0x08, 0x1b, 0x0c, 0x09, 0x01, 0x1d, 0x05, 0x0f, 0x11, 0x0a, 0x10, 0x0d,\n        )\n        ord5 = (\n            0x1b, 0x03, 0x15, 0x1a, 0x11, 0x0b, 0x14, 0x1d, 0x13, 0x00, 0x0c, 0x07, 0x0d, 0x08, 0x1f, 0x0a,\n            0x05, 0x09, 0x0e, 0x1e, 0x12, 0x06, 0x1c, 0x18, 0x02, 0x17, 0x10, 0x16, 0x04, 0x01, 0x19, 0x0f,\n        )\n\n        # Table 2 permutations phi (indices into coords=[x6,x5,x4,x3,x2,x1,x0])\n        phi_3_1 = (0x05, 0x06, 0x03, 0x01, 0x00, 0x04, 0x02)\n        phi_3_2 = (0x02, 0x04, 0x05, 0x06, 0x01, 0x03, 0x00)\n        phi_3_3 = (0x00, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06)\n\n        phi_4_1 = (0x04, 0x00, 0x05, 0x02, 0x01, 0x03, 0x06)\n        phi_4_2 = (0x03, 0x01, 0x04, 0x06, 0x05, 0x00, 0x02)\n        phi_4_3 = (0x05, 0x02, 0x03, 0x00, 0x06, 0x04, 0x01)\n        phi_4_4 = (0x00, 0x02, 0x06, 0x01, 0x04, 0x05, 0x03)\n\n        phi_5_1 = (0x03, 0x02, 0x05, 0x06, 0x01, 0x04, 0x00)\n        phi_5_2 = (0x00, 0x04, 0x05, 0x06, 0x03, 0x02, 0x01)\n        phi_5_3 = (0x04, 0x00, 0x06, 0x02, 0x03, 0x05, 0x01)\n        phi_5_4 = (0x05, 0x01, 0x03, 0x04, 0x06, 0x02, 0x00)\n        phi_5_5 = (0x04, 0x01, 0x06, 0x00, 0x02, 0x03, 0x05)\n\n        # Constants from pi (D0..D7, then K2, K3, K4, K5)\n        const = (\n            0x243f_6a88, 0x85a3_08d3, 0x1319_8a2e, 0x0370_7344, 0xa409_3822, 0x299f_31d0, 0x082e_fa98, 0xec4e_6c89,\n            0x4528_21e6, 0x38d0_1377, 0xbe54_66cf, 0x34e9_0c6c, 0xc0ac_29b7, 0xc97c_50dd, 0x3f84_d5b5, 0xb547_0917,\n            0x9216_d5d9, 0x8979_fb1b, 0xd131_0ba6, 0x98df_b5ac, 0x2ffd_72db, 0xd01a_dfb7, 0xb8e1_afed, 0x6a26_7e96,\n            0xba7c_9045, 0xf12c_7f99, 0x24a1_9947, 0xb391_6cf7, 0x0801_f2e2, 0x858e_fc16, 0x6369_20d8, 0x7157_4e69,\n            0xa458_fea3, 0xf493_3d7e, 0x0d95_748f, 0x728e_b658, 0x718b_cd58, 0x8215_4aee, 0x7b54_a41d, 0xc25a_59b5,\n            0x9c30_d539, 0x2af2_6013, 0xc5d1_b023, 0x2860_85f0, 0xca41_7918, 0xb8db_38ef, 0x8e79_dcb0, 0x603a_180e,\n            0x6c9e_0e8b, 0xb01e_8a3e, 0xd715_77c1, 0xbd31_4b27, 0x78af_2fda, 0x5560_5c60, 0xe655_25f3, 0xaa55_ab94,\n            0x5748_9862, 0x63e8_1440, 0x55ca_396a, 0x2aab_10b6, 0xb4cc_5c34, 0x1141_e8ce, 0xa154_86af, 0x7c72_e993,\n            0xb3ee_1411, 0x636f_bc2a, 0x2ba9_c55d, 0x7418_31f6, 0xce5c_3e16, 0x9b87_931e, 0xafd6_ba33, 0x6c24_cf5c,\n            0x7a32_5381, 0x2895_8677, 0x3b8f_4898, 0x6b4b_b9af, 0xc4bf_e81b, 0x6628_2193, 0x61d8_09cc, 0xfb21_a991,\n            0x487c_ac60, 0x5dec_8032, 0xef84_5d5d, 0xe985_75b1, 0xdc26_2302, 0xeb65_1b88, 0x2389_3e81, 0xd396_acc5,\n            0x0f6d_6ff3, 0x83f4_4239, 0x2e0b_4482, 0xa484_2004, 0x69c8_f04a, 0x9e1f_9b5e, 0x21c6_6842, 0xf6e9_6c9a,\n            0x670c_9c61, 0xabd3_88f0, 0x6a51_a0d2, 0xd854_2f68, 0x960f_a728, 0xab51_33a3, 0x6eef_0b6c, 0x137a_3be4,\n            0xba3b_f050, 0x7efb_2a98, 0xa1f1_651d, 0x39af_0176, 0x66ca_593e, 0x8243_0e88, 0x8cee_8619, 0x456f_9fb4,\n            0x7d84_a5c3, 0x3b8b_5ebe, 0xe06f_75d8, 0x85c1_2073, 0x401a_449f, 0x56c1_6aa6, 0x4ed3_aa62, 0x363f_7706,\n            0x1bfe_df72, 0x429b_023d, 0x37d0_d724, 0xd00a_1248, 0xdb0f_ead3, 0x49f1_c09b, 0x0753_72c9, 0x8099_1b7b,\n            0x25d4_79d8, 0xf6e8_def7, 0xe3fe_501a, 0xb679_4c3b, 0x976c_e0bd, 0x04c0_06ba, 0xc1a9_4fb6, 0x409f_60c4,\n        )\n\n        def __init__(self, data=b\"\", digest_bits=256, passes=5):\n            if digest_bits not in (128, 160, 192, 224, 256):\n                raise ValueError(\"digest_bits must be one of 128,160,192,224,256\")\n            if passes not in (3, 4, 5):\n                raise ValueError(\"passes must be one of 3,4,5\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.digest_bits = digest_bits\n            self.passes = passes\n            self.digest_size = digest_bits // 8\n            if len(self.const) != 136:\n                raise ValueError(\"constant table size mismatch\")\n            self.iv = list(self.const[0:8])\n            self.k2 = list(self.const[8:40])\n            self.k3 = list(self.const[40:72])\n            self.k4 = list(self.const[72:104])\n            self.k5 = list(self.const[104:136])\n            self.h = self.iv[:]\n            self.buf = bytearray()\n            self.bitlen = 0  # in bits\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.digest_bits, self.passes)\n            other.h = self.h[:]\n            other.buf = bytearray(self.buf)\n            other.bitlen = self.bitlen\n            return other\n\n        def tailor(self, state, out_bits):\n\n            def split_lsb(word, lens_lsb):\n                seg = []\n                w = word & 0xffff_ffff\n                for l in lens_lsb:  # noqa: E741\n                    seg.append(w & ((1 << l) - 1))\n                    w >>= l\n                return seg\n\n            def concat(parts):\n                out = 0\n                for v, bl in parts:\n                    out = (out << bl) | (v & ((1 << bl) - 1))\n                return out\n\n            d = [x & 0xffff_ffff for x in state]\n            if out_bits == 256:\n                return d[0:8]\n            if out_bits == 224:\n                seg7 = split_lsb(d[7], [4, 5, 4, 5, 4, 5, 5])\n                y0 = (d[0] + seg7[6]) & 0xffff_ffff\n                y1 = (d[1] + seg7[5]) & 0xffff_ffff\n                y2 = (d[2] + seg7[4]) & 0xffff_ffff\n                y3 = (d[3] + seg7[3]) & 0xffff_ffff\n                y4 = (d[4] + seg7[2]) & 0xffff_ffff\n                y5 = (d[5] + seg7[1]) & 0xffff_ffff\n                y6 = (d[6] + seg7[0]) & 0xffff_ffff\n                return [y0, y1, y2, y3, y4, y5, y6]\n            if out_bits == 192:\n                seg7 = split_lsb(d[7], [5, 5, 6, 5, 5, 6])\n                seg6 = split_lsb(d[6], [5, 5, 6, 5, 5, 6])\n                y0 = (d[0] + concat([(seg7[0], 5), (seg6[5], 6)])) & 0xffff_ffff\n                y1 = (d[1] + concat([(seg7[1], 5), (seg6[0], 5)])) & 0xffff_ffff\n                y2 = (d[2] + concat([(seg7[2], 6), (seg6[1], 5)])) & 0xffff_ffff\n                y3 = (d[3] + concat([(seg7[3], 5), (seg6[2], 6)])) & 0xffff_ffff\n                y4 = (d[4] + concat([(seg7[4], 5), (seg6[3], 5)])) & 0xffff_ffff\n                y5 = (d[5] + concat([(seg7[5], 6), (seg6[4], 5)])) & 0xffff_ffff\n                return [y0, y1, y2, y3, y4, y5]\n            if out_bits == 160:\n                seg7 = split_lsb(d[7], [6, 6, 7, 6, 7])\n                seg6 = split_lsb(d[6], [6, 6, 7, 6, 7])\n                seg5 = split_lsb(d[5], [6, 6, 7, 6, 7])\n                y0 = (d[0] + concat([(seg7[0], 6), (seg6[4], 7), (seg5[3], 6)])) & 0xffff_ffff\n                y1 = (d[1] + concat([(seg7[1], 6), (seg6[0], 6), (seg5[4], 7)])) & 0xffff_ffff\n                y2 = (d[2] + concat([(seg7[2], 7), (seg6[1], 6), (seg5[0], 6)])) & 0xffff_ffff\n                y3 = (d[3] + concat([(seg7[3], 6), (seg6[2], 7), (seg5[1], 6)])) & 0xffff_ffff\n                y4 = (d[4] + concat([(seg7[4], 7), (seg6[3], 6), (seg5[2], 7)])) & 0xffff_ffff\n                return [y0, y1, y2, y3, y4]\n            if out_bits == 128:\n                seg7 = split_lsb(d[7], [8, 8, 8, 8])\n                seg6 = split_lsb(d[6], [8, 8, 8, 8])\n                seg5 = split_lsb(d[5], [8, 8, 8, 8])\n                seg4 = split_lsb(d[4], [8, 8, 8, 8])\n                y0 = (d[0] + concat([(seg7[0], 8), (seg6[3], 8), (seg5[2], 8), (seg4[1], 8)])) & 0xffff_ffff\n                y1 = (d[1] + concat([(seg7[1], 8), (seg6[0], 8), (seg5[3], 8), (seg4[2], 8)])) & 0xffff_ffff\n                y2 = (d[2] + concat([(seg7[2], 8), (seg6[1], 8), (seg5[0], 8), (seg4[3], 8)])) & 0xffff_ffff\n                y3 = (d[3] + concat([(seg7[3], 8), (seg6[2], 8), (seg5[1], 8), (seg4[0], 8)])) & 0xffff_ffff\n                return [y0, y1, y2, y3]\n            raise ValueError(\"invalid out_bits\")\n\n        def compress(self, block):\n\n            def u32le(b, off):\n                return int.from_bytes(b[off:off + 4], \"little\")\n\n            def f1(x6, x5, x4, x3, x2, x1, x0):\n                return (x1 & x4) ^ (x2 & x5) ^ (x3 & x6) ^ (x0 & x1) ^ x0\n\n            def f2(x6, x5, x4, x3, x2, x1, x0):\n                return (\n                    (x1 & x2 & x3) ^ (x2 & x4 & x5) ^\n                    (x1 & x2) ^ (x1 & x4) ^ (x2 & x6) ^\n                    (x3 & x5) ^ (x4 & x5) ^ (x0 & x2) ^ x0\n                )\n\n            def f3(x6, x5, x4, x3, x2, x1, x0):\n                return (x1 & x2 & x3) ^ (x1 & x4) ^ (x2 & x5) ^ (x3 & x6) ^ (x0 & x3) ^ x0\n\n            def f4(x6, x5, x4, x3, x2, x1, x0):\n                return (\n                    (x1 & x2 & x3) ^ (x2 & x4 & x5) ^ (x3 & x4 & x6) ^\n                    (x1 & x4) ^ (x2 & x6) ^ (x3 & x4) ^ (x3 & x5) ^\n                    (x3 & x6) ^ (x4 & x5) ^ (x4 & x6) ^ (x0 & x4) ^ x0\n                )\n\n            def f5(x6, x5, x4, x3, x2, x1, x0):\n                return (x1 & x4) ^ (x2 & x5) ^ (x3 & x6) ^ (x0 & x1 & x2 & x3) ^ (x0 & x5) ^ x0\n\n            def do_pass(func, phi, order, kconst, t, w):\n\n                def ror32(x, r):\n                    x &= 0xffff_ffff\n                    r = r & 31\n                    return ((x >> r) | ((x << (32 - r)) & 0xffff_ffff)) & 0xffff_ffff\n\n                for i in range(32):\n                    coords = [t[6], t[5], t[4], t[3], t[2], t[1], t[0]]\n                    a0 = coords[phi[0]]\n                    a1 = coords[phi[1]]\n                    a2 = coords[phi[2]]\n                    a3 = coords[phi[3]]\n                    a4 = coords[phi[4]]\n                    a5 = coords[phi[5]]\n                    a6 = coords[phi[6]]\n                    p = func(a0, a1, a2, a3, a4, a5, a6)\n                    r = (ror32(p, 7) + ror32(t[7], 11) + w[order[i]] + kconst[i]) & 0xffff_ffff\n                    t = [r, t[0], t[1], t[2], t[3], t[4], t[5], t[6]]\n                return t\n\n            w = [u32le(block, 4 * i) for i in range(32)]\n            t = self.h[:]\n            zero32 = [0] * 32\n            if self.passes == 3:\n                t = do_pass(f1, self.phi_3_1, self.ord1, zero32, t, w)\n                t = do_pass(f2, self.phi_3_2, self.ord2, self.k2, t, w)\n                t = do_pass(f3, self.phi_3_3, self.ord3, self.k3, t, w)\n            elif self.passes == 4:\n                t = do_pass(f1, self.phi_4_1, self.ord1, zero32, t, w)\n                t = do_pass(f2, self.phi_4_2, self.ord2, self.k2, t, w)\n                t = do_pass(f3, self.phi_4_3, self.ord3, self.k3, t, w)\n                t = do_pass(f4, self.phi_4_4, self.ord4, self.k4, t, w)\n            else:\n                t = do_pass(f1, self.phi_5_1, self.ord1, zero32, t, w)\n                t = do_pass(f2, self.phi_5_2, self.ord2, self.k2, t, w)\n                t = do_pass(f3, self.phi_5_3, self.ord3, self.k3, t, w)\n                t = do_pass(f4, self.phi_5_4, self.ord4, self.k4, t, w)\n                t = do_pass(f5, self.phi_5_5, self.ord5, self.k5, t, w)\n            for i in range(8):\n                self.h[i] = (self.h[i] + t[i]) & 0xffff_ffff\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.bitlen += len(data) * 8\n            while len(self.buf) >= 128:\n                block = bytes(self.buf[:128])\n                del self.buf[:128]\n                self.compress(block)\n            return self\n\n        def finalize(self):\n            # padding: 0x01, zeros, then 2 bytes (version/passes/outbits), then 8 bytes bitlen (LE)\n            msg = bytes(self.buf)\n            bitlen = self.bitlen\n            pad = bytearray()\n            pad.append(0x01)\n            while ((len(msg) + len(pad)) % 128) != 118:\n                pad.append(0x00)\n            # tail (2 bytes) + bitlen (8 bytes, little-endian)\n            b0 = (self.version & 0x07) | ((self.passes & 0x07) << 3) | ((self.digest_bits & 0x03) << 6)\n            b1 = (self.digest_bits >> 2) & 0xff\n            tail = bytes([b0, b1]) + bitlen.to_bytes(8, \"little\")\n\n            self.update(bytes(pad) + tail)\n            if len(self.buf) != 0:\n                raise RuntimeError(\"internal error: buffer not empty after finalize\")\n            return\n\n        def output(self):\n            out_words = self.tailor(self.h, self.digest_bits)\n            out = bytearray()\n            for x in out_words:\n                out.extend(int(x & 0xffff_ffff).to_bytes(4, \"little\"))\n            return bytes(out[: self.digest_size])\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class MurmurHashBase:\n        block_size = None\n        digest_size = None\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(seed, int):\n                raise TypeError(\"seed must be int\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.seed = seed\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            other.set_state(self.get_state())\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def finalize(self):\n            if self.finalized:\n                return\n            full = bytes(self.buf)\n            self.process_all(full)\n            self.finalize_state()\n            self.buf.clear()\n            self.finalized = True\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.pack_digest()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize_state(self):\n            return\n\n        def digest_normalize(self, digest):\n            digest = bytes.fromhex(digest)\n            return str(int.from_bytes(digest[::-1], \"big\"))\n\n    class MurmurHash32Base(MurmurHashBase):\n        block_size = 4\n        digest_size = 4\n\n        def init_state(self):\n            self.seed &= 0xffff_ffff\n            self.h = 0\n            return\n\n        def get_state(self):\n            return (self.h & 0xffff_ffff,)\n\n        def set_state(self, state):\n            self.h = state[0] & 0xffff_ffff\n            return\n\n        def pack_digest(self):\n            return struct.pack(\"<I\", self.h & 0xffff_ffff)\n\n    class MurmurHash1(MurmurHash32Base):\n        def process_all(self, data):\n            length = len(data)\n            m = 0xc6a4_a793\n            r = 16\n            h = (self.seed ^ (length * m)) & 0xffff_ffff\n            i = 0\n            while i + 4 <= length:\n                k =  struct.unpack_from(\"<I\", data, i)[0]\n                h = (h + k) & 0xffff_ffff\n                h = (h * m) & 0xffff_ffff\n                h ^= (h >> 16)\n                h &= 0xffff_ffff\n                i += 4\n\n            tail = data[i:]\n            tl = len(tail)\n            if tl == 3:\n                h = (h + (tail[2] << 16)) & 0xffff_ffff\n                h = (h + (tail[1] << 8)) & 0xffff_ffff\n                h = (h + tail[0]) & 0xffff_ffff\n                h = (h * m) & 0xffff_ffff\n                h ^= (h >> r)\n                h &= 0xffff_ffff\n            elif tl == 2:\n                h = (h + (tail[1] << 8)) & 0xffff_ffff\n                h = (h + tail[0]) & 0xffff_ffff\n                h = (h * m) & 0xffff_ffff\n                h ^= (h >> r)\n                h &= 0xffff_ffff\n            elif tl == 1:\n                h = (h + tail[0]) & 0xffff_ffff\n                h = (h * m) & 0xffff_ffff\n                h ^= (h >> r)\n                h &= 0xffff_ffff\n            else:\n                pass\n\n            h = (h * m) & 0xffff_ffff\n            h ^= (h >> 10)\n            h = (h * m) & 0xffff_ffff\n            h ^= (h >> 17)\n            h &= 0xffff_ffff\n\n            self.h = h\n            return\n\n    class MurmurHash2(MurmurHash32Base):\n        def process_all(self, data):\n            length = len(data)\n            m = 0x5bd1_e995\n            r = 24\n            h = (self.seed ^ length) & 0xffff_ffff\n            i = 0\n            while i + 4 <= length:\n                k =  struct.unpack_from(\"<I\", data, i)[0]\n                k = (k * m) & 0xffff_ffff\n                k ^= (k >> r)\n                k = (k * m) & 0xffff_ffff\n                h = (h * m) & 0xffff_ffff\n                h ^= k\n                h &= 0xffff_ffff\n\n                i += 4\n\n            tail = data[i:]\n            tl = len(tail)\n            if tl == 3:\n                h ^= (tail[2] << 16)\n                h ^= (tail[1] << 8)\n                h ^= tail[0]\n                h = (h * m) & 0xffff_ffff\n            elif tl == 2:\n                h ^= (tail[1] << 8)\n                h ^= tail[0]\n                h = (h * m) & 0xffff_ffff\n            elif tl == 1:\n                h ^= tail[0]\n                h = (h * m) & 0xffff_ffff\n            else:\n                pass\n\n            h ^= (h >> 13)\n            h = (h * m) & 0xffff_ffff\n            h ^= (h >> 15)\n            h &= 0xffff_ffff\n\n            self.h = h\n            return\n\n    class MurmurHash2A(MurmurHash32Base):\n        def mmix(self, h, k):\n            m = 0x5bd1_e995\n            r = 24\n            k = (k * m) & 0xffff_ffff\n            k ^= (k >> r)\n            k = (k * m) & 0xffff_ffff\n            h = (h * m) & 0xffff_ffff\n            h ^= k\n            h &= 0xffff_ffff\n            return h\n\n        def process_all(self, data):\n            length = len(data)\n            m = 0x5bd1_e995\n            h = self.seed & 0xffff_ffff\n            l = length & 0xffff_ffff  # noqa: E741\n            i = 0\n            while i + 4 <= length:\n                k = struct.unpack_from(\"<I\", data, i)[0]\n                h = self.mmix(h, k)\n                i += 4\n\n            tail = data[i:]\n            tl = len(tail)\n            t = 0\n            if tl == 3:\n                t ^= tail[2] << 16\n                t ^= tail[1] << 8\n                t ^= tail[0]\n            elif tl == 2:\n                t ^= tail[1] << 8\n                t ^= tail[0]\n            elif tl == 1:\n                t ^= tail[0]\n            else:\n                pass\n\n            h = self.mmix(h, t)\n            h = self.mmix(h, l)\n\n            h ^= (h >> 13)\n            h = (h * m) & 0xffff_ffff\n            h ^= (h >> 15)\n            h &= 0xffff_ffff\n\n            self.h = h\n            return\n\n    class MurmurHash64Base(MurmurHashBase):\n        block_size = 8\n        digest_size = 8\n\n        def init_state(self):\n            self.seed &= 0xffff_ffff_ffff_ffff\n            self.h = 0\n            return\n\n        def get_state(self):\n            return (self.h & 0xffff_ffff_ffff_ffff,)\n\n        def set_state(self, state):\n            self.h = state[0] & 0xffff_ffff_ffff_ffff\n            return\n\n        def pack_digest(self):\n            return struct.pack(\"<Q\", self.h & 0xffff_ffff_ffff_ffff)\n\n    class MurmurHash64A(MurmurHash64Base):\n        def process_all(self, data):\n            length = len(data)\n            m = 0xc6a4_a793_5bd1_e995\n            r = 47\n            h = (self.seed ^ (length * m)) & 0xffff_ffff_ffff_ffff\n            i = 0\n            while i + 8 <= length:\n                k = struct.unpack_from(\"<Q\", data, i)[0]\n                k = (k * m) & 0xffff_ffff_ffff_ffff\n                k ^= (k >> r)\n                k = (k * m) & 0xffff_ffff_ffff_ffff\n                h ^= k\n                h = (h * m) & 0xffff_ffff_ffff_ffff\n                i += 8\n\n            tail = data[i:]\n            tl = len(tail)\n            if tl >= 7:\n                h ^= (tail[6] << 48)\n            if tl >= 6:\n                h ^= (tail[5] << 40)\n            if tl >= 5:\n                h ^= (tail[4] << 32)\n            if tl >= 4:\n                h ^= (tail[3] << 24)\n            if tl >= 3:\n                h ^= (tail[2] << 16)\n            if tl >= 2:\n                h ^= (tail[1] << 8)\n            if tl >= 1:\n                h ^= (tail[0] << 0)\n                h = (h * m) & 0xffff_ffff_ffff_ffff\n\n            h ^= (h >> r)\n            h = (h * m) & 0xffff_ffff_ffff_ffff\n            h ^= (h >> r)\n            h &= 0xffff_ffff_ffff_ffff\n\n            self.h = h\n            return\n\n    class MurmurHash64B(MurmurHash64Base):\n        block_size = 4\n\n        def process_all(self, data):\n            length = len(data)\n            m = 0x5bd1_e995\n            r = 24\n            seed_lo = self.seed & 0xffff_ffff\n            seed_hi = (self.seed >> 32) & 0xffff_ffff\n            h1 = (seed_lo ^ length) & 0xffff_ffff\n            h2 = seed_hi & 0xffff_ffff\n            i = 0\n            l = length  # noqa: E741\n            while l >= 8:\n                k1 = struct.unpack_from(\"<I\", data, i)[0]\n                i += 4\n                k1 = (k1 * m) & 0xffff_ffff\n                k1 ^= (k1 >> r)\n                k1 = (k1 * m) & 0xffff_ffff\n                h1 = (h1 * m) & 0xffff_ffff\n                h1 ^= k1\n                h1 &= 0xffff_ffff\n                l -= 4  # noqa: E741\n\n                k2 = struct.unpack_from(\"<I\", data, i)[0]\n                i += 4\n                k2 = (k2 * m) & 0xffff_ffff\n                k2 ^= (k2 >> r)\n                k2 = (k2 * m) & 0xffff_ffff\n                h2 = (h2 * m) & 0xffff_ffff\n                h2 ^= k2\n                h2 &= 0xffff_ffff\n                l -= 4  # noqa: E741\n\n            if l >= 4:\n                k1 = struct.unpack_from(\"<I\", data, i)[0]\n                i += 4\n                k1 = (k1 * m) & 0xffff_ffff\n                k1 ^= (k1 >> r)\n                k1 = (k1 * m) & 0xffff_ffff\n                h1 = (h1 * m) & 0xffff_ffff\n                h1 ^= k1\n                h1 &= 0xffff_ffff\n                l -= 4  # noqa: E741\n\n            tail = data[i:]\n            tl = len(tail)\n            if tl == 3:\n                h2 ^= tail[2] << 16\n                h2 ^= tail[1] << 8\n                h2 ^= tail[0]\n                h2 = (h2 * m) & 0xffff_ffff\n            elif tl == 2:\n                h2 ^= tail[1] << 8\n                h2 ^= tail[0]\n                h2 = (h2 * m) & 0xffff_ffff\n            elif tl == 1:\n                h2 ^= tail[0]\n                h2 = (h2 * m) & 0xffff_ffff\n            else:\n                pass\n\n            h1 ^= (h2 >> 18)\n            h1 = (h1 * m) & 0xffff_ffff\n            h2 ^= (h1 >> 22)\n            h2 = (h2 * m) & 0xffff_ffff\n            h1 ^= (h2 >> 17)\n            h1 = (h1 * m) & 0xffff_ffff\n            h2 ^= (h1 >> 19)\n            h2 = (h2 * m) & 0xffff_ffff\n\n            h = ((h1 & 0xffff_ffff) << 32) | (h2 & 0xffff_ffff)\n            self.h = h & 0xffff_ffff_ffff_ffff\n            return\n\n    class MurmurHash3Base:\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(seed, int):\n                raise TypeError(\"seed must be int\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.seed = seed\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            other.set_state(self.get_state())\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            bs = self.block_size\n            while len(self.buf) >= bs:\n                block = bytes(self.buf[:bs])\n                del self.buf[:bs]\n                self.process_block(block)\n            return self\n\n        def finalize(self):\n            if self.finalized:\n                return\n            tail = bytes(self.buf)\n            self.process_tail(tail)\n            self.finalize_state()\n            self.buf.clear()\n            self.finalized = True\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.pack_digest()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def rol32(self, x, r):\n            x &= 0xffff_ffff\n            return ((x << r) | (x >> (32 - r))) & 0xffff_ffff\n\n        def rol64(self, x, r):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x << r) | (x >> (64 - r))) & 0xffff_ffff_ffff_ffff\n\n    class MurmurHash3_x86_32(MurmurHash3Base):\n        block_size = 4\n        digest_size = 4\n\n        def init_state(self):\n            self.seed &= 0xffff_ffff\n            self.h1 = self.seed\n            return\n\n        def get_state(self):\n            return (self.h1 & 0xffff_ffff,)\n\n        def set_state(self, state):\n            self.h1 = state[0] & 0xffff_ffff\n            return\n\n        def mix_k1(self, k1):\n            c1 = 0xcc9e_2d51\n            c2 = 0x1b87_3593\n            k1 &= 0xffff_ffff\n            k1 = (k1 * c1) & 0xffff_ffff\n            k1 = self.rol32(k1, 15)\n            k1 = (k1 * c2) & 0xffff_ffff\n            return k1\n\n        def process_block(self, block):\n            k1 = struct.unpack(\"<I\", block)[0]\n            self.h1 ^= self.mix_k1(k1)\n            self.h1 = self.rol32(self.h1, 13)\n            self.h1 = (self.h1 * 5 + 0xe654_6b64) & 0xffff_ffff\n            return\n\n        def process_tail(self, tail):\n            tl = len(tail)\n            k1 = 0\n            if tl == 3:\n                k1 ^= tail[2] << 16\n                k1 ^= tail[1] << 8\n                k1 ^= tail[0]\n            elif tl == 2:\n                k1 ^= tail[1] << 8\n                k1 ^= tail[0]\n            elif tl == 1:\n                k1 ^= tail[0]\n            else:\n                k1 = 0\n            if k1 != 0:\n                self.h1 ^= self.mix_k1(k1)\n            return\n\n        def finalize_state(self):\n\n            def fmix32(h):\n                h &= 0xffff_ffff\n                h ^= (h >> 16)\n                h = (h * 0x85eb_ca6b) & 0xffff_ffff\n                h ^= (h >> 13)\n                h = (h * 0xc2b2_ae35) & 0xffff_ffff\n                h ^= (h >> 16)\n                return h & 0xffff_ffff\n\n            self.h1 ^= (self.msg_len & 0xffff_ffff)\n            self.h1 = fmix32(self.h1)\n            return\n\n        def pack_digest(self):\n            return struct.pack(\"<I\", self.h1 & 0xffff_ffff)\n\n        def digest_normalize(self, digest):\n            digest = bytes.fromhex(digest)\n            return str(int.from_bytes(digest[::-1], \"little\"))\n\n    class MurmurHash3_x86_128(MurmurHash3Base):\n        block_size = 16\n        digest_size = 16\n\n        def init_state(self):\n            self.seed &= 0xffff_ffff\n            self.h1 = self.seed\n            self.h2 = self.seed\n            self.h3 = self.seed\n            self.h4 = self.seed\n            return\n\n        def get_state(self):\n            return (\n                self.h1 & 0xffff_ffff,\n                self.h2 & 0xffff_ffff,\n                self.h3 & 0xffff_ffff,\n                self.h4 & 0xffff_ffff,\n            )\n\n        def set_state(self, state):\n            self.h1 = state[0] & 0xffff_ffff\n            self.h2 = state[1] & 0xffff_ffff\n            self.h3 = state[2] & 0xffff_ffff\n            self.h4 = state[3] & 0xffff_ffff\n            return\n\n        def process_block(self, block):\n            k1, k2, k3, k4 = struct.unpack(\"<4I\", block)\n\n            c1 = 0x239b_961b\n            c2 = 0xab0e_9789\n            c3 = 0x38b3_4ae5\n            c4 = 0xa1e3_8b93\n\n            k1 = (k1 * c1) & 0xffff_ffff\n            k1 = self.rol32(k1, 15)\n            k1 = (k1 * c2) & 0xffff_ffff\n            self.h1 ^= k1\n            self.h1 = self.rol32(self.h1, 19)\n            self.h1 = (self.h1 + self.h2) & 0xffff_ffff\n            self.h1 = (self.h1 * 5 + 0x561c_cd1b) & 0xffff_ffff\n\n            k2 = (k2 * c2) & 0xffff_ffff\n            k2 = self.rol32(k2, 16)\n            k2 = (k2 * c3) & 0xffff_ffff\n            self.h2 ^= k2\n            self.h2 = self.rol32(self.h2, 17)\n            self.h2 = (self.h2 + self.h3) & 0xffff_ffff\n            self.h2 = (self.h2 * 5 + 0x0bc_aa747) & 0xffff_ffff\n\n            k3 = (k3 * c3) & 0xffff_ffff\n            k3 = self.rol32(k3, 17)\n            k3 = (k3 * c4) & 0xffff_ffff\n            self.h3 ^= k3\n            self.h3 = self.rol32(self.h3, 15)\n            self.h3 = (self.h3 + self.h4) & 0xffff_ffff\n            self.h3 = (self.h3 * 5 + 0x96cd_1c35) & 0xffff_ffff\n\n            k4 = (k4 * c4) & 0xffff_ffff\n            k4 = self.rol32(k4, 18)\n            k4 = (k4 * c1) & 0xffff_ffff\n            self.h4 ^= k4\n            self.h4 = self.rol32(self.h4, 13)\n            self.h4 = (self.h4 + self.h1) & 0xffff_ffff\n            self.h4 = (self.h4 * 5 + 0x32ac_3b17) & 0xffff_ffff\n            return\n\n        def process_tail(self, tail):\n            tl = len(tail)\n\n            k1 = 0\n            k2 = 0\n            k3 = 0\n            k4 = 0\n\n            c1 = 0x239b_961b\n            c2 = 0xab0e_9789\n            c3 = 0x38b3_4ae5\n            c4 = 0xa1e3_8b93\n\n            if tl >= 15:\n                k4 ^= tail[14] << 16\n            if tl >= 14:\n                k4 ^= tail[13] << 8\n            if tl >= 13:\n                k4 ^= tail[12] << 0\n                k4 = (k4 * c4) & 0xffff_ffff\n                k4 = self.rol32(k4, 18)\n                k4 = (k4 * c1) & 0xffff_ffff\n                self.h4 ^= k4\n\n            if tl >= 12:\n                k3 ^= tail[11] << 24\n            if tl >= 11:\n                k3 ^= tail[10] << 16\n            if tl >= 10:\n                k3 ^= tail[9] << 8\n            if tl >= 9:\n                k3 ^= tail[8] << 0\n                k3 = (k3 * c3) & 0xffff_ffff\n                k3 = self.rol32(k3, 17)\n                k3 = (k3 * c4) & 0xffff_ffff\n                self.h3 ^= k3\n\n            if tl >= 8:\n                k2 ^= tail[7] << 24\n            if tl >= 7:\n                k2 ^= tail[6] << 16\n            if tl >= 6:\n                k2 ^= tail[5] << 8\n            if tl >= 5:\n                k2 ^= tail[4] << 0\n                k2 = (k2 * c2) & 0xffff_ffff\n                k2 = self.rol32(k2, 16)\n                k2 = (k2 * c3) & 0xffff_ffff\n                self.h2 ^= k2\n\n            if tl >= 4:\n                k1 ^= tail[3] << 24\n            if tl >= 3:\n                k1 ^= tail[2] << 16\n            if tl >= 2:\n                k1 ^= tail[1] << 8\n            if tl >= 1:\n                k1 ^= tail[0] << 0\n                k1 = (k1 * c1) & 0xffff_ffff\n                k1 = self.rol32(k1, 15)\n                k1 = (k1 * c2) & 0xffff_ffff\n                self.h1 ^= k1\n            return\n\n        def finalize_state(self):\n\n            def fmix32(h):\n                h &= 0xffff_ffff\n                h ^= (h >> 16)\n                h = (h * 0x85eb_ca6b) & 0xffff_ffff\n                h ^= (h >> 13)\n                h = (h * 0xc2b2_ae35) & 0xffff_ffff\n                h ^= (h >> 16)\n                return h & 0xffff_ffff\n\n            length = self.msg_len & 0xffff_ffff\n            self.h1 ^= length\n            self.h2 ^= length\n            self.h3 ^= length\n            self.h4 ^= length\n            self.h1 = (self.h1 + self.h2 + self.h3 + self.h4) & 0xffff_ffff\n            self.h2 = (self.h2 + self.h1) & 0xffff_ffff\n            self.h3 = (self.h3 + self.h1) & 0xffff_ffff\n            self.h4 = (self.h4 + self.h1) & 0xffff_ffff\n            self.h1 = fmix32(self.h1)\n            self.h2 = fmix32(self.h2)\n            self.h3 = fmix32(self.h3)\n            self.h4 = fmix32(self.h4)\n            self.h1 = (self.h1 + self.h2 + self.h3 + self.h4) & 0xffff_ffff\n            self.h2 = (self.h2 + self.h1) & 0xffff_ffff\n            self.h3 = (self.h3 + self.h1) & 0xffff_ffff\n            self.h4 = (self.h4 + self.h1) & 0xffff_ffff\n            return\n\n        def pack_digest(self):\n            return struct.pack(\"<4I\", self.h1, self.h2, self.h3, self.h4)\n\n        def digest_normalize(self, digest):\n            digest = bytes.fromhex(digest)\n            a, b, c, d = digest[:4], digest[4:8], digest[8:12], digest[12:]\n            return \" \".join(x[::-1].hex() for x in [a, b, c, d])\n\n    class MurmurHash3_x64_128(MurmurHash3Base):\n        block_size = 16\n        digest_size = 16\n        word_bits = [64, 64]\n\n        def init_state(self):\n            self.seed &= 0xffff_ffff_ffff_ffff\n            self.h1 = self.seed\n            self.h2 = self.seed\n            return\n\n        def get_state(self):\n            return (\n                self.h1 & 0xffff_ffff_ffff_ffff,\n                self.h2 & 0xffff_ffff_ffff_ffff,\n            )\n\n        def set_state(self, state):\n            self.h1 = state[0] & 0xffff_ffff_ffff_ffff\n            self.h2 = state[1] & 0xffff_ffff_ffff_ffff\n            return\n\n        def process_block(self, block):\n            k1, k2 = struct.unpack(\"<2Q\", block)\n\n            c1 = 0x87c3_7b91_1142_53d5\n            c2 = 0x4cf5_ad43_2745_937f\n\n            k1 = (k1 * c1) & 0xffff_ffff_ffff_ffff\n            k1 = self.rol64(k1, 31)\n            k1 = (k1 * c2) & 0xffff_ffff_ffff_ffff\n            self.h1 ^= k1\n\n            self.h1 = self.rol64(self.h1, 27)\n            self.h1 = (self.h1 + self.h2) & 0xffff_ffff_ffff_ffff\n            self.h1 = (self.h1 * 5 + 0x52dc_e729) & 0xffff_ffff_ffff_ffff\n\n            k2 = (k2 * c2) & 0xffff_ffff_ffff_ffff\n            k2 = self.rol64(k2, 33)\n            k2 = (k2 * c1) & 0xffff_ffff_ffff_ffff\n            self.h2 ^= k2\n\n            self.h2 = self.rol64(self.h2, 31)\n            self.h2 = (self.h2 + self.h1) & 0xffff_ffff_ffff_ffff\n            self.h2 = (self.h2 * 5 + 0x3849_5ab5) & 0xffff_ffff_ffff_ffff\n            return\n\n        def process_tail(self, tail):\n            tl = len(tail)\n            k1 = 0\n            k2 = 0\n\n            c1 = 0x87c3_7b91_1142_53d5\n            c2 = 0x4cf5_ad43_2745_937f\n\n            if tl >= 15:\n                k2 ^= tail[14] << 48\n            if tl >= 14:\n                k2 ^= tail[13] << 40\n            if tl >= 13:\n                k2 ^= tail[12] << 32\n            if tl >= 12:\n                k2 ^= tail[11] << 24\n            if tl >= 11:\n                k2 ^= tail[10] << 16\n            if tl >= 10:\n                k2 ^= tail[9] << 8\n            if tl >= 9:\n                k2 ^= tail[8] << 0\n\n            if k2 != 0:\n                k2 = (k2 * c2) & 0xffff_ffff_ffff_ffff\n                k2 = self.rol64(k2, 33)\n                k2 = (k2 * c1) & 0xffff_ffff_ffff_ffff\n                self.h2 ^= k2\n\n            if tl >= 8:\n                k1 ^= tail[7] << 56\n            if tl >= 7:\n                k1 ^= tail[6] << 48\n            if tl >= 6:\n                k1 ^= tail[5] << 40\n            if tl >= 5:\n                k1 ^= tail[4] << 32\n            if tl >= 4:\n                k1 ^= tail[3] << 24\n            if tl >= 3:\n                k1 ^= tail[2] << 16\n            if tl >= 2:\n                k1 ^= tail[1] << 8\n            if tl >= 1:\n                k1 ^= tail[0] << 0\n\n            if k1 != 0:\n                k1 = (k1 * c1) & 0xffff_ffff_ffff_ffff\n                k1 = self.rol64(k1, 31)\n                k1 = (k1 * c2) & 0xffff_ffff_ffff_ffff\n                self.h1 ^= k1\n            return\n\n        def finalize_state(self):\n\n            def fmix64(k):\n                k &= 0xffff_ffff_ffff_ffff\n                k ^= (k >> 33)\n                k = (k * 0xff51_afd7_ed55_8ccd) & 0xffff_ffff_ffff_ffff\n                k ^= (k >> 33)\n                k = (k * 0xc4ce_b9fe_1a85_ec53) & 0xffff_ffff_ffff_ffff\n                k ^= (k >> 33)\n                return k & 0xffff_ffff_ffff_ffff\n\n            length = self.msg_len & 0xffff_ffff_ffff_ffff\n            self.h1 ^= length\n            self.h2 ^= length\n            self.h1 = (self.h1 + self.h2) & 0xffff_ffff_ffff_ffff\n            self.h2 = (self.h2 + self.h1) & 0xffff_ffff_ffff_ffff\n            self.h1 = fmix64(self.h1)\n            self.h2 = fmix64(self.h2)\n            self.h1 = (self.h1 + self.h2) & 0xffff_ffff_ffff_ffff\n            self.h2 = (self.h2 + self.h1) & 0xffff_ffff_ffff_ffff\n            return\n\n        def pack_digest(self):\n            return struct.pack(\"<2Q\", self.h1, self.h2)\n\n        def digest_normalize(self, digest):\n            digest = bytes.fromhex(digest)\n            a, b = digest[:8], digest[8:]\n            return \" \".join(x[::-1].hex() for x in [a, b])\n\n    class FORK256:\n        block_size = 64   # 512 bits\n        digest_size = 32  # 256 bits\n\n        def __init__(self, data=b\"\"):\n            # IV0 (same as SHA-256 IV)\n            self.h0 = 0x6a09_e667\n            self.h1 = 0xbb67_ae85\n            self.h2 = 0x3c6e_f372\n            self.h3 = 0xa54f_f53a\n            self.h4 = 0x510e_527f\n            self.h5 = 0x9b05_688c\n            self.h6 = 0x1f83_d9ab\n            self.h7 = 0x5be0_cd19\n\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h0 = self.h0\n            other.h1 = self.h1\n            other.h2 = self.h2\n            other.h3 = self.h3\n            other.h4 = self.h4\n            other.h5 = self.h5\n            other.h6 = self.h6\n            other.h7 = self.h7\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return struct.pack(\">8I\", c.h0, c.h1, c.h2, c.h3, c.h4, c.h5, c.h6, c.h7)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n\n            self.buf.append(0x80)\n            while (len(self.buf) % 64) != 56:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\">Q\", bit_len))\n\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return\n\n        def step(self, v, m0, m1, alpha, beta):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            def add32(a, b):\n                return (a + b) & 0xffff_ffff\n\n            def add32_3(a, b, c):\n                return (a + b + c) & 0xffff_ffff\n\n            def f(x):\n                # f(x) = x + (x<<<7 XOR x<<<22)\n                return add32(x, rol32(x, 7) ^ rol32(x, 22))\n\n            def g(x):\n                # g(x) = x XOR (x<<<13 + x<<<27)\n                return (x ^ add32(rol32(x, 13), rol32(x, 27))) & 0xffff_ffff\n\n            av, bv, cv, dv, ev, fv, gv, hv = v\n\n            ae = add32(av, m0)\n            ee = add32(ev, m1)\n            ae_alpha = add32(ae, alpha)\n            ee_beta = add32(ee, beta)\n\n            a1 = add32(hv, rol32(g(ee), 21)) ^ rol32(f(ee_beta), 17)\n            b1 = add32_3(av, m0, alpha)\n            c1 = add32(bv, f(ae)) ^ g(ae_alpha)\n            d1 = add32(cv, rol32(f(ae), 5)) ^ rol32(g(ae_alpha), 9)\n            e1 = add32(dv, rol32(f(ae), 17)) ^ rol32(g(ae_alpha), 21)\n            f1 = add32_3(ev, m1, beta)\n            g1 = add32(fv, g(ee)) ^ f(ee_beta)\n            h1 = add32(gv, rol32(g(ee), 9)) ^ rol32(f(ee_beta), 5)\n\n            return [\n                a1 & 0xffff_ffff,\n                b1 & 0xffff_ffff,\n                c1 & 0xffff_ffff,\n                d1 & 0xffff_ffff,\n                e1 & 0xffff_ffff,\n                f1 & 0xffff_ffff,\n                g1 & 0xffff_ffff,\n                h1 & 0xffff_ffff,\n            ]\n\n        def compress(self, block):\n\n            def add_words(x, y):\n                return [(x[i] + y[i]) & 0xffff_ffff for i in range(8)]\n\n            def xor_words(x, y):\n                return [(x[i] ^ y[i]) & 0xffff_ffff for i in range(8)]\n\n            m = list(struct.unpack(\">16I\", block))\n\n            sigma = [\n                [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F],\n                [0x0E, 0x0F, 0x0B, 0x09, 0x08, 0x0A, 0x03, 0x04, 0x02, 0x0D, 0x00, 0x05, 0x06, 0x07, 0x0C, 0x01],\n                [0x07, 0x06, 0x0A, 0x0E, 0x0D, 0x02, 0x09, 0x0C, 0x0B, 0x04, 0x0F, 0x08, 0x05, 0x00, 0x01, 0x03],\n                [0x05, 0x0C, 0x01, 0x08, 0x0F, 0x00, 0x0D, 0x0B, 0x03, 0x0A, 0x09, 0x02, 0x07, 0x0E, 0x04, 0x06],\n            ]\n\n            delta = [\n                0x428a_2f98, 0x7137_4491, 0xb5c0_fbcf, 0xe9b5_dba5,\n                0x3956_c25b, 0x59f1_11f1, 0x923f_82a4, 0xab1c_5ed5,\n                0xd807_aa98, 0x1283_5b01, 0x2431_85be, 0x550c_7dc3,\n                0x72be_5d74, 0x80de_b1fe, 0x9bdc_06a7, 0xc19b_f174,\n            ]\n\n            # alpha/beta table per (branch, step)\n            ab = [\n                # branch 1\n                [(delta[0], delta[1]), (delta[2], delta[3]), (delta[4], delta[5]), (delta[6], delta[7]),\n                 (delta[8], delta[9]), (delta[10], delta[11]), (delta[12], delta[13]), (delta[14], delta[15])],\n                # branch 2\n                [(delta[15], delta[14]), (delta[13], delta[12]), (delta[11], delta[10]), (delta[9], delta[8]),\n                 (delta[7], delta[6]), (delta[5], delta[4]), (delta[3], delta[2]), (delta[1], delta[0])],\n                # branch 3\n                [(delta[1], delta[0]), (delta[3], delta[2]), (delta[5], delta[4]), (delta[7], delta[6]),\n                 (delta[9], delta[8]), (delta[11], delta[10]), (delta[13], delta[12]), (delta[15], delta[14])],\n                # branch 4\n                [(delta[14], delta[15]), (delta[12], delta[13]), (delta[10], delta[11]), (delta[8], delta[9]),\n                 (delta[6], delta[7]), (delta[4], delta[5]), (delta[2], delta[3]), (delta[0], delta[1])],\n            ]\n\n            cv = [self.h0, self.h1, self.h2, self.h3, self.h4, self.h5, self.h6, self.h7]\n\n            outs = []\n            for j in range(4):\n                v = list(cv)\n                perm = sigma[j]\n                for k in range(8):\n                    m0 = m[perm[2 * k]]\n                    m1 = m[perm[2 * k + 1]]\n                    alpha, beta = ab[j][k]\n                    v = self.step(v, m0, m1, alpha, beta)\n                outs.append(v)\n\n            t12 = add_words(outs[0], outs[1])\n            t34 = add_words(outs[2], outs[3])\n            mixed = xor_words(t12, t34)\n            new_cv = add_words(cv, mixed)\n\n            self.h0, self.h1, self.h2, self.h3, self.h4, self.h5, self.h6, self.h7 = new_cv\n            return\n\n    class BELT:\n        block_size = 32\n        digest_size = 32\n        h5 = (\n            0x0000_1620, 0x0000_1280, 0x0000_1740, 0x0000_1900, 0x0000_0140, 0x0000_0100, 0x0000_1ea0, 0x0000_0760,\n            0x0000_06c0, 0x0000_0da0, 0x0000_0000, 0x0000_11c0, 0x0000_0b00, 0x0000_0940, 0x0000_0ba0, 0x0000_1c80,\n            0x0000_10a0, 0x0000_0080, 0x0000_1f40, 0x0000_13a0, 0x0000_0360, 0x0000_16c0, 0x0000_18e0, 0x0000_1580,\n            0x0000_04a0, 0x0000_05c0, 0x0000_0e40, 0x0000_1840, 0x0000_0040, 0x0000_1fa0, 0x0000_19c0, 0x0000_01a0,\n            0x0000_0b60, 0x0000_1c60, 0x0000_1ac0, 0x0000_0240, 0x0000_02e0, 0x0000_1720, 0x0000_0c20, 0x0000_1020,\n            0x0000_1fc0, 0x0000_0ce0, 0x0000_10c0, 0x0000_15a0, 0x0000_0e20, 0x0000_0d60, 0x0000_1120, 0x0000_0160,\n            0x0000_0b80, 0x0000_1600, 0x0000_1800, 0x0000_1fe0, 0x0000_0660, 0x0000_1860, 0x0000_0ac0, 0x0000_1700,\n            0x0000_06a0, 0x0000_1880, 0x0000_00a0, 0x0000_15c0, 0x0000_1b00, 0x0000_1c00, 0x0000_0fe0, 0x0000_1320,\n            0x0000_1c20, 0x0000_0560, 0x0000_1b80, 0x0000_0340, 0x0000_1c40, 0x0000_1040, 0x0000_0ae0, 0x0000_1d80,\n            0x0000_0e00, 0x0000_07e0, 0x0000_1980, 0x0000_1e00, 0x0000_12a0, 0x0000_1dc0, 0x0000_11a0, 0x0000_1e20,\n            0x0000_1820, 0x0000_1560, 0x0000_0ec0, 0x0000_0700, 0x0000_13e0, 0x0000_1cc0, 0x0000_0f00, 0x0000_1940,\n            0x0000_1ee0, 0x0000_18c0, 0x0000_1f00, 0x0000_0c00, 0x0000_1aa0, 0x0000_1760, 0x0000_1380, 0x0000_09e0,\n            0x0000_1e60, 0x0000_0780, 0x0000_0ca0, 0x0000_0f60, 0x0000_0c60, 0x0000_0f80, 0x0000_0600, 0x0000_0d40,\n            0x0000_1ba0, 0x0000_09c0, 0x0000_14e0, 0x0000_0f20, 0x0000_13c0, 0x0000_1640, 0x0000_07a0, 0x0000_0620,\n            0x0000_07c0, 0x0000_1300, 0x0000_16a0, 0x0000_0dc0, 0x0000_04e0, 0x0000_1a60, 0x0000_1780, 0x0000_19e0,\n            0x0000_0b20, 0x0000_03c0, 0x0000_0300, 0x0000_03e0, 0x0000_0980, 0x0000_0b40, 0x0000_16e0, 0x0000_1260,\n            0x0000_1d20, 0x0000_1bc0, 0x0000_1ce0, 0x0000_0580, 0x0000_11e0, 0x0000_0180, 0x0000_01e0, 0x0000_14c0,\n            0x0000_05a0, 0x0000_1b60, 0x0000_0920, 0x0000_1e80, 0x0000_0de0, 0x0000_0e60, 0x0000_12c0, 0x0000_08e0,\n            0x0000_00c0, 0x0000_00e0, 0x0000_0a60, 0x0000_02c0, 0x0000_1da0, 0x0000_0480, 0x0000_0f40, 0x0000_06e0,\n            0x0000_0720, 0x0000_1960, 0x0000_1460, 0x0000_1060, 0x0000_0060, 0x0000_1520, 0x0000_1160, 0x0000_1ec0,\n            0x0000_1240, 0x0000_17a0, 0x0000_1360, 0x0000_0380, 0x0000_1ca0, 0x0000_1a20, 0x0000_0820, 0x0000_0020,\n            0x0000_0a80, 0x0000_08a0, 0x0000_1f60, 0x0000_1920, 0x0000_0bc0, 0x0000_09a0, 0x0000_01c0, 0x0000_1e40,\n            0x0000_0d00, 0x0000_0400, 0x0000_1000, 0x0000_1540, 0x0000_0440, 0x0000_0fa0, 0x0000_0c80, 0x0000_05e0,\n            0x0000_04c0, 0x0000_10e0, 0x0000_1f20, 0x0000_0680, 0x0000_1200, 0x0000_0800, 0x0000_0aa0, 0x0000_0220,\n            0x0000_17c0, 0x0000_0640, 0x0000_12e0, 0x0000_0260, 0x0000_0860, 0x0000_1f80, 0x0000_1340, 0x0000_0900,\n            0x0000_1400, 0x0000_0540, 0x0000_1100, 0x0000_0be0, 0x0000_0320, 0x0000_0960, 0x0000_0120, 0x0000_1420,\n            0x0000_0fc0, 0x0000_19a0, 0x0000_1480, 0x0000_1a00, 0x0000_02a0, 0x0000_0880, 0x0000_15e0, 0x0000_1180,\n            0x0000_14a0, 0x0000_1080, 0x0000_0a00, 0x0000_17e0, 0x0000_0cc0, 0x0000_1a40, 0x0000_1d00, 0x0000_1140,\n            0x0000_1440, 0x0000_1ae0, 0x0000_08c0, 0x0000_0a40, 0x0000_0840, 0x0000_1500, 0x0000_1be0, 0x0000_1660,\n            0x0000_0d20, 0x0000_0e80, 0x0000_18a0, 0x0000_0a20, 0x0000_1d60, 0x0000_0460, 0x0000_0520, 0x0000_0420,\n            0x0000_1a80, 0x0000_1de0, 0x0000_1b20, 0x0000_1680, 0x0000_0740, 0x0000_0c40, 0x0000_0500, 0x0000_0ea0,\n            0x0000_1220, 0x0000_0280, 0x0000_0200, 0x0000_1d40, 0x0000_0ee0, 0x0000_0d80, 0x0000_1b40, 0x0000_03a0\n        )\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.r = 0\n            self.s = [0, 0, 0, 0]\n            self.h = [\n                0xc8ba_94b1, 0x3bf5_080a, 0x8e00_6d36, 0xe45d_4a58, 0x9dfa_0485, 0xacc7_b61b, 0xc272_2e25, 0x0dce_fd02,\n            ]\n            self.buf = bytearray()\n            self.done = False\n            self.out = None\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.r = self.r\n            other.s = list(self.s)\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.done = self.done\n            other.out = None if self.out is None else list(self.out)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.done:\n                raise ValueError(\"hash context is finalized\")\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.r += 1\n                self.compress_block(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytearray()\n            for w in c.out:\n                out.extend(w.to_bytes(4, \"little\"))\n            return bytes(out)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n\n            def encode_r(r_bits):\n                r = int(r_bits)\n                return [\n                    (r & 0xffff_ffff),\n                    ((r >> 32) & 0xffff_ffff),\n                    ((r >> 64) & 0xffff_ffff),\n                    ((r >> 96) & 0xffff_ffff),\n                ]\n\n            if self.done:\n                return\n            pos = len(self.buf)\n            if pos != 0:\n                block = bytes(self.buf) + b\"\\x00\" * (self.block_size - pos)\n                self.buf.clear()\n                self.compress_block(block)\n            bit_len = (self.r * self.block_size + pos) * 8\n            r_words = encode_r(bit_len)\n            _, y = self.belt_compress(r_words, self.s, self.h)\n            self.out = y\n            self.done = True\n            return\n\n        def compress_block(self, block):\n\n            def u32le(data, i):\n                return int.from_bytes(data[4 * i : 4 * i + 4], \"little\")\n\n            x1 = [\n                u32le(block, 0),\n                u32le(block, 1),\n                u32le(block, 2),\n                u32le(block, 3),\n            ]\n            x2 = [\n                u32le(block, 4),\n                u32le(block, 5),\n                u32le(block, 6),\n                u32le(block, 7),\n            ]\n            t, h = self.belt_compress(x1, x2, self.h)\n            self.h = h\n            self.s = [(self.s[i] ^ t[i]) & 0xffff_ffff for i in range(4)]\n            return\n\n        def belt_block_raw(self, x, key):\n\n            def key_idx(key, i, delta):\n                return key[(7 * i - delta - 1) % 8] & 0xffff_ffff\n\n            def h13_entry(i):\n                return (h5[i] << 8) & 0xffff_ffff\n\n            def h21_entry(i):\n                return (h5[i] << 16) & 0xffff_ffff\n\n            def h29_entry(i):\n                v = h5[i] & 0xffff_ffff\n                return ((v >> 8) | ((v & 0xff) << 24)) & 0xffff_ffff\n\n            def g5(u):\n                return (\n                    h29_entry((u >> 24) & 0xff) ^ h21_entry((u >> 16) & 0xff) ^ h13_entry((u >> 8) & 0xff) ^ h5[u & 0xff]\n                ) & 0xffff_ffff\n\n            def g13(u):\n                return (\n                    h5[(u >> 24) & 0xff] ^ h29_entry((u >> 16) & 0xff) ^ h21_entry((u >> 8) & 0xff) ^ h13_entry(u & 0xff)\n                ) & 0xffff_ffff\n\n            def g21(u):\n                return (\n                    h13_entry((u >> 24) & 0xff) ^ h5[(u >> 16) & 0xff] ^ h29_entry((u >> 8) & 0xff) ^ h21_entry(u & 0xff)\n                ) & 0xffff_ffff\n\n            h5 = self.h5\n            a = x[0] & 0xffff_ffff\n            b = x[1] & 0xffff_ffff\n            c = x[2] & 0xffff_ffff\n            d = x[3] & 0xffff_ffff\n\n            for i in range(1, 9):\n                b ^= g5(a + key_idx(key, i, 6))\n                c ^= g21(d + key_idx(key, i, 5))\n                a = (a - g13(b + key_idx(key, i, 4))) & 0xffff_ffff\n                e = (g21(b + c + key_idx(key, i, 3)) ^ i) & 0xffff_ffff\n                b = (b + e) & 0xffff_ffff\n                c = (c - e) & 0xffff_ffff\n                d = (d + g13(c + key_idx(key, i, 2))) & 0xffff_ffff\n                b ^= g21(a + key_idx(key, i, 1))\n                c ^= g5(d + key_idx(key, i, 0))\n                a, b, c, d = b, d, a, c\n\n            return [b & 0xffff_ffff, d & 0xffff_ffff, a & 0xffff_ffff, c & 0xffff_ffff]\n\n        def belt_compress(self, x1, x2, x34):\n\n            def xor4(a, b):\n                return [\n                    (a[0] ^ b[0]) & 0xffff_ffff,\n                    (a[1] ^ b[1]) & 0xffff_ffff,\n                    (a[2] ^ b[2]) & 0xffff_ffff,\n                    (a[3] ^ b[3]) & 0xffff_ffff,\n                ]\n\n            def concat4(a, b):\n                return [a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]]\n\n            x3 = [x34[0], x34[1], x34[2], x34[3]]\n            x4 = [x34[4], x34[5], x34[6], x34[7]]\n\n            t1 = self.belt_block_raw(xor4(x3, x4), concat4(x1, x2))\n            s = xor4(xor4(t1, x3), x4)\n            t2 = self.belt_block_raw(x1, concat4(s, x4))\n            y1 = xor4(t2, x1)\n            s_inv = [(~v) & 0xffff_ffff for v in s]\n            t3 = self.belt_block_raw(x2, concat4(s_inv, x3))\n            y2 = xor4(t3, x2)\n            return (s, concat4(y1, y2))\n\n    class CityFarmBase:\n        # CityHash/FarmHash 64-bit constants\n        k0 = 0xc3a5_c85c_97cb_3127\n        k1 = 0xb492_b66f_be98_f273\n        k2 = 0x9ae1_6a3b_2f90_404f\n\n        # Murmur3 32-bit constants\n        c1 = 0xcc9e_2d51\n        c2 = 0x1b87_3593\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.data = data\n            self.seed = seed\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.data += data\n            return\n\n        def ror32(self, x, r):\n            x &= 0xffff_ffff\n            r &= 31\n            if r == 0:\n                return x\n            return ((x >> r) | (x << (32 - r))) & 0xffff_ffff\n\n        def ror64(self, x, r):\n            x &= 0xffff_ffff_ffff_ffff\n            r &= 63\n            if r == 0:\n                return x\n            return ((x >> r) | (x << (64 - r))) & 0xffff_ffff_ffff_ffff\n\n        def u32le(self, data, off):\n            return int.from_bytes(data[off:off + 4], \"little\", signed=False)\n\n        def u64le(self, data, off):\n            return int.from_bytes(data[off:off + 8], \"little\", signed=False)\n\n        def bswap32(self, x):\n            return (\n                ((x & 0x0000_00ff) << 24)\n                | ((x & 0x0000_ff00) << 8)\n                | ((x & 0x00ff_0000) >> 8)\n                | ((x & 0xff00_0000) >> 24)\n            )\n\n        def bswap64(self, x):\n            return (\n                ((x & 0x0000_0000_0000_00ff) << 56)\n                | ((x & 0x0000_0000_0000_ff00) << 40)\n                | ((x & 0x0000_0000_00ff_0000) << 24)\n                | ((x & 0x0000_0000_ff00_0000) << 8)\n                | ((x & 0x0000_00ff_0000_0000) >> 8)\n                | ((x & 0x0000_ff00_0000_0000) >> 24)\n                | ((x & 0x00ff_0000_0000_0000) >> 40)\n                | ((x & 0xff00_0000_0000_0000) >> 56)\n            )\n\n    class CityHash32(CityFarmBase):\n        digest_size = 4\n\n        def hexdigest(self):\n            value = self.cityhash32(self.data)\n            return f\"{value:08x}\"\n\n        def cityhash32_fmix(self, h):\n            h &= 0xffff_ffff\n            h ^= (h >> 16)\n            h = (h * 0x85eb_ca6b) & 0xffff_ffff\n            h ^= (h >> 13)\n            h = (h * 0xc2b2_ae35) & 0xffff_ffff\n            h ^= (h >> 16)\n            return h & 0xffff_ffff\n\n        def cityhash32_mur(self, a, h):\n            a &= 0xffff_ffff\n            h &= 0xffff_ffff\n            a = (a * self.c1) & 0xffff_ffff\n            a = self.ror32(a, 17)\n            a = (a * self.c2) & 0xffff_ffff\n            h ^= a\n            h = self.ror32(h, 19)\n            h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n            return h & 0xffff_ffff\n\n        def cityhash32_len0to4(self, data, seed):\n\n            def signed_byte(b):\n                if b >= 128:\n                    return b - 256\n                return b\n\n            b = seed & 0xffff_ffff\n            c = 9\n            n = len(data)\n            for i in range(n):\n                v = signed_byte(data[i]) & 0xffff_ffff\n                b = (b * self.c1 + v) & 0xffff_ffff\n                c ^= b\n            return self.cityhash32_fmix(\n                self.cityhash32_mur(\n                    b, self.cityhash32_mur(n, c)\n                )\n            )\n\n        def cityhash32_len5to12(self, data, seed):\n            seed &= 0xffff_ffff\n            n = len(data)\n            a = n & 0xffff_ffff\n            b = (a * 5) & 0xffff_ffff\n            c = 9\n            d = (b + seed) & 0xffff_ffff\n            a = (a + self.u32le(data, 0)) & 0xffff_ffff\n            b = (b + self.u32le(data, n - 4)) & 0xffff_ffff\n            c = (c + self.u32le(data, (n >> 1) & 4)) & 0xffff_ffff\n            return self.cityhash32_fmix(\n                self.cityhash32_mur(\n                    c, self.cityhash32_mur(\n                        b, self.cityhash32_mur(a, d)\n                    )\n                ) ^ seed\n            )\n\n        def cityhash32_len13to24(self, data):\n            n = len(data)\n            a = self.u32le(data, (n >> 1) - 4)\n            b = self.u32le(data, 4)\n            c = self.u32le(data, n - 8)\n            d = self.u32le(data, n >> 1)\n            e = self.u32le(data, 0)\n            f = self.u32le(data, n - 4)\n            h = n & 0xffff_ffff\n            return self.cityhash32_fmix(\n                self.cityhash32_mur(\n                    f, self.cityhash32_mur(\n                        e, self.cityhash32_mur(\n                            d, self.cityhash32_mur(\n                                c, self.cityhash32_mur(\n                                    b, self.cityhash32_mur(a, h)\n                                )\n                            )\n                        )\n                    )\n                )\n            )\n\n        def cityhash32(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            if n <= 24:\n                if n <= 12:\n                    if n <= 4:\n                        return self.cityhash32_len0to4(data, 0)\n                    return self.cityhash32_len5to12(data, 0)\n                return self.cityhash32_len13to24(data)\n\n            h = n & 0xffff_ffff\n            g = (self.c1 * h) & 0xffff_ffff\n            f = g\n\n            a0 = (self.ror32(self.u32le(data, n - 4) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a1 = (self.ror32(self.u32le(data, n - 8) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a2 = (self.ror32(self.u32le(data, n - 16) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a3 = (self.ror32(self.u32le(data, n - 12) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a4 = (self.ror32(self.u32le(data, n - 20) * self.c1, 17) * self.c2) & 0xffff_ffff\n\n            h ^= a0\n            h = self.ror32(h, 19)\n            h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n            h ^= a2\n            h = self.ror32(h, 19)\n            h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n\n            g ^= a1\n            g = self.ror32(g, 19)\n            g = (g * 5 + 0xe654_6b64) & 0xffff_ffff\n            g ^= a3\n            g = self.ror32(g, 19)\n            g = (g * 5 + 0xe654_6b64) & 0xffff_ffff\n\n            f = (f + a4) & 0xffff_ffff\n            f = self.ror32(f, 19)\n            f = (f * 5 + 0xe654_6b64) & 0xffff_ffff\n\n            iters = (n - 1) // 20\n            off = 0\n            while iters != 0:\n                a0 = (self.ror32(self.u32le(data, off) * self.c1, 17) * self.c2) & 0xffff_ffff\n                a1 = self.u32le(data, off + 4)\n                a2 = (self.ror32(self.u32le(data, off + 8) * self.c1, 17) * self.c2) & 0xffff_ffff\n                a3 = (self.ror32(self.u32le(data, off + 12) * self.c1, 17) * self.c2) & 0xffff_ffff\n                a4 = self.u32le(data, off + 16)\n\n                h ^= a0\n                h = self.ror32(h, 18)\n                h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n\n                f = (f + a1) & 0xffff_ffff\n                f = self.ror32(f, 19)\n                f = (f * self.c1) & 0xffff_ffff\n\n                g = (g + a2) & 0xffff_ffff\n                g = self.ror32(g, 18)\n                g = (g * 5 + 0xe654_6b64) & 0xffff_ffff\n\n                h ^= (a3 + a1) & 0xffff_ffff\n                h = self.ror32(h, 19)\n                h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n\n                g ^= a4\n                g = (self.bswap32(g) * 5) & 0xffff_ffff\n\n                h = (h + a4 * 5) & 0xffff_ffff\n                h = self.bswap32(h)\n\n                f = (f + a0) & 0xffff_ffff\n                f, h, g = g, f, h\n\n                off += 20\n                iters -= 1\n\n            g = (self.ror32(g, 11) * self.c1) & 0xffff_ffff\n            g = (self.ror32(g, 17) * self.c1) & 0xffff_ffff\n            f = (self.ror32(f, 11) * self.c1) & 0xffff_ffff\n            f = (self.ror32(f, 17) * self.c1) & 0xffff_ffff\n\n            h = self.ror32(h + g, 19)\n            h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n            h = (self.ror32(h, 17) * self.c1) & 0xffff_ffff\n\n            h = self.ror32(h + f, 19)\n            h = (h * 5 + 0xe654_6b64) & 0xffff_ffff\n            h = (self.ror32(h, 17) * self.c1) & 0xffff_ffff\n            return h & 0xffff_ffff\n\n    class CityHash64(CityFarmBase):\n        digest_size = 8\n\n        def hexdigest(self):\n            if self.seed:\n                value = self.cityhash64_with_seed(self.data, self.seed)\n            else:\n                value = self.cityhash64(self.data)\n            return f\"{value:016x}\"\n\n        def shift_mix(self, x):\n            x &= 0xffff_ffff_ffff_ffff\n            return x ^ (x >> 47)\n\n        def cityhash64_len16_mul(self, u, v, mul):\n            u &= 0xffff_ffff_ffff_ffff\n            v &= 0xffff_ffff_ffff_ffff\n            mul &= 0xffff_ffff_ffff_ffff\n            a = ((u ^ v) * mul) & 0xffff_ffff_ffff_ffff\n            a ^= (a >> 47)\n            b = ((v ^ a) * mul) & 0xffff_ffff_ffff_ffff\n            b ^= (b >> 47)\n            b = (b * mul) & 0xffff_ffff_ffff_ffff\n            return b & 0xffff_ffff_ffff_ffff\n\n        def cityhash64_len16(self, u, v):\n            return self.cityhash64_len16_mul(u, v, 0x9ddf_ea08_eb38_2d69)\n\n        def cityhash64_len0to16(self, data):\n            n = len(data)\n            if n >= 8:\n                mul = (self.k2 + n * 2) & 0xffff_ffff_ffff_ffff\n                a = (self.u64le(data, 0) + self.k2) & 0xffff_ffff_ffff_ffff\n                b = self.u64le(data, n - 8)\n                c = (self.ror64(b, 37) * mul + a) & 0xffff_ffff_ffff_ffff\n                d = ((self.ror64(a, 25) + b) * mul) & 0xffff_ffff_ffff_ffff\n                return self.cityhash64_len16_mul(c, d, mul)\n            if n >= 4:\n                mul = (self.k2 + n * 2) & 0xffff_ffff_ffff_ffff\n                a = self.u32le(data, 0)\n                return self.cityhash64_len16_mul(n + (a << 3), self.u32le(data, n - 4), mul)\n            if n > 0:\n                a = data[0]\n                b = data[n >> 1]\n                c = data[n - 1]\n                y = a + (b << 8)\n                z = n + (c << 2)\n                return (self.shift_mix((y * self.k2) ^ (z * self.k0)) * self.k2) & 0xffff_ffff_ffff_ffff\n            return self.k2 & 0xffff_ffff_ffff_ffff\n\n        def cityhash64_len17to32(self, data):\n            n = len(data)\n            mul = (self.k2 + n * 2) & 0xffff_ffff_ffff_ffff\n            a = (self.u64le(data, 0) * self.k1) & 0xffff_ffff_ffff_ffff\n            b = self.u64le(data, 8)\n            c = (self.u64le(data, n - 8) * mul) & 0xffff_ffff_ffff_ffff\n            d = (self.u64le(data, n - 16) * self.k2) & 0xffff_ffff_ffff_ffff\n            return self.cityhash64_len16_mul(\n                self.ror64(a + b, 43) + self.ror64(c, 30) + d,\n                a + self.ror64(b + self.k2, 18) + c,\n                mul,\n            )\n\n        def cityhash64_len33to64(self, data):\n            n = len(data)\n            mul = (self.k2 + n * 2) & 0xffff_ffff_ffff_ffff\n            a = (self.u64le(data, 0) * self.k2) & 0xffff_ffff_ffff_ffff\n            b = self.u64le(data, 8)\n            c = self.u64le(data, n - 24)\n            d = self.u64le(data, n - 32)\n            e = (self.u64le(data, 16) * self.k2) & 0xffff_ffff_ffff_ffff\n            f = (self.u64le(data, 24) * 9) & 0xffff_ffff_ffff_ffff\n            g = self.u64le(data, n - 8)\n            h = (self.u64le(data, n - 16) * mul) & 0xffff_ffff_ffff_ffff\n\n            u = (self.ror64(a + g, 43) + (self.ror64(b, 30) + c) * 9) & 0xffff_ffff_ffff_ffff\n            v = (((a + g) ^ d) + f + 1) & 0xffff_ffff_ffff_ffff\n            w = (self.bswap64((u + v) * mul) + h) & 0xffff_ffff_ffff_ffff\n            x = (self.ror64(e + f, 42) + c) & 0xffff_ffff_ffff_ffff\n            y = ((self.bswap64((v + w) * mul) + g) * mul) & 0xffff_ffff_ffff_ffff\n            z = (e + f + c) & 0xffff_ffff_ffff_ffff\n\n            a2 = (self.bswap64((x + z) * mul + y) + b) & 0xffff_ffff_ffff_ffff\n            b2 = (self.shift_mix((z + a2) * mul + d + h) * mul) & 0xffff_ffff_ffff_ffff\n            return (b2 + x) & 0xffff_ffff_ffff_ffff\n\n        def cityhash64(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            if n <= 32:\n                if n <= 16:\n                    return self.cityhash64_len0to16(data)\n                return self.cityhash64_len17to32(data)\n            if n <= 64:\n                return self.cityhash64_len33to64(data)\n\n            x = self.u64le(data, n - 40)\n            y = (self.u64le(data, n - 16) + self.u64le(data, n - 56)) & 0xffff_ffff_ffff_ffff\n            z = self.cityhash64_len16(self.u64le(data, n - 48) + n, self.u64le(data, n - 24))\n            v = self.cityhash64_weak_hash_len32_with_seeds(data, n - 64, n, z)\n            w = self.cityhash64_weak_hash_len32_with_seeds(data, n - 32, y + self.k1, x)\n            x = (x * self.k1 + self.u64le(data, 0)) & 0xffff_ffff_ffff_ffff\n\n            length = (n - 1) & ~63\n            off = 0\n            while length != 0:\n                x = (self.ror64(x + y + v[0] + self.u64le(data, off + 8), 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                y = (self.ror64(y + v[1] + self.u64le(data, off + 48), 42) * self.k1) & 0xffff_ffff_ffff_ffff\n                x ^= w[1]\n                y = (y + v[0] + self.u64le(data, off + 40)) & 0xffff_ffff_ffff_ffff\n                z = (self.ror64(z + w[0], 33) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off, v[1] * self.k1, x + w[0],\n                )\n                w = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off + 32, z + w[1], y + self.u64le(data, off + 16),\n                )\n                x, z = z, x\n                off += 64\n                length -= 64\n\n            return self.cityhash64_len16(\n                self.cityhash64_len16(v[0], w[0]) + self.shift_mix(y) * self.k1 + z,\n                self.cityhash64_len16(v[1], w[1]) + x,\n            )\n\n        def cityhash64_with_seeds(self, data, seed0, seed1):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            seed0 &= 0xffff_ffff_ffff_ffff\n            seed1 &= 0xffff_ffff_ffff_ffff\n            return self.cityhash64_len16(self.cityhash64(data) - seed0, seed1)\n\n        def cityhash64_with_seed(self, data, seed):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            seed &= 0xffff_ffff_ffff_ffff\n            return self.cityhash64_with_seeds(data, self.k2, seed)\n\n        def cityhash64_weak_hash_len32_with_seeds(self, data, off, a, b):\n            w = self.u64le(data, off)\n            x = self.u64le(data, off + 8)\n            y = self.u64le(data, off + 16)\n            z = self.u64le(data, off + 24)\n\n            a = (a + w) & 0xffff_ffff_ffff_ffff\n            b = self.ror64(b + a + z, 21)\n            c = a\n            a = (a + x + y) & 0xffff_ffff_ffff_ffff\n            b = (b + self.ror64(a, 44)) & 0xffff_ffff_ffff_ffff\n            return ((a + z) & 0xffff_ffff_ffff_ffff, (b + c) & 0xffff_ffff_ffff_ffff)\n\n    class CityHash128(CityHash64):\n        digest_size = 16\n\n        def hexdigest(self):\n            if self.seed:\n                if isinstance(self.seed, tuple) and len(self.seed) == 2:\n                    seed_lo, seed_hi = self.seed\n                else:\n                    seed_lo, seed_hi = self.seed, self.seed\n                lo, hi = self.cityhash128_with_seed(self.data, seed_lo, seed_hi)\n            else:\n                lo, hi = self.cityhash128(self.data)\n            return f\"{lo & 0xffff_ffff_ffff_ffff:016x}{hi & 0xffff_ffff_ffff_ffff:016x}\"\n\n        def cityhash128_murmur(self, data, seed_lo, seed_hi):\n            a = seed_lo & 0xffff_ffff_ffff_ffff\n            b = seed_hi & 0xffff_ffff_ffff_ffff\n            c = 0\n            d = 0\n            n = len(data)\n\n            if n <= 16:\n                a = (self.shift_mix(a * self.k1) * self.k1) & 0xffff_ffff_ffff_ffff\n                c = (b * self.k1 + self.cityhash64_len0to16(data)) & 0xffff_ffff_ffff_ffff\n                if n >= 8:\n                    d = self.shift_mix(a + self.u64le(data, 0)) & 0xffff_ffff_ffff_ffff\n                else:\n                    d = self.shift_mix(a + c) & 0xffff_ffff_ffff_ffff\n            else:\n                c = self.cityhash64_len16(self.u64le(data, n - 8) + self.k1, a)\n                d = self.cityhash64_len16(b + n, c + self.u64le(data, n - 16))\n                a = (a + d) & 0xffff_ffff_ffff_ffff\n                off = 0\n                left = n\n                while left > 16:\n                    a ^= (self.shift_mix(self.u64le(data, off) * self.k1) * self.k1) & 0xffff_ffff_ffff_ffff\n                    a = (a * self.k1) & 0xffff_ffff_ffff_ffff\n                    b ^= a\n                    c ^= (self.shift_mix(self.u64le(data, off + 8) * self.k1) * self.k1) & 0xffff_ffff_ffff_ffff\n                    c = (c * self.k1) & 0xffff_ffff_ffff_ffff\n                    d ^= c\n                    off += 16\n                    left -= 16\n\n            a = self.cityhash64_len16(a, c)\n            b = self.cityhash64_len16(d, b)\n            return (a ^ b, self.cityhash64_len16(b, a))\n\n        def cityhash128_with_seed(self, data, seed_lo, seed_hi):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            if n < 128:\n                return self.cityhash128_murmur(data, seed_lo, seed_hi)\n\n            x = seed_lo & 0xffff_ffff_ffff_ffff\n            y = seed_hi & 0xffff_ffff_ffff_ffff\n            z = (n * self.k1) & 0xffff_ffff_ffff_ffff\n\n            v0 = (self.ror64(y ^ self.k1, 49) * self.k1 + self.u64le(data, 0)) & 0xffff_ffff_ffff_ffff\n            v1 = (self.ror64(v0, 42) * self.k1 + self.u64le(data, 8)) & 0xffff_ffff_ffff_ffff\n            w0 = (self.ror64(y + z, 35) * self.k1 + x) & 0xffff_ffff_ffff_ffff\n            w1 = (self.ror64(x + self.u64le(data, 88), 53) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            off = 0\n            length = n\n            while length >= 128:\n                x = (self.ror64(x + y + v0 + self.u64le(data, off + 8), 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                y = (self.ror64(y + v1 + self.u64le(data, off + 48), 42) * self.k1) & 0xffff_ffff_ffff_ffff\n                x ^= w1\n                y = (y + v0 + self.u64le(data, off + 40)) & 0xffff_ffff_ffff_ffff\n                z = (self.ror64(z + w0, 33) * self.k1) & 0xffff_ffff_ffff_ffff\n                v0, v1 = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off, v1 * self.k1, x + w0,\n                )\n                w0, w1 = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off + 32, z + w1, y + self.u64le(data, off + 16),\n                )\n                x, z = z, x\n                off += 64\n\n                x = (self.ror64(x + y + v0 + self.u64le(data, off + 8), 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                y = (self.ror64(y + v1 + self.u64le(data, off + 48), 42) * self.k1) & 0xffff_ffff_ffff_ffff\n                x ^= w1\n                y = (y + v0 + self.u64le(data, off + 40)) & 0xffff_ffff_ffff_ffff\n                z = (self.ror64(z + w0, 33) * self.k1) & 0xffff_ffff_ffff_ffff\n                v0, v1 = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off, v1 * self.k1, x + w0,\n                )\n                w0, w1 = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off + 32, z + w1, y + self.u64le(data, off + 16),\n                )\n                x, z = z, x\n                off += 64\n\n                length -= 128\n\n            x = (x + self.ror64(v0 + z, 49) * self.k0) & 0xffff_ffff_ffff_ffff\n            y = ((y * self.k0) + self.ror64(w1, 37)) & 0xffff_ffff_ffff_ffff\n            z = ((z * self.k0) + self.ror64(w0, 27)) & 0xffff_ffff_ffff_ffff\n            w0 = (w0 * 9) & 0xffff_ffff_ffff_ffff\n            v0 = (v0 * self.k0) & 0xffff_ffff_ffff_ffff\n\n            tail_done = 0\n            while tail_done < length:\n                tail_done += 32\n                y = (self.ror64(x + y, 42) * self.k0 + v1) & 0xffff_ffff_ffff_ffff\n                w0 = (w0 + self.u64le(data, off + length - tail_done + 16)) & 0xffff_ffff_ffff_ffff\n                x = (x * self.k0 + w0) & 0xffff_ffff_ffff_ffff\n                z = (z + w1 + self.u64le(data, off + length - tail_done)) & 0xffff_ffff_ffff_ffff\n                w1 = (w1 + v0) & 0xffff_ffff_ffff_ffff\n                v0, v1 = self.cityhash64_weak_hash_len32_with_seeds(data, off + length - tail_done, v0 + z, v1)\n                v0 = (v0 * self.k0) & 0xffff_ffff_ffff_ffff\n\n            x = self.cityhash64_len16(x, v0)\n            y = self.cityhash64_len16(y + z, w0)\n            lo = (self.cityhash64_len16(x + v1, w1) + y) & 0xffff_ffff_ffff_ffff\n            hi = self.cityhash64_len16(x + w1, y + v1)\n            return (lo, hi)\n\n        def cityhash128(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            if n >= 16:\n                seed_lo = self.u64le(data, 0)\n                seed_hi = (self.u64le(data, 8) + self.k0) & 0xffff_ffff_ffff_ffff\n                return self.cityhash128_with_seed(data[16:], seed_lo, seed_hi)\n            return self.cityhash128_with_seed(data, self.k0, self.k1)\n\n    class FarmHash32(CityHash32):\n        digest_size = 4\n\n        def __init__(self, data=b\"\", seed=0):\n            super().__init__(data=data, seed=seed)\n            return\n\n        def hexdigest(self):\n            if self.seed:\n                value = self.farmhash32_with_seed(self.data, self.seed)\n            else:\n                value = self.farmhash32(self.data)\n            return f\"{value:08x}\"\n\n        def farmhash32_len13to24(self, data, seed):\n            n = len(data)\n            seed &= 0xffff_ffff\n            a = self.u32le(data, (n >> 1) - 4)\n            b = self.u32le(data, 4)\n            c = self.u32le(data, n - 8)\n            d = self.u32le(data, n >> 1)\n            e = self.u32le(data, 0)\n            f = self.u32le(data, n - 4)\n            h = (d * self.c1 + n + seed) & 0xffff_ffff\n            a = (self.ror32(a, 12) + f) & 0xffff_ffff\n            h = (self.cityhash32_mur(c, h) + a) & 0xffff_ffff\n            a = (self.ror32(a, 3) + c) & 0xffff_ffff\n            h = (self.cityhash32_mur(e, h) + a) & 0xffff_ffff\n            a = (self.ror32((a + f) & 0xffff_ffff, 12) + d) & 0xffff_ffff\n            h = (self.cityhash32_mur(b ^ seed, h) + a) & 0xffff_ffff\n            return self.cityhash32_fmix(h)\n\n        def farmhash32(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            if n <= 24:\n                if n >= 13:\n                    return self.farmhash32_len13to24(data, 0)\n                if n >= 5:\n                    return self.cityhash32_len5to12(data, 0)\n                return self.cityhash32_len0to4(data, 0)\n\n            h = n & 0xffff_ffff\n            g = (self.c1 * n) & 0xffff_ffff\n            f = g\n\n            a0 = (self.ror32(self.u32le(data, n - 4) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a1 = (self.ror32(self.u32le(data, n - 8) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a2 = (self.ror32(self.u32le(data, n - 16) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a3 = (self.ror32(self.u32le(data, n - 12) * self.c1, 17) * self.c2) & 0xffff_ffff\n            a4 = (self.ror32(self.u32le(data, n - 20) * self.c1, 17) * self.c2) & 0xffff_ffff\n\n            h ^= a0\n            h = (self.ror32(h, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n            h ^= a2\n            h = (self.ror32(h, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n\n            g ^= a1\n            g = (self.ror32(g, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n            g ^= a3\n            g = (self.ror32(g, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n\n            f = (f + a4) & 0xffff_ffff\n            f = (self.ror32(f, 19) + 113) & 0xffff_ffff\n\n            iters = (n - 1) // 20\n            off = 0\n            while iters != 0:\n                a = self.u32le(data, off)\n                b = self.u32le(data, off + 4)\n                c = self.u32le(data, off + 8)\n                d = self.u32le(data, off + 12)\n                e = self.u32le(data, off + 16)\n\n                h = (h + a) & 0xffff_ffff\n                g = (g + b) & 0xffff_ffff\n                f = (f + c) & 0xffff_ffff\n\n                h = (self.cityhash32_mur(d, h) + e) & 0xffff_ffff\n                g = (self.cityhash32_mur(c, g) + a) & 0xffff_ffff\n                f = (self.cityhash32_mur(b + e * self.c1, f) + d) & 0xffff_ffff\n\n                f = (f + g) & 0xffff_ffff\n                g = (g + f) & 0xffff_ffff\n\n                off += 20\n                iters -= 1\n\n            g = (self.ror32(g, 11) * self.c1) & 0xffff_ffff\n            g = (self.ror32(g, 17) * self.c1) & 0xffff_ffff\n            f = (self.ror32(f, 11) * self.c1) & 0xffff_ffff\n            f = (self.ror32(f, 17) * self.c1) & 0xffff_ffff\n\n            h = (self.ror32(h + g, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n            h = (self.ror32(h, 17) * self.c1) & 0xffff_ffff\n\n            h = (self.ror32(h + f, 19) * 5 + 0xe654_6b64) & 0xffff_ffff\n            h = (self.ror32(h, 17) * self.c1) & 0xffff_ffff\n            return h & 0xffff_ffff\n\n        def farmhash32_with_seed(self, data, seed):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            seed &= 0xffff_ffff\n            n = len(data)\n            if n <= 24:\n                if n >= 13:\n                    return self.farmhash32_len13to24(data, seed * self.c1)\n                if n >= 5:\n                    return self.cityhash32_len5to12(data, seed)\n                return self.cityhash32_len0to4(data, seed)\n\n            h = self.farmhash32_len13to24(data[:24], seed ^ n)\n            return self.cityhash32_mur(self.farmhash32(data[24:]) + seed, h)\n\n    class FarmHash64(CityHash64):\n        digest_size = 8\n\n        def __init__(self, data=b\"\", seed=0):\n            super().__init__(data=data, seed=seed)\n            return\n\n        def hexdigest(self):\n            if self.seed:\n                value = self.farmhash64_with_seed(self.data, self.seed)\n            else:\n                value = self.farmhash64(self.data)\n            return f\"{value:016x}\"\n\n        def farmhash64_len33to64(self, data):\n            n = len(data)\n            mul = (self.k2 + n * 2) & 0xffff_ffff_ffff_ffff\n            a = (self.u64le(data, 0) * self.k2) & 0xffff_ffff_ffff_ffff\n            b = self.u64le(data, 8)\n            c = (self.u64le(data, n - 8) * mul) & 0xffff_ffff_ffff_ffff\n            d = (self.u64le(data, n - 16) * self.k2) & 0xffff_ffff_ffff_ffff\n            y = (self.ror64(a + b, 43) + self.ror64(c, 30) + d) & 0xffff_ffff_ffff_ffff\n            z = self.cityhash64_len16_mul(y, a + self.ror64(b + self.k2, 18) + c, mul)\n            e = (self.u64le(data, 16) * mul) & 0xffff_ffff_ffff_ffff\n            f = self.u64le(data, 24)\n            g = ((y + self.u64le(data, n - 32)) * mul) & 0xffff_ffff_ffff_ffff\n            h = ((z + self.u64le(data, n - 24)) * mul) & 0xffff_ffff_ffff_ffff\n            return self.cityhash64_len16_mul(\n                self.ror64(e + f, 43) + self.ror64(g, 30) + h,\n                e + self.ror64(f + a, 18) + g,\n                mul,\n            )\n\n        def farmhash64(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            n = len(data)\n            seed = 81\n            if n <= 32:\n                if n <= 16:\n                    return self.cityhash64_len0to16(data)\n                return self.cityhash64_len17to32(data)\n            if n <= 64:\n                return self.farmhash64_len33to64(data)\n\n            x = seed & 0xffff_ffff_ffff_ffff\n            y = (seed * self.k1 + 113) & 0xffff_ffff_ffff_ffff\n            z = (self.shift_mix(y * self.k2 + 113) * self.k2) & 0xffff_ffff_ffff_ffff\n            v = [0, 0]\n            w = [0, 0]\n            x = (x * self.k2 + self.u64le(data, 0)) & 0xffff_ffff_ffff_ffff\n\n            end = ((n - 1) // 64) * 64\n            off = 0\n            while off != end:\n                x = (self.ror64(x + y + v[0] + self.u64le(data, off + 8), 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                y = (self.ror64(y + v[1] + self.u64le(data, off + 48), 42) * self.k1) & 0xffff_ffff_ffff_ffff\n                x ^= w[1]\n                y = (y + v[0] + self.u64le(data, off + 40)) & 0xffff_ffff_ffff_ffff\n                z = (self.ror64(z + w[0], 33) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off, v[1] * self.k1, x + w[0],\n                )\n                w = self.cityhash64_weak_hash_len32_with_seeds(\n                    data, off + 32, z + w[1], y + self.u64le(data, off + 16),\n                )\n                x, z = z, x\n                off += 64\n\n            mul = (self.k1 + ((z & 0xff) << 1)) & 0xffff_ffff_ffff_ffff\n            off = n - 64\n\n            w = ((w[0] + ((n - 1) & 63)) & 0xffff_ffff_ffff_ffff, w[1])\n            v = ((v[0] + w[0]) & 0xffff_ffff_ffff_ffff, v[1])\n            w = ((w[0] + v[0]) & 0xffff_ffff_ffff_ffff, w[1])\n\n            x = (self.ror64(x + y + v[0] + self.u64le(data, off + 8), 37) * mul) & 0xffff_ffff_ffff_ffff\n            y = (self.ror64(y + v[1] + self.u64le(data, off + 48), 42) * mul) & 0xffff_ffff_ffff_ffff\n            x ^= (w[1] * 9) & 0xffff_ffff_ffff_ffff\n            y = (y + (v[0] * 9) + self.u64le(data, off + 40)) & 0xffff_ffff_ffff_ffff\n            z = (self.ror64(z + w[0], 33) * mul) & 0xffff_ffff_ffff_ffff\n            v = self.cityhash64_weak_hash_len32_with_seeds(\n                data, off, v[1] * mul, x + w[0],\n            )\n            w = self.cityhash64_weak_hash_len32_with_seeds(\n                data, off + 32, z + w[1], y + self.u64le(data, off + 16),\n            )\n            x, z = z, x\n\n            return self.cityhash64_len16_mul(\n                self.cityhash64_len16_mul(v[0], w[0], mul) + self.shift_mix(y) * self.k0 + z,\n                self.cityhash64_len16_mul(v[1], w[1], mul) + x,\n                mul,\n            )\n\n        def farmhash64_with_seeds(self, data, seed0, seed1):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            seed0 &= 0xffff_ffff_ffff_ffff\n            seed1 &= 0xffff_ffff_ffff_ffff\n            return self.cityhash64_len16(self.farmhash64(data) - seed0, seed1)\n\n        def farmhash64_with_seed(self, data, seed):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            seed &= 0xffff_ffff_ffff_ffff\n            return self.farmhash64_with_seeds(data, self.k2, seed)\n\n    class FarmHash128(CityHash128):\n        digest_size = 16\n\n        def hexdigest(self):\n            if self.seed:\n                if isinstance(self.seed, tuple) and len(self.seed) == 2:\n                    seed_lo, seed_hi = self.seed\n                else:\n                    seed_lo, seed_hi = self.seed, self.seed\n                lo, hi = self.cityhash128_with_seed(self.data, seed_lo, seed_hi)\n            else:\n                lo, hi = self.cityhash128(self.data)\n            return f\"{hi:016x}{lo:016x}\"\n\n    class SipHashBase:\n        block_size = 8\n        key_size = 16\n\n        iv0 = 0x736f_6d65_7073_6575\n        iv1 = 0x646f_7261_6e64_6f6d\n        iv2 = 0x6c79_6765_6e65_7261\n        iv3 = 0x7465_6462_7974_6573\n\n        def __init__(self, key=b\"\\0\" * 16, data=b\"\"):\n            if not isinstance(key, (bytes, bytearray, memoryview)):\n                raise TypeError(\"key must be bytes-like\")\n            if len(key) != self.key_size:\n                raise ValueError(\"key must be 16 bytes\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.key = key\n            self.buf = bytearray()\n            self.msg_len = 0\n            k0 = struct.unpack_from(\"<Q\", key, 0)[0]\n            k1 = struct.unpack_from(\"<Q\", key, 8)[0]\n            self.v0 = self.iv0 ^ k0\n            self.v1 = self.iv1 ^ k1\n            self.v2 = self.iv2 ^ k0\n            self.v3 = self.iv3 ^ k1\n            if self.digest_size == 16:\n                self.v1 ^= 0xee\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(self.key)\n            other.v0 = self.v0\n            other.v1 = self.v1\n            other.v2 = self.v2\n            other.v3 = self.v3\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:8])\n                del self.buf[:8]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.result\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            b = ((self.msg_len & 0xff) << 56) & 0xffff_ffff_ffff_ffff\n            left = len(self.buf)\n            for i in range(left):\n                b |= (self.buf[i] & 0xff) << (8 * i)\n            b &= 0xffff_ffff_ffff_ffff\n\n            self.v3 ^= b\n            for _ in range(self.c_rounds):\n                self.sipround()\n            self.v0 ^= b\n\n            if self.digest_size == 16:\n                self.v2 ^= 0xee\n            else:\n                self.v2 ^= 0xff\n\n            for _ in range(self.d_rounds):\n                self.sipround()\n\n            out0 = (self.v0 ^ self.v1 ^ self.v2 ^ self.v3) & 0xffff_ffff_ffff_ffff\n            if self.digest_size == 8:\n                self.result = struct.pack(\"<Q\", out0)\n                return\n\n            self.v1 ^= 0xdd\n            for _ in range(self.d_rounds):\n                self.sipround()\n            out1 = (self.v0 ^ self.v1 ^ self.v2 ^ self.v3) & 0xffff_ffff_ffff_ffff\n            self.result = struct.pack(\"<QQ\", out0, out1)\n            return\n\n        def compress(self, block):\n            m = struct.unpack_from(\"<Q\", block, 0)[0]\n            self.v3 ^= m\n            for _ in range(self.c_rounds):\n                self.sipround()\n            self.v0 ^= m\n            return\n\n        def sipround(self):\n\n            def rol64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            self.v0 = (self.v0 + self.v1) & 0xffff_ffff_ffff_ffff\n            self.v1 = rol64(self.v1, 13)\n            self.v1 ^= self.v0\n            self.v0 = rol64(self.v0, 32)\n            self.v2 = (self.v2 + self.v3) & 0xffff_ffff_ffff_ffff\n            self.v3 = rol64(self.v3, 16)\n            self.v3 ^= self.v2\n            self.v0 = (self.v0 + self.v3) & 0xffff_ffff_ffff_ffff\n            self.v3 = rol64(self.v3, 21)\n            self.v3 ^= self.v0\n            self.v2 = (self.v2 + self.v1) & 0xffff_ffff_ffff_ffff\n            self.v1 = rol64(self.v1, 17)\n            self.v1 ^= self.v2\n            self.v2 = rol64(self.v2, 32)\n            return\n\n    class SipHash64_2_4(SipHashBase):\n        digest_size = 8\n        c_rounds = 2\n        d_rounds = 4\n\n    class SipHash64_1_3(SipHashBase):\n        digest_size = 8\n        c_rounds = 1\n        d_rounds = 3\n\n    class SipHash64_4_8(SipHashBase):\n        digest_size = 8\n        c_rounds = 4\n        d_rounds = 8\n\n    class SipHash128_2_4(SipHashBase):\n        digest_size = 16\n        c_rounds = 2\n        d_rounds = 4\n\n    class SipHash128_4_8(SipHashBase):\n        digest_size = 16\n        c_rounds = 4\n        d_rounds = 8\n\n    class HalfSipHashBase:\n        block_size = 4\n        key_size = 8\n\n        iv2 = 0x6c79_6765\n        iv3 = 0x7465_6462\n\n        def __init__(self, key=b\"\\0\" * 8, data=b\"\"):\n            if not isinstance(key, (bytes, bytearray, memoryview)):\n                raise TypeError(\"key must be bytes-like\")\n            if len(key) != self.key_size:\n                raise ValueError(\"key must be 8 bytes\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.key = key\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.v0 = 0\n            self.v1 = 0\n            self.v2 = self.iv2\n            self.v3 = self.iv3\n            k0 = struct.unpack_from(\"<I\", key, 0)[0]\n            k1 = struct.unpack_from(\"<I\", key, 4)[0]\n            self.v3 ^= k1\n            self.v2 ^= k0\n            self.v1 ^= k1\n            self.v0 ^= k0\n            if self.digest_size == 8:\n                self.v1 ^= 0xee\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(self.key)\n            other.v0 = self.v0\n            other.v1 = self.v1\n            other.v2 = self.v2\n            other.v3 = self.v3\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:4])\n                del self.buf[:4]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.result\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            b = ((self.msg_len & 0xff_ff_ff_ff) << 24) & 0xffff_ffff\n            left = len(self.buf)\n            if left >= 1:\n                b |= (self.buf[0] & 0xff) << 0\n            if left >= 2:\n                b |= (self.buf[1] & 0xff) << 8\n            if left >= 3:\n                b |= (self.buf[2] & 0xff) << 16\n            b &= 0xffff_ffff\n\n            self.v3 ^= b\n            for _ in range(self.c_rounds):\n                self.sipround()\n            self.v0 ^= b\n\n            if self.digest_size == 8:\n                self.v2 ^= 0xee\n            else:\n                self.v2 ^= 0xff\n\n            for _ in range(self.d_rounds):\n                self.sipround()\n\n            out0 = (self.v1 ^ self.v3) & 0xffff_ffff\n            if self.digest_size == 4:\n                self.result = struct.pack(\"<I\", out0)\n                return\n\n            self.v1 ^= 0xdd\n            for _ in range(self.d_rounds):\n                self.sipround()\n            out1 = (self.v1 ^ self.v3) & 0xffff_ffff\n\n            self.result = struct.pack(\"<II\", out0, out1)\n            return\n\n        def compress(self, block):\n            m = struct.unpack_from(\"<I\", block, 0)[0]\n            self.v3 ^= m\n            for _ in range(self.c_rounds):\n                self.sipround()\n            self.v0 ^= m\n            return\n\n        def sipround(self):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            self.v0 = (self.v0 + self.v1) & 0xffff_ffff\n            self.v1 = rol32(self.v1, 5)\n            self.v1 ^= self.v0\n            self.v0 = rol32(self.v0, 16)\n            self.v2 = (self.v2 + self.v3) & 0xffff_ffff\n            self.v3 = rol32(self.v3, 8)\n            self.v3 ^= self.v2\n            self.v0 = (self.v0 + self.v3) & 0xffff_ffff\n            self.v3 = rol32(self.v3, 7)\n            self.v3 ^= self.v0\n            self.v2 = (self.v2 + self.v1) & 0xffff_ffff\n            self.v1 = rol32(self.v1, 13)\n            self.v1 ^= self.v2\n            self.v2 = rol32(self.v2, 16)\n            return\n\n    class HalfSipHash32_2_4(HalfSipHashBase):\n        digest_size = 4\n        c_rounds = 2\n        d_rounds = 4\n\n    class HalfSipHash64_2_4(HalfSipHashBase):\n        digest_size = 8\n        c_rounds = 2\n        d_rounds = 4\n\n    class SpookyHashBase:\n        block_size = 96\n        digest_size = 16\n\n        sc_const = 0xdead_beef_dead_beef\n        sc_num_vars = 12\n        sc_block_size = sc_num_vars * 8\n        sc_buf_size = 2 * sc_block_size\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.seed = seed & 0xffff_ffff_ffff_ffff\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.hash1 = 0\n            self.hash2 = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.hash1 = self.hash1\n            other.hash2 = self.hash2\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.format_digest(c.hash1, c.hash2)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            h1, h2 = self.hash128(bytes(self.buf), self.seed, self.seed)\n            self.hash1 = h1\n            self.hash2 = h2\n            return\n\n        def rol64(self, x, k):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x << k) | (x >> (64 - k))) & 0xffff_ffff_ffff_ffff\n\n        def mix(self, data, s):\n            rc = (\n                11, 32, 43, 31, 17, 28, 39, 57, 55, 54, 22, 46,\n            )\n            for i in range(12):\n                s[i] = (s[i] + data[i]) & 0xffff_ffff_ffff_ffff\n                s[(i + 2) % 12] ^= s[(i + 10) % 12]\n                s[(i + 11) % 12] ^= s[i]\n                s[i] = self.rol64(s[i], rc[i])\n                s[(i + 11) % 12] = (s[(i + 11) % 12] + s[(i + 1) % 12]) & 0xffff_ffff_ffff_ffff\n            return s\n\n        def end_partial(self, h):\n            rc = (\n                44, 15, 34, 21, 38, 33, 10, 13, 38, 53, 42, 54,\n            )\n            for i in range(12):\n                h[(i + 11) % 12] = (h[(i + 11) % 12] + h[(i + 1) % 12]) & 0xffff_ffff_ffff_ffff\n                h[(i + 2) % 12] ^= h[(i + 11) % 12]\n                h[(i + 1) % 12] = self.rol64(h[i], rc[i])\n            return h\n\n        def end(self, h):\n            h = self.end_partial(h)\n            h = self.end_partial(h)\n            h = self.end_partial(h)\n            return h\n\n        def end_data(self, data, h):\n            for i in range(12):\n                h[i] = (h[i] + data[i]) & 0xffff_ffff_ffff_ffff\n            return self.end(h)\n\n        def short_mix(self, h):\n            rc = (\n                50, 52, 30, 41, 54, 48, 38, 37, 62, 34, 5, 36,\n            )\n            for i in range(12):\n                h[(i + 2) % 4] = self.rol64(h[(i + 2) % 4], rc[i])\n                h[(i + 2) % 4] = (h[(i + 2) % 4] + h[(i + 3) % 4]) & 0xffff_ffff_ffff_ffff\n                h[i % 4] ^= h[(i + 2) % 4]\n            return h\n\n        def short_end(self, h):\n            rc = (\n                15, 52, 26, 51, 28, 9, 47, 54, 32, 25, 63,\n            )\n            for i in range(11):\n                h[(i + 3) % 4] ^= h[(i + 2) % 4]\n                h[(i + 2) % 4] = self.rol64(h[(i + 2) % 4], rc[i])\n                h[(i + 3) % 4] = (h[(i + 3) % 4] + h[(i + 2) % 4]) & 0xffff_ffff_ffff_ffff\n            return h\n\n        def short(self, message, hash1, hash2):\n\n            def u64le(data, offset):\n                return int.from_bytes(data[offset:offset + 8], \"little\")\n\n            def u32le(data, offset):\n                return int.from_bytes(data[offset:offset + 4], \"little\")\n\n            length = len(message)\n            remainder = length % 32\n\n            a = hash1 & 0xffff_ffff_ffff_ffff\n            b = hash2 & 0xffff_ffff_ffff_ffff\n            c = self.sc_const\n            d = self.sc_const\n\n            pos = 0\n            if length > 15:\n                end = (length // 32) * 32\n                while pos < end:\n                    c = (c + u64le(message, pos)) & 0xffff_ffff_ffff_ffff\n                    d = (d + u64le(message, pos + 8)) & 0xffff_ffff_ffff_ffff\n                    a, b, c, d = self.short_mix([a, b, c, d])\n                    a = (a + u64le(message, pos + 16)) & 0xffff_ffff_ffff_ffff\n                    b = (b + u64le(message, pos + 24)) & 0xffff_ffff_ffff_ffff\n                    pos += 32\n\n                if remainder >= 16:\n                    c = (c + u64le(message, pos)) & 0xffff_ffff_ffff_ffff\n                    d = (d + u64le(message, pos + 8)) & 0xffff_ffff_ffff_ffff\n                    a, b, c, d = self.short_mix(a, b, c, d)\n                    pos += 16\n                    remainder -= 16\n\n            tail = message[pos:pos + remainder]\n            d = (d + (((length & 0xffff_ffff_ffff_ffff) << 56) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n            if remainder == 15:\n                d = (d + (tail[14] << 48)) & 0xffff_ffff_ffff_ffff\n            if remainder >= 14:\n                d = (d + (tail[13] << 40)) & 0xffff_ffff_ffff_ffff\n            if remainder >= 13:\n                d = (d + (tail[12] << 32)) & 0xffff_ffff_ffff_ffff\n\n            if remainder >= 12:\n                d = (d + u32le(tail + b\"\\x00\" * 4, 8)) & 0xffff_ffff_ffff_ffff\n                c = (c + u64le(tail + b\"\\x00\" * 8, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 11:\n                d = (d + (tail[10] << 16)) & 0xffff_ffff_ffff_ffff\n                d = (d + (tail[9] << 8)) & 0xffff_ffff_ffff_ffff\n                d = (d + tail[8]) & 0xffff_ffff_ffff_ffff\n                c = (c + u64le(tail + b\"\\x00\" * 8, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 10:\n                d = (d + (tail[9] << 8)) & 0xffff_ffff_ffff_ffff\n                d = (d + tail[8]) & 0xffff_ffff_ffff_ffff\n                c = (c + u64le(tail + b\"\\x00\" * 8, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 9:\n                d = (d + tail[8]) & 0xffff_ffff_ffff_ffff\n                c = (c + u64le(tail + b\"\\x00\" * 8, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 8:\n                c = (c + u64le(tail, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 7:\n                c = (c + (tail[6] << 48)) & 0xffff_ffff_ffff_ffff\n                c = (c + (tail[5] << 40)) & 0xffff_ffff_ffff_ffff\n                c = (c + (tail[4] << 32)) & 0xffff_ffff_ffff_ffff\n                c = (c + u32le(tail + b\"\\x00\" * 4, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 6:\n                c = (c + (tail[5] << 40)) & 0xffff_ffff_ffff_ffff\n                c = (c + (tail[4] << 32)) & 0xffff_ffff_ffff_ffff\n                c = (c + u32le(tail + b\"\\x00\" * 4, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 5:\n                c = (c + (tail[4] << 32)) & 0xffff_ffff_ffff_ffff\n                c = (c + u32le(tail + b\"\\x00\" * 4, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 4:\n                c = (c + u32le(tail, 0)) & 0xffff_ffff_ffff_ffff\n            elif remainder == 3:\n                c = (c + (tail[2] << 16)) & 0xffff_ffff_ffff_ffff\n                c = (c + (tail[1] << 8)) & 0xffff_ffff_ffff_ffff\n                c = (c + tail[0]) & 0xffff_ffff_ffff_ffff\n            elif remainder == 2:\n                c = (c + (tail[1] << 8)) & 0xffff_ffff_ffff_ffff\n                c = (c + tail[0]) & 0xffff_ffff_ffff_ffff\n            elif remainder == 1:\n                c = (c + tail[0]) & 0xffff_ffff_ffff_ffff\n            elif remainder == 0:\n                c = (c + self.sc_const) & 0xffff_ffff_ffff_ffff\n                d = (d + self.sc_const) & 0xffff_ffff_ffff_ffff\n\n            a, b, c, d = self.short_end([a, b, c, d])\n            return a, b\n\n        def hash128(self, message, seed1, seed2):\n            length = len(message)\n            if length < self.sc_buf_size:\n                h1, h2 = self.short(message, seed1, seed2)\n                return h1, h2\n\n            h0 = h3 = h6 = h9 = seed1 & 0xffff_ffff_ffff_ffff\n            h1 = h4 = h7 = h10 = seed2 & 0xffff_ffff_ffff_ffff\n            h2 = h5 = h8 = h11 = self.sc_const\n\n            nblocks = length // self.sc_block_size\n            pos = 0\n            for _ in range(nblocks):\n                block = struct.unpack_from(\"<12Q\", message, pos)\n                state = [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11]\n                state = self.mix(block, state)\n                h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11 = state\n                pos += self.sc_block_size\n\n            remainder = length - pos\n            tail = message[pos:]\n\n            buf = bytearray(self.sc_block_size)\n            buf[:remainder] = tail\n            buf[-1] = remainder & 0xff\n            block = struct.unpack_from(\"<12Q\", bytes(buf), 0)\n\n            state = self.end_data(block, [h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11])\n            return state[0], state[1]\n\n        def format_digest(self, hash1, hash2):\n            return struct.pack(\"<2Q\", hash1 & 0xffff_ffff_ffff_ffff, hash2 & 0xffff_ffff_ffff_ffff)\n\n    class SpookyHash32(SpookyHashBase):\n        digest_size = 4\n\n        def format_digest(self, hash1, hash2):\n            return struct.pack(\"<I\", hash1 & 0xffff_ffff)\n\n    class SpookyHash64(SpookyHashBase):\n        digest_size = 8\n\n        def format_digest(self, hash1, hash2):\n            return struct.pack(\"<Q\", hash1 & 0xffff_ffff_ffff_ffff)\n\n    class SpookyHash128(SpookyHashBase):\n        digest_size = 16\n\n        def format_digest(self, hash1, hash2):\n            return struct.pack(\"<2Q\", hash1 & 0xffff_ffff_ffff_ffff, hash2 & 0xffff_ffff_ffff_ffff)\n\n    class MetroHashBase:\n        block_size = 32\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(seed, (int,)):\n                raise TypeError(\"seed must be int\")\n            self.seed = seed & 0xffff_ffff_ffff_ffff\n            self.state = [0, 0, 0, 0]\n            self.input = bytearray(32)\n            self.bytes = 0\n            self.result = b\"\"\n            self.initialize(self.seed)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.state = list(self.state)\n            other.input = bytearray(self.input)\n            other.bytes = self.bytes\n            if hasattr(self, \"vseed\"):\n                other.vseed = self.vseed\n            other.result = self.result\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            ptr = 0\n            end = len(data)\n\n            if self.bytes % 32:\n                fill = 32 - (self.bytes % 32)\n                if fill > end:\n                    fill = end\n\n                off = self.bytes % 32\n                self.input[off:off + fill] = data[ptr:ptr + fill]\n                ptr += fill\n                self.bytes += fill\n\n                if (self.bytes % 32) != 0:\n                    return self\n\n                self.process_block(self.input, 0)\n\n            self.bytes += (end - ptr)\n            while ptr <= (end - 32):\n                self.process_block(data, ptr)\n                ptr += 32\n\n            if ptr < end:\n                rem = end - ptr\n                self.input[0:rem] = data[ptr:end]\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.result\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def ror64(self, x, r):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x >> r) | ((x << (64 - r)) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n        def u64le(self, data, offset):\n            return int.from_bytes(data[offset:offset + 8], \"little\")\n\n        def u32le(self, data, offset):\n            return int.from_bytes(data[offset:offset + 4], \"little\")\n\n        def u16le(self, data, offset):\n            return int.from_bytes(data[offset:offset + 2], \"little\")\n\n        def u8le(self, data, offset):\n            return data[offset]\n\n        def process_block(self, data, offset):\n            v0, v1, v2, v3 = self.state\n            v0 = (v0 + self.u64le(data, offset + 0) * self.k0) & 0xffff_ffff_ffff_ffff\n            v0 = (self.ror64(v0, 29) + v2) & 0xffff_ffff_ffff_ffff\n            v1 = (v1 + self.u64le(data, offset + 8) * self.k1) & 0xffff_ffff_ffff_ffff\n            v1 = (self.ror64(v1, 29) + v3) & 0xffff_ffff_ffff_ffff\n            v2 = (v2 + self.u64le(data, offset + 16) * self.k2) & 0xffff_ffff_ffff_ffff\n            v2 = (self.ror64(v2, 29) + v0) & 0xffff_ffff_ffff_ffff\n            v3 = (v3 + self.u64le(data, offset + 24) * self.k3) & 0xffff_ffff_ffff_ffff\n            v3 = (self.ror64(v3, 29) + v1) & 0xffff_ffff_ffff_ffff\n            self.state = [v0, v1, v2, v3]\n            return\n\n    class MetroHash64(MetroHashBase):\n        digest_size = 8\n\n        k0 = 0xd6d0_18f5\n        k1 = 0xa2aa_033b\n        k2 = 0x6299_2fc1\n        k3 = 0x30bc_5b29\n\n        def initialize(self, seed):\n            self.vseed = ((seed + self.k2) * self.k0) & 0xffff_ffff_ffff_ffff\n            self.state = [self.vseed, self.vseed, self.vseed, self.vseed]\n            self.bytes = 0\n            return\n\n        def finalize(self):\n            v0, v1, v2, v3 = self.state\n\n            if self.bytes >= 32:\n                v = (((v0 + v3) * self.k0) + v1) & 0xffff_ffff_ffff_ffff\n                v2 ^= (self.ror64(v, 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = (((v1 + v2) * self.k1) + v0) & 0xffff_ffff_ffff_ffff\n                v3 ^= (self.ror64(v, 37) * self.k0) & 0xffff_ffff_ffff_ffff\n                v = (((v0 + v2) * self.k0) + v3) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v, 37) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = (((v1 + v3) * self.k1) + v2) & 0xffff_ffff_ffff_ffff\n                v1 ^= (self.ror64(v, 37) * self.k0) & 0xffff_ffff_ffff_ffff\n                v0 = (self.vseed + (v0 ^ v1)) & 0xffff_ffff_ffff_ffff\n\n            ptr = 0\n            end = self.bytes % 32\n\n            if (end - ptr) >= 16:\n                t1 = (v0 + self.u64le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                t1 = (self.ror64(t1, 29) * self.k3) & 0xffff_ffff_ffff_ffff\n\n                t2 = (v0 + self.u64le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                t2 = (self.ror64(t2, 29) * self.k3) & 0xffff_ffff_ffff_ffff\n\n                t = (t1 * self.k0) & 0xffff_ffff_ffff_ffff\n                t1 ^= (self.ror64(t, 21) + t2) & 0xffff_ffff_ffff_ffff\n                t = (t2 * self.k3) & 0xffff_ffff_ffff_ffff\n                t2 ^= (self.ror64(t, 21) + t1) & 0xffff_ffff_ffff_ffff\n                v0 = (v0 + t2) & 0xffff_ffff_ffff_ffff\n\n                v1 = t1\n                v2 = t2\n\n            if (end - ptr) >= 8:\n                v0 = (v0 + self.u64le(self.input, ptr) * self.k3) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                v0 ^= (self.ror64(v0, 55) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 4:\n                v0 = (v0 + self.u32le(self.input, ptr) * self.k3) & 0xffff_ffff_ffff_ffff\n                ptr += 4\n                v0 ^= (self.ror64(v0, 26) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 2:\n                v0 = (v0 + self.u16le(self.input, ptr) * self.k3) & 0xffff_ffff_ffff_ffff\n                ptr += 2\n                v0 ^= (self.ror64(v0, 48) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 1:\n                v0 = (v0 + self.u8le(self.input, ptr) * self.k3) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v0, 37) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            v0 ^= self.ror64(v0, 28)\n            v0 = (v0 * self.k0) & 0xffff_ffff_ffff_ffff\n            v0 ^= self.ror64(v0, 29)\n\n            self.state = [v0, v1, v2, v3]\n            self.bytes = 0\n\n            self.result = v0.to_bytes(8, \"little\")\n            return\n\n    class MetroHash128(MetroHashBase):\n        digest_size = 16\n\n        k0 = 0xc83a_91e1\n        k1 = 0x8648_dbdb\n        k2 = 0x7bde_c03b\n        k3 = 0x2f58_70a5\n\n        def initialize(self, seed):\n            self.state[0] = ((seed - self.k0) * self.k3) & 0xffff_ffff_ffff_ffff\n            self.state[1] = ((seed + self.k1) * self.k2) & 0xffff_ffff_ffff_ffff\n            self.state[2] = ((seed + self.k0) * self.k2) & 0xffff_ffff_ffff_ffff\n            self.state[3] = ((seed - self.k1) * self.k3) & 0xffff_ffff_ffff_ffff\n            self.bytes = 0\n            return\n\n        def finalize(self):\n            v0, v1, v2, v3 = self.state\n\n            if self.bytes >= 32:\n                v = (((v0 + v3) * self.k0) + v1) & 0xffff_ffff_ffff_ffff\n                v2 ^= (self.ror64(v, 21) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = (((v1 + v2) * self.k1) + v0) & 0xffff_ffff_ffff_ffff\n                v3 ^= (self.ror64(v, 21) * self.k0) & 0xffff_ffff_ffff_ffff\n                v = (((v0 + v2) * self.k0) + v3) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v, 21) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = (((v1 + v3) * self.k1) + v2) & 0xffff_ffff_ffff_ffff\n                v1 ^= (self.ror64(v, 21) * self.k0) & 0xffff_ffff_ffff_ffff\n\n            ptr = 0\n            end = self.bytes % 32\n\n            if (end - ptr) >= 16:\n                v0 = (v0 + self.u64le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                v0 = (self.ror64(v0, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n\n                v1 = (v1 + self.u64le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                v1 = (self.ror64(v1, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n\n                v = ((v0 * self.k2) + v1) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v, 45) * self.k1) & 0xffff_ffff_ffff_ffff\n                v = ((v1 * self.k3) + v0) & 0xffff_ffff_ffff_ffff\n                v1 ^= (self.ror64(v, 45) * self.k0) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 8:\n                v0 = (v0 + self.u64le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 8\n                v0 = (self.ror64(v0, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n                v = ((v0 * self.k2) + v1) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v, 27) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 4:\n                v1 = (v1 + self.u32le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 4\n                v1 = (self.ror64(v1, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n                v = ((v1 * self.k3) + v0) & 0xffff_ffff_ffff_ffff\n                v1 ^= (self.ror64(v, 46) * self.k0) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 2:\n                v0 = (v0 + self.u16le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                ptr += 2\n                v0 = (self.ror64(v0, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n                v = ((v0 * self.k2) + v1) & 0xffff_ffff_ffff_ffff\n                v0 ^= (self.ror64(v, 22) * self.k1) & 0xffff_ffff_ffff_ffff\n\n            if (end - ptr) >= 1:\n                v1 = (v1 + self.u8le(self.input, ptr) * self.k2) & 0xffff_ffff_ffff_ffff\n                v1 = (self.ror64(v1, 33) * self.k3) & 0xffff_ffff_ffff_ffff\n                v = ((v1 * self.k3) + v0) & 0xffff_ffff_ffff_ffff\n                v1 ^= (self.ror64(v, 58) * self.k0) & 0xffff_ffff_ffff_ffff\n\n            v = ((v0 * self.k0) + v1) & 0xffff_ffff_ffff_ffff\n            v0 = (v0 + self.ror64(v, 13)) & 0xffff_ffff_ffff_ffff\n            v = ((v1 * self.k1) + v0) & 0xffff_ffff_ffff_ffff\n            v1 = (v1 + self.ror64(v, 37)) & 0xffff_ffff_ffff_ffff\n            v = ((v0 * self.k2) + v1) & 0xffff_ffff_ffff_ffff\n            v0 = (v0 + self.ror64(v, 13)) & 0xffff_ffff_ffff_ffff\n            v = ((v1 * self.k3) + v0) & 0xffff_ffff_ffff_ffff\n            v1 = (v1 + self.ror64(v, 37)) & 0xffff_ffff_ffff_ffff\n\n            self.state = [v0, v1, v2, v3]\n            self.bytes = 0\n\n            self.result = v0.to_bytes(8, \"little\") + v1.to_bytes(8, \"little\")\n            return\n\n    class HighwayHashBase:\n        block_size = 32\n        digest_size = 0\n        output_words = 0\n        final_rounds = 0\n\n        def __init__(self, data=b\"\", key=None):\n            self.key = self.normalize_key(key)\n            self.mul0 = [0, 0, 0, 0]\n            self.mul1 = [0, 0, 0, 0]\n            self.v0 = [0, 0, 0, 0]\n            self.v1 = [0, 0, 0, 0]\n            self.buf = bytearray()\n            self.finalized = False\n            self.result_words = None\n            self.reset(self.key)\n            if data:\n                self.update(data)\n            return\n\n        def normalize_key(self, key):\n            if key is None:\n                return (0, 0, 0, 0)\n            if isinstance(key, (bytes, bytearray, memoryview)):\n                key_bytes = bytes(key)\n                if len(key_bytes) != 32:\n                    raise ValueError(\"key must be 32 bytes\")\n                w0 = int.from_bytes(key_bytes[0:8], \"little\")\n                w1 = int.from_bytes(key_bytes[8:16], \"little\")\n                w2 = int.from_bytes(key_bytes[16:24], \"little\")\n                w3 = int.from_bytes(key_bytes[24:32], \"little\")\n                return (w0, w1, w2, w3)\n            values = list(key)\n            if len(values) != 4:\n                raise ValueError(\"key must be 4x uint64 or 32 bytes\")\n            return (\n                int(values[0]) & 0xffff_ffff_ffff_ffff,\n                int(values[1]) & 0xffff_ffff_ffff_ffff,\n                int(values[2]) & 0xffff_ffff_ffff_ffff,\n                int(values[3]) & 0xffff_ffff_ffff_ffff,\n            )\n\n        def reset(self, key=None):\n            if key is not None:\n                self.key = self.normalize_key(key)\n            self.mul0 = [\n                0xdbe6_d5d5_fe4c_ce2f, 0xa409_3822_299f_31d0, 0x1319_8a2e_0370_7344, 0x243f_6a88_85a3_08d3,\n            ]\n            self.mul1 = [\n                0x3bd3_9e10_cb0e_f593, 0xc0ac_f169_b5f1_8a8c, 0xbe54_66cf_34e9_0c6c, 0x4528_21e6_38d0_1377,\n            ]\n            self.v0 = [\n                (self.mul0[0] ^ self.key[0]) & 0xffff_ffff_ffff_ffff,\n                (self.mul0[1] ^ self.key[1]) & 0xffff_ffff_ffff_ffff,\n                (self.mul0[2] ^ self.key[2]) & 0xffff_ffff_ffff_ffff,\n                (self.mul0[3] ^ self.key[3]) & 0xffff_ffff_ffff_ffff,\n            ]\n            self.v1 = [\n                (self.mul1[0] ^ self.swap32(self.key[0])) & 0xffff_ffff_ffff_ffff,\n                (self.mul1[1] ^ self.swap32(self.key[1])) & 0xffff_ffff_ffff_ffff,\n                (self.mul1[2] ^ self.swap32(self.key[2])) & 0xffff_ffff_ffff_ffff,\n                (self.mul1[3] ^ self.swap32(self.key[3])) & 0xffff_ffff_ffff_ffff,\n            ]\n            self.buf = bytearray()\n            self.finalized = False\n            self.result_words = None\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.key)\n            other.mul0 = list(self.mul0)\n            other.mul1 = list(self.mul1)\n            other.v0 = list(self.v0)\n            other.v1 = list(self.v1)\n            other.buf = bytearray(self.buf)\n            other.finalized = self.finalized\n            other.result_words = None if self.result_words is None else list(self.result_words)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            data_bytes = bytes(data)\n            if not data_bytes:\n                return self\n            if self.buf:\n                need = self.block_size - len(self.buf)\n                if len(data_bytes) < need:\n                    self.buf.extend(data_bytes)\n                    return self\n                self.buf.extend(data_bytes[:need])\n                self.update_packet(bytes(self.buf))\n                self.buf.clear()\n                data_bytes = data_bytes[need:]\n            i = 0\n            n = len(data_bytes)\n            while i + 32 <= n:\n                self.update_packet(data_bytes[i : i + 32])\n                i += 32\n            if i != n:\n                self.buf.extend(data_bytes[i:])\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytearray()\n            for w in c.result_words:\n                out.extend(c.bswap64(w).to_bytes(8, \"big\"))\n            return bytes(out)\n\n        def hexdigest(self):\n\n            def bswap64(x):\n                x &= 0xffff_ffff_ffff_ffff\n                return int.from_bytes(x.to_bytes(8, \"little\"), \"big\")\n\n            c = self.copy()\n            c.finalize()\n            parts = []\n            for w in c.result_words:\n                parts.append(format(bswap64(w), \"016x\"))\n            return \"\".join(parts)\n\n        def finalize(self):\n            if self.finalized:\n                return\n            if self.buf:\n                self.update_remainder(bytes(self.buf))\n                self.buf.clear()\n            self.final_permutes(self.final_rounds)\n            self.result_words = self.finalize_words()\n            self.finalized = True\n            return\n\n        def swap32(self, x):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x >> 32) | ((x << 32) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n        def zipper_merge_and_add(self, v1, v0, add1, idx1, add0, idx0):\n\n            def byte_of(value, index):\n                return (value >> (index * 8)) & 0xff\n\n            term0 = (\n                (byte_of(v0, 3) << 0)  # out[0]\n                | (byte_of(v1, 4) << 8)  # out[1]\n                | (byte_of(v0, 2) << 16)  # out[2]\n                | (byte_of(v0, 5) << 24)  # out[3]\n                | (byte_of(v1, 6) << 32)  # out[4]\n                | (byte_of(v0, 1) << 40)  # out[5]\n                | (byte_of(v1, 7) << 48)  # out[6]\n                | (byte_of(v0, 0) << 56)  # out[7]\n            )\n            term1 = (\n                (byte_of(v1, 3) << 0)  # out[0]\n                | (byte_of(v0, 4) << 8)  # out[1]\n                | (byte_of(v1, 2) << 16)  # out[2]\n                | (byte_of(v1, 5) << 24)  # out[3]\n                | (byte_of(v1, 1) << 32)  # out[4]\n                | (byte_of(v0, 6) << 40)  # out[5]\n                | (byte_of(v1, 0) << 48)  # out[6]\n                | (byte_of(v0, 7) << 56)  # out[7]\n            )\n            add0[idx0] = (add0[idx0] + term0) & 0xffff_ffff_ffff_ffff\n            add1[idx1] = (add1[idx1] + term1) & 0xffff_ffff_ffff_ffff\n            return\n\n        def update_lanes(self, lanes):\n            for i in range(4):\n                self.v1[i] = (self.v1[i] + self.mul0[i] + lanes[i]) & 0xffff_ffff_ffff_ffff\n                v = (self.v1[i] & 0xffff_ffff) * (self.v0[i] >> 32)\n                self.mul0[i] = (self.mul0[i] ^ v) & 0xffff_ffff_ffff_ffff\n                self.v0[i] = (self.v0[i] + self.mul1[i]) & 0xffff_ffff_ffff_ffff\n                v = (self.v0[i] & 0xffff_ffff) * (self.v1[i] >> 32)\n                self.mul1[i] = (self.mul1[i] ^ v) & 0xffff_ffff_ffff_ffff\n\n            self.zipper_merge_and_add(self.v1[1], self.v1[0], self.v0, 1, self.v0, 0)\n            self.zipper_merge_and_add(self.v1[3], self.v1[2], self.v0, 3, self.v0, 2)\n            self.zipper_merge_and_add(self.v0[1], self.v0[0], self.v1, 1, self.v1, 0)\n            self.zipper_merge_and_add(self.v0[3], self.v0[2], self.v1, 3, self.v1, 2)\n            return\n\n        def update_packet(self, packet):\n            lanes = [\n                int.from_bytes(packet[0:8], \"little\"),\n                int.from_bytes(packet[8:16], \"little\"),\n                int.from_bytes(packet[16:24], \"little\"),\n                int.from_bytes(packet[24:32], \"little\"),\n            ]\n            self.update_lanes(lanes)\n            return\n\n        def update_remainder(self, bytes_data):\n\n            def rotate32_by(count, lanes):\n                out = [0, 0, 0, 0]\n                for i in range(4):\n                    x = lanes[i] & 0xffff_ffff_ffff_ffff\n                    half0 = x & 0xffff_ffff\n                    half1 = (x >> 32) & 0xffff_ffff\n                    r0 = ((half0 << count) | (half0 >> (32 - count))) & 0xffff_ffff\n                    r1 = ((half1 << count) | (half1 >> (32 - count))) & 0xffff_ffff\n                    out[i] = (r0 | (r1 << 32)) & 0xffff_ffff_ffff_ffff\n                return out\n\n            size_mod32 = len(bytes_data)\n            size_mod4 = size_mod32 & 3\n            packet = bytearray(32)\n\n            for i in range(4):\n                self.v0[i] = (self.v0[i] + ((size_mod32 << 32) + size_mod32)) & 0xffff_ffff_ffff_ffff\n            self.v1 = rotate32_by(size_mod32, self.v1)\n\n            upto = size_mod32 & ~3\n            packet[:upto] = bytes_data[:upto]\n\n            if size_mod32 & 16:\n                tail = bytes_data[size_mod32 - 4 : size_mod32]\n                packet[28:32] = tail\n            else:\n                if size_mod4:\n                    remainder = bytes_data[upto:]\n                    packet[16] = remainder[0]\n                    packet[17] = remainder[size_mod4 >> 1]\n                    packet[18] = remainder[size_mod4 - 1]\n\n            self.update_packet(bytes(packet))\n            return\n\n        def final_permutes(self, rounds):\n            v0 = self.v0\n            for _ in range(rounds):\n                v = [self.swap32(v0[2]), self.swap32(v0[3]), self.swap32(v0[0]), self.swap32(v0[1])]\n                self.update_lanes(v)\n            return\n\n        def finalize_words(self):\n\n            def modular_reduction(a3, a2, a1, a0):\n                a3 &= 0x3fff_ffff_ffff_ffff\n                a3_1l = (a3 << 1) & 0xffff_ffff_ffff_ffff\n                a3_2l = (a3 << 2) & 0xffff_ffff_ffff_ffff\n                a2_1l = (a2 << 1) & 0xffff_ffff_ffff_ffff\n                a2_2l = (a2 << 2) & 0xffff_ffff_ffff_ffff\n                a2_63r = a2 >> 63\n                a2_62r = a2 >> 62\n\n                m1 = a1 ^ (a3_1l | a2_63r) ^ (a3_2l | a2_62r)\n                m0 = a0 ^ a2_1l ^ a2_2l\n                return (m0, m1)\n\n            if self.output_words == 1:\n                w0 = (self.v0[0] + self.v1[0] + self.mul0[0] + self.mul1[0]) & 0xffff_ffff_ffff_ffff\n                return [w0]\n            if self.output_words == 2:\n                w0 = (self.v0[0] + self.mul0[0] + self.v1[2] + self.mul1[2]) & 0xffff_ffff_ffff_ffff\n                w1 = (self.v0[1] + self.mul0[1] + self.v1[3] + self.mul1[3]) & 0xffff_ffff_ffff_ffff\n                return [w0, w1]\n            if self.output_words == 4:\n                a3 = (self.v1[1] + self.mul1[1]) & 0xffff_ffff_ffff_ffff\n                a2 = (self.v1[0] + self.mul1[0]) & 0xffff_ffff_ffff_ffff\n                a1 = (self.v0[1] + self.mul0[1]) & 0xffff_ffff_ffff_ffff\n                a0 = (self.v0[0] + self.mul0[0]) & 0xffff_ffff_ffff_ffff\n                h0, h1 = modular_reduction(a3, a2, a1, a0)\n\n                b3 = (self.v1[3] + self.mul1[3]) & 0xffff_ffff_ffff_ffff\n                b2 = (self.v1[2] + self.mul1[2]) & 0xffff_ffff_ffff_ffff\n                b1 = (self.v0[3] + self.mul0[3]) & 0xffff_ffff_ffff_ffff\n                b0 = (self.v0[2] + self.mul0[2]) & 0xffff_ffff_ffff_ffff\n                h2, h3 = modular_reduction(b3, b2, b1, b0)\n                return [h0, h1, h2, h3]\n            raise ValueError(\"invalid output_words\")\n\n    class HighwayHash64(HighwayHashBase):\n        digest_size = 8\n        output_words = 1\n        final_rounds = 4\n\n    class HighwayHash128(HighwayHashBase):\n        digest_size = 16\n        output_words = 2\n        final_rounds = 6\n\n    class HighwayHash256(HighwayHashBase):\n        digest_size = 32\n        output_words = 4\n        final_rounds = 10\n\n    class GOST:  # codespell:ignore\n        block_size = 32\n        digest_size = 32\n        sbox = None\n\n        sbox = (\n            [0x04, 0x0a, 0x09, 0x02, 0x0d, 0x08, 0x00, 0x0e, 0x06, 0x0b, 0x01, 0x0c, 0x07, 0x0f, 0x05, 0x03],\n            [0x0e, 0x0b, 0x04, 0x0c, 0x06, 0x0d, 0x0f, 0x0a, 0x02, 0x03, 0x08, 0x01, 0x00, 0x07, 0x05, 0x09],\n            [0x05, 0x08, 0x01, 0x0d, 0x0a, 0x03, 0x04, 0x02, 0x0e, 0x0f, 0x0c, 0x07, 0x06, 0x00, 0x09, 0x0b],\n            [0x07, 0x0d, 0x0a, 0x01, 0x00, 0x08, 0x09, 0x0f, 0x0e, 0x04, 0x06, 0x0c, 0x0b, 0x02, 0x05, 0x03],\n            [0x06, 0x0c, 0x07, 0x01, 0x05, 0x0f, 0x0d, 0x08, 0x04, 0x0a, 0x09, 0x0e, 0x00, 0x03, 0x0b, 0x02],\n            [0x04, 0x0b, 0x0a, 0x00, 0x07, 0x02, 0x01, 0x0d, 0x03, 0x06, 0x08, 0x05, 0x09, 0x0c, 0x0f, 0x0e],\n            [0x0d, 0x0b, 0x04, 0x01, 0x03, 0x0f, 0x05, 0x09, 0x00, 0x0a, 0x0e, 0x07, 0x06, 0x08, 0x02, 0x0c],\n            [0x01, 0x0f, 0x0d, 0x00, 0x05, 0x07, 0x0a, 0x04, 0x09, 0x02, 0x03, 0x0e, 0x06, 0x0b, 0x08, 0x0c],\n        )\n\n        def __init__(self, data=b\"\"):\n            if self.sbox is None:\n                raise ValueError(\"sbox must be defined in subclass\")\n            self.hash = [0] * 8\n            self.sum = [0] * 8\n            self.message = bytearray(32)\n            self.msg_length = 0\n            self.gost_sbox = [[0] * 256 for _ in range(4)]\n            self.init_table()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.hash = list(self.hash)\n            other.sum = list(self.sum)\n            other.message = bytearray(self.message)\n            other.msg_length = self.msg_length\n            other.gost_sbox = self.gost_sbox\n            return other\n\n        def rol32(self, x, n):\n            x &= 0xffff_ffff\n            n &= 31\n            return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n        def init_table(self):\n            sbox = self.sbox\n            for a in range(16):\n                ax = (sbox[1][a] << 15) & 0xffff_ffff\n                bx = (sbox[3][a] << 23) & 0xffff_ffff\n                cx = self.rol32(sbox[5][a], 31)\n                dx = (sbox[7][a] << 7) & 0xffff_ffff\n                for b in range(16):\n                    i = a * 16 + b\n                    self.gost_sbox[0][i] = (ax | (sbox[0][b] << 11)) & 0xffff_ffff\n                    self.gost_sbox[1][i] = (bx | (sbox[2][b] << 19)) & 0xffff_ffff\n                    self.gost_sbox[2][i] = (cx | (sbox[4][b] << 27)) & 0xffff_ffff\n                    self.gost_sbox[3][i] = (dx | (sbox[6][b] << 3)) & 0xffff_ffff\n            return\n\n        def encrypt_round(self, key1, key2, r, l):  # noqa: E741\n            tmp = (key1 + r) & 0xffff_ffff\n            l ^= (  # noqa: E741\n                self.gost_sbox[0][tmp & 0xff]\n                ^ self.gost_sbox[1][(tmp >> 8) & 0xff]\n                ^ self.gost_sbox[2][(tmp >> 16) & 0xff]\n                ^ self.gost_sbox[3][(tmp >> 24) & 0xff]\n            )\n            l &= 0xffff_ffff  # noqa: E741\n\n            tmp = (key2 + l) & 0xffff_ffff\n            r ^= (\n                self.gost_sbox[0][tmp & 0xff]\n                ^ self.gost_sbox[1][(tmp >> 8) & 0xff]\n                ^ self.gost_sbox[2][(tmp >> 16) & 0xff]\n                ^ self.gost_sbox[3][(tmp >> 24) & 0xff]\n            )\n            r &= 0xffff_ffff\n            return r, l\n\n        def encrypt(self, ii, key, varhash):\n            r = varhash[ii] & 0xffff_ffff\n            l = varhash[ii + 1] & 0xffff_ffff  # noqa: E741\n\n            r, l = self.encrypt_round(key[0], key[1], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[2], key[3], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[4], key[5], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[6], key[7], r, l)  # noqa: E741\n\n            r, l = self.encrypt_round(key[0], key[1], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[2], key[3], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[4], key[5], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[6], key[7], r, l)  # noqa: E741\n\n            r, l = self.encrypt_round(key[0], key[1], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[2], key[3], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[4], key[5], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[6], key[7], r, l)  # noqa: E741\n\n            r, l = self.encrypt_round(key[7], key[6], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[5], key[4], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[3], key[2], r, l)  # noqa: E741\n            r, l = self.encrypt_round(key[1], key[0], r, l)  # noqa: E741\n\n            return [l & 0xffff_ffff, r & 0xffff_ffff]\n\n        def block_compress(self, block):\n\n            def get_byte32(value, index):\n                return (value >> (index * 8)) & 0xff\n\n            def pack_byte_column(words, byte_index):\n                return (\n                    (get_byte32(words[0], byte_index) << 0)\n                    | (get_byte32(words[1], byte_index) << 8)\n                    | (get_byte32(words[2], byte_index) << 16)\n                    | (get_byte32(words[3], byte_index) << 24)\n                )\n\n            def lo16(value):\n                return value & 0x0000_ffff\n\n            def hi16(value):\n                return value & 0xffff_0000\n\n            def shl16(value):\n                return (value << 16) & 0xffff_ffff\n\n            def shr16(value):\n                return value >> 16\n\n            key = [0] * 8\n            u = [0] * 8\n            v = [0] * 8\n            w = [0] * 8\n            s = [0] * 8\n\n            for i in range(8):\n                u[i] = self.hash[i]\n                v[i] = block[i]\n                w[i] = u[i] ^ v[i]\n\n            i = 0\n            while True:\n                even_words = w[0::2]\n                odd_words = w[1::2]\n                key[0] = pack_byte_column(even_words, 0)\n                key[1] = pack_byte_column(even_words, 1)\n                key[2] = pack_byte_column(even_words, 2)\n                key[3] = pack_byte_column(even_words, 3)\n                key[4] = pack_byte_column(odd_words, 0)\n                key[5] = pack_byte_column(odd_words, 1)\n                key[6] = pack_byte_column(odd_words, 2)\n                key[7] = pack_byte_column(odd_words, 3)\n\n                res = self.encrypt(i, key, self.hash)\n                s[i] = res[0]\n                s[i + 1] = res[1]\n\n                if i == 0:\n                    w[0] = u[2] ^ v[4]\n                    w[1] = u[3] ^ v[5]\n                    w[2] = u[4] ^ v[6]\n                    w[3] = u[5] ^ v[7]\n                    v[0] ^= v[2]\n                    v[1] ^= v[3]\n                    w[4] = u[6] ^ v[0]\n                    w[5] = u[7] ^ v[1]\n                    u[0] ^= u[2]\n                    u[1] ^= u[3]\n                    v[2] ^= v[4]\n                    v[3] ^= v[5]\n                    w[6] = u[0] ^ v[2]\n                    w[7] = u[1] ^ v[3]\n                elif (i & 2) != 0:\n                    if i == 6:\n                        break\n\n                    u[2] ^= u[4] ^ 0x0000_00ff\n                    u[3] ^= u[5] ^ 0xff00_ffff\n                    u[4] ^= 0xff00_ff00\n                    u[5] ^= 0xff00_ff00\n                    u[6] ^= 0x00ff_00ff\n                    u[7] ^= 0x00ff_00ff\n                    u[0] ^= 0x00ff_ff00\n                    u[1] ^= 0xff00_00ff\n\n                    w[0] = u[4] ^ v[0]\n                    w[2] = u[6] ^ v[2]\n                    v[4] ^= v[6]\n                    w[4] = u[0] ^ v[4]\n                    v[6] ^= v[0]\n                    w[6] = u[2] ^ v[6]\n                    w[1] = u[5] ^ v[1]\n                    w[3] = u[7] ^ v[3]\n                    v[5] ^= v[7]\n                    w[5] = u[1] ^ v[5]\n                    v[7] ^= v[1]\n                    w[7] = u[3] ^ v[7]\n                else:\n                    w[0] = u[6] ^ v[4]\n                    w[1] = u[7] ^ v[5]\n                    w[2] = u[0] ^ v[6]\n                    w[3] = u[1] ^ v[7]\n                    v[0] ^= v[2]\n                    v[1] ^= v[3]\n                    w[4] = u[2] ^ v[0]\n                    w[5] = u[3] ^ v[1]\n                    u[4] ^= u[6]\n                    u[5] ^= u[7]\n                    v[2] ^= v[4]\n                    v[3] ^= v[5]\n                    w[6] = u[4] ^ v[2]\n                    w[7] = u[5] ^ v[3]\n\n                for j in range(8):\n                    u[j] &= 0xffff_ffff\n                    v[j] &= 0xffff_ffff\n                    w[j] &= 0xffff_ffff\n\n                i += 2\n\n            u = [0] * 8\n            u[0] = block[0] ^ s[6]\n            u[1] = block[1] ^ s[7]\n            u[2] = (\n                block[2]\n                ^ shl16(s[0]) ^ shr16(s[0]) ^ lo16(s[0])\n                ^ lo16(s[1]) ^ shr16(s[1])\n                ^ shl16(s[2])\n                ^ s[6] ^ shl16(s[6])\n                ^ hi16(s[7]) ^ shr16(s[7])\n            )\n            u[3] = (\n                block[3]\n                ^ lo16(s[0]) ^ shl16(s[0])\n                ^ lo16(s[1]) ^ shl16(s[1]) ^ shr16(s[1])\n                ^ shl16(s[2]) ^ shr16(s[2])\n                ^ shl16(s[3])\n                ^ s[6] ^ shl16(s[6]) ^ shr16(s[6])\n                ^ lo16(s[7]) ^ shl16(s[7]) ^ shr16(s[7])\n            )\n            u[4] = (\n                block[4]\n                ^ hi16(s[0]) ^ shl16(s[0]) ^ shr16(s[0])\n                ^ hi16(s[1]) ^ shr16(s[1])\n                ^ shl16(s[2]) ^ shr16(s[2])\n                ^ shl16(s[3]) ^ shr16(s[3])\n                ^ shl16(s[4])\n                ^ shl16(s[6]) ^ shr16(s[6])\n                ^ lo16(s[7]) ^ shl16(s[7]) ^ shr16(s[7])\n            )\n            u[5] = (\n                block[5]\n                ^ shl16(s[0]) ^ shr16(s[0]) ^ hi16(s[0])\n                ^ lo16(s[1])\n                ^ s[2] ^ shr16(s[2])\n                ^ shl16(s[3]) ^ shr16(s[3])\n                ^ shl16(s[4]) ^ shr16(s[4])\n                ^ shl16(s[5])\n                ^ shl16(s[6]) ^ shr16(s[6])\n                ^ hi16(s[7]) ^ shl16(s[7]) ^ shr16(s[7])\n            )\n            u[6] = (\n                block[6]\n                ^ s[0]\n                ^ shr16(s[1])\n                ^ shl16(s[2])\n                ^ s[3] ^ shr16(s[3])\n                ^ shl16(s[4]) ^ shr16(s[4])\n                ^ shl16(s[5]) ^ shr16(s[5])\n                ^ s[6] ^ shl16(s[6]) ^ shr16(s[6])\n                ^ shl16(s[7])\n            )\n            u[7] = (\n                block[7]\n                ^ hi16(s[0]) ^ shl16(s[0])\n                ^ lo16(s[1]) ^ shl16(s[1])\n                ^ shr16(s[2])\n                ^ shl16(s[3])\n                ^ s[4] ^ shr16(s[4])\n                ^ shl16(s[5]) ^ shr16(s[5])\n                ^ shr16(s[6])\n                ^ lo16(s[7]) ^ shl16(s[7]) ^ shr16(s[7])\n            )\n\n            h = self.hash\n            v = [\n                h[0] ^ shl16(u[1]) ^ shr16(u[0]),\n                h[1] ^ shl16(u[2]) ^ shr16(u[1]),\n                h[2] ^ shl16(u[3]) ^ shr16(u[2]),\n                h[3] ^ shl16(u[4]) ^ shr16(u[3]),\n                h[4] ^ shl16(u[5]) ^ shr16(u[4]),\n                h[5] ^ shl16(u[6]) ^ shr16(u[5]),\n                h[6] ^ shl16(u[7]) ^ shr16(u[6]),\n                h[7] ^ hi16(u[0]) ^ shl16(u[0]) ^ hi16(u[1]) ^ shl16(u[1]) ^ shl16(u[6]) ^ hi16(u[7]) ^ shr16(u[7]),\n            ]\n\n            self.hash = [\n                (\n                    shl16(v[0]) ^ shr16(v[0]) ^ hi16(v[0])\n                    ^ shr16(v[1]) ^ hi16(v[1])\n                    ^ shl16(v[2])\n                    ^ shr16(v[3])\n                    ^ shl16(v[4])\n                    ^ shr16(v[5]) ^ v[5]\n                    ^ shr16(v[6])\n                    ^ shl16(v[7]) ^ shr16(v[7]) ^ lo16(v[7])\n                ),\n                (\n                    shl16(v[0]) ^ shr16(v[0]) ^ hi16(v[0])\n                    ^ lo16(v[1])\n                    ^ shr16(v[2]) ^ v[2]\n                    ^ shl16(v[3])\n                    ^ shr16(v[4])\n                    ^ shl16(v[5])\n                    ^ shl16(v[6]) ^ v[6]\n                    ^ shr16(v[7]) ^ hi16(v[7])\n                ),\n                (\n                    shl16(v[0]) ^ lo16(v[0])\n                    ^ shl16(v[1]) ^ shr16(v[1]) ^ hi16(v[1])\n                    ^ shl16(v[2])\n                    ^ shr16(v[3]) ^ v[3]\n                    ^ shl16(v[4])\n                    ^ shr16(v[5])\n                    ^ shr16(v[6]) ^ v[6]\n                    ^ shl16(v[7]) ^ shr16(v[7]) ^ lo16(v[7])\n                ),\n                (\n                    shl16(v[0]) ^ shr16(v[0]) ^ hi16(v[0])\n                    ^ shr16(v[1]) ^ hi16(v[1])\n                    ^ shl16(v[2]) ^ shr16(v[2]) ^ v[2]\n                    ^ shl16(v[3])\n                    ^ shr16(v[4]) ^ v[4]\n                    ^ shl16(v[5])\n                    ^ shl16(v[6])\n                    ^ shr16(v[7]) ^ lo16(v[7])\n                ),\n                (\n                    shr16(v[0])\n                    ^ shl16(v[1]) ^ v[1]\n                    ^ shr16(v[2]) ^ v[2]\n                    ^ shl16(v[3]) ^ shr16(v[3]) ^ v[3]\n                    ^ shl16(v[4])\n                    ^ shr16(v[5]) ^ v[5]\n                    ^ shl16(v[6]) ^ shr16(v[6])\n                    ^ shl16(v[7])\n                ),\n                (\n                    shl16(v[0]) ^ hi16(v[0])\n                    ^ shl16(v[1]) ^ shr16(v[1]) ^ hi16(v[1])\n                    ^ shl16(v[2]) ^ v[2]\n                    ^ shr16(v[3]) ^ v[3]\n                    ^ shl16(v[4]) ^ shr16(v[4]) ^ v[4]\n                    ^ shl16(v[5])\n                    ^ shl16(v[6]) ^ shr16(v[6]) ^ v[6]\n                    ^ shl16(v[7]) ^ shr16(v[7]) ^ hi16(v[7])\n                ),\n                (\n                    v[0]\n                    ^ shr16(v[2]) ^ v[2]\n                    ^ shl16(v[3]) ^ v[3]\n                    ^ shr16(v[4]) ^ v[4]\n                    ^ shl16(v[5]) ^ shr16(v[5]) ^ v[5]\n                    ^ shl16(v[6]) ^ shr16(v[6]) ^ v[6]\n                    ^ shl16(v[7]) ^ v[7]\n                ),\n                (\n                    shr16(v[0]) ^ v[0]\n                    ^ shl16(v[1]) ^ shr16(v[1])\n                    ^ shl16(v[2])\n                    ^ shr16(v[3]) ^ v[3]\n                    ^ shl16(v[4]) ^ v[4]\n                    ^ shr16(v[5]) ^ v[5]\n                    ^ shl16(v[6]) ^ shr16(v[6])\n                    ^ shl16(v[7]) ^ v[7]\n                ),\n            ]\n            return\n\n        def compute_sum_and_hash(self, block):\n            carry = 0\n            for i in range(8):\n                hb = (self.sum[i] >> 24) & 0xff\n                self.sum[i] = (self.sum[i] & 0x00ff_ffff) + (block[i] & 0x00ff_ffff) + carry\n                hb = hb + ((block[i] >> 24) & 0xff) + ((self.sum[i] >> 24) & 0xff)\n                self.sum[i] = (self.sum[i] & 0x00ff_ffff) | ((hb & 0xff) << 24)\n                carry = 1 if (hb & 0x100) != 0 else 0\n                self.sum[i] &= 0xffff_ffff\n            self.block_compress(block)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            size = len(data)\n            index = self.msg_length & 31\n            self.msg_length += size\n            p = 0\n\n            if index != 0:\n                left = 32 - index\n                if size < left:\n                    self.message[index : index + size] = data[:size]\n                    return self\n                self.message[index : index + left] = data[:left]\n                block = [0] * 8\n                for i in range(8):\n                    j = 4 * i\n                    block[i] = (\n                        self.message[j]\n                        | (self.message[j + 1] << 8)\n                        | (self.message[j + 2] << 16)\n                        | (self.message[j + 3] << 24)\n                    ) & 0xffff_ffff\n                self.compute_sum_and_hash(block)\n                p += left\n                size -= left\n\n            while size >= 32:\n                self.message[:] = data[p : p + 32]\n                block = [0] * 8\n                for i in range(8):\n                    j = 4 * i\n                    block[i] = (\n                        self.message[j]\n                        | (self.message[j + 1] << 8)\n                        | (self.message[j + 2] << 16)\n                        | (self.message[j + 3] << 24)\n                    ) & 0xffff_ffff\n                self.compute_sum_and_hash(block)\n                p += 32\n                size -= 32\n\n            if size != 0:\n                self.message[:size] = data[p : p + size]\n            return self\n\n        def finalize(self):\n            index = self.msg_length & 31\n\n            if index > 0:\n                for i in range(32 - index):\n                    self.message[index + i] = 0\n                block = [0] * 8\n                for i in range(8):\n                    j = 4 * i\n                    block[i] = (\n                        self.message[j]\n                        | (self.message[j + 1] << 8)\n                        | (self.message[j + 2] << 16)\n                        | (self.message[j + 3] << 24)\n                    ) & 0xffff_ffff\n                self.compute_sum_and_hash(block)\n\n            block = [0] * 8\n            block[0] = (self.msg_length << 3) & 0xffff_ffff\n            block[1] = (self.msg_length >> 29) & 0xffff_ffff\n            for i in range(2, 8):\n                block[i] = 0\n\n            self.block_compress(block)\n            self.block_compress(self.sum)\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytearray()\n            for w in c.hash:\n                out.extend(struct.pack(\"<I\", w & 0xffff_ffff))\n            return bytes(out)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class GOST94cp(GOST):  # codespell:ignore\n        sbox = (\n            (0x0a, 0x04, 0x05, 0x06, 0x08, 0x01, 0x03, 0x07, 0x0d, 0x0c, 0x0e, 0x00, 0x09, 0x02, 0x0b, 0x0f),\n            (0x05, 0x0f, 0x04, 0x00, 0x02, 0x0d, 0x0b, 0x09, 0x01, 0x07, 0x06, 0x03, 0x0c, 0x0e, 0x0a, 0x08),\n            (0x07, 0x0f, 0x0c, 0x0e, 0x09, 0x04, 0x01, 0x00, 0x03, 0x0b, 0x05, 0x02, 0x06, 0x0a, 0x08, 0x0d),\n            (0x04, 0x0a, 0x07, 0x0c, 0x00, 0x0f, 0x02, 0x08, 0x0e, 0x01, 0x06, 0x05, 0x0d, 0x0b, 0x09, 0x03),\n            (0x07, 0x06, 0x04, 0x0b, 0x09, 0x0c, 0x02, 0x0a, 0x01, 0x08, 0x00, 0x0e, 0x0f, 0x0d, 0x03, 0x05),\n            (0x07, 0x06, 0x02, 0x04, 0x0d, 0x09, 0x0f, 0x00, 0x0a, 0x01, 0x05, 0x0b, 0x08, 0x0e, 0x0c, 0x03),\n            (0x0d, 0x0e, 0x04, 0x01, 0x07, 0x00, 0x05, 0x0a, 0x03, 0x0c, 0x08, 0x0f, 0x06, 0x02, 0x09, 0x0b),\n            (0x01, 0x03, 0x0a, 0x09, 0x05, 0x0b, 0x04, 0x0f, 0x08, 0x06, 0x07, 0x0e, 0x0d, 0x00, 0x02, 0x0c),\n        )\n\n    class Mt19937_64:\n        n = 312\n        m = 156\n        matrix_a = 0xb502_6f5a_a966_19e9\n        upper_mask = 0xffff_ffff_8000_0000\n        lower_mask = 0x7fff_ffff\n        f = 0x5851_f42d_4c95_7f2d\n\n        def __init__(self, seed=0x1571):\n            self.mt = [0] * self.n\n            self.index = self.n\n            self.seed(seed)\n            return\n\n        def seed(self, seed):\n            self.mt[0] = seed & 0xffff_ffff_ffff_ffff\n            for i in range(1, self.n):\n                prev = self.mt[i - 1]\n                self.mt[i] = (self.f * (prev ^ (prev >> 62)) + i) & 0xffff_ffff_ffff_ffff\n            self.index = self.n\n            return\n\n        def twist(self):\n            for i in range(self.n):\n                x = (self.mt[i] & self.upper_mask) + (self.mt[(i + 1) % self.n] & self.lower_mask)\n                x_a = x >> 1\n                if x & 1:\n                    x_a ^= self.matrix_a\n                self.mt[i] = (self.mt[(i + self.m) % self.n] ^ x_a) & 0xffff_ffff_ffff_ffff\n            self.index = 0\n            return\n\n        def next_u64(self):\n            if self.index >= self.n:\n                self.twist()\n            y = self.mt[self.index]\n            self.index += 1\n            y ^= (y >> 29) & 0x5555_5555_5555_5555\n            y ^= (y << 17) & 0x71d6_7fff_eda6_0000\n            y ^= (y << 37) & 0xfff7_eee0_0000_0000\n            y ^= (y >> 43)\n            return y & 0xffff_ffff_ffff_ffff\n\n    class HalfTimeHashBase:\n        out_width = 2\n        in_width = 3\n        dimension = 6\n        encoded_dimension = 7\n        fanout = 8\n        max_stack_size = 9\n        digest_size = 8\n        block_size = 1\n        lanes = 1\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.digest_bytes\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            data = bytes(self.buf)\n            value = self.hash_uint64(data)\n            self.digest_bytes = struct.pack(\">Q\", value)\n            return\n\n        def entropy_words_needed_for_hasher(self, length):\n\n            def floor_log(a, b):\n                if a <= 1:\n                    return 0\n                h = 0\n                while b >= a:\n                    b //= a\n                    h += 1\n                return h\n\n            b = self.lanes\n            h = floor_log(self.fanout, length // (b * self.dimension * self.in_width))\n            words = (self.encoded_dimension * self.in_width) \\\n                    + (self.fanout - 1) * self.out_width * h \\\n                    + b * self.fanout * self.out_width * h \\\n                    + b * self.dimension * self.in_width \\\n                    + self.out_width - 1\n            return words\n\n        def hash_uint64(self, data):\n\n            def tabulate_bytes(value, entropy, base):\n                result = 0\n                for i in range(8):\n                    index = (value >> (8 * i)) & 0xff\n                    result ^= entropy[base + i * 256 + index]\n                return result & 0xffff_ffff_ffff_ffff\n\n            def ensure_entropy_words(needed):\n                entropy_mt = Hash.Mt19937_64()\n                entropy_words = []\n                while len(entropy_words) < needed:\n                    entropy_words.append(entropy_mt.next_u64())\n                return entropy_words\n\n            length = len(data)\n            table_max = 24 * 256\n            entropy_for_hasher_offset = self.out_width * 256\n            hasher_words = self.entropy_words_needed_for_hasher(length)\n            needed = max(table_max, entropy_for_hasher_offset + hasher_words + (self.out_width + 2) * self.lanes + 32)\n            entropy = ensure_entropy_words(needed)\n\n            output0, output1 = self.hasher(entropy, entropy_for_hasher_offset, data, length)\n\n            result = tabulate_bytes(length, entropy, 0)\n            result ^= tabulate_bytes(output0, entropy, 8 * 256)\n            result ^= tabulate_bytes(output1, entropy, 16 * 256)\n            return result\n\n        def load_one(self, word):\n            w = word & 0xffff_ffff_ffff_ffff\n            return [w] * self.lanes\n\n        def load_block_words(self, entropy, offset):\n            return [(entropy[offset + i] & 0xffff_ffff_ffff_ffff) for i in range(self.lanes)]\n\n        def load_block_bytes(self, data, offset_bytes):\n            out = []\n            for i in range(self.lanes):\n                chunk = data[offset_bytes + 8 * i: offset_bytes + 8 * (i + 1)]\n                if len(chunk) < 8:\n                    chunk = chunk + b\"\\x00\" * (8 - len(chunk))\n                out.append(int.from_bytes(chunk, \"little\") & 0xffff_ffff_ffff_ffff)\n            return out\n\n        def plus(self, a, b):\n            return [((x + y) & 0xffff_ffff_ffff_ffff) for x, y in zip(a, b)]\n\n        def minus(self, a, b):\n            return [((x - y) & 0xffff_ffff_ffff_ffff) for x, y in zip(a, b)]\n\n        def xor(self, a, b):\n            return [((x ^ y) & 0xffff_ffff_ffff_ffff) for x, y in zip(a, b)]\n\n        def left_shift(self, a, s):\n            return [((x << s) & 0xffff_ffff_ffff_ffff) for x in a]\n\n        def right_shift32(self, a):\n            return [((x >> 32) & 0xffff_ffff_ffff_ffff) for x in a]\n\n        def plus32(self, a, b):\n            out = []\n            for x, y in zip(a, b):\n                lo = (x & 0xffff_ffff) + (y & 0xffff_ffff)\n                hi = ((x >> 32) & 0xffff_ffff) + ((y >> 32) & 0xffff_ffff)\n                lo &= 0xffff_ffff\n                hi &= 0xffff_ffff\n                out.append((lo | (hi << 32)) & 0xffff_ffff_ffff_ffff)\n            return out\n\n        def times(self, a, b):\n            out = []\n            for x, y in zip(a, b):\n                out.append(((x & 0xffff_ffff) * (y & 0xffff_ffff)) & 0xffff_ffff_ffff_ffff)\n            return out\n\n        def negate(self, a):\n            return [(-x) & 0xffff_ffff_ffff_ffff for x in a]\n\n        def sum_block(self, a):\n            s = 0\n            for x in a:\n                s = (s + x) & 0xffff_ffff_ffff_ffff\n            return s\n\n        def multiply_add(self, summand, factor1, factor2):\n            return self.plus(summand, self.times(factor1, factor2))\n\n        def mix(self, accum, input_block, entropy_block):\n            out = self.plus32(entropy_block, input_block)\n            twin = self.right_shift32(out)\n            out = self.multiply_add(accum, out, twin)\n            return out\n\n        def mix_one(self, accum, input_block, entropy_word):\n            return self.mix(accum, input_block, self.load_one(entropy_word))\n\n        def mix_none(self, input_block, entropy_word):\n            out = self.plus32(self.load_one(entropy_word), input_block)\n            twin = self.right_shift32(out)\n            out = self.times(out, twin)\n            return out\n\n        def simpler_times(self, k, x):\n            if k == -1:\n                return self.negate(x)\n            if k == 0:\n                return [0] * self.lanes\n            if k == 1:\n                return x\n            if k == 2:\n                return self.left_shift(x, 1)\n            if k == 3:\n                return self.plus(x, self.left_shift(x, 1))\n            if k == 4:\n                return self.left_shift(x, 2)\n            if k == 5:\n                return self.plus(x, self.left_shift(x, 2))\n            if k == 7:\n                return self.minus(self.left_shift(x, 3), x)\n            if k == 8:\n                return self.left_shift(x, 3)\n            if k == 9:\n                return self.plus(x, self.left_shift(x, 3))\n            raise ValueError(\"unsupported multiplier\")\n\n        def dot2(self, sinks, x, c0, c1):\n            sinks[0] = self.plus(sinks[0], self.simpler_times(c0, x))\n            sinks[1] = self.plus(sinks[1], self.simpler_times(c1, x))\n            return sinks\n\n        def combine2(self, input_blocks):\n            sinks = [input_blocks[0], input_blocks[1]]\n            self.dot2(sinks, input_blocks[2], 1, 1)\n            self.dot2(sinks, input_blocks[3], 1, 2)\n            self.dot2(sinks, input_blocks[4], 2, 1)\n            self.dot2(sinks, input_blocks[5], 1, 4)\n            self.dot2(sinks, input_blocks[6], 4, 1)\n            return sinks\n\n        def encode2(self, io):\n            for i in range(self.in_width):\n                acc = io[0][i]\n                for j in range(1, self.dimension):\n                    acc = self.xor(acc, io[j][i])\n                io[self.dimension][i] = acc\n            return io\n\n        def parse_entropy_matrix(self, entropy, offset):\n            m = []\n            idx = offset\n            for _i in range(self.encoded_dimension):\n                row = []\n                for _j in range(self.in_width):\n                    row.append(entropy[idx] & 0xffff_ffff_ffff_ffff)\n                    idx += 1\n                m.append(row)\n            return m\n\n        def hash_matrix(self, input_matrix, entropy_matrix):\n            out = [None] * self.encoded_dimension\n            for i in range(self.encoded_dimension):\n                out[i] = self.mix_none(input_matrix[i][0], entropy_matrix[i][0])\n            for j in range(1, self.in_width):\n                for i in range(self.encoded_dimension):\n                    out[i] = self.mix_one(out[i], input_matrix[i][j], entropy_matrix[i][j])\n            return out\n\n        def ehc_base_layer(self, entropy, entropy_offset, data, data_offset_bytes):\n            block_size = 8 * self.lanes\n            io = [[None] * self.in_width for _ in range(self.encoded_dimension)]\n            zero = [0] * self.lanes\n            for i in range(self.dimension):\n                for j in range(self.in_width):\n                    io[i][j] = self.load_block_bytes(data, data_offset_bytes + (i * self.in_width + j) * block_size)\n            for i in range(self.dimension, self.encoded_dimension):\n                for j in range(self.in_width):\n                    io[i][j] = zero\n            self.encode2(io)\n            entropy_matrix = self.parse_entropy_matrix(entropy, entropy_offset)\n            tmp = self.hash_matrix(io, entropy_matrix)\n            out_blocks = self.combine2(tmp)\n            return out_blocks\n\n        def ehc_upper_layer(self, entropy, entropy_offset, input_blocks):\n            output = [None] * self.out_width\n            for i in range(self.out_width):\n                acc = input_blocks[0][i]\n                for j in range(1, self.fanout):\n                    acc = self.mix_one(acc, input_blocks[j][i], entropy[entropy_offset + (self.fanout - 1) * i + (j - 1)])\n                output[i] = acc\n            return output\n\n        def dfs_tree_hash(self, entropy, entropy_offset, data, block_group_length, stack, stack_lengths):\n            group_bytes = self.dimension * self.in_width * 8 * self.lanes\n            for k in range(block_group_length):\n                i = 0\n                while stack_lengths[i] == self.fanout:\n                    i += 1\n                for j in range(i - 1, -1, -1):\n                    upper_entropy_offset = entropy_offset + (self.encoded_dimension * self.in_width) + \\\n                        (self.fanout - 1) * self.out_width * j\n                    stack[j + 1][stack_lengths[j + 1]] = self.ehc_upper_layer(entropy, upper_entropy_offset, stack[j])\n                    stack_lengths[j] = 0\n                    stack_lengths[j + 1] += 1\n                stack[0][stack_lengths[0]] = self.ehc_base_layer(entropy, entropy_offset, data, k * group_bytes)\n                stack_lengths[0] += 1\n            return\n\n        def dfs_greedy_finalizer(self, entropy, entropy_offset, stack, stack_lengths, tail_bytes):\n            block_words = self.lanes\n            block_size = 8 * self.lanes\n            accum = [[0] * self.lanes for _ in range(self.out_width)]\n            idx = entropy_offset\n\n            j = 0\n            while j < len(stack_lengths) and stack_lengths[j] > 0:\n                for k in range(stack_lengths[j]):\n                    x_out = stack[j][k]\n                    for i in range(self.out_width):\n                        seed_block = self.load_block_words(entropy, idx)\n                        accum[i] = self.mix(accum[i], x_out[i], seed_block)\n                        idx += block_words\n                j += 1\n\n            i = 0\n            while i + block_size <= len(tail_bytes):\n                x_block = self.load_block_bytes(tail_bytes, i)\n                base = idx\n                for o in range(self.out_width):\n                    seed_block = self.load_block_words(entropy, base + o * block_words)\n                    accum[o] = self.mix(accum[o], x_block, seed_block)\n                idx += block_words\n                i += block_size\n\n            x_block = self.load_block_bytes(tail_bytes, i)\n            base = idx\n            for o in range(self.out_width):\n                seed_block = self.load_block_words(entropy, base + o * block_words)\n                accum[o] = self.mix(accum[o], x_block, seed_block)\n            idx += block_words\n\n            output0 = self.sum_block(accum[0])\n            output1 = self.sum_block(accum[1])\n            return output0, output1\n\n        def hasher(self, entropy, entropy_offset, data, length):\n            group_bytes = self.dimension * self.in_width * 8 * self.lanes\n            wide_length = length // group_bytes\n\n            stack = [\n                [\n                    [ [0] * self.lanes for _ in range(self.out_width)]\n                    for _ in range(self.fanout)\n                ] for _ in range(self.max_stack_size)\n            ]\n            stack_lengths = [0] * self.max_stack_size\n\n            self.dfs_tree_hash(entropy, entropy_offset, data, wide_length, stack, stack_lengths)\n\n            greedy_entropy_offset = entropy_offset + (self.encoded_dimension * self.in_width) + \\\n                self.out_width * (self.fanout - 1) * self.max_stack_size\n            used = wide_length * group_bytes\n            tail = data[used:]\n            return self.dfs_greedy_finalizer(entropy, greedy_entropy_offset, stack, stack_lengths, tail)\n\n    class HalfTimeHash64(HalfTimeHashBase):\n        lanes = 1\n\n    class HalfTimeHash128(HalfTimeHashBase):\n        lanes = 2\n\n    class HalfTimeHash256(HalfTimeHashBase):\n        lanes = 4\n\n    class HalfTimeHash512(HalfTimeHashBase):\n        lanes = 8\n\n    class WYHashBase:\n        block_size = 64\n        digest_size = 0\n        mask = 0\n        default_seed = 0\n\n        def __init__(self, data=b\"\", seed=None):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if seed is None:\n                self.seed = self.default_seed & self.mask\n            else:\n                if not isinstance(seed, int):\n                    raise TypeError(\"seed must be int\")\n                self.seed = seed & self.mask\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.result = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.result = self.result\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def sum(self):\n            c = self.copy()\n            c.finalize()\n            return c.result\n\n        def digest(self):\n            h = self.sum()\n            return int(h).to_bytes(self.digest_size, byteorder=\"big\", signed=False)\n\n        def hexdigest(self):\n            width = self.digest_size * 2\n            return format(self.sum(), \"0{}x\".format(width))\n\n        def finalize(self):\n            data = bytes(self.buf)\n            self.result = self.hash(data) & self.mask\n            return\n\n        def u32le(self, data, off):\n            return int.from_bytes(data[off:off + 4], byteorder=\"little\", signed=False)\n\n        def u64le(self, data, off):\n            return int.from_bytes(data[off:off + 8], byteorder=\"little\", signed=False)\n\n    class WYHash32(WYHashBase):\n        digest_size = 4\n        mask = 0xffff_ffff\n        default_seed = 0\n        prime1 = 0x53c5_ca59\n        prime2 = 0x7474_3c1b\n\n        def mix32(self, a, b):\n            a &= self.mask\n            b &= self.mask\n            c = (a ^ self.prime1) * (b ^ self.prime2)\n            lo = c & self.mask\n            hi = (c >> 32) & self.mask\n            return lo, hi\n\n        def r24(self, data, off, k):\n            return (((data[off] & 0xff) << 16) | ((data[off + (k >> 1)] & 0xff) << 8) | (data[off + k - 1] & 0xff)) & self.mask\n\n        def hash(self, data):\n            length = len(data)\n            p = 0\n            i = length\n            seed = self.seed & self.mask\n            see1 = length & self.mask\n            seed ^= (length >> 32) & self.mask\n            seed, see1 = self.mix32(seed, see1)\n\n            while i > 8:\n                seed ^= self.u32le(data, p)\n                see1 ^= self.u32le(data, p + 4)\n                seed, see1 = self.mix32(seed, see1)\n                p += 8\n                i -= 8\n\n            if i >= 4:\n                seed ^= self.u32le(data, p)\n                see1 ^= self.u32le(data, p + i - 4)\n            elif i:\n                seed ^= self.r24(data, p, i)\n\n            seed, see1 = self.mix32(seed, see1)\n            seed, see1 = self.mix32(seed, see1)\n            return seed ^ see1\n\n    class WYHash64(WYHashBase):\n        digest_size = 8\n        mask = 0xffff_ffff_ffff_ffff\n        secret = (\n            0xa076_1d64_78bd_642f, 0xe703_7ed1_a0b4_28db, 0x8ebc_6af0_9c88_c6e3, 0x5899_65cc_7537_4cc3,\n        )\n        default_seed = secret[0]\n\n        def mix64(self, a, b):\n            a &= self.mask\n            b &= self.mask\n            c = a * b\n            lo = c & self.mask\n            hi = (c >> 64) & self.mask\n            return lo ^ hi\n\n        def r3(self, data, off, k):\n            return ((data[off] << 16) | (data[off + (k >> 1)] << 8) | data[off + k - 1]) & self.mask\n\n        def hash(self, data):\n            length = len(data)\n            p = 0\n            seed = self.seed\n            a = 0\n            b = 0\n\n            if length <= 16:\n                if length >= 4:\n                    a = (\n                        (self.u32le(data, p) << 32)\n                        | self.u32le(data, p + ((length >> 3) << 2))\n                    ) & self.mask\n                    b = (\n                        (self.u32le(data, p + length - 4) << 32)\n                        | self.u32le(data, p + length - 4 - ((length >> 3) << 2))\n                    ) & self.mask\n                elif length > 0:\n                    a = self.r3(data, p, length)\n                    b = 0\n                else:\n                    a = 0\n                    b = 0\n            else:\n                i = length\n                if i > 48:\n                    see1 = see2 = seed\n                    while i > 48:\n                        seed = self.mix64(self.u64le(data, p) ^ self.secret[1], self.u64le(data, p + 8) ^ seed)\n                        see1 = self.mix64(self.u64le(data, p + 16) ^ self.secret[2], self.u64le(data, p + 24) ^ see1)\n                        see2 = self.mix64(self.u64le(data, p + 32) ^ self.secret[3], self.u64le(data, p + 40) ^ see2)\n                        p += 48\n                        i -= 48\n                    seed = seed ^ see1 ^ see2\n                while i > 16:\n                    seed = self.mix64(self.u64le(data, p) ^ self.secret[1], self.u64le(data, p + 8) ^ seed)\n                    p += 16\n                    i -= 16\n                a = self.u64le(data, p + i - 16)\n                b = self.u64le(data, p + i - 8)\n\n            return self.mix64(self.secret[1] ^ (length & self.mask), self.mix64(a ^ self.secret[1], b ^ seed))\n\n    class HAS160:\n        block_size = 64  # 512 bits\n        digest_size = 20  # 160 bits\n\n        ROT_A = (5, 11, 7, 15, 6, 13, 8, 14, 7, 12, 9, 11, 8, 15, 6, 12, 9, 14, 5, 13)\n        ROT_B = (10, 17, 25, 30)\n        K = (0x0000_0000, 0x5a82_7999, 0x6ed9_eba1, 0x8f1b_bcdc)\n        ORDER = (\n            (18, 0, 1, 2, 3, 19, 4, 5, 6, 7, 16, 8, 9, 10, 11, 17, 12, 13, 14, 15),\n            (18, 3, 6, 9, 12, 19, 15, 2, 5, 8, 16, 11, 14, 1, 4, 17, 7, 10, 13, 0),\n            (18, 12, 5, 14, 7, 19, 0, 9, 2, 11, 16, 4, 13, 6, 15, 17, 8, 1, 10, 3),\n            (18, 7, 2, 13, 8, 19, 3, 14, 9, 4, 16, 15, 10, 5, 0, 17, 11, 6, 1, 12),\n        )\n\n        def __init__(self, data=b\"\"):\n            self.h0 = 0x6745_2301\n            self.h1 = 0xefcd_ab89\n            self.h2 = 0x98ba_dcfe\n            self.h3 = 0x1032_5476\n            self.h4 = 0xc3d2_e1f0\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h0 = self.h0\n            other.h1 = self.h1\n            other.h2 = self.h2\n            other.h3 = self.h3\n            other.h4 = self.h4\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return struct.pack(\"<5I\", c.h0, c.h1, c.h2, c.h3, c.h4)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n            while (len(self.buf) % 64) != 56:\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\"<Q\", bit_len))\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.compress(block)\n            return\n\n        def compress(self, block):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            def f0(x, y, z):\n                return ((x & y) | ((~x) & z)) & 0xffff_ffff\n\n            def f1(x, y, z):\n                return (x ^ y ^ z) & 0xffff_ffff\n\n            def f2(x, y, z):\n                return (y ^ (x | (~z))) & 0xffff_ffff\n\n            a = self.h0\n            b = self.h1\n            c = self.h2\n            d = self.h3\n            e = self.h4\n            x = list(struct.unpack(\"<16I\", block))\n\n            for r in range(4):\n                if r == 0:\n                    x16 = x[0] ^ x[1] ^ x[2] ^ x[3]\n                    x17 = x[4] ^ x[5] ^ x[6] ^ x[7]\n                    x18 = x[8] ^ x[9] ^ x[10] ^ x[11]\n                    x19 = x[12] ^ x[13] ^ x[14] ^ x[15]\n                    f = f0\n                elif r == 1:\n                    x16 = x[3] ^ x[6] ^ x[9] ^ x[12]\n                    x17 = x[15] ^ x[2] ^ x[5] ^ x[8]\n                    x18 = x[11] ^ x[14] ^ x[1] ^ x[4]\n                    x19 = x[7] ^ x[10] ^ x[13] ^ x[0]\n                    f = f1\n                elif r == 2:\n                    x16 = x[12] ^ x[5] ^ x[14] ^ x[7]\n                    x17 = x[0] ^ x[9] ^ x[2] ^ x[11]\n                    x18 = x[4] ^ x[13] ^ x[6] ^ x[15]\n                    x19 = x[8] ^ x[1] ^ x[10] ^ x[3]\n                    f = f2\n                else:\n                    x16 = x[7] ^ x[2] ^ x[13] ^ x[8]\n                    x17 = x[3] ^ x[14] ^ x[9] ^ x[4]\n                    x18 = x[15] ^ x[10] ^ x[5] ^ x[0]\n                    x19 = x[11] ^ x[6] ^ x[1] ^ x[12]\n                    f = f1\n\n                words = x + [x16, x17, x18, x19]\n                k = self.K[r]\n                rb = self.ROT_B[r]\n                order = self.ORDER[r]\n\n                for t in range(20):\n                    w = words[order[t]]\n                    temp = (rol32(a, self.ROT_A[t]) + f(b, c, d) + e + w + k) & 0xffff_ffff\n                    e = d\n                    d = c\n                    c = rol32(b, rb)\n                    b = a\n                    a = temp\n\n            self.h0 = (self.h0 + a) & 0xffff_ffff\n            self.h1 = (self.h1 + b) & 0xffff_ffff\n            self.h2 = (self.h2 + c) & 0xffff_ffff\n            self.h3 = (self.h3 + d) & 0xffff_ffff\n            self.h4 = (self.h4 + e) & 0xffff_ffff\n            return\n\n    class SnefruBase:\n        block_size = 64\n        security_level = 8\n        standard_sboxes = (\n            (\n                0x64f9_001b, 0xfedd_cdf6, 0x7c8f_f1e2, 0x11d7_1514, 0x8b8c_18d3, 0xdddf_881e, 0x6eab_5056, 0x88ce_d8e1,\n                0x4914_8959, 0x69c5_6fd5, 0xb799_4f03, 0x0fbc_ee3e, 0x3c26_4940, 0x2155_7e58, 0xe14b_3fc2, 0x2e5c_f591,\n                0xdcef_f8ce, 0x092a_1648, 0xbe81_2936, 0xff7b_0c6a, 0xd525_1037, 0xafa4_48f1, 0x7daf_c95a, 0x1ea6_9c3f,\n                0xa417_abe7, 0x5890_e423, 0xb0cb_70c0, 0xc850_25f7, 0x244d_97e3, 0x1ff3_595f, 0xc4ec_6396, 0x5918_1e17,\n                0xe635_b477, 0x354e_7dbf, 0x796f_7753, 0x66eb_52cc, 0x77c3_f995, 0x32e3_a927, 0x80cc_aed6, 0x4e2b_e89d,\n                0x375b_bd28, 0xad1a_3d05, 0x2b1b_42b3, 0x16c4_4c71, 0x4d54_bfa8, 0xe57d_dc7a, 0xec6d_8144, 0x5a71_046b,\n                0xd822_9650, 0x87fc_8f24, 0xcbc6_0e09, 0xb639_0366, 0xd9f7_6092, 0xd393_a70b, 0x1d31_a08a, 0x9cd9_71c9,\n                0x5c1e_f445, 0x86fa_b694, 0xfdb4_4165, 0x8eaa_fcbe, 0x4bca_c6eb, 0xfb7a_94e5, 0x5789_d04e, 0xfa13_cf35,\n                0x236b_8da9, 0x4133_f000, 0x6224_261c, 0xf412_f23b, 0xe75e_56a4, 0x3002_2116, 0xbaf1_7f1f, 0xd098_72f9,\n                0xc1a3_699c, 0xf1e8_02aa, 0x0dd1_45dc, 0x4fdc_e093, 0x8d84_12f0, 0x6cd0_f376, 0x3de6_b73d, 0x84ba_737f,\n                0xb43a_30f2, 0x4456_9f69, 0x00e4_eaca, 0xb58d_e3b0, 0x9591_13c8, 0xd62e_fee9, 0x9086_1f83, 0xced6_9874,\n                0x2f79_3cee, 0xe857_1c30, 0x4836_65d1, 0xab07_b031, 0x914c_844f, 0x15bf_3be8, 0x2c3f_2a9a, 0x9eb9_5fd4,\n                0x92e7_472d, 0x2297_cc5b, 0xee5f_2782, 0x5377_b562, 0xdb8e_bbcf, 0xf961_dedd, 0xc59b_5c60, 0x1bd3_910d,\n                0x26d2_06ad, 0xb285_14d8, 0x5ecf_6b52, 0x7fea_78bb, 0x5048_79ac, 0xed34_a884, 0x36e5_1d3c, 0x1753_741d,\n                0x8c47_caed, 0x9d0a_40ef, 0x3145_e221, 0xda27_eb70, 0xdf73_0ba3, 0x183c_8789, 0x739a_c0a6, 0x9a58_dfc6,\n                0x54b1_34c1, 0xac3e_242e, 0xcc49_3902, 0x7b2d_da99, 0x8f15_bc01, 0x29fd_38c7, 0x27d5_318f, 0x604a_aff5,\n                0xf29c_6818, 0xc38a_a2ec, 0x1019_d4c3, 0xa8fb_936e, 0x20ed_7b39, 0x0b68_6119, 0x89a0_906f, 0x1cc7_829e,\n                0x9952_ef4b, 0x850e_9e8c, 0xcd06_3a90, 0x6700_2f8e, 0xcfac_8cb7, 0xeaa2_4b11, 0x988b_4e6c, 0x46f0_66df,\n                0xca7e_ec08, 0xc7bb_a664, 0x831d_17bd, 0x63f5_75e6, 0x9764_350e, 0x4787_0d42, 0x026c_a4a2, 0x8167_d587,\n                0x61b6_adab, 0xaa65_64d2, 0x70da_237b, 0x25e1_c74a, 0xa1c9_01a0, 0x0eb0_a5da, 0x7670_f741, 0x51c0_5aea,\n                0x933d_fa32, 0x0759_ff1a, 0x5601_0ab8, 0x5fde_cb78, 0x3f32_edf8, 0xaebe_dbb9, 0x39f8_326d, 0xd208_58c5,\n                0x9b63_8be4, 0xa572_c80a, 0x28e0_a19f, 0x4320_99fc, 0x3a37_c3cd, 0xbf95_c585, 0xb392_c12a, 0x6aa7_07d7,\n                0x52f6_6a61, 0x12d4_83b1, 0x9643_5b5e, 0x3e75_802b, 0x3ba5_2b33, 0xa99f_51a5, 0xbda1_e157, 0x78c2_e70c,\n                0xfcae_7ce0, 0xd160_2267, 0x2aff_ac4d, 0x4a51_0947, 0x0ab2_b83a, 0x7a04_e579, 0x340d_fd80, 0xb916_e922,\n                0xe29d_5e9b, 0xf562_4af4, 0x4ca9_d9af, 0x6bbd_2cfe, 0xe3b7_f620, 0xc274_6e07, 0x5b42_b9b6, 0xa069_19bc,\n                0xf0f2_c40f, 0x7221_7ab5, 0x14c1_9df3, 0xf380_2dae, 0xe094_beb4, 0xa210_1aff, 0x0529_575d, 0x55cd_b27c,\n                0xa33b_ddb2, 0x6528_b37d, 0x740c_05db, 0xe96a_62c4, 0x4078_2846, 0x6d30_d706, 0xbbf4_8e2c, 0xbce2_d3de,\n                0x049e_37fa, 0x01b5_e634, 0x2d88_6d8d, 0x7e5a_2e7e, 0xd741_2013, 0x06e9_0f97, 0xe45d_3eba, 0xb8ad_3386,\n                0x1305_1b25, 0x0c03_5354, 0x71c8_9b75, 0xc638_fbd0, 0x197f_11a1, 0xef0f_08fb, 0xf844_8651, 0x3840_9563,\n                0x452f_4443, 0x5d46_4d55, 0x03d8_764c, 0xb1b8_d638, 0xa70b_ba2f, 0x94b3_d210, 0xeb66_92a7, 0xd409_c2d9,\n                0x6883_8526, 0xa6db_8a15, 0x751f_6c98, 0xde76_9a88, 0xc9ee_4668, 0x1a82_a373, 0x0896_aa49, 0x4223_3681,\n                0xf62c_55cb, 0x9f1c_5404, 0xf74f_b15c, 0xc06e_4312, 0x6ffe_5d72, 0x8aa8_678b, 0x337c_d129, 0x8211_cefd,\n            ),\n            (\n                0x074a_1d09, 0x52a1_0e5a, 0x9275_a3f8, 0x4b82_506c, 0x37df_7e1b, 0x4c78_b3c5, 0xcefa_b1da, 0xf472_267e,\n                0xb630_45f6, 0xd66a_1fc0, 0x4002_98e3, 0x27e6_0c94, 0x87d2_f1b8, 0xdf9e_56cc, 0x45cd_1803, 0x1d35_e098,\n                0xcce7_c736, 0x0348_3bf1, 0x1f73_07d7, 0xc6e8_f948, 0xe613_c111, 0x3955_c6ff, 0x1170_ed7c, 0x8e95_da41,\n                0x99c3_1bf4, 0xa4da_8021, 0x7b5f_94fb, 0xdd0d_a51f, 0x6562_aa77, 0x556b_cb23, 0xdb1b_acc6, 0x7980_40b9,\n                0xbfe5_378f, 0x731d_55e6, 0xdaa5_bfee, 0x389b_bc60, 0x1b33_fba4, 0x9c56_7204, 0x36c2_6c68, 0x77ee_9d69,\n                0x8aeb_3e88, 0x2d50_b5ce, 0x9579_e790, 0x42b1_3cfc, 0x33fb_d32b, 0xee05_03a7, 0xb586_2824, 0x15e4_1ead,\n                0xc841_2ef7, 0x9d44_1275, 0x2fce_c582, 0x5ff4_83b7, 0x8f39_31df, 0x2e5d_2a7b, 0x4946_7bf9, 0x0653_dea9,\n                0x2684_ce35, 0x7e65_5e5c, 0xf127_71d8, 0xbb15_cc67, 0xab09_7ca1, 0x983d_cf52, 0x10dd_f026, 0x2126_7f57,\n                0x2c58_f6b4, 0x3104_3265, 0x0bab_8c01, 0xd549_2099, 0xacaa_e619, 0x944c_e54a, 0xf2d1_3d39, 0xadd3_fc32,\n                0xcda0_8a40, 0xe2b0_d451, 0x9efe_08ae, 0xb9d5_0fd2, 0xea5c_d7fd, 0xc9a7_49dd, 0x13ea_2253, 0x832d_ebaa,\n                0x24be_640f, 0xe03e_926a, 0x29e0_1cde, 0x8bf5_9f18, 0x0f9d_00b6, 0xe123_8b46, 0x1e7d_8e34, 0x9361_9adb,\n                0x76b3_2f9f, 0xbd97_2cec, 0xe31f_a976, 0xa68f_bb10, 0xfb3b_a49d, 0x8587_c41d, 0xa5ad_d1d0, 0xf3cf_84bf,\n                0xd4e1_1150, 0xd9ff_a6bc, 0xc3f6_018c, 0xaef1_0572, 0x74a6_4b2f, 0xe7dc_9559, 0x2aae_35d5, 0x5b6f_587f,\n                0xa9e3_53fe, 0xca4f_b674, 0x04ba_24a8, 0xe5c6_875f, 0xdcbc_6266, 0x6bc5_c03f, 0x661e_ef02, 0xed74_0bab,\n                0x058e_34e4, 0xb7e9_46cf, 0x8869_8125, 0x72ec_48ed, 0xb110_73a3, 0xa134_85eb, 0xa2a2_429c, 0xfa40_7547,\n                0x50b7_6713, 0x5418_c37d, 0x9619_2da5, 0x170b_b04b, 0x518a_021e, 0xb0ac_13d1, 0x0963_fa2a, 0x4a6e_10e1,\n                0x5847_2bdc, 0xf7f8_d962, 0x9791_39ea, 0x8d85_6538, 0xc099_7042, 0x4832_4d7a, 0x4476_23cb, 0x8cbb_e364,\n                0x6e0c_6b0e, 0xd36d_63b0, 0x3f24_4c84, 0x3542_c971, 0x2b22_8dc1, 0xcb03_25bb, 0xf8c0_d6e9, 0xde11_066b,\n                0xa864_9327, 0xfc31_f83e, 0x7dd8_0406, 0xf916_dd61, 0xd89f_79d3, 0x6151_44c2, 0xebb4_5d31, 0x2800_2958,\n                0x5689_0a37, 0xf05b_3808, 0x123a_e844, 0x8683_9e16, 0x914b_0d83, 0xc506_b43c, 0xcf3c_ba5e, 0x7c60_f5c9,\n                0x22de_b2a0, 0x5d9c_2715, 0xc77b_a0ef, 0x4f45_360b, 0xc101_7d8b, 0xe45a_dc29, 0xa759_909b, 0x412c_d293,\n                0xd7d7_96b1, 0x00c8_ff30, 0x23a3_4a80, 0x4ec1_5c91, 0x714e_78b5, 0x47b9_e42e, 0x78f3_ea4d, 0x7f07_8f5b,\n                0x346c_593a, 0xa3a8_7a1a, 0x9bcb_fe12, 0x3d43_9963, 0xb2ef_6d8e, 0xb8d4_6028, 0x6c2f_d5ca, 0x6267_5256,\n                0x01f2_a2f3, 0xbc96_ae0a, 0x709a_8920, 0xb414_6e87, 0x6308_b9e2, 0x64bd_a7ba, 0xafed_6892, 0x6037_f2a2,\n                0xf529_69e0, 0x0adb_43a6, 0x8281_1400, 0x90d0_bdf0, 0x19c9_549e, 0x203f_6a73, 0x1acc_af4f, 0x8971_4e6d,\n                0x164d_4705, 0x6766_5f07, 0xec20_6170, 0x0c21_82b2, 0xa02b_9c81, 0x5328_9722, 0xf6a9_7686, 0x140e_4179,\n                0x9f77_8849, 0x9a88_e15d, 0x25ca_db54, 0xd157_f36f, 0x32a4_21c3, 0xb368_e98a, 0x5a92_cd0d, 0x757a_a8d4,\n                0xc20a_c278, 0x08b5_51c7, 0x8494_91e8, 0x4dc7_5ad6, 0x697c_33be, 0xbaf0_ca33, 0x4612_5b4e, 0x59d6_77b3,\n                0x30d9_c8f2, 0xd0af_860c, 0x1c7f_d0fa, 0xfe0f_f72c, 0x5c8d_6f43, 0x57fd_ec3b, 0x6ab6_ad97, 0xd22a_df89,\n                0x1817_1785, 0x02bf_e22d, 0x6db8_0917, 0x80b2_16af, 0xe85e_4f9a, 0x7a1c_306e, 0x6fc4_9bf5, 0x3af7_a11c,\n                0x81e2_15e7, 0x6836_3fcd, 0x3e93_57c8, 0xef52_fd55, 0x3b8b_ab4c, 0x3c8c_f495, 0xbefc_eebd, 0xfd25_b714,\n                0xc498_d83d, 0x0d2e_1a8d, 0xe9f9_66ac, 0x0e38_7445, 0x4354_19e5, 0x5e7e_bec4, 0xaa90_b8d9, 0xff1a_3a96,\n            ),\n            (\n                0x4a8f_e4e3, 0xf27d_99cd, 0xd04a_40ca, 0xcb5f_f194, 0x3668_275a, 0xff48_16be, 0xa78b_394c, 0x4c6b_e9db,\n                0x4eec_38d2, 0x4296_ec80, 0xcdce_96f8, 0x888c_2f38, 0xe755_08f5, 0x7b91_6414, 0x060a_a14a, 0xa214_f327,\n                0xbe60_8daf, 0x1ebb_dec2, 0x61f9_8ce9, 0xe921_56fe, 0x4f22_d7a3, 0x3f76_a8d9, 0x559a_4b33, 0x38ad_2959,\n                0xf3f1_7e9e, 0x85e1_ba91, 0xe5eb_a6fb, 0x73dc_d48c, 0xf5c3_ff78, 0x481b_6058, 0x8a32_97f7, 0x8f1f_3bf4,\n                0x9378_5ab2, 0x477a_4a5b, 0x6334_eb5d, 0x6d25_1b2e, 0x74a9_102d, 0x07e3_8ffa, 0x915c_9c62, 0xccc2_75ea,\n                0x6be2_73ec, 0x3ebd_dd70, 0xd895_796c, 0xdc54_a91b, 0xc9af_df81, 0x2363_3f73, 0x2751_19b4, 0xb19f_6b67,\n                0x5075_6e22, 0x2bb1_52e2, 0x76ea_46a2, 0xa353_e232, 0x2f59_6ad6, 0x0b1e_db0b, 0x02d3_d9a4, 0x78b4_7843,\n                0x6489_3e90, 0x40f0_caad, 0xf68d_3ad7, 0x46fd_1707, 0x1c9c_67ef, 0xb5e0_86de, 0x96ee_6ca6, 0x9aa3_4774,\n                0x1ba4_f48a, 0x8d01_abfd, 0x183e_e1f6, 0x5ff8_aa7a, 0x17e4_faae, 0x3039_83b0, 0x6c08_668b, 0xd4ac_4382,\n                0xe6c5_849f, 0x92fe_fb53, 0xc1ca_c4ce, 0x4350_1388, 0x4411_18cf, 0xec4f_b308, 0x53a0_8e86, 0x9e0f_e0c5,\n                0xf91c_1525, 0xac45_be05, 0xd798_7cb5, 0x49ba_1487, 0x5793_8940, 0xd587_7648, 0xa958_727f, 0x58df_e3c3,\n                0xf436_cf77, 0x399e_4d11, 0xf0a5_bfa9, 0xef61_a33b, 0xa64c_ac60, 0x04a8_d0ba, 0x030d_d572, 0xb83d_320f,\n                0xcab2_3045, 0xe366_f2f0, 0x815d_008d, 0xc897_a43a, 0x1d35_2df3, 0xb9cc_571d, 0x8bf3_8744, 0x7220_9092,\n                0xeba1_24eb, 0xfb99_ce5e, 0x3bb9_4293, 0x28da_549c, 0xaab8_a228, 0xa419_7785, 0x33c7_0296, 0x25f6_259b,\n                0x5c85_da21, 0xdf15_bdee, 0x15b7_c7e8, 0xe2ab_ef75, 0xfcc1_9bc1, 0x417f_f868, 0x1488_4434, 0x6282_5179,\n                0xc6d5_c11c, 0x0e47_05dc, 0x2270_0de0, 0xd3d2_af18, 0x9be8_22a0, 0x35b6_69f1, 0xc42b_b55c, 0x0a80_1252,\n                0x115b_f0fc, 0x3cd7_d856, 0xb43f_5f9d, 0xc230_6516, 0xa123_1c47, 0xf149_207e, 0x5209_a795, 0x34b3_ccd8,\n                0x67ae_fe54, 0x2c83_924e, 0x6662_cbac, 0x5eed_d161, 0x84e6_81aa, 0x5d57_d26b, 0xfa46_5cc4, 0x7e3a_c3a8,\n                0xbf7c_0cc6, 0xe18a_9aa1, 0xc32f_0a6f, 0xb22c_c00d, 0x3d28_0369, 0x994e_554f, 0x68f4_80d3, 0xadcf_f5e6,\n                0x3a8e_b265, 0x8326_9831, 0xbd56_8a09, 0x4bc8_ae6a, 0x69f5_6d2b, 0x0f17_eac8, 0x772e_b6c7, 0x9f41_343c,\n                0xab1d_0742, 0x826a_6f50, 0xfea2_097c, 0x1912_c283, 0xce18_5899, 0xe444_4839, 0x2d86_35d5, 0x65d0_b1ff,\n                0x865a_7f17, 0x326d_9fb1, 0x59e5_2820, 0x0090_ade1, 0x753c_7149, 0x9ddd_8b98, 0xa5a6_91da, 0x0d03_82bb,\n                0x8904_c930, 0x086c_b000, 0x6e69_d3bd, 0x24d4_e7a7, 0x0524_4fd0, 0x101a_5e0c, 0x6a94_7dcb, 0xe840_f77b,\n                0x7d0c_5003, 0x7c37_0f1f, 0x8052_45ed, 0xe05e_3d3f, 0x7906_880e, 0xbabf_cd35, 0x1a7e_c697, 0x8c05_2324,\n                0x0c6e_c8df, 0xd129_a589, 0xc7a7_5b02, 0x12d8_1de7, 0xd9be_2a66, 0x1f42_63ab, 0xde73_fdb6, 0x2a00_680a,\n                0x5664_9e36, 0x3133_ed55, 0x90fa_0bf2, 0x2910_a02a, 0x949d_9d46, 0xa0d1_dcdd, 0xcfc9_b7d4, 0xd267_7be5,\n                0x95cb_36b3, 0x13cd_9410, 0xdbf7_3313, 0xb7c6_e8c0, 0xf781_414b, 0x510b_016d, 0xb0de_1157, 0xd6b0_f62c,\n                0xbb07_4ecc, 0x7f13_95b7, 0xee79_2cf9, 0xea6f_d63e, 0x5bd6_938e, 0xaf02_fc64, 0xdab5_7ab8, 0x8edb_3784,\n                0x8716_318f, 0x164d_1a01, 0x26f2_6141, 0xb372_e6b9, 0xf8fc_2b06, 0x7ac0_0e04, 0x3727_b89a, 0x97e9_bca5,\n                0x9c2a_742f, 0xbc3b_1f7d, 0x7165_b471, 0x609b_4c29, 0x2092_5351, 0x5ae7_2112, 0x454b_e5d1, 0xc0ff_b95f,\n                0xdd0e_f919, 0x6f2d_70c9, 0x0974_c5bf, 0x98aa_6263, 0x01d9_1e4d, 0x2184_bb6e, 0x70c4_3c1e, 0x4d43_5915,\n                0xae7b_8523, 0xb6fb_06bc, 0x5431_ee76, 0xfdbc_5d26, 0xed77_493d, 0xc571_2ee4, 0xa838_0437, 0x2eef_261a,\n            ),\n            (\n                0x5a79_392b, 0xb8af_32c2, 0x41f7_720a, 0x833a_61ec, 0x13df_edac, 0xc499_0bc4, 0xdc0f_54bc, 0xfedd_5e88,\n                0x80da_1881, 0x4dea_1afd, 0xfd40_2cc6, 0xae67_cc7a, 0xc523_8525, 0x8ea0_1254, 0xb56b_9bd5, 0x862f_bd6d,\n                0xac85_75d3, 0x6fba_3714, 0xda7e_bf46, 0x59cd_5238, 0x8ac9_dbfe, 0x3537_29fc, 0xe497_d7f2, 0xc3ab_84e0,\n                0xf05a_114b, 0x7b88_7a75, 0xedc6_03dd, 0x5e6f_e680, 0x2c84_b399, 0x884e_b1da, 0x1cb8_c8bf, 0xaa51_098a,\n                0xc862_231c, 0x8bac_2221, 0x21b3_87e5, 0x208a_430d, 0x2a3f_0f8b, 0xa5ff_9cd2, 0x6012_a2ea, 0x147a_9ee7,\n                0xf62a_501d, 0xb4b2_e51a, 0x3ef3_484c, 0xc025_3c59, 0x2b82_b536, 0x0aa9_696b, 0xbe0c_109b, 0xc70b_7929,\n                0xce3e_8a19, 0x2f66_950e, 0x459f_1c2c, 0xe68f_b93d, 0xa3c3_ff3e, 0x62b4_5c62, 0x3009_91cb, 0x0191_4c57,\n                0x7f7b_c06a, 0x1828_31f5, 0xe7b7_4bca, 0xfa50_f6d0, 0x523c_aa61, 0xe3a7_cf05, 0xe9e4_1311, 0x280a_21d1,\n                0x6a42_97e1, 0xf24d_c67e, 0xfc31_89e6, 0xb72b_f34f, 0x4b1e_67af, 0x5434_02ce, 0x79a5_9867, 0x0648_e02a,\n                0x00a3_ac17, 0xc620_8d35, 0x6e7f_5f76, 0xa45b_b4be, 0xf168_fa63, 0x3f41_25f3, 0xf311_406f, 0x0270_6565,\n                0xbfe5_8022, 0x0cfc_fdd9, 0x0735_a7f7, 0x8f04_9092, 0xd98e_dc27, 0xf5c5_d55c, 0xe0f2_01db, 0x0dca_fc9a,\n                0x7727_fb79, 0xaf43_abf4, 0x26e9_38c1, 0x401b_26a6, 0x9007_20fa, 0x2752_d97b, 0xcff1_d1b3, 0xa9d9_e424,\n                0x42db_99ab, 0x6cf8_be5f, 0xe82c_ebe3, 0x3afb_733b, 0x6b73_4eb6, 0x1036_414a, 0x975f_667c, 0x049d_6377,\n                0xba58_7c60, 0xb1d1_0483, 0xde1a_efcc, 0x1129_d055, 0x7205_1e91, 0x6946_d623, 0xf9e8_6ea7, 0x4876_8c00,\n                0xb016_6c93, 0x9956_bbf0, 0x1f1f_6d84, 0xfb15_e18e, 0x033b_495d, 0x56e3_362e, 0x4f44_c53c, 0x747c_ba51,\n                0x89d3_7872, 0x5d9c_331b, 0xd2ef_9fa8, 0x2549_17f8, 0x1b10_6f47, 0x37d7_5553, 0xb3f0_53b0, 0x7dcc_d8ef,\n                0xd30e_b802, 0x5889_f42d, 0x6102_06d7, 0x1a7d_34a1, 0x92d8_7dd8, 0xe5f4_a315, 0xd1cf_0e71, 0xb22d_fe45,\n                0xb901_e8eb, 0x0fc0_ce5e, 0x2efa_60c9, 0x2de7_4290, 0x36d0_c906, 0x381c_70e4, 0x4c6d_a5b5, 0x3d81_a682,\n                0x7e38_1f34, 0x396c_4f52, 0x95ad_5901, 0x1db5_0c5a, 0x2998_2e9e, 0x1557_689f, 0x3471_ee42, 0xd7e2_f7c0,\n                0x8795_a1e2, 0xbc32_4d8d, 0xe224_c3c8, 0x1283_7e39, 0xcdee_3d74, 0x7ad2_143f, 0x0e13_d40c, 0x78bd_4a68,\n                0xa2eb_194d, 0xdb94_51f9, 0x859b_71dc, 0x5c4f_5b89, 0xca14_a8a4, 0xef92_f003, 0x1674_1d98, 0x33aa_4444,\n                0x9e96_7fbb, 0x092e_3020, 0xd86a_35b8, 0x8cc1_7b10, 0xe1bf_08ae, 0x5569_3fc5, 0x7680_ad13, 0x1e65_46e8,\n                0x23b6_e7b9, 0xee77_a4b2, 0x08ed_0533, 0x44fd_2895, 0xb639_3b69, 0x05d6_cacf, 0x9819_b209, 0xecbb_b72f,\n                0x9a75_779c, 0xeaec_0749, 0x94a6_5aee, 0xbdf5_2dc3, 0xd6a2_5d04, 0x8200_8e4e, 0xa6de_160f, 0x9b03_6afb,\n                0x228b_3a66, 0x5fb1_0a70, 0xcc33_8b58, 0x5378_a9df, 0xc908_bca9, 0x4959_e25b, 0x4690_9a97, 0x66ae_8f6e,\n                0xdd06_83e9, 0x65f9_94b4, 0x6426_cda5, 0xc24b_8840, 0x3253_9da0, 0x6317_5650, 0xd0c8_15ff, 0x50cb_c41e,\n                0xf7c7_74a3, 0x31b0_c231, 0x8d0d_8116, 0x24be_f16c, 0xd555_d256, 0xdf47_ea8c, 0x6d21_eccd, 0xa887_a012,\n                0x8454_2aed, 0xa7b9_c1bd, 0x914c_1bb1, 0xa0d5_b67d, 0x438c_e937, 0x7030_f873, 0x71f6_b0c7, 0x5745_76ba,\n                0xf8bc_4541, 0x9c61_d348, 0x1960_579d, 0x17c4_daad, 0x96a4_cb0b, 0xc193_f2f6, 0x756e_afa2, 0x7c1d_2f94,\n                0xf4fe_2b43, 0xcb86_e33a, 0xebd4_c728, 0x9d18_ae64, 0x9fe1_3e30, 0x3ce0_f5de, 0xaba1_f985, 0xaddc_2718,\n                0x68ce_6278, 0xd45e_241f, 0xa15c_82b7, 0x3b22_93d4, 0x739e_dd32, 0x674a_6bf1, 0x5b5d_587f, 0x4772_deaa,\n                0x4a63_968f, 0x0be6_8686, 0x513d_6426, 0x939a_4787, 0xbba8_9296, 0x4ec2_0007, 0x818d_0d08, 0xff64_dfd6,\n            ),\n            (\n                0xcb22_97cb, 0xdb48_a144, 0xa16c_be4b, 0xbbea_1d6c, 0x5af6_b6b7, 0x8a81_10b6, 0xf923_6ef9, 0xc98f_83e6,\n                0x0f9c_65b8, 0x252d_4a89, 0xa497_f068, 0xa5d7_ed2d, 0x94c2_2845, 0x9da1_c8c4, 0xe27c_2e2e, 0x6e8b_a2b4,\n                0xc3dd_17fb, 0x498c_d482, 0x0dfe_6a9f, 0xb070_5829, 0x9a1e_6dc1, 0xf829_717c, 0x07bb_8e3a, 0xda3c_0b02,\n                0x1af8_2fc7, 0x73b7_0955, 0x7a04_379c, 0x5ee2_0a28, 0x8371_2ae5, 0xf4c4_7c6d, 0xdf72_ba56, 0xd794_858d,\n                0x8c0c_f709, 0x18f0_f390, 0xb6c6_9b35, 0xbf2f_01db, 0x2fa7_4dca, 0xd0cd_9127, 0xbde6_6cec, 0x3dee_bd46,\n                0x57c8_8fc3, 0xcee1_406f, 0x0066_385a, 0xf3c3_444f, 0x3a79_d5d5, 0x7575_1eb9, 0x3e7f_8185, 0x521c_2605,\n                0xe1aa_ab6e, 0x38eb_b80f, 0xbee7_e904, 0x61cb_9647, 0xea54_904e, 0x05ae_00e4, 0x2d7a_c65f, 0x0877_51a1,\n                0xdcd8_2915, 0x0921_ee16, 0xdd86_d33b, 0xd6bd_491a, 0x40fb_adf0, 0x4232_cbd2, 0x3380_8d10, 0x3909_8c42,\n                0x193f_3199, 0x0bc1_e47a, 0x4a82_b149, 0x02b6_5a8a, 0x104c_dc8e, 0x24a8_f52c, 0x685c_6077, 0xc79f_95c9,\n                0x1d11_fe50, 0xc08d_afcd, 0x7b1a_9a03, 0x1c1f_11d8, 0x8425_0e7f, 0x979d_b248, 0xebdc_0501, 0xb955_3395,\n                0xe3c0_5ea8, 0xb1e5_1c4c, 0x13b0_e681, 0x3b40_7766, 0x36db_3087, 0xee17_c9fc, 0x6c53_ecf2, 0xadcc_c58f,\n                0xc427_660b, 0xefd5_867d, 0x9b6d_54a5, 0x6ff1_aeff, 0x8e78_7952, 0x9e2b_ffe0, 0x8761_d034, 0xe00b_dbad,\n                0xae99_a8d3, 0xcc03_f6e2, 0xfd0e_d807, 0x0e50_8ae3, 0xb741_82ab, 0x4349_245d, 0xd120_a465, 0xb246_a641,\n                0xaf3b_7ab0, 0x2a64_88bb, 0x4b3a_0d1f, 0xe7c7_e58c, 0x3faf_f2eb, 0x9044_5ffd, 0xcf38_c393, 0x995d_07e7,\n                0xf24f_1b36, 0x356f_6891, 0x6d6e_bcbe, 0x8da9_e262, 0x50fd_520e, 0x5bca_9e1e, 0x3747_2cf3, 0x6907_5057,\n                0x7ec5_fded, 0x0cab_892a, 0xfb24_12ba, 0x1728_debf, 0xa000_a988, 0xd843_ce79, 0x042e_20dd, 0x4fe8_f853,\n                0x5665_9c3c, 0x2739_d119, 0xa78a_6120, 0x8096_0375, 0x7042_0611, 0x85e0_9f78, 0xabd1_7e96, 0x1b51_3eaf,\n                0x1e01_eb63, 0x26ad_2133, 0xa890_c094, 0x7613_cf60, 0x817e_781b, 0xa391_13d7, 0xe957_fa58, 0x4131_b99e,\n                0x28b1_efda, 0x66ac_fba7, 0xff68_944a, 0x77a4_4fd1, 0x7f33_1522, 0x59ff_b3fa, 0xa6df_935b, 0xfa12_d9df,\n                0xc6bf_6f3f, 0x8952_0cf6, 0x659e_dd6a, 0x544d_a739, 0x8b05_2538, 0x7c30_ea21, 0xc234_5525, 0x1592_7fb2,\n                0x144a_436b, 0xba10_7b8b, 0x1219_ac97, 0x0673_0432, 0x3183_1ab3, 0xc55a_5c24, 0xaa0f_cd3e, 0xe560_6be8,\n                0x5c88_f19b, 0x4c08_41ee, 0x1fe3_7267, 0x11f9_c4f4, 0x9f1b_9dae, 0x864e_76d0, 0xe637_c731, 0xd97d_23a6,\n                0x32f5_3d5c, 0xb816_1980, 0x93fa_0f84, 0xcaef_0870, 0x8874_487e, 0x98f2_cc73, 0x645f_b5c6, 0xcd85_3659,\n                0x2062_470d, 0x16ed_e8e9, 0x6b06_dab5, 0x78b4_3900, 0xfc95_b786, 0x5d8e_7de1, 0x465b_5954, 0xfe7b_a014,\n                0xf7d2_3f7b, 0x92bc_8b18, 0x0359_3592, 0x55ce_f4f7, 0x74b2_7317, 0x79de_1fc2, 0xc8a0_bfbd, 0x2293_98cc,\n                0x62a6_02ce, 0xbcb9_4661, 0x5336_d206, 0xd2a3_75fe, 0x6a6a_b483, 0x4702_a5a4, 0xa2e9_d73d, 0x23a2_e0f1,\n                0x9189_140a, 0x581d_18dc, 0xb39a_922b, 0x8235_6212, 0xd5f4_32a9, 0xd356_c2a3, 0x5f76_5b4d, 0x450a_fcc8,\n                0x4415_e137, 0xe8ec_dfbc, 0xed0d_e3ea, 0x60d4_2b13, 0xf13d_f971, 0x71fc_5da2, 0xc145_5340, 0xf087_742f,\n                0xf55e_5751, 0x67b3_c1f8, 0xac6b_8774, 0x7dcf_aaac, 0x9598_3bc0, 0x489b_b0b1, 0x2c18_4223, 0x964b_6726,\n                0x2bd3_271c, 0x7226_6472, 0xded6_4530, 0x0a2a_a343, 0xd4f7_16a0, 0xb4da_d6d9, 0x2184_345e, 0x512c_990c,\n                0x29d9_2d08, 0x2ebe_709a, 0x0114_4c69, 0x3458_4b9d, 0xe463_4ed6, 0xecc9_63cf, 0x3c69_84aa, 0x4ed0_56ef,\n                0x9ca5_6976, 0x8f3e_80d4, 0xb5ba_e7c5, 0x30b5_caf5, 0x63f3_3a64, 0xa9e4_bbde, 0xf6b8_2298, 0x4d67_3c1d,\n            ),\n            (\n                0x4b4f_1121, 0xba18_3081, 0xc784_f41f, 0xd17d_0bac, 0x083d_2267, 0x37b1_361e, 0x3581_ad05, 0xfda2_f6bc,\n                0x1e89_2cdd, 0xb56d_3c3a, 0x3214_0e46, 0x138d_8aab, 0xe147_73d4, 0x5b0e_71df, 0x5d1f_e055, 0x3fb9_91d3,\n                0xf1f4_6c71, 0xa325_988c, 0x10f6_6e80, 0xb100_6348, 0x726a_9f60, 0x3b67_f8ba, 0x4e11_4ef4, 0x05c5_2115,\n                0x4c5c_a11c, 0x99e1_efd8, 0x471b_83b3, 0xcbf7_e524, 0x43ad_82f5, 0x690c_a93b, 0xfaa6_1bb2, 0x12a8_32b5,\n                0xb734_f943, 0xbd22_aea7, 0x88fe_c626, 0x5e80_c3e7, 0xbe3e_af5e, 0x4461_7652, 0xa572_4475, 0xbb3b_9695,\n                0x7f3f_ee8f, 0x964e_7deb, 0x518c_052d, 0x2a0b_bc2b, 0xc217_5f5c, 0x9a7b_3889, 0xa70d_8d0c, 0xeacc_dd29,\n                0xcccd_6658, 0x34bb_25e6, 0xb839_1090, 0xf651_356f, 0x5298_7c9e, 0x0c16_c1cd, 0x8e37_2d3c, 0x2fc6_ebbd,\n                0x6e5d_a3e3, 0xb0e2_7239, 0x5f68_5738, 0x4541_1786, 0x067f_65f8, 0x6177_8b40, 0x81ab_2e65, 0x14c8_f0f9,\n                0xa6b7_b4ce, 0x4036_eaec, 0xbf62_b00a, 0xecfd_5e02, 0x0454_49a6, 0xb20a_fd28, 0x2166_d273, 0x0d13_a863,\n                0x8950_8756, 0xd51a_7530, 0x2d65_3f7a, 0x3cdb_dbc3, 0x80c9_df4f, 0x3d58_12d9, 0x53fb_b1f3, 0xc0f1_85c0,\n                0x7a3c_3d7e, 0x6864_6410, 0x8576_07a0, 0x1d12_622e, 0x97f3_3466, 0xdb4c_9917, 0x6469_607c, 0x566e_043d,\n                0x79ef_1edb, 0x2c05_898d, 0xc957_8e25, 0xcd38_0101, 0x46e0_4377, 0x7d1c_c7a9, 0x6552_b837, 0x2019_2608,\n                0xb975_00c5, 0xed29_6b44, 0x3686_48b4, 0x6299_5cd5, 0x8273_1400, 0xf9ae_bd8b, 0x3844_c0c7, 0x7c2d_e794,\n                0x33a1_a770, 0x8ae5_28c2, 0x5a2b_e812, 0x1f8f_4a07, 0x2b5e_d7ca, 0x937e_b564, 0x6fda_7e11, 0xe49b_5d6c,\n                0xb4b3_244e, 0x18aa_53a4, 0x3a06_1334, 0x4d60_67a3, 0x83ba_5868, 0x9bdf_4dfe, 0x7449_f261, 0x709f_8450,\n                0xcad1_33cb, 0xde94_1c3f, 0xf52a_e484, 0x781d_77ed, 0x7e43_95f0, 0xae10_3b59, 0x9223_31bb, 0x42ce_50c8,\n                0xe6f0_8153, 0xe7d9_41d0, 0x5028_ed6b, 0xb3d2_c49b, 0xad4d_9c3e, 0xd201_fb6e, 0xa45b_d5be, 0xffcb_7f4b,\n                0x579d_7806, 0xf821_bb5b, 0x59d5_92ad, 0xd0be_0c31, 0xd4e3_b676, 0x0107_165a, 0x0fe9_39d2, 0x49bc_aafd,\n                0x55ff_cfe5, 0x2ec1_f783, 0xf39a_09a5, 0x3eb4_2772, 0x19b5_5a5d, 0x024a_0679, 0x8c83_b3f7, 0x8642_ba1d,\n                0xacac_d9ea, 0x87d3_52c4, 0x6093_1f45, 0xa05f_97d7, 0x1cec_d42c, 0xe2fc_c87b, 0xb60f_94e2, 0x67a3_4b0b,\n                0xfcdd_40c9, 0x0b15_0a27, 0xd3ee_9e04, 0x582e_29e9, 0x4ac2_2b41, 0x6ac4_e1b8, 0xbcca_a51a, 0x237a_f30e,\n                0xebc3_b709, 0xc4a5_9d19, 0x284b_c98a, 0xe9d4_1a93, 0x6bfa_2018, 0x73b2_d651, 0x11f9_a2fa, 0xce09_bff1,\n                0x41a4_70aa, 0x2588_8f22, 0x77e7_54e8, 0xf733_0d8e, 0x158e_ab16, 0xc5d6_8842, 0xc685_a6f6, 0xe5b8_2fde,\n                0x09ea_3a96, 0x6dde_1536, 0x4fa9_19da, 0x26c0_be9f, 0x9eed_6f69, 0xf055_55f2, 0xe06f_c285, 0x9cd7_6d23,\n                0xaf45_2a92, 0xefc7_4cb7, 0x9d6b_4732, 0x8be4_08ee, 0x2240_1d0d, 0xee6c_459d, 0x7587_cb82, 0xe874_6862,\n                0x5cbd_de87, 0x9879_4278, 0x31af_b94d, 0xc11e_0f2f, 0x30e8_fc2a, 0xcf32_61ef, 0x1a30_23e1, 0xaa2f_86cf,\n                0xf202_e24a, 0x8d08_dcff, 0x7648_37c6, 0xa263_74cc, 0x9f7c_3e88, 0x949c_c57d, 0xdd26_a07f, 0xc39e_fab0,\n                0xc8f8_79a1, 0xdce6_7bb9, 0xf4b0_a435, 0x912c_9ae0, 0xd856_03e4, 0x953a_9bbf, 0xfb82_90d6, 0x0aeb_cd5f,\n                0x1620_6a9a, 0x6c78_7a14, 0xd9a0_f16a, 0x29bf_4f74, 0x8f8b_ce91, 0x0e5a_9354, 0xab03_8cb1, 0x1b8a_d11b,\n                0xe327_ff49, 0x0053_da20, 0x90cf_51dc, 0xda92_fe6d, 0x0390_ca47, 0xa895_8097, 0xa9dc_5baf, 0x3931_e3c1,\n                0x8404_46b6, 0x63d0_69fb, 0xd746_0299, 0x7124_ecd1, 0x0791_e613, 0x4859_18fc, 0xd635_d04c, 0xdf96_ac33,\n                0x66f2_d303, 0x2470_56ae, 0xa1a7_b2a8, 0x27d8_cc9c, 0x17b6_e998, 0x7bf5_590f, 0xfe97_f557, 0x5471_d8a2,\n            ),\n            (\n                0x83a3_27a1, 0x9f37_9f51, 0x40a7_d007, 0x1130_7423, 0x2245_87c1, 0xac27_d63b, 0x3b7e_64ea, 0x2e1c_bfa6,\n                0x0999_6000, 0x03bc_0e2c, 0xd4c4_478a, 0x4542_e0ab, 0xfeda_26d4, 0xc1d1_0fcb, 0x8252_f596, 0x4494_eb5c,\n                0xa362_f314, 0xf5ba_81fd, 0x75c3_a376, 0x4ca2_14ca, 0xe164_dedd, 0x5088_fa97, 0x4b09_30e0, 0x2fcf_b7e8,\n                0x33a6_f4b2, 0xc7e9_4211, 0x2d66_c774, 0x43be_8bae, 0xc663_d445, 0x908e_b130, 0xf4e3_be15, 0x63b9_d566,\n                0x5293_96b5, 0x1e1b_e743, 0x4d5f_f63f, 0x985e_4a83, 0x71ab_9df7, 0xc516_c6f5, 0x85c1_9ab4, 0x1f4d_aee4,\n                0xf297_3431, 0xb713_dc5e, 0x3f2e_159a, 0xc824_da16, 0x06bf_376a, 0xb2fe_23ec, 0xe39b_1c22, 0xf1ee_cb5f,\n                0x08e8_2d52, 0x5656_86c2, 0xab0a_ea93, 0xfd47_219f, 0xebdb_abd7, 0x2404_a185, 0x8c73_12b9, 0xa8f2_d828,\n                0x0c89_02da, 0x65b4_2b63, 0xc0bb_ef62, 0x4e3e_4cef, 0x788f_8018, 0xee1e_bab7, 0x9392_8f9d, 0x683d_2903,\n                0xd3b6_0689, 0xafcb_0ddc, 0x88a4_c47a, 0xf6dd_9c3d, 0x7ea5_fca0, 0x8a6d_7244, 0xbe11_f120, 0x04ff_91b8,\n                0x8d2d_c8c0, 0x27f9_7fdb, 0x7f9e_1f47, 0x1734_f0c7, 0x26f3_ed8e, 0x0df8_f2bf, 0xb083_3d9e, 0xe420_a4e5,\n                0xa423_cae6, 0x9561_6772, 0x9ae6_c049, 0x0759_41f2, 0xd8e1_2812, 0x000f_6f4f, 0x3c0d_6b05, 0x6cef_921c,\n                0xb82b_c264, 0x396c_b008, 0x5d60_8a6f, 0x6d77_82c8, 0x1865_50aa, 0x6b6f_ec09, 0x28e7_0b13, 0x57ce_5688,\n                0xecd3_af84, 0x2333_5a95, 0x91f4_0cd2, 0x7b6a_3b26, 0xbd32_b3b6, 0x3754_a6fb, 0x8ed0_88f0, 0xf867_e87c,\n                0x2085_1746, 0x6410_f9c6, 0x3538_0442, 0xc2ca_10a7, 0x1ade_a27f, 0x76bd_dd79, 0x9274_2cf4, 0x0e98_f7ee,\n                0x164e_931d, 0xb9c8_35b3, 0x6906_0a99, 0xb44c_531e, 0xfa7b_66fe, 0xc98a_5b53, 0x7d95_aae9, 0x302f_467b,\n                0x74b8_11de, 0xf386_6abd, 0xb5b3_d32d, 0xfc31_57a4, 0xd251_fe19, 0x0b5d_8eac, 0xda71_ffd5, 0x47ea_05a3,\n                0x05c6_a9e1, 0xca0e_e958, 0x9939_034d, 0x25dc_5edf, 0x7908_3cb1, 0x8676_8450, 0xcf75_7d6d, 0x5972_b6bc,\n                0xa78d_59c9, 0xc4ad_8d41, 0x2a36_2ad3, 0xd117_9991, 0x6014_07ff, 0xdcf5_0917, 0x5870_69d0, 0xe082_1ed6,\n                0xdbb5_9427, 0x7391_1a4b, 0x7c90_4fc3, 0x844a_fb92, 0x6f8c_955d, 0xe8c0_c5bb, 0xb67a_b987, 0xa529_d96c,\n                0xf91f_7181, 0x618b_1b06, 0xe718_bb0c, 0x8bd7_615b, 0xd5a9_3a59, 0x54ae_f81b, 0x7721_36e3, 0xce44_fd9c,\n                0x10cd_a57e, 0x87d6_6e0b, 0x3d79_8967, 0x1b2c_1804, 0x3edf_bd68, 0x15f6_e62b, 0xef68_b854, 0x3896_db35,\n                0x12b7_b5e2, 0xcb48_9029, 0x9e4f_98a5, 0x62eb_77a8, 0x217c_24a2, 0x9641_52f6, 0x49b2_080a, 0x53d2_3ee7,\n                0x48fb_6d69, 0x1903_d190, 0x9449_e494, 0xbf6e_7886, 0xfb35_6cfa, 0x3a26_1365, 0x424b_c1eb, 0xa119_2570,\n                0x019c_a782, 0x9d3f_7e0e, 0x9c12_7575, 0xedf0_2039, 0xad57_bcce, 0x5c15_3277, 0x81a8_4540, 0xbcaa_7356,\n                0xccd5_9b60, 0xa62a_629b, 0xa25c_cd10, 0x2b5b_65cf, 0x1c53_5832, 0x55fd_4e3a, 0x31d9_790d, 0xf06b_c37d,\n                0x4afc_1d71, 0xaeed_5533, 0xba46_1634, 0xbb69_4b78, 0x5f3a_5c73, 0x6a3c_764a, 0x8fb0_cca9, 0xf725_684c,\n                0x4fe5_382f, 0x1d01_63af, 0x5aa0_7a8f, 0xe205_a8ed, 0xc30b_ad38, 0xff22_cf1f, 0x7243_2e2e, 0x32c2_518b,\n                0x3487_ce4e, 0x7ae0_ac02, 0x709f_a098, 0x0a3b_395a, 0x5b40_43f8, 0xa9e4_8c36, 0x149a_8521, 0xd07d_ee6b,\n                0x46ac_d2f3, 0x8958_dffc, 0xb3a1_223c, 0xb11d_31c4, 0xcd7f_4d3e, 0x0f28_e3ad, 0xe5b1_00be, 0xaac5_4824,\n                0xe9c9_d7ba, 0x9bd4_7001, 0x80f1_49b0, 0x6602_2f0f, 0x020c_4048, 0x6efa_192a, 0x6707_3f8d, 0x13ec_7bf9,\n                0x3655_011a, 0xe6af_e157, 0xd984_5f6e, 0xdecc_4425, 0x511a_e2cc, 0xdf81_b4d8, 0xd780_9e55, 0xd6d8_83d9,\n                0x2cc7_978c, 0x5e78_7cc5, 0xdd00_33d1, 0xa050_c937, 0x97f7_5dcd, 0x299d_e580, 0x41e2_b261, 0xea5a_54f1,\n            ),\n            (\n                0x7e67_2590, 0xbea5_13bb, 0x2c90_6fe6, 0x8602_9c2b, 0x55dc_4f74, 0x0553_398e, 0x63e0_9647, 0xcafd_0bab,\n                0x264c_37df, 0x8272_210f, 0x67af_a669, 0x12d9_8a5f, 0x8cab_23c4, 0x75c6_8bd1, 0xc337_0470, 0x33f3_7f4e,\n                0x2839_92ff, 0xe73a_3a67, 0x1032_f283, 0xf5ad_9fc2, 0x963f_0c5d, 0x664f_bc45, 0x202b_a41c, 0xc7c0_2d80,\n                0x5473_1e84, 0x8a10_85f5, 0x601d_80fb, 0x2f96_8e55, 0x35e9_6812, 0xe45a_8f78, 0xbd7d_e662, 0x3b6e_6ead,\n                0x8097_c5ef, 0x070b_6781, 0xb1e5_08f3, 0x24e4_fae3, 0xb81a_7805, 0xec0f_c918, 0x43c8_774b, 0x9b25_12a9,\n                0x2b05_ad04, 0x32c2_536f, 0xedf2_36e0, 0x8bc4_b0cf, 0xbace_b837, 0x4535_b289, 0x0d0e_94c3, 0xa5a3_71d0,\n                0xad69_5a58, 0x39e3_437d, 0x9186_bffc, 0x2103_8c3b, 0x0aa9_dff9, 0x5d1f_06ce, 0x62de_f8a4, 0xf740_a2b4,\n                0xa257_5868, 0x6826_83c1, 0xdbb3_0fac, 0x61fe_1928, 0x468a_6511, 0xc61c_d5f4, 0xe54d_9800, 0x6b98_d7f7,\n                0x8418_b6a5, 0x5f09_a5d2, 0x90b4_e80b, 0x49b2_c852, 0x69f1_1c77, 0x1741_2b7e, 0x7f6f_c0ed, 0x5683_8dcc,\n                0x6e95_46a2, 0xd075_8619, 0x087b_9b9a, 0xd231_a01d, 0xaf46_d415, 0x0970_60fd, 0xd920_f657, 0x882d_3f9f,\n                0x3ae7_c3c9, 0xe8a0_0d9b, 0x4fe6_7ebe, 0x2ef8_0eb2, 0xc191_6b0c, 0xf4df_fea0, 0xb97e_b3eb, 0xfdff_84dd,\n                0xff8b_14f1, 0xe96b_0572, 0xf64b_508c, 0xae22_0a6e, 0x4423_ae5a, 0xc2be_ce5e, 0xde27_567c, 0xfc93_5c63,\n                0x4707_5573, 0xe65b_27f0, 0xe121_fd22, 0xf266_8753, 0x2deb_f5d7, 0x8347_e08d, 0xac5e_da03, 0x2a7c_ebe9,\n                0x3fe8_d92e, 0x2354_2fe4, 0x1fa7_bd50, 0xcf9b_4102, 0x9d0d_ba39, 0x9cb8_902a, 0xa724_9d8b, 0x0f6d_667a,\n                0x5ebf_a9ec, 0x6a59_4df2, 0x7960_0938, 0x023b_7591, 0xea2c_79c8, 0xc99d_07ea, 0x64cb_5ee1, 0x1a9c_ab3d,\n                0x76db_9527, 0xc08e_012f, 0x3dfb_481a, 0x872f_22e7, 0x2948_d15c, 0xa478_2c79, 0x6f50_d232, 0x78f0_728a,\n                0x5a87_aab1, 0xc4e2_c19c, 0xee76_7387, 0x1b2a_1864, 0x7b8d_10d3, 0xd171_3161, 0x0eea_c456, 0xd879_9e06,\n                0xb645_b548, 0x4043_cb65, 0xa874_fb29, 0x4b12_d030, 0x7d68_7413, 0x18ef_9a1f, 0xd763_1d4c, 0x5829_c7da,\n                0xcdfa_30fa, 0xc508_4bb0, 0x92cd_20e2, 0xd4c1_6940, 0x0328_3ec0, 0xa917_813f, 0x9a58_7d01, 0x7004_1f8f,\n                0xdc6a_b1dc, 0xddae_e3d5, 0x3182_9742, 0x198c_022d, 0x1c9e_afcb, 0x5bbc_6c49, 0xd3d3_293a, 0x16d5_0007,\n                0x04bb_8820, 0x3c5c_2a41, 0x37ee_7af8, 0x8eb0_4025, 0x9313_ecba, 0xbffc_4799, 0x8955_a744, 0xef85_d633,\n                0x5044_99a7, 0xa6ca_6a86, 0xbb3d_3297, 0xb34a_8236, 0x6dcc_be4f, 0x0614_3394, 0xce19_fc7b, 0xccc3_c6c6,\n                0xe362_54ae, 0x77b7_eda1, 0xa133_dd9e, 0xebf9_356a, 0x513c_cf88, 0xe2a1_b417, 0x972e_e5bd, 0x8538_24cd,\n                0x5752_f4ee, 0x6c11_42e8, 0x3ea4_f309, 0xb2b5_934a, 0xdfd6_28aa, 0x59ac_ea3e, 0xa01e_b92c, 0x3899_64bc,\n                0xda30_5dd4, 0x019a_59b7, 0x11d2_ca93, 0xfaa6_d3b9, 0x4e77_2eca, 0x7265_1776, 0xfb4e_5b0e, 0xa38f_91a8,\n                0x1d06_63b5, 0x30f4_f192, 0xb500_51b6, 0xb716_ccb3, 0x4abd_1b59, 0x146c_5f26, 0xf134_e2de, 0x00f6_7c6c,\n                0xb0e1_b795, 0x98aa_4ec7, 0x0cc7_3b34, 0x6542_76a3, 0x8d1b_a871, 0x740a_5216, 0xe0d0_1a23, 0x9ed1_61d6,\n                0x9f36_a324, 0x993e_bb7f, 0xfeb9_491b, 0x365d_dcdb, 0x810c_ffc5, 0x71ec_0382, 0x2249_e7bf, 0x4881_7046,\n                0xf3a2_4a5b, 0x4288_e4d9, 0x0bf5_c243, 0x257f_e151, 0x95b6_4c0d, 0x4164_f066, 0xaaf7_db08, 0x73b1_119d,\n                0x8f9f_7bb8, 0xd684_4596, 0xf07a_34a6, 0x5394_3d0a, 0xf9dd_166d, 0x7a89_57af, 0xf8ba_3ce5, 0x27c9_621e,\n                0x5cda_e910, 0xc851_8998, 0x9415_38fe, 0x1361_15d8, 0xaba8_443c, 0x4d01_f931, 0x34ed_f760, 0xb45f_266b,\n                0xd5d4_de14, 0x52d8_ac35, 0x15cf_d885, 0xcbc5_cd21, 0x4cd7_6d4d, 0x7c80_ef54, 0xbc92_ee75, 0x1e56_a1f6,\n            ),\n            (\n                0xbaa2_0b6c, 0x9ffb_ad26, 0xe1f7_d738, 0x794a_ec8d, 0xc9e9_cf3c, 0x8a9a_7846, 0xc57c_4685, 0xb9a9_2fed,\n                0x29cb_141f, 0x52f9_ddb7, 0xf68b_a6bc, 0x19cc_c020, 0x4f58_4aaa, 0x3bf6_a596, 0x003b_7cf7, 0x54f0_ce9a,\n                0xa7ec_4303, 0x46cf_0077, 0x78d3_3aa1, 0x2152_47d9, 0x74bc_df91, 0x0838_1d30, 0xdac4_3e40, 0x6487_2531,\n                0x0bef_fe5f, 0xb317_f457, 0xaebb_12da, 0xd5d0_d67b, 0x7d75_c6b4, 0x42a6_d241, 0x1502_d0a9, 0x3fd9_7fff,\n                0xc6c3_ed28, 0x8186_8d0a, 0x9262_8bc5, 0x8667_9544, 0xfd18_67af, 0x5ca3_ea61, 0x568d_5578, 0x4a2d_71f4,\n                0x43c9_d549, 0x8d95_de2b, 0x6e5c_74a0, 0x9120_ffc7, 0x0d05_d14a, 0xa930_49d3, 0xbfa8_0e17, 0xf409_6810,\n                0x043f_5ef5, 0xa673_b4f1, 0x6d78_0298, 0xa484_7783, 0x5ee7_26fb, 0x9934_c281, 0x220a_588c, 0x384e_240f,\n                0x933d_5c69, 0x39e5_ef47, 0x26e8_b8f3, 0x4c1c_6212, 0x8040_f75d, 0x074b_7093, 0x6625_a8d7, 0x3629_8945,\n                0x7628_5088, 0x651d_37c3, 0x24f5_274d, 0xdbca_3dab, 0x186b_7ee1, 0xd80f_8182, 0x1421_0c89, 0x943a_3075,\n                0x4e6e_11c4, 0x4d7e_6bad, 0xf050_64c8, 0x025d_cd97, 0x4bc1_0302, 0x7ced_e572, 0x8f90_a970, 0xab88_eeba,\n                0xb599_8029, 0x5124_d839, 0xb0ee_b6a3, 0x89dd_abdc, 0xe807_4d76, 0xa146_5223, 0x3251_8cf2, 0x9d39_d4eb,\n                0xc0d8_4524, 0xe35e_6ea8, 0x7abf_3804, 0x113e_2348, 0x9ae6_069d, 0xb4df_dabb, 0xa8c5_313f, 0x23ea_3f79,\n                0x530e_36a2, 0xa5fd_228b, 0x95d1_d350, 0x2b14_cc09, 0x4004_2956, 0x879d_05cc, 0x2064_b9ca, 0xacac_a40e,\n                0xb29c_846e, 0x9676_c9e3, 0x752b_7b8a, 0x7be2_bcc2, 0x6bd5_8f5e, 0xd48f_4c32, 0x6068_35e4, 0x9cd7_c364,\n                0x2c26_9b7a, 0x3a0d_079c, 0x73b6_83fe, 0x4537_4f1e, 0x10af_a242, 0x577f_8666, 0xddaa_10f6, 0xf34f_561c,\n                0x3d35_5d6b, 0xe470_48ae, 0xaa13_c492, 0x0503_44fd, 0x2aab_5151, 0xf5b2_6ae5, 0xed91_9a59, 0x5ac6_7900,\n                0xf1cd_e380, 0x0c79_a11b, 0x3515_33fc, 0xcd4d_8e36, 0x1f85_6005, 0x690b_9fdd, 0xe736_dccf, 0x1d47_bf6a,\n                0x7f66_c72a, 0x85f2_1b7f, 0x983c_bdb6, 0x01eb_bebf, 0x035f_3b99, 0xeb11_1f34, 0x28ce_fdc6, 0x5bfc_9ecd,\n                0xf22e_acb0, 0x9e41_cbb2, 0xe0f8_327c, 0x82e3_e26f, 0xfc43_fc86, 0xd0ba_66df, 0x489e_f2a7, 0xd9e0_c81d,\n                0x6869_0d52, 0xcc45_1367, 0xc223_2e16, 0xe95a_7335, 0x0fda_e19b, 0xff5b_962c, 0x9759_6527, 0xc46d_b333,\n                0x3ed4_c562, 0xc14c_9d9e, 0x5d6f_aa21, 0x638e_940d, 0xf931_6d58, 0x47b3_b0ea, 0x30ff_cad2, 0xce1b_ba7d,\n                0x1e61_08e6, 0x2e1e_a33d, 0x507b_f05b, 0xfafe_f94b, 0xd17d_e8e2, 0x5598_b214, 0x1663_f813, 0x17d2_5a2d,\n                0xeefa_5ff9, 0x582f_4e37, 0x1212_8773, 0xfef1_7ab8, 0x0600_5322, 0xbb32_bbc9, 0x8c89_8508, 0x592c_15f0,\n                0xd38a_4054, 0x4957_b7d6, 0xd2b8_91db, 0x37bd_2d3e, 0x34ad_20cb, 0x6222_88e9, 0x2dc7_345a, 0xafb4_16c0,\n                0x1cf4_59b1, 0xdc77_39fa, 0x0a71_1a25, 0x13e1_8a0c, 0x5f72_af4c, 0x6ac8_db11, 0xbe53_c18e, 0x1aa5_69b9,\n                0xef55_1ea4, 0xa02a_429f, 0xbd16_e790, 0x7eb9_171a, 0x77d6_93d8, 0x8e06_993a, 0x9bde_7560, 0xe580_1987,\n                0xc37a_09be, 0xb8db_76ac, 0xe208_7294, 0x6c81_616d, 0xb7f3_0fe7, 0xbc9b_82bd, 0xfba4_e4d4, 0xc7b1_012f,\n                0xa20c_043b, 0xde9f_ebd0, 0x2f92_97ce, 0xe610_aef8, 0x70b0_6f19, 0xc86a_e00b, 0x0e01_988f, 0x4119_2ae0,\n                0x448c_1cb5, 0xadbe_92ee, 0x7293_a007, 0x1b54_b5b3, 0xd61f_63d1, 0xeae4_0a74, 0x61a7_2b55, 0xec83_a7d5,\n                0x8894_2806, 0x90a0_7da5, 0xd742_4b95, 0x6774_5b4e, 0xa31a_1853, 0xca60_21ef, 0xdfb5_6c4f, 0xcbc2_d915,\n                0x3c48_e918, 0x8bae_3c63, 0x6f65_9c71, 0xf8b7_54c1, 0x2782_f3de, 0xf796_f168, 0x7149_2c84, 0x33c0_f5a6,\n                0x3144_f6ec, 0x25dc_412e, 0xb16c_5743, 0x83a1_fa7e, 0x0997_b101, 0xb627_e6e8, 0xcf33_905c, 0x8456_fb65,\n            ),\n            (\n                0xb29b_ea74, 0xc35d_a605, 0x305c_1ca3, 0xd2e9_f5bc, 0x6fd5_bff4, 0xff34_7703, 0xfc45_b163, 0xf498_e068,\n                0xb712_29fc, 0x81ac_c3fb, 0x7853_8a8b, 0x984e_cf81, 0xa5da_47a4, 0x8f25_9eef, 0x6475_dc65, 0x0818_65b9,\n                0x49e1_4a3c, 0x19e6_6079, 0xd382_e91b, 0x5b10_9794, 0x3f9f_81e1, 0x4470_a388, 0x4160_1abe, 0xaaf9_f407,\n                0x8e17_5ef6, 0xed84_2297, 0x893a_4271, 0x1790_839a, 0xd566_a99e, 0x6b41_7dee, 0x75c9_0d23, 0x715e_db31,\n                0x7235_53f7, 0x9afb_50c9, 0xfbc5_f600, 0xcd3b_6a4e, 0x97ed_0fba, 0x2968_9aec, 0x6313_5c8e, 0xf0e2_6c7e,\n                0x0692_ae7f, 0xdbb2_08ff, 0x2ede_3e9b, 0x6a65_bebd, 0xd408_67e9, 0xc954_afc5, 0x73b0_8201, 0x7ffd_f809,\n                0x1195_c24f, 0x1ca5_adca, 0x74bd_6d1f, 0xb393_c455, 0xcadf_d3fa, 0x99f1_3011, 0x0ebc_a813, 0x60e7_91b8,\n                0x6597_ac7a, 0x18a7_e46b, 0x09cb_49d3, 0x0b27_df6d, 0xcfe5_2f87, 0xcef6_6837, 0xe632_8035, 0xfa87_c592,\n                0x37ba_ff93, 0xd71f_cc99, 0xdcab_205c, 0x4d7a_5638, 0x4801_2510, 0x6279_7558, 0xb6cf_1fe5, 0xbc31_1834,\n                0x9c23_73ac, 0x14ec_6175, 0xa439_cbdf, 0x54af_b0ea, 0xd686_960b, 0xfdd0_d47b, 0x7b06_3902, 0x8b78_bac3,\n                0x26c6_a4d5, 0x5c00_55b6, 0x2376_102e, 0x0411_783e, 0x2aa3_f1cd, 0x51fc_6ea8, 0x701c_e243, 0x9b2a_0abb,\n                0x0ad9_3733, 0x6e80_d03d, 0xaf62_95d1, 0xf629_896f, 0xa30b_0648, 0x463d_8dd4, 0x963f_84cb, 0x01ff_94f8,\n                0x8d7f_efdc, 0x5536_11c0, 0xa97c_1719, 0xb96a_f759, 0xe0e3_c95e, 0x0528_335b, 0x21fe_5925, 0x821a_5245,\n                0x8072_38b1, 0x67f2_3db5, 0xea6b_4eab, 0x0da6_f985, 0xab1b_c85a, 0xef8c_90e4, 0x4526_230e, 0x38eb_8b1c,\n                0x1b91_cd91, 0x9fce_5f0c, 0xf72c_c72b, 0xc64f_2617, 0xdaf7_857d, 0x7d37_3cf1, 0x28ea_edd7, 0x2038_87d0,\n                0xc49a_155f, 0xa251_b3b0, 0xf2d4_7ae3, 0x3d9e_f267, 0x4a94_ab2f, 0x7755_a222, 0x0205_e329, 0xc28f_a7a7,\n                0xaec1_fe51, 0x270f_164c, 0x8c6d_01bf, 0x53b5_bc98, 0xc09d_3feb, 0x8349_86cc, 0x4309_a12c, 0x578b_2a96,\n                0x3bb7_4b86, 0x6956_1b4a, 0x037e_32f3, 0xde33_5b08, 0xc515_6be0, 0xe7ef_09ad, 0x93b8_34c7, 0xa771_9352,\n                0x5930_2821, 0xe352_9d26, 0xf961_da76, 0xcb14_2c44, 0xa0f3_b98d, 0x7650_2457, 0x945a_414b, 0x078e_eb12,\n                0xdff8_de69, 0xeb6c_8c2d, 0xbda9_0c4d, 0xe9c4_4d16, 0x168d_fd66, 0xad64_763b, 0xa65f_d764, 0x95a2_9c06,\n                0x32d7_713f, 0x40f0_b277, 0x224a_f08f, 0x004c_b5e8, 0x9257_4814, 0x8877_d827, 0x3e5b_2d04, 0x68c2_d5f2,\n                0x8696_6273, 0x1d43_3ada, 0x8774_988a, 0x3c0e_0bfe, 0xddad_581d, 0x2fd6_54ed, 0x0f47_69fd, 0xc181_ee9d,\n                0x5fd8_8f61, 0x341d_bb3a, 0x5285_43f9, 0xd922_35cf, 0x1ea8_2eb4, 0xb5cd_790f, 0x91d2_4f1e, 0xa869_e6c2,\n                0x61f4_74d2, 0xcc20_5add, 0x0c7b_fba9, 0xbf2b_0489, 0xb02d_72d8, 0x2b46_ece6, 0xe4dc_d90a, 0xb8a1_1440,\n                0xee8a_63b7, 0x854d_d1a1, 0xd1e0_0583, 0x42b4_0e24, 0x9e89_64de, 0xb4b3_5d78, 0xbec7_6f6e, 0x24b9_c620,\n                0xd8d3_99a6, 0x5adb_2190, 0x2db1_2730, 0x3a58_66af, 0x58c8_fadb, 0x5d88_44e7, 0x8a4b_f380, 0x15a0_1d70,\n                0x79f5_c028, 0x66be_3b8c, 0xf3e4_2b53, 0x5699_0039, 0x2c0c_3182, 0x5e16_407c, 0xecc0_4515, 0x6c44_0284,\n                0x4cb6_701a, 0x13bf_c142, 0x9d03_9f6a, 0x4f6e_92c8, 0xa140_7c62, 0x8483_a095, 0xc70a_e1c4, 0xe202_13a2,\n                0xbaca_fc41, 0x4ecc_12b3, 0x4bee_3646, 0x1fe8_07ae, 0x2521_7f9c, 0x35dd_e5f5, 0x7a7d_d6ce, 0xf89c_ce50,\n                0xac07_b718, 0x7e73_d2c6, 0xe563_e76c, 0x123c_a536, 0x3948_ca56, 0x9019_dd49, 0x10aa_88d9, 0xc824_51e2,\n                0x473e_b6d6, 0x506f_e854, 0xe8bb_03a5, 0x332f_4c32, 0xfe1e_1e72, 0xb1ae_572a, 0x7c0d_7bc1, 0xe1c3_7eb2,\n                0xf542_aa60, 0xf1a4_8ea0, 0xd067_b89f, 0xbbfa_195d, 0x1a04_9b0d, 0x3159_46aa, 0x36d1_b447, 0x6d2e_bdf0,\n            ),\n            (\n                0x0d18_8a6d, 0x12ce_a0db, 0x7e63_740e, 0x6a44_4821, 0x253d_234f, 0x6ffc_6597, 0x94a6_bdef, 0x33ee_1b2f,\n                0x0a6c_00c0, 0x3aa3_36b1, 0x5af5_5d17, 0x265f_b3dc, 0x0e89_cf4d, 0x0786_b008, 0xc800_55b8, 0x6b17_c3ce,\n                0x72b0_5a74, 0xd21a_8d78, 0xa6b7_0840, 0xfe8e_ae77, 0xed69_565c, 0x55e1_bcf4, 0x585c_2f60, 0xe06f_1a62,\n                0xad67_c0cd, 0x7712_af88, 0x9cc2_6aca, 0x1888_053d, 0x37eb_853e, 0x9215_abd7, 0xde30_adfc, 0x1f10_38e6,\n                0x70c5_1c8a, 0x8d58_6c26, 0xf72b_dd90, 0x4dc3_ce15, 0x68ea_eefa, 0xd0e9_c8b9, 0x200f_9c44, 0xddd1_41ba,\n                0x024b_f1d3, 0x0f64_c9d4, 0xc421_e9e9, 0x9d11_c14c, 0x9a0d_d9e4, 0x5f92_ec19, 0x1b98_0df0, 0x1dcc_4542,\n                0xb8fe_8c56, 0x0c9c_9167, 0x4e81_eb49, 0xca36_8f27, 0xe360_3b37, 0xea08_accc, 0xac51_6992, 0xc34f_513b,\n                0x804d_100d, 0x6edc_a4c4, 0xfc91_2939, 0x29d2_19b0, 0x278a_aa3c, 0x4868_da7d, 0x54e8_90b7, 0xb46d_735a,\n                0x5145_89aa, 0xd6c6_30af, 0x4980_dfe8, 0xbe3c_cc55, 0x59d4_1202, 0x650c_078b, 0xaf3a_9e7b, 0x3ed9_827a,\n                0x9e79_fc6e, 0xaadb_fbae, 0xc5f7_d803, 0x3daf_7f50, 0x67b4_f465, 0x7340_6e11, 0x3931_3f8c, 0x8a6e_6686,\n                0xd807_5f1f, 0xd3cb_fed1, 0x69c7_e49c, 0x9305_81e0, 0xe4b1_a5a8, 0xbbc4_5472, 0x09dd_bf58, 0xc91d_687e,\n                0xbdbf_fda5, 0x88c0_8735, 0xe9e3_6bf9, 0xdb5e_a9b6, 0x9555_9404, 0x08f4_32fb, 0xe24e_a281, 0x6466_3579,\n                0x000b_8010, 0x7914_e7d5, 0x32fd_0473, 0xd1a7_f0a4, 0x445a_b98e, 0xec72_993f, 0xa29a_4d32, 0xb773_06d8,\n                0xc7c9_7cf6, 0x7b6a_b645, 0xf5ef_7adf, 0xfb2e_15f7, 0xe747_f757, 0x5e94_4354, 0x234a_2669, 0x47e4_6359,\n                0x9b9d_11a9, 0x4076_2ced, 0x56f1_de98, 0x1133_4668, 0x890a_9a70, 0x1a29_6113, 0xb3bd_4af5, 0x163b_7548,\n                0xd51b_4f84, 0xb99b_2abc, 0x3cc1_dc30, 0xa9f0_b56c, 0x8122_72b2, 0x0b23_3a5f, 0xb650_dbf2, 0xf1a0_771b,\n                0x3656_2b76, 0xdc03_7b0f, 0x104c_97ff, 0xc2ec_98d2, 0x9059_6f22, 0x28b6_620b, 0xdf42_b212, 0xfdbc_4243,\n                0xf3fb_175e, 0x4a2d_8b00, 0xe8f3_869b, 0x30d6_9bc3, 0x8537_14c8, 0xa775_1d2e, 0x31e5_6dea, 0xd484_0b0c,\n                0x9685_d783, 0x068c_9333, 0x8fba_032c, 0x76d7_bb47, 0x6d0e_e22b, 0xb546_794b, 0xd971_b894, 0x8b09_d253,\n                0xa0ad_5761, 0xee77_ba06, 0x4635_9f31, 0x577c_c7ec, 0x5282_5efd, 0xa4be_ed95, 0x9825_c52a, 0xeb48_029a,\n                0xbaae_59f8, 0xcf49_0ee1, 0xbc99_0164, 0x8ca4_9dfe, 0x4f38_a6e7, 0x2ba9_8389, 0x8228_f538, 0x199f_64ac,\n                0x01a1_cac5, 0xa8b5_1641, 0x5ce7_2d01, 0x8e5d_f26b, 0x60f2_8e1e, 0xcd5b_e125, 0xe5b3_76bf, 0x1c8d_3116,\n                0x7132_cbb3, 0xcb7a_e320, 0xc0fa_5366, 0xd765_3e34, 0x971c_88c2, 0xc62c_7dd0, 0x34d0_a3da, 0x868f_6709,\n                0x7ae6_fa8f, 0x22bb_d523, 0x66cd_3d5b, 0x1ef9_288d, 0xf9cf_58c1, 0x5b78_4e80, 0x7439_a191, 0xae13_4c36,\n                0x9116_c463, 0x2e9e_1396, 0xf861_1f3a, 0x2d2f_3307, 0x247f_37dd, 0xc1e2_ff9d, 0x43c8_21e5, 0x05ed_5cab,\n                0xef74_e80a, 0x4cca_6028, 0xf0ac_3cbd, 0x5d87_4b29, 0x6c62_f6a6, 0x4b2a_2ef3, 0xb1aa_2087, 0x62a5_d0a3,\n                0x0327_221c, 0xb096_b4c6, 0x417e_c693, 0xaba8_40d6, 0x7897_25eb, 0xf4b9_e02d, 0xe6e0_0975, 0xcc04_961a,\n                0x63f6_24bb, 0x7fa2_1ecb, 0x2c01_ea7f, 0xb241_5005, 0x2a8b_beb5, 0x83b2_b14e, 0xa383_d1a7, 0x5352_f96a,\n                0x043e_cdad, 0xce19_18a1, 0xfa6b_e6c9, 0x50de_f36f, 0xf6b8_0ce2, 0x4543_ef7c, 0x9953_d651, 0xf257_955d,\n                0x8724_4914, 0xda1e_0a24, 0xffda_4785, 0x14d3_27a2, 0x3b93_c29f, 0x8406_84b4, 0x61ab_71a0, 0x9f7b_784a,\n                0x2fd5_70cf, 0x1595_5bde, 0x38f8_d471, 0x3534_a718, 0x133f_b71d, 0x3fd8_0f52, 0x4290_a8be, 0x75ff_44c7,\n                0xa554_e546, 0xe102_3499, 0xbf26_52e3, 0x7d20_399e, 0xa1df_7e82, 0x1770_92ee, 0x217d_d3f1, 0x7c1f_f8d9,\n            ),\n            (\n                0x1211_3f2e, 0xbfbd_0785, 0xf117_93fb, 0xa5bf_f566, 0x83c7_b0e5, 0x72fb_316b, 0x7552_6a9a, 0x41e0_e612,\n                0x7156_ba09, 0x53ce_7dee, 0x0aa2_6881, 0xa43e_0d7d, 0x3da7_3ca3, 0x1827_61ed, 0xbd50_77ff, 0x56db_4aa0,\n                0xe792_711c, 0xf0a4_eb1d, 0x7f87_8237, 0xec65_c4e8, 0x08dc_8d43, 0x0f8c_e142, 0x8258_abda, 0xf415_4e16,\n                0x49de_c2fd, 0xcd8d_5705, 0x6c2c_3a0f, 0x5c12_bb88, 0xeff3_cdb6, 0x2c89_ed8c, 0x7beb_a967, 0x2a14_2157,\n                0xc6d0_836f, 0xb4f9_7e96, 0x6931_e969, 0x514e_6c7c, 0xa779_2600, 0x0bbb_f780, 0x5967_1bbd, 0x0707_b676,\n                0x3748_2d93, 0x80af_1479, 0x3805_a60d, 0xe1f4_cac1, 0x580b_3074, 0x30b8_d6ce, 0x05a3_04be, 0xd176_626d,\n                0xebca_97f3, 0xbb20_1f11, 0x6a1a_fe23, 0xffaa_86e4, 0x62b4_da49, 0x1b66_29f5, 0xf5d9_e092, 0xf37f_3dd1,\n                0x619b_d45b, 0xa6ec_8e4f, 0x29c8_0939, 0x0c7c_0c34, 0x9cfe_6e48, 0xe65f_d3ac, 0x7361_3b65, 0xb3c6_69f9,\n                0xbe2e_8a9e, 0x286f_9678, 0x5797_fd13, 0x9980_5d75, 0xcfb6_41c5, 0xa910_74ba, 0x6343_af47, 0x6403_cb46,\n                0x8894_c8db, 0x2663_034c, 0x3c40_dc5e, 0x0099_5231, 0x9678_9aa2, 0x2efd_e4b9, 0x7dc1_95e1, 0x547d_add5,\n                0x06a8_ea04, 0xf234_7a63, 0x5e0d_c6f7, 0x8462_dfc2, 0x1e6b_2c3c, 0x9bd2_75b3, 0x91d4_19e2, 0xbcef_d17e,\n                0xb900_3924, 0xd07e_7320, 0xdef0_495c, 0xc36a_d00e, 0x1785_b1ab, 0x92e2_0bcf, 0xb139_f0e9, 0x675b_b9a1,\n                0xaecf_a4af, 0x1323_76cb, 0xe845_89d3, 0x79a0_5456, 0xa2f8_60bc, 0x1ae4_f8b5, 0x20df_4db4, 0xa1e1_428b,\n                0x3bf6_0a1a, 0x27ff_7bf1, 0xcb44_c0e7, 0xf7f5_87c4, 0x1f3b_9b21, 0x9436_8f01, 0x856e_23a4, 0x6f93_de3f,\n                0x773f_5bbf, 0x8b22_056e, 0xdf41_f654, 0xb824_6ff4, 0x8d57_bff2, 0xd571_67ea, 0xc569_9f22, 0x4073_4ba7,\n                0x5d5c_2772, 0x0330_20a8, 0xe30a_7c4d, 0xadc4_0fd6, 0x7635_3441, 0x5aa5_229b, 0x8151_6590, 0xda49_f14e,\n                0x4fa6_72a5, 0x4d9f_ac5f, 0x154b_e230, 0x8a7a_5cc0, 0xce3d_2f84, 0xcca1_5514, 0x5221_360c, 0xaf0f_b81e,\n                0x5bdd_5873, 0xf682_5f8f, 0x1113_d228, 0x70ad_996c, 0x9332_0051, 0x6047_1c53, 0xe9ba_567b, 0x3a46_2ae3,\n                0x5f55_e72d, 0x1d3c_5ad7, 0xdcfc_45ec, 0x34d8_12ef, 0xfa96_ee1b, 0x369d_1ef8, 0xc9b1_a189, 0x7c1d_3555,\n                0x5084_5edc, 0x4bb3_1877, 0x8764_a060, 0x8c9a_9415, 0x230e_1a3a, 0xb05e_9133, 0x242b_9e03, 0xa3b9_9db7,\n                0xc2d7_fb0a, 0x3333_849d, 0xd272_78d4, 0xb5d3_efa6, 0x78ac_28ad, 0xc7b2_c135, 0x0926_ecf0, 0xc137_4c91,\n                0x74f1_6d98, 0x2274_084a, 0x3f6d_9cfa, 0x7ac0_a383, 0xb73a_ff1f, 0x3909_a23d, 0x9f16_53ae, 0x4e2f_3e71,\n                0xca5a_b22a, 0xe01e_3858, 0x90c5_a7eb, 0x3e4a_17df, 0xaa98_7fb0, 0x488b_bd62, 0xb625_062b, 0x2d77_6bb8,\n                0x43b5_fc08, 0x1490_d532, 0xd6d1_2495, 0x44e8_9845, 0x2fe6_0118, 0x9d9e_f950, 0xac38_133e, 0xd386_4329,\n                0x017b_255a, 0xfdc2_dd26, 0x2568_51e6, 0x318e_7086, 0x2bfa_4861, 0x89ea_c706, 0xee59_40c6, 0x68c3_bc2f,\n                0xe260_334b, 0x98da_90bb, 0xf818_f270, 0x4706_d897, 0x212d_3799, 0x4cf7_e5d0, 0xd9c9_649f, 0xa85d_b5cd,\n                0x35e9_0e82, 0x6b88_1152, 0xab1c_02c7, 0x4675_2b02, 0x664f_598e, 0x45ab_2e64, 0xc4cd_b4b2, 0xba42_107f,\n                0xea2a_808a, 0x971b_f3de, 0x4a54_a836, 0x4253_aecc, 0x1029_be68, 0x6dcc_9225, 0xe4bc_a56a, 0xc0ae_50b1,\n                0x7e01_1d94, 0xe59c_162c, 0xd8e5_c340, 0xd470_fa0b, 0xb2be_79dd, 0xd783_889c, 0x1ced_e8f6, 0x8f4c_817a,\n                0xddb7_85c9, 0x8602_32d8, 0x198a_aad9, 0xa081_4738, 0x3219_cffc, 0x1695_46d2, 0xfc0c_b759, 0x5591_1510,\n                0x04d5_cec3, 0xed08_cc3b, 0x0d6c_f427, 0xc8e3_8cca, 0x0eee_e3fe, 0x9ee7_d7c8, 0xf9f2_4fa9, 0xdb04_b35d,\n                0x9ab0_c9e0, 0x651f_4417, 0x028f_8b07, 0x6e28_d9aa, 0xfba9_6319, 0x8ed6_6687, 0xfecb_c58d, 0x954d_db44,\n            ),\n            (\n                0x7b0b_dffe, 0x865d_16b1, 0x49a0_58c0, 0x97ab_aa3f, 0xcaac_c75d, 0xaba6_c17d, 0xf874_6f92, 0x6f48_aeed,\n                0x8841_d4b5, 0xf36a_146a, 0x73c3_90ab, 0xe6fb_558f, 0x87b1_019e, 0x2697_0252, 0x2463_77b2, 0xcbf6_76ae,\n                0xf923_db06, 0xf738_9116, 0x14c8_1a90, 0x8311_4eb4, 0x8b13_7559, 0x95a8_6a7a, 0xd5b8_da8c, 0xc4df_780e,\n                0x5a9c_b3e2, 0xe44d_4062, 0xe8dc_8ef6, 0x9d18_0845, 0x817a_d18b, 0xc286_c85b, 0x251f_20de, 0xee6d_5933,\n                0xf6ed_ef81, 0xd4d1_6c1e, 0xc94a_0c32, 0x8437_fd22, 0x3271_ee43, 0x4257_2aee, 0x5f91_962a, 0x1c52_2d98,\n                0x59b2_3f0c, 0xd86b_8804, 0x08c6_3531, 0x2c0d_7a40, 0xb97c_4729, 0x0496_4df9, 0x13c7_4a17, 0x5878_362f,\n                0x4c80_8cd6, 0x092c_b1e0, 0x6df0_2885, 0xa0c2_105e, 0x8aba_9e68, 0x64e0_3057, 0xe5d6_1325, 0x0e43_a628,\n                0x16db_d62b, 0x2733_d90b, 0x3ae5_7283, 0xc0c1_052c, 0x4b6f_b620, 0x3751_3953, 0xfc89_8bb3, 0x471b_179f,\n                0xdf6e_66b8, 0xd321_42f5, 0x9b30_fafc, 0x4ed9_2549, 0x105c_6d99, 0x4acd_69ff, 0x2b1a_27d3, 0x6bfc_c067,\n                0x6301_a278, 0xad36_e6f2, 0xef3f_f64e, 0x56b3_cadb, 0x0184_bb61, 0x17be_b9fd, 0xfaec_6109, 0xa2e1_ffa1,\n                0x2fd2_24f8, 0x238f_5be6, 0x8f85_70cf, 0xaeb5_f25a, 0x4f1d_3e64, 0x4377_eb24, 0x1fa4_5346, 0xb205_6386,\n                0x5209_5e76, 0xbb7b_5adc, 0x3514_e472, 0xdde8_1e6e, 0x7ace_a9c4, 0xac15_cc48, 0x71c9_7d93, 0x767f_941c,\n                0x9110_52a2, 0xffea_09bf, 0xfe3d_dcf0, 0x15eb_f3aa, 0x9235_b8bc, 0x7540_8615, 0x9a72_3437, 0xe1a1_bd38,\n                0x3354_1b7e, 0x1bdd_6856, 0xb307_e13e, 0x9081_4bb0, 0x51d7_217b, 0x0bb9_2219, 0x689f_4500, 0xc568_b01f,\n                0x5df3_d2d7, 0x3c0e_cd0d, 0x2a02_44c8, 0x8525_74e8, 0xe72f_23a9, 0x8e26_ed02, 0x2d92_cbdd, 0xdabc_0458,\n                0xcdf5_feb6, 0x9e4e_8dcc, 0xf4f1_e344, 0x0d8c_436d, 0x4427_603b, 0xbdd3_7fda, 0x8050_5f26, 0x8c7d_2b8e,\n                0xb732_73c5, 0x3973_62ea, 0x618a_3811, 0x608b_fb88, 0x06f7_d714, 0x212e_4677, 0x28ef_cead, 0x076c_0371,\n                0x36a3_a4d9, 0x5487_b455, 0x3429_a365, 0x65d4_67ac, 0x78ee_7eeb, 0x99bf_12b7, 0x4d12_9896, 0x772a_5601,\n                0xcce2_84c7, 0x2ed8_5c21, 0xd099_e8a4, 0xa179_158a, 0x6ac0_ab1a, 0x299a_4807, 0xbe67_a58d, 0xdc19_544a,\n                0xb894_9b54, 0x8d31_5779, 0xb6f8_49c1, 0x53c5_ac34, 0x66de_92a5, 0xf195_dd13, 0x318d_3a73, 0x301e_c542,\n                0x0cc4_0da6, 0xf253_ade4, 0x467e_e566, 0xea55_85ec, 0x3baf_19bb, 0x7de9_f480, 0x7900_6e7c, 0xa9b7_a197,\n                0xa44b_d8f1, 0xfb2b_a739, 0xec34_2fd4, 0xed4f_d32d, 0x3d17_89ba, 0x400f_5d7f, 0xc798_f594, 0x4506_a847,\n                0x034c_0a95, 0xe216_2c9d, 0x55a9_cfd0, 0x692d_832e, 0xcf9d_b2ca, 0x5e22_87e9, 0xd261_0ef3, 0x1ae7_ecc2,\n                0x4839_9ca0, 0xa7e4_269b, 0x6ee3_a0af, 0x7065_bfe1, 0xa6ff_e708, 0x2256_804c, 0x7476_e21b, 0x41b0_796c,\n                0x7c24_3b05, 0x000a_950f, 0x1858_416b, 0xf5a5_3c89, 0xe9fe_f823, 0x3f44_3275, 0xe0cb_f091, 0x0af2_7b84,\n                0x3ebb_0f27, 0x1de6_f7f4, 0xc31c_29f7, 0xb166_de3d, 0x1293_2ec3, 0x9c0c_0674, 0x5cda_81b9, 0xd1bd_9d12,\n                0xaffd_7c82, 0x8962_bca7, 0xa342_c4a8, 0x6245_7151, 0x8208_9f03, 0xeb49_c670, 0x5b5f_6530, 0x7e28_bad2,\n                0x2088_0ba3, 0xf0fa_afcd, 0xce82_b56f, 0x0275_335c, 0xc18e_8afb, 0xde60_1d69, 0xba9b_820a, 0xc8a2_be4f,\n                0xd7ca_c335, 0xd9a7_3741, 0x115e_974d, 0x7f5a_c21d, 0x383b_f9c6, 0xbcae_b75f, 0xfd03_50ce, 0xb5d0_6b87,\n                0x9820_e03c, 0x72d5_f163, 0xe364_4fc9, 0xa546_4c4b, 0x5704_8fcb, 0x9690_c9df, 0xdbf9_eafa, 0xbff4_649a,\n                0x053c_00e3, 0xb4b6_1136, 0x6759_3dd1, 0x503e_e960, 0x9fb4_993a, 0x1983_1810, 0xc670_d518, 0xb05b_51d8,\n                0x0f3a_1ce5, 0x6caa_1f9c, 0xaacc_31be, 0x949e_d050, 0x1ead_07e7, 0xa847_9abd, 0xd6cf_fcd5, 0x9369_93ef,\n            ),\n            (\n                0x472e_91cb, 0x5444_b5b6, 0x62be_5861, 0x1be1_02c7, 0x63e4_b31e, 0xe81f_71b7, 0x9e23_17c9, 0x39a4_08ae,\n                0x5180_24f4, 0x1731_c66f, 0x68cb_c918, 0x71fb_0c9e, 0xd03b_7fdd, 0x7d62_22eb, 0x9057_eda3, 0x1a34_a407,\n                0x8cc2_253d, 0xb6f6_979d, 0x8356_75dc, 0xf319_be9f, 0xbe1c_d743, 0x4d32_fee4, 0x77e7_d887, 0x37e9_ebfd,\n                0x15f8_51e8, 0x23dc_3706, 0x19d7_8385, 0xbd50_6933, 0xa13a_d4a6, 0x913f_1a0e, 0xdde5_60b9, 0x9a5f_0996,\n                0xa65a_0435, 0x48d3_4c4d, 0xe908_39a7, 0x8abb_a54e, 0x6fd1_3ce1, 0xc7ee_bd3c, 0x0e29_7602, 0x58b9_bbb4,\n                0xef79_01e6, 0x64a2_8a62, 0xa509_875a, 0xf883_4442, 0x2702_c709, 0x0735_3f31, 0x3b39_f665, 0xf5b1_8b49,\n                0x4010_ae37, 0x784d_e00b, 0x7a11_21e9, 0xde91_8ed3, 0xc852_9dcd, 0x816a_5d05, 0x02ed_8298, 0x04e3_dd84,\n                0xfd2b_c3e2, 0xaf16_7089, 0x96af_367e, 0xa4da_6232, 0x18ff_7325, 0x05f9_a9f1, 0x4fef_b9f9, 0xcd94_eaa5,\n                0xbfaa_5069, 0xa0b8_c077, 0x60d8_6f57, 0xfe71_c813, 0x29eb_d2c8, 0x4ca8_6538, 0x6bf1_a030, 0xa237_b88a,\n                0xaa8a_f41d, 0xe1f7_b6ec, 0xe214_d953, 0x3305_7879, 0x49ca_a736, 0xfa45_cff3, 0xc063_b411, 0xba7e_27d0,\n                0x3153_3819, 0x2a00_4ac1, 0x210e_fc3f, 0x2646_885e, 0x6672_7dcf, 0x9d7f_bf54, 0xa8dd_0ea8, 0x3447_cace,\n                0x3f0c_14db, 0xb838_2aac, 0x4ace_3539, 0x0a51_8d51, 0x9517_8981, 0x35ae_e2ca, 0x73f0_f7e3, 0x9428_1140,\n                0x59d0_e523, 0xd292_cb88, 0x565d_1b27, 0x7ec8_fbaf, 0x069a_f08d, 0xc127_fd24, 0x0bc7_7b10, 0x5f03_e7ef,\n                0x453e_99ba, 0xeed9_ff7f, 0x87b5_5215, 0x7915_ab4c, 0xd389_a358, 0x5e75_ce6d, 0x28d6_55c0, 0xdad2_6c73,\n                0x2e25_10ff, 0x9fa7_eecc, 0x1d06_29c3, 0xdc9c_9c46, 0x2d67_ecd7, 0xe75e_94bd, 0x3d64_9e2a, 0x6c41_3a2b,\n                0x706f_0d7c, 0xdfb0_127b, 0x4e36_6b55, 0x2c82_5650, 0x2420_5720, 0xb5c9_98f7, 0x3e95_462c, 0x756e_5c72,\n                0x3259_488f, 0x11e8_771a, 0xa7c0_a617, 0x5776_63e5, 0x089b_6401, 0x8eab_1941, 0xae55_ef8c, 0x3aac_5460,\n                0xd4e6_262f, 0x5d97_9a47, 0xb198_23b0, 0x7f8d_6a0c, 0xffa0_8683, 0x0170_cd0f, 0x858c_d5d8, 0x5396_1c90,\n                0xc4c6_1556, 0x41f2_f226, 0xcfcd_062d, 0xf24c_03b8, 0xea81_df5b, 0x7be2_fa52, 0xb361_f98b, 0xc290_1316,\n                0x55ba_4bbc, 0x93b2_34a9, 0x0fbc_6603, 0x80a9_6822, 0x6d60_491f, 0x22bd_00f8, 0xbcad_5aad, 0x52f3_f13b,\n                0x42fd_2b28, 0xb41d_d01c, 0xc52c_93bf, 0xfc66_3094, 0x8f58_d100, 0x43fe_cc08, 0xc633_1e5d, 0xe648_0f66,\n                0xca84_7204, 0x4bdf_1da0, 0x30cc_2efb, 0x13e0_2dea, 0xfb49_ac45, 0xf9d4_434f, 0xf47c_5b9c, 0x1488_79c2,\n                0x039f_c234, 0xa3db_9bfc, 0xd1a1_dc5c, 0x763d_7cd4, 0xed6d_2f93, 0xab13_af6e, 0x1e8e_054a, 0xd68f_4f9a,\n                0xc304_84b3, 0xd7d5_0afa, 0x6930_855f, 0xcc07_db95, 0xce74_6db1, 0x744e_967d, 0xf16c_f575, 0x8643_e8b5,\n                0xf0ea_e38e, 0xe52d_e1d1, 0x6587_dae0, 0x0c4b_8121, 0x1c7a_c567, 0xac0d_b20a, 0x36c3_a812, 0x5b1a_4514,\n                0xa9a3_f868, 0xb926_3baa, 0xcb3c_e9d2, 0xe44f_b1a4, 0x9221_bc82, 0xb293_90fe, 0x6ab4_1863, 0x974a_3e2e,\n                0x89f5_31c5, 0x255c_a13e, 0x8b65_d348, 0xec24_8f78, 0xd8fc_16f0, 0x50ec_deee, 0x0901_0792, 0x3c7d_1fb2,\n                0xeba5_426b, 0x847b_417a, 0x468b_40d9, 0x8dc4_e680, 0x7cc1_f391, 0x2f1e_b086, 0x6e5b_aa6a, 0xe0b3_95da,\n                0xe31b_2cf6, 0xd969_0b0d, 0x729e_c464, 0x3840_3dde, 0x610b_80a2, 0x5cf4_33ab, 0xb078_5fc4, 0xd512_e4c6,\n                0xbbb7_d699, 0x5a86_591b, 0x10cf_5376, 0x12bf_9f4b, 0x980f_baa1, 0x992a_4e70, 0x20fa_7ae7, 0xf799_6ebb,\n                0xc918_a2be, 0x82de_74f2, 0xad54_209b, 0xf66b_4d74, 0x1fc5_b771, 0x169d_9229, 0x8877_61df, 0x00b6_67d5,\n                0xdb42_5e59, 0xb72f_2844, 0x9b0a_c1f5, 0x9c73_7e3a, 0x2b85_476c, 0x6722_add6, 0x44a6_3297, 0x0d68_8ced,\n            ),\n            (\n                0xabc5_9484, 0x4107_778a, 0x8ad9_4c6f, 0xfe83_df90, 0x0f64_053f, 0xd129_2e9d, 0xc574_4356, 0x8dd1_abb4,\n                0x4c4e_7667, 0xfb4a_7fc1, 0x74f4_02cb, 0x70f0_6afd, 0xa822_86f2, 0x918d_d076, 0x7a97_c5ce, 0x48f7_bde3,\n                0x6a04_d11d, 0xac24_3ef7, 0x33ac_10ca, 0x2f7a_341e, 0x5f75_157a, 0xf477_3381, 0x591c_870e, 0x78df_8cc8,\n                0x22f3_adb0, 0x251a_5993, 0x09fb_ef66, 0x7969_42a8, 0x9754_1d2e, 0x2373_daa9, 0x1bd2_f142, 0xb57e_8eb2,\n                0xe1a5_bfdb, 0x7d0e_fa92, 0xb344_2c94, 0xd2cb_6447, 0x386a_c97e, 0x66d6_1805, 0xbdad_a15e, 0x11bc_1aa7,\n                0x14e9_f6ea, 0xe533_a0c0, 0xf935_ee0a, 0x8fee_8a04, 0x810d_6d85, 0x7c68_b6d6, 0x4edc_9aa2, 0x956e_897d,\n                0xed87_581a, 0x264b_e9d7, 0xff4d_db29, 0x8238_57c2, 0xe005_a9a0, 0xf1cc_2450, 0x6f99_51e1, 0xaade_2310,\n                0xe70c_75f5, 0x83e1_a31f, 0x4f7d_de8e, 0xf723_b563, 0x368e_0928, 0x8636_2b71, 0x21e8_982d, 0xdfb3_f92b,\n                0x4467_6352, 0x99ef_ba31, 0x2eab_4e1c, 0xfc6c_a5e7, 0x0ebe_5d4e, 0xa071_7d0c, 0xb64f_8199, 0x946b_31a1,\n                0x5656_cbc6, 0xcffe_c3ef, 0x6227_66c9, 0xfa21_1e35, 0x52f9_8b89, 0x6d01_674b, 0x4978_a802, 0xf651_f701,\n                0x15b0_d43d, 0xd6ff_4683, 0x3463_855f, 0x672b_a29c, 0xbc12_8312, 0x4626_a70d, 0xc892_7a5a, 0xb848_1cf9,\n                0x1c96_2262, 0xa211_96ba, 0xbaba_5ee9, 0x5bb1_62d0, 0x6994_3bd1, 0x0c47_e35c, 0x8cc9_619a, 0xe284_d948,\n                0x271b_f264, 0xc27f_b398, 0x4bc7_0897, 0x60cf_202c, 0x7f42_d6aa, 0xa5a1_3506, 0x5d3e_8860, 0xcea6_3d3c,\n                0x63bf_0a8f, 0xf02e_9efa, 0xb17b_0674, 0xb072_b1d3, 0x06e5_723b, 0x3737_e436, 0x24aa_49c7, 0x0ded_0d18,\n                0xdb25_6b14, 0x58b2_7877, 0xecb4_9f54, 0x6c40_256a, 0x6ea9_2ffb, 0x3906_aa4c, 0xc986_6fd5, 0x4549_323e,\n                0xa7b8_5fab, 0x1918_cc27, 0x7308_d7b5, 0x1e16_c7ad, 0x7185_0b37, 0x3095_fd78, 0xa63b_70e6, 0xd880_e2ae,\n                0x3e28_2769, 0xa39b_a6bc, 0x9870_0fa3, 0xf34c_53e8, 0x288a_f426, 0xb99d_930f, 0xf5b9_9df1, 0xe9d0_c8cf,\n                0x5ac8_405d, 0x50e7_217b, 0x511f_bbbe, 0x2ca2_e639, 0xc020_301b, 0x356d_bc00, 0x8e43_ddb9, 0x4d32_7b4a,\n                0xf20f_f3ed, 0x1dbb_29bd, 0x43d4_4779, 0xa1b6_8f70, 0x6114_455b, 0xe63d_280b, 0x6bf6_ff65, 0x10fc_39e5,\n                0x3dae_126e, 0xc1d7_cf11, 0xcb60_b795, 0x1789_d5b3, 0x9bca_36b7, 0x0830_6075, 0x8461_5608, 0x8b3a_0186,\n                0xe88f_becd, 0x7ba4_7c4d, 0x2de4_4dac, 0x653f_e58d, 0xcca0_b968, 0xd7fa_0e72, 0x9390_1780, 0x1f2c_26cc,\n                0xae59_5b6b, 0xa9ec_ea9b, 0xe3db_f8c4, 0x319c_c130, 0x1298_1196, 0x01a3_a4de, 0x32c4_54b6, 0x755b_d817,\n                0x3cd8_71e4, 0xa48b_b8da, 0x02fd_ec09, 0xfd2d_c2e2, 0x9e57_8088, 0x9a9f_916d, 0x4065_fe6c, 0x1853_999e,\n                0xc779_3f23, 0xdc10_16bb, 0x9693_55ff, 0x7ef2_92f6, 0xcdce_4adc, 0x05e2_4416, 0x85c1_6c46, 0xd441_d37f,\n                0x57bd_6855, 0x8746_f54f, 0x9ca7_73df, 0x770b_ae22, 0x5482_8413, 0xb75e_4b19, 0x04c3_5c03, 0xbf7c_ca07,\n                0x2955_c4dd, 0x721d_b041, 0xb239_4f33, 0x03f5_1387, 0x89b7_3c9f, 0x0b17_37f3, 0x07e6_9024, 0x9231_d245,\n                0x7619_3861, 0x8815_9c15, 0xdeb5_52d9, 0xd976_7e40, 0x20c6_c0c3, 0x4281_977c, 0xf8af_e1e0, 0xd32a_0751,\n                0x3fc2_7432, 0xddf1_dcc5, 0x6858_1f34, 0x3bcd_5025, 0x0091_b2ee, 0x4aeb_6944, 0x1602_e743, 0xea09_eb58,\n                0xef0a_2a8b, 0x641e_03a5, 0xeb50_e021, 0x5c8c_cef8, 0x802f_f0b8, 0xd5e3_edfe, 0xc4dd_1b49, 0x5334_cd2a,\n                0x13f8_2d2f, 0x4745_0c20, 0x55da_fbd2, 0xbec0_c6f4, 0xb45d_7959, 0x3ad3_6e8c, 0x0aa8_ac57, 0x1a3c_8d73,\n                0xe45a_afb1, 0x9f66_4838, 0xc688_0053, 0xd003_9bbf, 0xee5f_19eb, 0xca00_41d8, 0xbbea_3aaf, 0xda62_8291,\n                0x9d5c_95d4, 0xadd5_04a6, 0xc39a_b482, 0x5e9e_14a4, 0x2be0_65f0, 0x2a13_fc3a, 0x9052_e8ec, 0xaf6f_5afc,\n            ),\n            (\n                0x519a_a8b5, 0xbb30_3da9, 0xe00e_2b10, 0xdfa6_c1db, 0x2e6b_952e, 0xee10_dc23, 0x3793_6d09, 0x1fc4_2e92,\n                0x39b2_5a9f, 0x13ff_89f4, 0xc8f5_3fea, 0x1850_0bc7, 0x95a0_379d, 0x98f7_51c2, 0x2289_c42f, 0xa21e_4098,\n                0x6f39_1f41, 0xf27e_7e58, 0x0d0d_f887, 0x4b79_d540, 0x8e84_09aa, 0x71fe_46f8, 0x688a_9b29, 0x3f08_b548,\n                0x84ab_e03a, 0x5e91_b6c1, 0xfde4_c2ae, 0x251d_0e72, 0x92d4_fee5, 0xf937_1967, 0x9175_108f, 0xe6e8_1835,\n                0x8c8c_b8ee, 0xb55a_67b3, 0xcef1_38cc, 0x8b25_6268, 0x00d8_15f5, 0xe881_0812, 0x7782_6189, 0xea73_267d,\n                0x19b9_0f8d, 0x45c3_3bb4, 0x8247_7056, 0xe177_0075, 0x0946_7aa6, 0xa7c6_f54a, 0x7976_8742, 0x61b8_6bca,\n                0xd664_4a44, 0xe33f_0171, 0xc229_fbcd, 0x41b0_8feb, 0xd190_3e30, 0x65ec_9080, 0x563d_6fbd, 0xf56d_a488,\n                0xebf6_4cd8, 0x4934_426b, 0x7c85_92fc, 0x6aca_8cf2, 0x1cea_111b, 0x3a57_ee7a, 0xace1_1c0d, 0x9942_d85e,\n                0xc461_3407, 0xfa8e_643b, 0x327f_c701, 0x4ca9_be82, 0x3352_526d, 0x2c04_7f63, 0xf3a8_f7dd, 0x1a4a_98a8,\n                0x762e_d4d1, 0x27c7_5008, 0xbdf4_97c0, 0x7a7b_84df, 0x315c_28ab, 0x801f_93e3, 0xf19b_0ca1, 0x8f14_e46a,\n                0xe48b_a333, 0x9605_e625, 0xf03e_cb60, 0x6038_5f2d, 0x9028_45ba, 0x7f96_d66f, 0x24bf_f05c, 0x2820_730b,\n                0x9471_33cb, 0xd444_828a, 0xb343_f6f1, 0x0bef_4705, 0x8da5_74f9, 0x01e2_5d6c, 0x1732_793e, 0x4f0f_7b27,\n                0x364b_7117, 0xb2d1_da77, 0xa6c5_f1e9, 0x574c_a5b1, 0x386a_3076, 0xad68_94d6, 0x1156_d7fa, 0xa48d_1d9a,\n                0x4794_c0af, 0x150c_0aa0, 0x26d3_48ac, 0x29fd_eabe, 0xa5de_de53, 0x8167_1e8e, 0x594e_e3bf, 0xa96c_56e6,\n                0x3426_a726, 0xc597_6579, 0xbc22_e5e4, 0xc100_6319, 0xdaaf_dd2a, 0xa1a1_aa83, 0x3bad_d0e7, 0xc3b1_4981,\n                0xd770_b155, 0xccd7_c693, 0x42e9_44c5, 0x03e0_064f, 0xca95_b4ef, 0x3dee_81c3, 0xfbbc_d98c, 0x1e07_e15b,\n                0x667c_e949, 0xe7d6_773f, 0x21b6_124b, 0x6b2a_6ef7, 0xd327_8a9c, 0x9a98_8304, 0x75d2_ae9b, 0xfe49_e2ff,\n                0x9bc2_4f46, 0x74cc_2cf6, 0xa313_9f36, 0x6c9e_f35a, 0x9fc1_dffe, 0x9e5f_acdc, 0xaadc_8bbb, 0x5abd_bc5f,\n                0x44b3_b390, 0xf754_efa7, 0x5fe3_bdb7, 0x4e59_c886, 0x06a4_c984, 0xa033_8878, 0xcd51_3cd7, 0x63eb_d27e,\n                0x8aba_80ad, 0x50da_144e, 0x5d9f_4e97, 0x025b_751c, 0x2d58_0200, 0xb6c0_5837, 0x580a_a15d, 0x5402_2a6e,\n                0xb41a_5415, 0x4863_fab6, 0xb0b7_9957, 0x46d0_d159, 0xdc2b_8650, 0x20a7_bb0c, 0x4a03_2974, 0xec86_36a2,\n                0x8548_f24c, 0xf6a2_bf16, 0x1088_f4b0, 0x0c2f_3a94, 0x525d_c396, 0x1406_5785, 0x2b4d_ca52, 0x08ae_ed39,\n                0xabed_fc99, 0xb1db_cf18, 0x87f8_5bbc, 0xae3a_ff61, 0x433c_cd70, 0x5b23_cc64, 0x7b45_3213, 0x5355_c545,\n                0x9318_ec0a, 0x7869_2d31, 0x0a21_693d, 0xd566_6814, 0x05fb_59d9, 0xc719_85b2, 0x2abb_8e0e, 0xcf6e_6c91,\n                0xd9cf_e7c6, 0xefe7_132c, 0x9711_ab28, 0x3ce5_2732, 0x12d5_16d2, 0x7209_a0d0, 0xd278_d306, 0x70fa_4b7b,\n                0x1d40_7dd3, 0xdb0b_eba4, 0xbfd9_7621, 0xa8be_21e1, 0x1b6f_1b66, 0x3065_0dda, 0xba7d_dbb9, 0x7df9_53fb,\n                0x9d1c_3902, 0xedf0_e8d5, 0xb874_1ae0, 0x0f24_0565, 0x62cd_438b, 0xc616_a924, 0xaf7a_96a3, 0x3536_5538,\n                0xe583_af4d, 0x7341_5eb8, 0x2317_6a47, 0xfc9c_cee8, 0x7efc_9de2, 0x695e_03cf, 0xf8ce_66d4, 0x88b4_781d,\n                0x67dd_9c03, 0x3e8f_9e73, 0xc0c9_5c51, 0xbe31_4d22, 0x55aa_0795, 0xcb1b_b011, 0xe980_fdc8, 0x9c62_b7ce,\n                0xde2d_239e, 0x042c_adf3, 0xffdf_04de, 0x5ce6_a60f, 0xd8c8_31ed, 0xb7b5_b9ec, 0xb9cb_f962, 0xe253_b254,\n                0x0735_ba1f, 0x16ac_917f, 0xdd60_7c2b, 0x64a3_35c4, 0x4015_9a7c, 0x8692_22f0, 0x6ef2_1769, 0x839d_20a5,\n                0xd03b_24c9, 0xf412_601e, 0x6d72_a243, 0x0e01_8dfd, 0x89f3_721a, 0xc94f_4134, 0x2f99_2f20, 0x4d87_253c,\n            ),\n        )\n\n        def __init__(self, data=b\"\"):\n            self.chunk_size = (16 - self.output_words) * 4\n            self.h = [0] * self.output_words\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not data:\n                return self\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.chunk_size:\n                chunk = bytes(self.buf[:self.chunk_size])\n                del self.buf[:self.chunk_size]\n                self.process_chunk(chunk)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            fmt = \">\" + str(c.output_words) + \"I\"\n            return struct.pack(fmt, *c.h)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n            if len(self.buf) > 0:\n                chunk = bytes(self.buf) + b\"\\x00\" * (self.chunk_size - len(self.buf))\n                self.buf.clear()\n                self.process_chunk(chunk)\n\n            bit_len = self.msg_len * 8\n            hi = (bit_len >> 32) & 0xffff_ffff\n            lo = bit_len & 0xffff_ffff\n\n            input_words = list(self.h) + [0] * (16 - self.output_words)\n            input_words[14] = hi\n            input_words[15] = lo\n            self.h = self.hash512(input_words)\n            self.finalized = True\n            return\n\n        def process_chunk(self, chunk):\n            words = list(struct.unpack(f\">{len(chunk) // 4}I\", chunk))\n            input_words = list(self.h) + words\n            self.h = self.hash512(input_words)\n            return\n\n        def hash512(self, input_words):\n\n            def ror32(x, shift):\n                x &= 0xffff_ffff\n                return ((x >> shift) | (x << (32 - shift))) & 0xffff_ffff\n\n            shift_table = (16, 8, 16, 24)\n            b = input_words[::]\n\n            for index in range(self.security_level):\n                s0 = self.standard_sboxes[2 * index + 0]\n                s1 = self.standard_sboxes[2 * index + 1]\n                for byte_in_word in range(4):\n                    for i in range(16):\n                        if i & 0b10 == 0:\n                            s = s0\n                        else:\n                            s = s1\n                        sbe = s[b[i] & 0xff]\n                        b[(i + 15) % 16] ^= sbe\n                        b[(i + 1) % 16] ^= sbe\n                    shift = shift_table[byte_in_word]\n                    for i in range(16):\n                        b[i] = ror32(b[i], shift)\n\n            output = []\n            output.append(input_words[0] ^ b[15])\n            output.append(input_words[1] ^ b[14])\n            output.append(input_words[2] ^ b[13])\n            output.append(input_words[3] ^ b[12])\n            if self.output_words == 4:\n                return output\n            output.append(input_words[4] ^ b[11])\n            output.append(input_words[5] ^ b[10])\n            output.append(input_words[6] ^ b[9])\n            output.append(input_words[7] ^ b[8])\n            if self.output_words == 8:\n                return output\n            raise ValueError(\"bad output_words\")\n\n    class Snefru128(SnefruBase):\n        output_words = 4\n        digest_size = 16\n\n    class Snefru256(SnefruBase):\n        output_words = 8\n        digest_size = 32\n\n    class StreebogBase:\n        block_size = 64\n\n        PI = (\n            0xfc, 0xee, 0xdd, 0x11, 0xcf, 0x6e, 0x31, 0x16, 0xfb, 0xc4, 0xfa, 0xda, 0x23, 0xc5, 0x04, 0x4d,\n            0xe9, 0x77, 0xf0, 0xdb, 0x93, 0x2e, 0x99, 0xba, 0x17, 0x36, 0xf1, 0xbb, 0x14, 0xcd, 0x5f, 0xc1,\n            0xf9, 0x18, 0x65, 0x5a, 0xe2, 0x5c, 0xef, 0x21, 0x81, 0x1c, 0x3c, 0x42, 0x8b, 0x01, 0x8e, 0x4f,\n            0x05, 0x84, 0x02, 0xae, 0xe3, 0x6a, 0x8f, 0xa0, 0x06, 0x0b, 0xed, 0x98, 0x7f, 0xd4, 0xd3, 0x1f,\n            0xeb, 0x34, 0x2c, 0x51, 0xea, 0xc8, 0x48, 0xab, 0xf2, 0x2a, 0x68, 0xa2, 0xfd, 0x3a, 0xce, 0xcc,\n            0xb5, 0x70, 0x0e, 0x56, 0x08, 0x0c, 0x76, 0x12, 0xbf, 0x72, 0x13, 0x47, 0x9c, 0xb7, 0x5d, 0x87,\n            0x15, 0xa1, 0x96, 0x29, 0x10, 0x7b, 0x9a, 0xc7, 0xf3, 0x91, 0x78, 0x6f, 0x9d, 0x9e, 0xb2, 0xb1,\n            0x32, 0x75, 0x19, 0x3d, 0xff, 0x35, 0x8a, 0x7e, 0x6d, 0x54, 0xc6, 0x80, 0xc3, 0xbd, 0x0d, 0x57,\n            0xdf, 0xf5, 0x24, 0xa9, 0x3e, 0xa8, 0x43, 0xc9, 0xd7, 0x79, 0xd6, 0xf6, 0x7c, 0x22, 0xb9, 0x03,\n            0xe0, 0x0f, 0xec, 0xde, 0x7a, 0x94, 0xb0, 0xbc, 0xdc, 0xe8, 0x28, 0x50, 0x4e, 0x33, 0x0a, 0x4a,\n            0xa7, 0x97, 0x60, 0x73, 0x1e, 0x00, 0x62, 0x44, 0x1a, 0xb8, 0x38, 0x82, 0x64, 0x9f, 0x26, 0x41,\n            0xad, 0x45, 0x46, 0x92, 0x27, 0x5e, 0x55, 0x2f, 0x8c, 0xa3, 0xa5, 0x7d, 0x69, 0xd5, 0x95, 0x3b,\n            0x07, 0x58, 0xb3, 0x40, 0x86, 0xac, 0x1d, 0xf7, 0x30, 0x37, 0x6b, 0xe4, 0x88, 0xd9, 0xe7, 0x89,\n            0xe1, 0x1b, 0x83, 0x49, 0x4c, 0x3f, 0xf8, 0xfe, 0x8d, 0x53, 0xaa, 0x90, 0xca, 0xd8, 0x85, 0x61,\n            0x20, 0x71, 0x67, 0xa4, 0x2d, 0x2b, 0x09, 0x5b, 0xcb, 0x9b, 0x25, 0xd0, 0xbe, 0xe5, 0x6c, 0x52,\n            0x59, 0xa6, 0x74, 0xd2, 0xe6, 0xf4, 0xb4, 0xc0, 0xd1, 0x66, 0xaf, 0xc2, 0x39, 0x4b, 0x63, 0xb6,\n        )\n\n        A_ROWS = (\n            0x8e20_faa7_2ba0_b470, 0x4710_7ddd_9b50_5a38, 0xad08_b0e0_c328_2d1c, 0xd804_5870_ef14_980e,\n            0x6c02_2c38_f90a_4c07, 0x3601_161c_f205_268d, 0x1b8e_0b0e_798c_13c8, 0x8347_8b07_b246_8764,\n            0xa011_d380_818e_8f40, 0x5086_e740_ce47_c920, 0x2843_fd20_67ad_ea10, 0x14af_f010_bdd8_7508,\n            0x0ad9_7808_d06c_b404, 0x05e2_3c04_6836_5a02, 0x8c71_1e02_341b_2d01, 0x46b6_0f01_1a83_988e,\n            0x90da_b52a_387a_e76f, 0x486d_d415_1c3d_fdb9, 0x24b8_6a84_0e90_f0d2, 0x125c_3542_0748_7869,\n            0x092e_9421_8d24_3cba, 0x8a17_4a9e_c812_1e5d, 0x4585_254f_6409_0fa0, 0xaccc_9ca9_328a_8950,\n            0x9d4d_f05d_5f66_1451, 0xc0a8_78a0_a133_0aa6, 0x6054_3c50_de97_0553, 0x302a_1e28_6fc5_8ca7,\n            0x1815_0f14_b9ec_46dd, 0x0c84_890a_d276_23e0, 0x0642_ca05_693b_9f70, 0x0321_658c_ba93_c138,\n            0x8627_5df0_9ce8_aaa8, 0x439d_a078_4e74_5554, 0xafc0_503c_273a_a42a, 0xd960_281e_9d1d_5215,\n            0xe230_140f_c080_2984, 0x7118_0a89_6040_9a42, 0xb60c_05ca_3020_4d21, 0x5b06_8c65_1810_a89e,\n            0x456c_3488_7a38_05b9, 0xac36_1a44_3d1c_8cd2, 0x561b_0d22_900e_4669, 0x2b83_8811_4807_23ba,\n            0x9bcf_4486_248d_9f5d, 0xc3e9_2243_12c8_c1a0, 0xeffa_11af_0964_ee50, 0xf97d_86d9_8a32_7728,\n            0xe4fa_2054_a80b_329c, 0x727d_102a_548b_194e, 0x39b0_0815_2acb_8227, 0x9258_0484_15eb_419d,\n            0x492c_0242_84fb_aec0, 0xaa16_0121_42f3_5760, 0x550b_8e9e_21f7_a530, 0xa48b_474f_9ef5_dc18,\n            0x70a6_a56e_2440_598e, 0x3853_dc37_1220_a247, 0x1ca7_6e95_0910_51ad, 0x0edd_37c4_8a08_a6d8,\n            0x07e0_9562_4504_536c, 0x8d70_c431_ac02_a736, 0xc838_6296_5601_dd1b, 0x641c_314b_2b8e_e083,\n        )\n\n        C_BYTES = (\n            bytes.fromhex(\n                \"b1085bda1ecadae9ebcb2f81c0657c1f2f6a76432e45d016714eb88d7585c4fc\"\n                \"4b7ce09192676901a2422a08a460d31505767436cc744d23dd806559f2a64507\"\n            ),\n            bytes.fromhex(\n                \"6fa3b58aa99d2f1a4fe39d460f70b5d7f3feea720a232b9861d55e0f16b50131\"\n                \"9ab5176b12d699585cb561c2db0aa7ca55dda21bd7cbcd56e679047021b19bb7\"\n            ),\n            bytes.fromhex(\n                \"f574dcac2bce2fc70a39fc286a3d843506f15e5f529c1f8bf2ea7514b1297b7b\"\n                \"d3e20fe490359eb1c1c93a376062db09c2b6f443867adb31991e96f50aba0ab2\"\n            ),\n            bytes.fromhex(\n                \"ef1fdfb3e81566d2f948e1a05d71e4dd488e857e335c3c7d9d721cad685e353f\"\n                \"a9d72c82ed03d675d8b71333935203be3453eaa193e837f1220cbebc84e3d12e\"\n            ),\n            bytes.fromhex(\n                \"4bea6bacad4747999a3f410c6ca923637f151c1f1686104a359e35d7800fffbd\"\n                \"bfcd1747253af5a3dfff00b723271a167a56a27ea9ea63f5601758fd7c6cfe57\"\n            ),\n            bytes.fromhex(\n                \"ae4faeae1d3ad3d96fa4c33b7a3039c02d66c4f95142a46c187f9ab49af08ec6\"\n                \"cffaa6b71c9ab7b40af21f66c2bec6b6bf71c57236904f35fa68407a46647d6e\"\n            ),\n            bytes.fromhex(\n                \"f4c70e16eeaac5ec51ac86febf240954399ec6c7e6bf87c9d3473e33197a93c9\"\n                \"0992abc52d822c3706476983284a05043517454ca23c4af38886564d3a14d493\"\n            ),\n            bytes.fromhex(\n                \"9b1f5b424d93c9a703e7aa020c6e41414eb7f8719c36de1e89b4443b4ddbc49a\"\n                \"f4892bcb929b069069d18d2bd1a5c42f36acc2355951a8d9a47f0dd4bf02e71e\"\n            ),\n            bytes.fromhex(\n                \"378f5a541631229b944c9ad8ec165fde3a7d3a1b258942243cd955b7e00d0984\"\n                \"800a440bdbb2ceb17b2b8a9aa6079c540e38dc92cb1f2a607261445183235adb\"\n            ),\n            bytes.fromhex(\n                \"abbedea680056f52382ae548b2e4f3f38941e71cff8a78db1fffe18a1b336103\"\n                \"9fe76702af69334b7a1e6c303b7652f43698fad1153bb6c374b4c7fb98459ced\"\n            ),\n            bytes.fromhex(\n                \"7bcd9ed0efc889fb3002c6cd635afe94d8fa6bbbebab07612001802114846679\"\n                \"8a1d71efea48b9caefbacd1d7d476e98dea2594ac06fd85d6bcaa4cd81f32d1b\"\n            ),\n            bytes.fromhex(\n                \"378ee767f11631bad21380b00449b17acda43c32bcdf1d77f82012d430219f9b\"\n                \"5d80ef9d1891cc86e71da4aa88e12852faf417d5d9b21b9948bc924af11bd720\"\n            ),\n        )\n\n        @classmethod\n        def ensure_table(cls):\n            if hasattr(Hash.StreebogBase, \"MUL_TABLE\"):\n                return\n\n            mul = [[0] * 256 for _ in range(8)]\n            for i in range(8):\n                for j in range(256):\n                    t = 0\n                    p = cls.PI[j]\n                    for k in range(8):\n                        if p & (1 << k):\n                            t ^= cls.A_ROWS[(i << 3) | (7 - k)]\n                    # byte swaps because of little-endian (exactly the C code)\n                    t = ((t << 8) & 0xff00_ff00_ff00_ff00) | ((t >> 8) & 0x00ff_00ff_00ff_00ff)\n                    t = ((t << 16) & 0xffff_0000_ffff_0000) | ((t >> 16) & 0x0000_ffff_0000_ffff)\n                    t = ((t << 32) & 0xffff_ffff_0000_0000) | ((t >> 32) & 0x0000_0000_ffff_ffff)\n                    mul[i][j] = t\n            Hash.StreebogBase.MUL_TABLE = mul\n            return\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.h = b\"\"\n            self.ensure_table()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.h = self.h\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.h\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def compute(self, msg, iv):\n\n            def xor_bytes(a, b):\n                return bytes(x ^ y for x, y in zip(a, b))\n\n            def sum512(a, b):\n                c = bytearray(64)\n                carry = 0\n                for i in range(63, -1, -1):\n                    s = a[i] + b[i] + carry\n                    carry = s >> 8\n                    c[i] = s & 0xff\n                return bytes(c)\n\n            def lps(inp):\n                mul = self.MUL_TABLE\n                out_words = [0] * 8\n                for i in range(8):\n                    t = mul[0][inp[i]]\n                    for k in range(1, 8):\n                        t ^= mul[k][inp[i | (k << 3)]]\n                    out_words[i] = t\n                return b\"\".join(w.to_bytes(8, \"little\") for w in out_words)\n\n            def E(k, m):\n                kk = k\n                mm = m\n                for i in range(12):\n                    mm = lps(xor_bytes(mm, kk))\n                    kk = lps(xor_bytes(kk, self.C_BYTES[i]))\n                return xor_bytes(mm, kk)\n\n            def g(h, m, n):\n                k = lps(xor_bytes(h, n))\n                e = E(k, m)\n                return xor_bytes(xor_bytes(e, h), m)\n\n            def tohex512(n):\n                out = bytearray(64)\n                out[56:64] = (n & 0xffff_ffff_ffff_ffff).to_bytes(8, \"big\")\n                return bytes(out)\n\n            h = iv\n            N = bytes(64)\n            sigma = bytes(64)\n\n            size = len(msg)\n            M = msg\n\n            while size >= 64:\n                m = M[:64][::-1]\n                h = g(h, m, N)\n                N = sum512(N, tohex512(512))\n                sigma = sum512(sigma, m)\n                M = M[64:]\n                size -= 64\n\n            m = bytearray(64)\n            m[64 - size - 1] = 1\n            m[64 - size:] = M[::-1]\n            m = bytes(m)\n\n            h = g(h, m, N)\n            N = sum512(N, tohex512(size * 8))\n            sigma = sum512(sigma, m)\n\n            z = bytes(64)\n            h = g(h, N, z)\n            h = g(h, sigma, z)\n            return h\n\n    class Streebog256(StreebogBase):\n        digest_size = 32\n\n        def finalize(self):\n            full = self.compute(bytes(self.buf), bytes([0x01] * 64))\n            self.h = full[:32][::-1]\n            return\n\n    class Streebog512(StreebogBase):\n        digest_size = 64\n\n        def finalize(self):\n            full = self.compute(bytes(self.buf), bytes(64))\n            self.h = full[::-1]\n            return\n\n    class AsconBase:\n        block_size = 8\n\n        round_constants = (\n            0x0000_0000_0000_00f0, 0x0000_0000_0000_00e1, 0x0000_0000_0000_00d2, 0x0000_0000_0000_00c3,\n            0x0000_0000_0000_00b4, 0x0000_0000_0000_00a5, 0x0000_0000_0000_0096, 0x0000_0000_0000_0087,\n            0x0000_0000_0000_0078, 0x0000_0000_0000_0069, 0x0000_0000_0000_005a, 0x0000_0000_0000_004b,\n        )\n\n        init_state = (0, 0, 0, 0, 0)\n        b_rounds = 12\n        digest_size = 32\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.x0, self.x1, self.x2, self.x3, self.x4 = self.init_state\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.x0 = self.x0\n            other.x1 = self.x1\n            other.x2 = self.x2\n            other.x3 = self.x3\n            other.x4 = self.x4\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.absorb_block(block)\n                self.permute(self.b_rounds)\n            return self\n\n        def digest(self, length=None):\n            c = self.copy()\n            c.finalize()\n            if length is None:\n                length = c.digest_size\n            out = c.squeeze(length)\n            return out\n\n        def hexdigest(self, length=None):\n            return self.digest(length).hex()\n\n        def finalize(self):\n            m = len(self.buf)\n            if m == 0:\n                block = b\"\\x80\" + b\"\\x00\" * (self.block_size - 1)\n            else:\n                pad_len = self.block_size - m\n                block = bytes(self.buf) + (b\"\\x80\" + b\"\\x00\" * (pad_len - 1))\n            self.buf.clear()\n            self.absorb_block(block)\n            self.permute(12)\n            return\n\n        def absorb_block(self, block):\n            if len(block) != self.block_size:\n                raise ValueError(\"invalid block size\")\n            self.x0 ^= int.from_bytes(block, \"big\")\n            self.x0 &= 0xffff_ffff_ffff_ffff\n            return\n\n        def squeeze(self, out_len):\n            if not isinstance(out_len, int) or out_len < 0:\n                raise ValueError(\"out_len must be a non-negative integer\")\n            out = bytearray()\n            while len(out) < out_len:\n                out.extend(int(self.x0 & 0xffff_ffff_ffff_ffff).to_bytes(8, \"big\"))\n                self.permute(self.b_rounds)\n            return bytes(out[:out_len])\n\n        def permute(self, rounds):\n\n            def ror64(x, n):\n                x &= 0xffff_ffff_ffff_ffff\n                n &= 63\n                return ((x >> n) | ((x << (64 - n)) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n            if rounds not in (6, 8, 12):\n                raise ValueError(\"invalid round count\")\n            start = 12 - rounds\n            for r in range(start, 12):\n                self.x2 ^= self.round_constants[r]\n\n                x0 = self.x0\n                x1 = self.x1\n                x2 = self.x2\n                x3 = self.x3\n                x4 = self.x4\n\n                x0 ^= x4\n                x4 ^= x3\n                x2 ^= x1\n\n                t0 = (~x0) & x1\n                t1 = (~x1) & x2\n                t2 = (~x2) & x3\n                t3 = (~x3) & x4\n                t4 = (~x4) & x0\n\n                x0 ^= t1\n                x1 ^= t2\n                x2 ^= t3\n                x3 ^= t4\n                x4 ^= t0\n\n                x1 ^= x0\n                x0 ^= x4\n                x3 ^= x2\n                x2 = ~x2\n\n                x0 ^= ror64(x0, 19) ^ ror64(x0, 28)\n                x1 ^= ror64(x1, 61) ^ ror64(x1, 39)\n                x2 ^= ror64(x2, 1) ^ ror64(x2, 6)\n                x3 ^= ror64(x3, 10) ^ ror64(x3, 17)\n                x4 ^= ror64(x4, 7) ^ ror64(x4, 41)\n\n                self.x0 = x0\n                self.x1 = x1\n                self.x2 = x2\n                self.x3 = x3\n                self.x4 = x4\n            return\n\n    class Ascon(AsconBase):\n        digest_size = 32\n        b_rounds = 12\n        init_state = (\n            0xee93_98aa_db67_f03d, 0x8bb2_1831_c60f_1002, 0xb48a_92db_98d5_da62, 0x4318_9921_b8f8_e3e8, 0x348f_a5c9_d525_e140,\n        )\n\n    class AsconA(AsconBase):\n        digest_size = 32\n        b_rounds = 8\n        init_state = (\n            0x0147_0194_fc65_28a6, 0x738e_c38a_c0ad_ffa7, 0x2ec8_e329_6c76_384c, 0xd6f6_a54d_7f52_377d, 0xa13c_42a2_23be_8d87,\n        )\n\n    class AsconX(AsconBase):\n        digest_size = 128\n        b_rounds = 12\n        init_state = (\n            0xb57e_273b_814c_d416, 0x2b51_0425_62ae_2420, 0x66a3_a776_8ddf_2218, 0x5aad_0a7a_8153_650c, 0x4f3e_0e32_5394_93b6,\n        )\n\n    class AsconXA(AsconBase):\n        digest_size = 128\n        b_rounds = 8\n        init_state = (\n            0x4490_6568_b77b_9832, 0xcd8d_6cae_5345_5532, 0xf7b5_2127_5642_2129, 0x2468_85e1_de0d_225b, 0xa8cb_5ce3_3449_973f,\n        )\n\n    class RSHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.b = 378551\n            self.a = 63689\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = ((self.hash * self.a) + c) & 0xffff_ffff\n                self.a = (self.a * self.b) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class JSHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 1315423911\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash ^= ((self.hash << 5) + c + (self.hash >> 2)) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class PJWHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = ((self.hash << 4) + c) & 0xffff_ffff\n                high = self.hash & 0xf000_0000\n                if high:\n                    self.hash = (self.hash ^ (high >> 24)) & 0x0fff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class ELFHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = ((self.hash << 4) + c) & 0xffff_ffff\n                high = self.hash & 0xf000_0000\n                if high:\n                    self.hash = (self.hash ^ (high >> 24)) & ~high\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class BKDRHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.seed = 131\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = ((self.hash * self.seed) + c) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class SDBMHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = (c + (self.hash << 6) + (self.hash << 16) - self.hash) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class DJB2Hash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 5381\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = (((self.hash << 5) + self.hash) + c) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class DEKHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf += data\n            return self\n\n        def digest(self):\n            h = len(self.buf)\n            for c in self.buf:\n                h = ((h << 5) ^ (h >> 27) ^ c) & 0xffff_ffff\n            return h.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class APHash:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 0xaaaa_aaaa\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for i, c in enumerate(bytes(data)):\n                if (i & 1) == 0:\n                    self.hash ^= (self.hash << 7) ^ (c * (self.hash >> 3))\n                else:\n                    self.hash ^= ~((self.hash << 11) + (c ^ (self.hash >> 5)))\n                self.hash &= 0xffff_ffff\n            return self\n\n        def digest(self):\n            return self.hash.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class JOAAT:  # Jenkins One-At-A-Time\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.hash = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for c in bytes(data):\n                self.hash = (self.hash + c) & 0xffff_ffff\n                self.hash = (self.hash + (self.hash << 10)) & 0xffff_ffff\n                self.hash = (self.hash ^ (self.hash >> 6)) & 0xffff_ffff\n            return self\n\n        def digest(self):\n            h = self.hash\n            h = (h + (h << 3)) & 0xffff_ffff\n            h = (h ^ (h >> 11)) & 0xffff_ffff\n            h = (h + (h << 15)) & 0xffff_ffff\n            return h.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class Adler:\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.a = 1\n            self.b = 0\n            if data:\n                self.update(data)\n            return\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            for d in data:\n                self.a = (self.a + d) % 65521\n                self.b = (self.a + self.b) % 65521\n            return\n\n        def digest(self):\n            h = (self.b << 16) + self.a\n            return h.to_bytes(4, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class T1HABase:\n        block_size = 32\n        digest_size = 8\n\n        prime_0 = 0xec99_bf0d_8372_caab\n        prime_1 = 0x8243_4fe9_0edc_ef39\n        prime_2 = 0xd4f0_6db9_9d67_be4b\n        prime_3 = 0xbd9c_acc2_2c6e_9571\n        prime_4 = 0x9c06_faf4_d023_e3ab\n        prime_5 = 0xc060_724a_8424_f345\n        prime_6 = 0xcb5a_f53a_e3aa_ac31\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.seed = seed & 0xffff_ffff_ffff_ffff\n            self.buf = bytearray()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            return self\n\n        def digest(self):\n            return self.digest_bytes(bytes(self.buf))\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def ror32(self, x, n):\n            x &= 0xffff_ffff\n            return ((x >> n) | ((x << (32 - n)) & 0xffff_ffff)) & 0xffff_ffff\n\n        def ror64(self, x, n):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x >> n) | ((x << (64 - n)) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n        def u32le(self, data, off):\n            return int.from_bytes(data[off:off + 4], \"little\")\n\n        def u64le(self, data, off):\n            return int.from_bytes(data[off:off + 8], \"little\")\n\n        def mul64x64_128(self, a, b):\n            p = (a & 0xffff_ffff_ffff_ffff) * (b & 0xffff_ffff_ffff_ffff)\n            lo = p & 0xffff_ffff_ffff_ffff\n            hi = (p >> 64) & 0xffff_ffff_ffff_ffff\n            return lo, hi\n\n        def mux64(self, v, prime):\n            lo, hi = self.mul64x64_128(v, prime)\n            return lo ^ hi\n\n        def mixup64(self, a, b, v, prime):\n            lo, hi = self.mul64x64_128(b + v, prime)\n            a ^= lo\n            b = (b + hi) & 0xffff_ffff_ffff_ffff\n            return a & 0xffff_ffff_ffff_ffff, b\n\n        def t1ha2_update(self, a, b, c, d, w0, w1, w2, w3):\n            d02 = (w0 + self.ror64(w2 + d, 56)) & 0xffff_ffff_ffff_ffff\n            c13 = (w1 + self.ror64(w3 + c, 19)) & 0xffff_ffff_ffff_ffff\n            d ^= (b + self.ror64(w1, 38)) & 0xffff_ffff_ffff_ffff\n            c ^= (a + self.ror64(w0, 57)) & 0xffff_ffff_ffff_ffff\n            b ^= (self.prime_6 * ((c13 + w2) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            a ^= (self.prime_5 * ((d02 + w3) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            return a, b, c, d\n\n    class T1HA0_32(T1HABase):\n        block_size = 16\n        digest_size = 4\n\n        prime32_0 = 0x92d7_8269\n        prime32_1 = 0xca9b_4735\n        prime32_2 = 0xa4ab_a1c3\n        prime32_3 = 0xf649_9843\n        prime32_4 = 0x86f0_fd61\n        prime32_5 = 0xca2d_a6fb\n        prime32_6 = 0xc4bb_3575\n\n        def mixup32(self, a, b, v, prime):\n            p = ((b + v) & 0xffff_ffff) * prime\n            a ^= p & 0xffff_ffff\n            b = (b + ((p >> 32) & 0xffff_ffff)) & 0xffff_ffff\n            return a & 0xffff_ffff, b\n\n        def t1ha0_32le(self, data, seed):\n            length = len(data)\n            a = (self.ror32(length, 17) + (seed & 0xffff_ffff)) & 0xffff_ffff\n            b = ((length & 0xffff_ffff) ^ ((seed >> 32) & 0xffff_ffff)) & 0xffff_ffff\n            off = 0\n\n            if length > 16:\n                c = (~a) & 0xffff_ffff\n                d = self.ror32(b, 5)\n                detent = length - 15\n\n                while off < detent:\n                    w0 = self.u32le(data, off + 0)\n                    w1 = self.u32le(data, off + 4)\n                    w2 = self.u32le(data, off + 8)\n                    w3 = self.u32le(data, off + 12)\n                    off += 16\n\n                    d13 = (w1 + self.ror32(w3 + d, 17)) & 0xffff_ffff\n                    c02 = (w0 ^ self.ror32(w2 + c, 11)) & 0xffff_ffff\n                    d ^= self.ror32(a + w0, 3)\n                    c ^= self.ror32(b + w1, 7)\n                    b = (self.prime32_1 * ((c02 + w3) & 0xffff_ffff)) & 0xffff_ffff\n                    a = (self.prime32_0 * (d13 ^ w2)) & 0xffff_ffff\n\n                c = (c + a) & 0xffff_ffff\n                d = (d + b) & 0xffff_ffff\n                a ^= (self.prime32_6 * ((self.ror32(c, 16) + d) & 0xffff_ffff)) & 0xffff_ffff\n                b ^= (self.prime32_5 * ((self.ror32(d, 16) + c) & 0xffff_ffff)) & 0xffff_ffff\n                tail = length & 15\n            else:\n                tail = length\n\n            tail_off = off\n            if tail > 12:\n                v = self.u32le(data, tail_off)\n                a, b = self.mixup32(a, b, v, self.prime32_4)\n                tail_off += 4\n            if tail > 8:\n                v = self.u32le(data, tail_off)\n                b, a = self.mixup32(b, a, v, self.prime32_3)\n                tail_off += 4\n            if tail > 4:\n                v = self.u32le(data, tail_off)\n                a, b = self.mixup32(a, b, v, self.prime32_2)\n                tail_off += 4\n            if tail != 0:\n                v = self.u32le(data + b\"\\0\" * (4 - (tail & 3)), tail_off)\n                b, a = self.mixup32(b, a, v, self.prime32_1)\n\n            return self.final32(a, b)\n\n        def final32(self, a, b):\n            l = ((b ^ self.ror32(a, 13)) | ((a & 0xffff_ffff) << 32)) & 0xffff_ffff_ffff_ffff  # noqa: E741\n            l = (l * self.prime_0) & 0xffff_ffff_ffff_ffff  # noqa: E741\n            l ^= l >> 41  # noqa: E741\n            l = (l * self.prime_4) & 0xffff_ffff_ffff_ffff  # noqa: E741\n            l ^= l >> 47  # noqa: E741\n            l = (l * self.prime_6) & 0xffff_ffff_ffff_ffff  # noqa: E741\n            return l\n\n        def digest_bytes(self, data):\n            v = self.t1ha0_32le(data, self.seed) & 0xffff_ffff\n            return struct.pack(\">I\", v)\n\n    class T1HA1_64(T1HABase):\n        block_size = 32\n        digest_size = 8\n\n        def t1ha1_le(self, data, seed):\n            length = len(data)\n            a = seed & 0xffff_ffff_ffff_ffff\n            b = length & 0xffff_ffff_ffff_ffff\n            off = 0\n            tail = length\n\n            if tail > 32:\n                c = (self.ror64(tail, 17) + seed) & 0xffff_ffff_ffff_ffff\n                d = self.ror64(seed, 17) ^ tail\n                detent = tail - 31\n\n                while off < detent:\n                    w0 = self.u64le(data, off + 0)\n                    w1 = self.u64le(data, off + 8)\n                    w2 = self.u64le(data, off + 16)\n                    w3 = self.u64le(data, off + 24)\n                    off += 32\n\n                    d02 = w0 ^ self.ror64(w2 + d, 17)\n                    c13 = w1 ^ self.ror64(w3 + c, 17)\n                    d = (d - (b ^ self.ror64(w1, 31))) & 0xffff_ffff_ffff_ffff\n                    c = (c + (a ^ self.ror64(w0, 41))) & 0xffff_ffff_ffff_ffff\n                    b ^= (self.prime_0 * ((c13 + w2) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n                    a ^= (self.prime_1 * ((d02 + w3) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n                a ^= (self.prime_6 * ((self.ror64(c, 17) + d) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n                b ^= (self.prime_5 * ((self.ror64(d, 17) + c) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n                tail &= 31\n\n            tail_off = off\n            if tail > 24:\n                b = (b + self.mux64(self.u64le(data, tail_off), self.prime_4)) & 0xffff_ffff_ffff_ffff\n                tail_off += 8\n            if tail > 16:\n                a = (a + self.mux64(self.u64le(data, tail_off), self.prime_3)) & 0xffff_ffff_ffff_ffff\n                tail_off += 8\n            if tail > 8:\n                b = (b + self.mux64(self.u64le(data, tail_off), self.prime_2)) & 0xffff_ffff_ffff_ffff\n                tail_off += 8\n            if tail != 0:\n                a = (a + self.mux64(self.u64le(data + b\"\\0\" * (8 - (tail & 7)), tail_off), self.prime_1)) & 0xffff_ffff_ffff_ffff\n\n            return self.final_weak_avalanche(a, b)\n\n        def mix64(self, v, p):\n            v = (v * p) & 0xffff_ffff_ffff_ffff\n            return (v ^ self.ror64(v, 41)) & 0xffff_ffff_ffff_ffff\n\n        def final_weak_avalanche(self, a, b):\n            r = self.mux64(self.ror64(a + b, 17), self.prime_4)\n            r = (r + self.mix64(a ^ b, self.prime_0)) & 0xffff_ffff_ffff_ffff\n            return r\n\n        def digest_bytes(self, data):\n            v = self.t1ha1_le(data, self.seed)\n            return struct.pack(\">Q\", v)\n\n    class T1HA2_64(T1HABase):\n        block_size = 32\n        digest_size = 8\n\n        def t1ha2_squash(self, a, b, c, d):\n            a ^= (self.prime_6 * ((self.ror64(d, 23) + c) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            b ^= (self.prime_5 * ((self.ror64(c, 19) + d) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            return a, b\n\n        def t1ha2_atonce(self, data, seed):\n            length = len(data)\n            a = seed & 0xffff_ffff_ffff_ffff\n            b = length & 0xffff_ffff_ffff_ffff\n            off = 0\n\n            if length > 32:\n                c = (self.ror64(length, 23) + ((~seed) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n                d = (((~length) & 0xffff_ffff_ffff_ffff) + self.ror64(seed, 19)) & 0xffff_ffff_ffff_ffff\n                detent = length - 31\n\n                while off < detent:\n                    w0 = self.u64le(data, off + 0)\n                    w1 = self.u64le(data, off + 8)\n                    w2 = self.u64le(data, off + 16)\n                    w3 = self.u64le(data, off + 24)\n                    a, b, c, d = self.t1ha2_update(a, b, c, d, w0, w1, w2, w3)\n                    off += 32\n\n                a, b = self.t1ha2_squash(a, b, c, d)\n                tail = length & 31\n            else:\n                tail = length\n\n            tail_off = off\n            if tail > 24:\n                w = self.u64le(data, tail_off)\n                a, b = self.mixup64(a, b, w, self.prime_4)\n                tail_off += 8\n            if tail > 16:\n                w = self.u64le(data, tail_off)\n                b, a = self.mixup64(b, a, w, self.prime_3)\n                tail_off += 8\n            if tail > 8:\n                w = self.u64le(data, tail_off)\n                a, b = self.mixup64(a, b, w, self.prime_2)\n                tail_off += 8\n            if tail != 0:\n                w = self.u64le(data + b\"\\0\" * (8 - (tail & 7)), tail_off)\n                b, a = self.mixup64(b, a, w, self.prime_1)\n\n            return self.final64(a, b)\n\n        def final64(self, a, b):\n            x = ((self.ror64(b, 41) + a) & 0xffff_ffff_ffff_ffff) * self.prime_0\n            y = ((self.ror64(a, 23) + b) & 0xffff_ffff_ffff_ffff) * self.prime_6\n            return self.mux64((x ^ y) & 0xffff_ffff_ffff_ffff, self.prime_5) & 0xffff_ffff_ffff_ffff\n\n        def digest_bytes(self, data):\n            v = self.t1ha2_atonce(data, self.seed)\n            return struct.pack(\">Q\", v)\n\n    class T1HA2_128(T1HABase):\n        block_size = 32\n        digest_size = 16\n\n        def t1ha2_atonce128(self, data, seed):\n            length = len(data)\n            a = seed & 0xffff_ffff_ffff_ffff\n            b = length & 0xffff_ffff_ffff_ffff\n            c = (self.ror64(length, 23) + ((~seed) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n            d = (((~length) & 0xffff_ffff_ffff_ffff) + self.ror64(seed, 19)) & 0xffff_ffff_ffff_ffff\n            off = 0\n\n            if length > 32:\n                detent = length - 31\n                while off < detent:\n                    w0 = self.u64le(data, off + 0)\n                    w1 = self.u64le(data, off + 8)\n                    w2 = self.u64le(data, off + 16)\n                    w3 = self.u64le(data, off + 24)\n                    a, b, c, d = self.t1ha2_update(a, b, c, d, w0, w1, w2, w3)\n                    off += 32\n                tail = length & 31\n            else:\n                tail = length\n\n            tail_off = off\n            if tail > 24:\n                w = self.u64le(data, tail_off)\n                a, d = self.mixup64(a, d, w, self.prime_4)\n                tail_off += 8\n            if tail > 16:\n                w = self.u64le(data, tail_off)\n                b, a = self.mixup64(b, a, w, self.prime_3)\n                tail_off += 8\n            if tail > 8:\n                w = self.u64le(data, tail_off)\n                c, b = self.mixup64(c, b, w, self.prime_2)\n                tail_off += 8\n            if tail != 0:\n                w = self.u64le(data + b\"\\0\" * (8 - (tail & 7)), tail_off)\n                d, c = self.mixup64(d, c, w, self.prime_1)\n\n            return self.t1ha2_final128(a, b, c, d)\n\n        def t1ha2_final128(self, a, b, c, d):\n            a, b = self.mixup64(a, b, self.ror64(c, 41) ^ d, self.prime_0)\n            b, c = self.mixup64(b, c, self.ror64(d, 23) ^ a, self.prime_6)\n            c, d = self.mixup64(c, d, self.ror64(a, 19) ^ b, self.prime_5)\n            d, a = self.mixup64(d, a, self.ror64(b, 31) ^ c, self.prime_4)\n            hi = (c + d) & 0xffff_ffff_ffff_ffff\n            lo = (a ^ b) & 0xffff_ffff_ffff_ffff\n            return lo, hi\n\n        def digest_bytes(self, data):\n            lo, hi = self.t1ha2_atonce128(data, self.seed)\n            return struct.pack(\">QQ\", hi, lo)\n\n    class KupynaBase:\n        matrix = (0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04)\n        s0 = (\n            0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,\n            0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45,\n            0x39, 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2,\n            0x93, 0xc6, 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58,\n            0xa4, 0xbb, 0xa1, 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a,\n            0x8f, 0x6e, 0x04, 0x27, 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66,\n            0x0f, 0xbc, 0xa9, 0x47, 0x41, 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9,\n            0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e, 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e,\n            0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55, 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46,\n            0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff, 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3,\n            0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1, 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68,\n            0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76, 0xb3, 0xbe, 0xce, 0xbd, 0xae,\n            0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26, 0x2f, 0xef, 0xe8, 0x8c,\n            0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82, 0xf7, 0xea, 0x0a,\n            0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8, 0xac, 0x52,\n            0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d, 0x81,\n            0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80,\n        )\n        s1 = (\n            0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,\n            0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,\n            0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,\n            0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,\n            0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,\n            0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,\n            0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,\n            0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,\n            0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,\n            0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,\n            0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,\n            0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,\n            0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,\n            0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,\n            0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,\n            0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7,\n        )\n        s2 = (\n            0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,\n            0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,\n            0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,\n            0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,\n            0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,\n            0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,\n            0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,\n            0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,\n            0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,\n            0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,\n            0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,\n            0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,\n            0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,\n            0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,\n            0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,\n            0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67,\n        )\n        s3 = (\n            0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,\n            0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,\n            0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,\n            0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,\n            0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,\n            0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,\n            0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,\n            0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,\n            0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,\n            0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,\n            0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,\n            0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,\n            0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,\n            0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,\n            0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,\n            0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61,\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n        #include <string.h>\n\n        static inline uint64_t load64_le(const uint8_t *p)\n        {\n            return ((uint64_t)p[0]      ) |\n                   ((uint64_t)p[1] <<  8) |\n                   ((uint64_t)p[2] << 16) |\n                   ((uint64_t)p[3] << 24) |\n                   ((uint64_t)p[4] << 32) |\n                   ((uint64_t)p[5] << 40) |\n                   ((uint64_t)p[6] << 48) |\n                   ((uint64_t)p[7] << 56);\n        }\n\n        static inline uint64_t sub_word(\n            uint64_t w, const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3)\n        {\n            return ((uint64_t)s0[(w >>  0) & 0xff])       |\n                   ((uint64_t)s1[(w >>  8) & 0xff] <<  8) |\n                   ((uint64_t)s2[(w >> 16) & 0xff] << 16) |\n                   ((uint64_t)s3[(w >> 24) & 0xff] << 24) |\n                   ((uint64_t)s0[(w >> 32) & 0xff] << 32) |\n                   ((uint64_t)s1[(w >> 40) & 0xff] << 40) |\n                   ((uint64_t)s2[(w >> 48) & 0xff] << 48) |\n                   ((uint64_t)s3[(w >> 56) & 0xff] << 56);\n        }\n\n        static inline void sub_bytes_u64(\n            uint64_t *s, int columns, const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3)\n        {\n            int col;\n            for (col = 0; col < columns; col++) {\n                s[col] = sub_word(s[col], s0, s1, s2, s3);\n            }\n        }\n\n        static inline void shift_rows_u64(uint64_t *s, int columns, int shift7)\n        {\n            uint64_t src[16];\n            int row;\n            int col;\n\n            memcpy(src, s, (size_t)columns * sizeof(uint64_t));\n            for (col = 0; col < columns; col++) {\n                s[col] = 0;\n            }\n\n            for (row = 0; row < 8; row++) {\n                int off = (row == 7) ? shift7 : row;\n                int shift = row * 8;\n                for (col = 0; col < columns; col++) {\n                    int dst_col = (col + off) % columns;\n                    s[dst_col] |= ((src[col] >> shift) & 0xffULL) << shift;\n                }\n            }\n        }\n\n        static inline uint64_t mix_word(\n            uint64_t w, const uint8_t *t4, const uint8_t *t5,\n            const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            uint64_t b0 = (w >>  0) & 0xff;\n            uint64_t b1 = (w >>  8) & 0xff;\n            uint64_t b2 = (w >> 16) & 0xff;\n            uint64_t b3 = (w >> 24) & 0xff;\n            uint64_t b4 = (w >> 32) & 0xff;\n            uint64_t b5 = (w >> 40) & 0xff;\n            uint64_t b6 = (w >> 48) & 0xff;\n            uint64_t b7 = (w >> 56) & 0xff;\n\n            uint64_t o0 = b0 ^ b1 ^ t5[b2] ^ b3 ^ t8[b4] ^ t6[b5] ^ t7[b6] ^ t4[b7];\n            uint64_t o1 = t4[b0] ^ b1 ^ b2 ^ t5[b3] ^ b4 ^ t8[b5] ^ t6[b6] ^ t7[b7];\n            uint64_t o2 = t7[b0] ^ t4[b1] ^ b2 ^ b3 ^ t5[b4] ^ b5 ^ t8[b6] ^ t6[b7];\n            uint64_t o3 = t6[b0] ^ t7[b1] ^ t4[b2] ^ b3 ^ b4 ^ t5[b5] ^ b6 ^ t8[b7];\n            uint64_t o4 = t8[b0] ^ t6[b1] ^ t7[b2] ^ t4[b3] ^ b4 ^ b5 ^ t5[b6] ^ b7;\n            uint64_t o5 = b0 ^ t8[b1] ^ t6[b2] ^ t7[b3] ^ t4[b4] ^ b5 ^ b6 ^ t5[b7];\n            uint64_t o6 = t5[b0] ^ b1 ^ t8[b2] ^ t6[b3] ^ t7[b4] ^ t4[b5] ^ b6 ^ b7;\n            uint64_t o7 = b0 ^ t5[b1] ^ b2 ^ t8[b3] ^ t6[b4] ^ t7[b5] ^ t4[b6] ^ b7;\n\n            return o0 | (o1 <<  8) | (o2 << 16) | (o3 << 24) | (o4 << 32) | (o5 << 40) | (o6 << 48) | (o7 << 56);\n        }\n\n        static inline void mix_columns_u64(\n            uint64_t *s, int columns, const uint8_t *t4, const uint8_t *t5,\n            const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            int col;\n            for (col = 0; col < columns; col++) {\n                s[col] = mix_word(s[col], t4, t5, t6, t7, t8);\n            }\n        }\n\n        static inline void perm_p_u64(\n            uint64_t *s, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3, const uint8_t *t4,\n            const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            int rnd;\n            int col;\n\n            for (rnd = 0; rnd < rounds; rnd++) {\n                for (col = 0; col < columns; col++) {\n                    s[col] ^= (uint64_t)((col << 4) ^ rnd);\n                }\n                shift_rows_u64(s, columns, shift7);\n                sub_bytes_u64(s, columns, s0, s1, s2, s3);\n                mix_columns_u64(s, columns, t4, t5, t6, t7, t8);\n            }\n        }\n\n        static inline void perm_q_u64(\n            uint64_t *s, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3, const uint8_t *t4,\n            const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            int rnd;\n            int col;\n\n            for (rnd = 0; rnd < rounds; rnd++) {\n                uint64_t rc =\n                    ((((uint64_t)(((columns - 1) << 4) ^ rnd)) << 56) |\n                     0x00f0f0f0f0f0f0f3ULL);\n\n                for (col = 0; col < columns; col++) {\n                    s[col] += rc;\n                    rc -= 0x1000000000000000ULL;\n                }\n\n                shift_rows_u64(s, columns, shift7);\n                sub_bytes_u64(s, columns, s0, s1, s2, s3);\n                mix_columns_u64(s, columns, t4, t5, t6, t7, t8);\n            }\n        }\n\n        void kupyna_process_block(\n            uint64_t *state, const uint8_t *block, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3, const uint8_t *t4,\n            const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            uint64_t words[16];\n            uint64_t t1[16];\n            uint64_t t2[16];\n            int i;\n\n            for (i = 0; i < columns; i++) {\n                words[i] = load64_le(block + (i * 8));\n                t1[i] = state[i] ^ words[i];\n                t2[i] = words[i];\n            }\n\n            perm_p_u64(t1, columns, rounds, shift7, s0, s1, s2, s3, t4, t5, t6, t7, t8);\n            perm_q_u64(t2, columns, rounds, shift7, s0, s1, s2, s3, t4, t5, t6, t7, t8);\n\n            for (i = 0; i < columns; i++) {\n                state[i] ^= t1[i] ^ t2[i];\n            }\n        }\n\n        void kupyna_output_transform(\n            uint64_t *state, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3, const uint8_t *t4,\n            const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8)\n        {\n            uint64_t t[16];\n            int i;\n\n            for (i = 0; i < columns; i++) {\n                t[i] = state[i];\n            }\n\n            perm_p_u64(t, columns, rounds, shift7, s0, s1, s2, s3, t4, t5, t6, t7, t8);\n\n            for (i = 0; i < columns; i++) {\n                state[i] ^= t[i];\n            }\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void kupyna_process_block(\n            uint64_t *state, const uint8_t *block, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3,\n            const uint8_t *t4, const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8);\n        void kupyna_output_transform(\n            uint64_t *state, int columns, int rounds, int shift7,\n            const uint8_t *s0, const uint8_t *s1, const uint8_t *s2, const uint8_t *s3,\n            const uint8_t *t4, const uint8_t *t5, const uint8_t *t6, const uint8_t *t7, const uint8_t *t8);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.KupynaBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            def pack_u8(seq):\n                buf = ffi.new(\"uint8_t[]\", len(seq))\n                for i, v in enumerate(seq):\n                    buf[i] = v & 0xff\n                return buf\n\n            try:\n                c_s0 = pack_u8(self.s0)\n                c_s1 = pack_u8(self.s1)\n                c_s2 = pack_u8(self.s2)\n                c_s3 = pack_u8(self.s3)\n                c_t4 = pack_u8(self.mul_tables[4])\n                c_t5 = pack_u8(self.mul_tables[5])\n                c_t6 = pack_u8(self.mul_tables[6])\n                c_t7 = pack_u8(self.mul_tables[7])\n                c_t8 = pack_u8(self.mul_tables[8])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib c_s0 c_s1 c_s2 c_s3 c_t4 c_t5 c_t6 c_t7 c_t8\")(\n                ffi, lib, c_s0, c_s1, c_s2, c_s3, c_t4, c_t5, c_t6, c_t7, c_t8,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n            if hasattr(Hash.KupynaBase, \"mul_tables\"):\n                return\n\n            def gf_mul(a, b):\n                res = 0\n                aa = a & 0xff\n                bb = b & 0xff\n                while bb:\n                    if bb & 1:\n                        res ^= aa\n                    aa <<= 1\n                    if aa & 0x100:\n                        aa ^= 0x11d\n                    aa &= 0x1ff\n                    bb >>= 1\n                return res & 0xff\n\n            Hash.KupynaBase.mul_tables = {\n                0x04: tuple(gf_mul(0x04, x) for x in range(256)),\n                0x05: tuple(gf_mul(0x05, x) for x in range(256)),\n                0x06: tuple(gf_mul(0x06, x) for x in range(256)),\n                0x07: tuple(gf_mul(0x07, x) for x in range(256)),\n                0x08: tuple(gf_mul(0x08, x) for x in range(256)),\n            }\n            return\n\n        def __init__(self, data=b\"\"):\n            if self.columns == 8:\n                self.shift_offsets = (0, 1, 2, 3, 4, 5, 6, 7)\n            else:\n                self.shift_offsets = (0, 1, 2, 3, 4, 5, 6, 11)\n            self.state = [0] * self.columns\n            self.state[0] = self.block_size\n            self.buf = bytearray()\n            self.msg_len_bits = 0\n            self.ensure_tables()\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len_bits = self.msg_len_bits\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.msg_len_bits += len(data) * 8\n            self.buf.extend(data)\n            block_size = self.block_size\n            process_block = self.process_block\n            while len(self.buf) >= block_size:\n                process_block(self.buf[:block_size])\n                del self.buf[:block_size]\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = c.digest_from_state()\n            return out\n\n        def hexdigest(self):\n            out = self.digest().hex()\n            return out\n\n        def finalize(self):\n            bit_len = self.msg_len_bits & ((1 << 96) - 1)\n            self.buf.append(0x80)\n            block_size = self.block_size\n            len_pos = block_size - 12\n            process_block = self.process_block\n            if len(self.buf) > len_pos:\n                while len(self.buf) < block_size:\n                    self.buf.append(0x00)\n                process_block(self.buf[:block_size])\n                del self.buf[:block_size]\n            while len(self.buf) < len_pos:\n                self.buf.append(0x00)\n            self.buf.extend(bit_len.to_bytes(12, \"little\"))\n            while len(self.buf) >= block_size:\n                process_block(self.buf[:block_size])\n                del self.buf[:block_size]\n            self.output_transform()\n            return\n\n        def digest_from_state(self):\n            needed_cols = self.digest_size // 8\n            start_col = self.columns - needed_cols\n            out = b\"\".join(self.state[i].to_bytes(8, \"little\") for i in range(start_col, self.columns))\n            return out\n\n        def process_block(self, block):\n            if self.USE_CFFI:\n                state_buf = self.cffi.ffi.new(\"uint64_t[]\", [x & 0xffff_ffff_ffff_ffff for x in self.state])\n                block_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(block))\n                self.cffi.lib.kupyna_process_block(\n                    state_buf, block_buf, self.columns, self.rounds, self.shift_offsets[7],\n                    self.cffi.c_s0, self.cffi.c_s1, self.cffi.c_s2, self.cffi.c_s3,\n                    self.cffi.c_t4, self.cffi.c_t5, self.cffi.c_t6, self.cffi.c_t7, self.cffi.c_t8,\n                )\n                for i in range(self.columns):\n                    self.state[i] = int(state_buf[i])\n                return\n\n            columns = self.columns\n            state = self.state\n            words = [0] * columns\n            for i in range(columns):\n                j = i * 8\n                words[i] = int.from_bytes(block[j:j + 8], \"little\")\n            t1 = [0] * columns\n            for i in range(columns):\n                t1[i] = state[i] ^ words[i]\n            t2 = list(words)\n            self.perm_p(t1)\n            self.perm_q(t2)\n            for i in range(columns):\n                state[i] ^= t1[i] ^ t2[i]\n            return\n\n        def output_transform(self):\n            if self.USE_CFFI:\n                state_buf = self.cffi.ffi.new(\"uint64_t[]\", [x & 0xffff_ffff_ffff_ffff for x in self.state])\n                self.cffi.lib.kupyna_output_transform(state_buf, self.columns, self.rounds, self.shift_offsets[7],\n                    self.cffi.c_s0, self.cffi.c_s1, self.cffi.c_s2, self.cffi.c_s3,\n                    self.cffi.c_t4, self.cffi.c_t5, self.cffi.c_t6, self.cffi.c_t7, self.cffi.c_t8,\n                )\n                for i in range(self.columns):\n                    self.state[i] = int(state_buf[i])\n                return\n\n            t = list(self.state)\n            self.perm_p(t)\n            for i in range(self.columns):\n                self.state[i] ^= t[i]\n            return\n\n        def perm_p(self, s):\n            for rnd in range(self.rounds):\n                for col in range(self.columns):\n                    s[col] ^= (col << 4) ^ rnd\n                self.shift_rows(s)\n                self.sub_bytes(s)\n                self.mix_columns(s)\n            return\n\n        def perm_q(self, s):\n            for rnd in range(self.rounds):\n                rc = ((((self.columns - 1) << 4) ^ rnd) << 56) | 0x00f0_f0f0_f0f0_f0f3\n                for col in range(self.columns):\n                    s[col] = (s[col] + rc) & 0xffff_ffff_ffff_ffff\n                    rc = (rc - 0x1000_0000_0000_0000) & 0xffff_ffff_ffff_ffff\n                self.shift_rows(s)\n                self.sub_bytes(s)\n                self.mix_columns(s)\n            return\n\n        def sub_bytes(self, s):\n            s0 = self.s0\n            s1 = self.s1\n            s2 = self.s2\n            s3 = self.s3\n            for col in range(self.columns):\n                w = s[col]\n                s[col] = (\n                    s0[(w >> 0) & 0xff]\n                    | (s1[(w >> 8) & 0xff] << 8)\n                    | (s2[(w >> 16) & 0xff] << 16)\n                    | (s3[(w >> 24) & 0xff] << 24)\n                    | (s0[(w >> 32) & 0xff] << 32)\n                    | (s1[(w >> 40) & 0xff] << 40)\n                    | (s2[(w >> 48) & 0xff] << 48)\n                    | (s3[(w >> 56) & 0xff] << 56)\n                )\n            return\n\n        def shift_rows(self, s):\n            columns = self.columns\n            offsets = self.shift_offsets\n            src = list(s)\n            for col in range(columns):\n                s[col] = 0\n            for row in range(8):\n                off = offsets[row]\n                shift = row * 8\n                for col in range(columns):\n                    dst_col = (col + off) % columns\n                    s[dst_col] |= ((src[col] >> shift) & 0xff) << shift\n            return\n\n        def mix_columns(self, s):\n            tables = self.mul_tables\n            t4 = tables[0x04]\n            t5 = tables[0x05]\n            t6 = tables[0x06]\n            t7 = tables[0x07]\n            t8 = tables[0x08]\n\n            for col in range(self.columns):\n                w = s[col]\n\n                b0 = (w >> 0) & 0xff\n                b1 = (w >> 8) & 0xff\n                b2 = (w >> 16) & 0xff\n                b3 = (w >> 24) & 0xff\n                b4 = (w >> 32) & 0xff\n                b5 = (w >> 40) & 0xff\n                b6 = (w >> 48) & 0xff\n                b7 = (w >> 56) & 0xff\n\n                o0 = b0 ^ b1 ^ t5[b2] ^ b3 ^ t8[b4] ^ t6[b5] ^ t7[b6] ^ t4[b7]\n                o1 = t4[b0] ^ b1 ^ b2 ^ t5[b3] ^ b4 ^ t8[b5] ^ t6[b6] ^ t7[b7]\n                o2 = t7[b0] ^ t4[b1] ^ b2 ^ b3 ^ t5[b4] ^ b5 ^ t8[b6] ^ t6[b7]\n                o3 = t6[b0] ^ t7[b1] ^ t4[b2] ^ b3 ^ b4 ^ t5[b5] ^ b6 ^ t8[b7]\n                o4 = t8[b0] ^ t6[b1] ^ t7[b2] ^ t4[b3] ^ b4 ^ b5 ^ t5[b6] ^ b7\n                o5 = b0 ^ t8[b1] ^ t6[b2] ^ t7[b3] ^ t4[b4] ^ b5 ^ b6 ^ t5[b7]\n                o6 = t5[b0] ^ b1 ^ t8[b2] ^ t6[b3] ^ t7[b4] ^ t4[b5] ^ b6 ^ b7\n                o7 = b0 ^ t5[b1] ^ b2 ^ t8[b3] ^ t6[b4] ^ t7[b5] ^ t4[b6] ^ b7\n\n                s[col] = (o0 | (o1 << 8) | (o2 << 16) | (o3 << 24) | (o4 << 32) | (o5 << 40) | (o6 << 48) | (o7 << 56))\n            return\n\n    class Kupyna256(KupynaBase):\n        block_size = 64\n        digest_size = 32\n        columns = 8\n        rounds = 10\n\n    class Kupyna384(KupynaBase):\n        block_size = 128\n        digest_size = 48\n        columns = 16\n        rounds = 14\n\n    class Kupyna512(KupynaBase):\n        block_size = 128\n        digest_size = 64\n        columns = 16\n        rounds = 14\n\n    class CubeHash:\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        void cube_round(uint32_t *s)\n        {\n            int i;\n            for (i = 0; i < 16; i++) s[i + 16] += s[i];\n            for (i = 0; i < 16; i++) s[i] = (s[i] << 7) | (s[i] >> 25);\n            for (i = 0; i < 8; i++) { uint32_t t = s[i]; s[i] = s[i + 8]; s[i + 8] = t; }\n            for (i = 0; i < 16; i++) s[i] ^= s[i + 16];\n            {\n                int a[] = {16, 17, 20, 21, 24, 25, 28, 29};\n                for (i = 0; i < 8; i++) { uint32_t t = s[a[i]]; s[a[i]] = s[a[i] + 2]; s[a[i] + 2] = t; }\n            }\n            for (i = 0; i < 16; i++) s[i + 16] += s[i];\n            for (i = 0; i < 16; i++) s[i] = (s[i] << 11) | (s[i] >> 21);\n            {\n                int a[] = {0, 1, 2, 3, 8, 9, 10,11};\n                for (i = 0; i < 8; i++) { uint32_t t = s[a[i]]; s[a[i]] = s[a[i] + 4]; s[a[i] + 4] = t; }\n            }\n            for (i = 0; i < 16; i++) s[i] ^= s[i + 16];\n            {\n                int a[] = {16, 18, 20, 22, 24, 26, 28, 30};\n                for (i = 0; i < 8; i++) { uint32_t t = s[a[i]]; s[a[i]] = s[a[i] + 1]; s[a[i] + 1] = t; }\n            }\n        }\n\n        void cube_transform(uint32_t *s, int n_rounds)\n        {\n            int i;\n            for (i = 0; i < n_rounds; i++) {\n                cube_round(s);\n            }\n            return;\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void cube_round(uint32_t *s);\n        void cube_transform(uint32_t *s, int n_rounds);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.CubeHash\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            try:\n                with warnings.catch_warnings():\n                    warnings.filterwarnings(\n                        \"ignore\",\n                        message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                        category=UserWarning,\n                        module=r\"cffi\\.vengine_cpy\",\n                    )\n                    ffi = cffi.FFI()\n                    ffi.cdef(base_class.DEF_TEMPLATE)\n                    lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib\")(\n                ffi, lib,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        def __init__(self, data=b\"\", params=\"CubeHash160+16/32+160-256\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            self.set_params(params)\n            self.init_cffi_backend()\n            self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def set_params(self, params):\n            if not isinstance(params, str):\n                raise TypeError(\"params must be str\")\n            m = re.fullmatch(r\"CubeHash(\\d+)\\+(\\d+)/(\\d+)\\+(\\d+)-(\\d+)\", params)\n            if not m:\n                raise ValueError(\"invalid params format\")\n            self.i = int(m.group(1))\n            self.r = int(m.group(2))\n            self.b = int(m.group(3))\n            self.f = int(m.group(4))\n            self.h = int(m.group(5))\n            if not (0 <= self.i):\n                raise ValueError(\"i must be >= 0\")\n            if not (0 <= self.f):\n                raise ValueError(\"f must be >= 0\")\n            if not (1 <= self.r <= 128):\n                raise ValueError(\"r must be 1..128\")\n            if not (1 <= self.b <= 128):\n                raise ValueError(\"b must be 1..128\")\n            if self.h % 8 != 0 or not (8 <= self.h <= 512):\n                raise ValueError(\"h must be multiple of 8 and 8..512\")\n            if (self.h // 8) > 128:\n                raise ValueError(\"h/8 too large\")\n            self.params = f\"CubeHash{self.i}+{self.r}/{self.b}+{self.f}-{self.h}\"\n            self.block_size = self.b\n            self.digest_size = self.h // 8\n            return\n\n        def init_state(self):\n            if self.USE_CFFI:\n                self.state = self.cffi.ffi.new(\"uint32_t[32]\")\n            else:\n                self.state = [0] * 32\n            self.state[0] = self.h // 8\n            self.state[1] = self.b\n            self.state[2] = self.r\n            self.transform(self.i)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", params=self.params)\n            if self.USE_CFFI:\n                for i in range(32):\n                    other.state[i] = self.state[i]\n            else:\n                other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.finalized:\n                raise ValueError(\"already finalized\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.b:\n                block = bytes(self.buf[:self.b])\n                del self.buf[:self.b]\n                self.xor_block(block)\n                self.transform(self.r)\n            return self\n\n        def finalize(self):\n            if self.finalized:\n                return\n            self.buf.append(0x80)\n            while (len(self.buf) % self.b) != 0:\n                self.buf.append(0x00)\n            while len(self.buf) >= self.b:\n                block = bytes(self.buf[:self.b])\n                del self.buf[:self.b]\n                self.xor_block(block)\n                self.transform(self.r)\n            self.state[31] ^= 1\n            self.transform(self.f)\n            self.finalized = True\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            raw = struct.pack(\"<32I\", *[(w & 0xffff_ffff) for w in c.state])\n            return raw[:self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def transform(self, n_rounds):\n            if self.USE_CFFI:\n                self.cffi.lib.cube_transform(self.state, n_rounds)\n                return\n\n            # --- pure Python ---\n            state = self.state\n            for _ in range(n_rounds):\n                for i in range(16):\n                    state[i + 16] = (state[i] + state[i + 16]) & 0xffff_ffff\n                for i in range(16):\n                    state[i] = ((state[i] << 7) | (state[i] >> 25)) & 0xffff_ffff\n                for i in range(8):\n                    state[i], state[i + 8] = state[i + 8], state[i]\n                for i in range(16):\n                    state[i] ^= state[i + 16]\n                for i in [16, 17, 20, 21, 24, 25, 28, 29]:\n                    state[i], state[i + 2] = state[i + 2], state[i]\n                for i in range(16):\n                    state[i + 16] = (state[i] + state[i + 16]) & 0xffff_ffff\n                for i in range(16):\n                    state[i] = ((state[i] << 11) | (state[i] >> 21)) & 0xffff_ffff\n                for i in [0, 1, 2, 3, 8, 9, 10, 11]:\n                    state[i], state[i + 4] = state[i + 4], state[i]\n                for i in range(16):\n                    state[i] ^= state[i + 16]\n                for i in [16, 18, 20, 22, 24, 26, 28, 30]:\n                    state[i], state[i + 1] = state[i + 1], state[i]\n            return\n\n        def xor_block(self, block):\n            x = self.state\n            n_full = self.b // 4\n            rem = self.b % 4\n            if n_full > 0:\n                words = struct.unpack(f\"<{n_full}I\", block[:n_full * 4])\n                for w in range(n_full):\n                    x[w] ^= words[w]\n            if rem:\n                v = int.from_bytes(block[n_full * 4:], \"little\")\n                x[n_full] ^= v\n            self.state = x\n            return\n\n    class ECHOBase:\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        @classmethod\n        def ensure_tables(cls):\n            t0, t1, t2, t3 = [], [], [], []\n            for i in range(256):\n                s = cls.sbox[i]\n                s2 = ((s << 1) ^ 0x1b) & 0xff if (s & 0x80) else (s << 1)\n                s3 = s2 ^ s\n                t0.append((s2, s, s, s3))\n                t1.append((s3, s2, s, s))\n                t2.append((s, s3, s2, s))\n                t3.append((s, s, s3, s2))\n            Hash.ECHOBase.T0 = tuple(t0)\n            Hash.ECHOBase.T1 = tuple(t1)\n            Hash.ECHOBase.T2 = tuple(t2)\n            Hash.ECHOBase.T3 = tuple(t3)\n            return\n\n        def __init__(self, data=b\"\", salt=b\"\"):\n            self.ensure_tables()\n            if not isinstance(salt, (bytes, bytearray, memoryview)):\n                raise TypeError(\"salt must be bytes-like\")\n            if len(salt) not in (0, 16):\n                raise ValueError(\"salt must be 16 bytes or empty\")\n            if len(salt) == 0:\n                self.salt = bytearray(16)\n            else:\n                self.salt = bytearray(salt)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.total_bits = 0\n            word = self.hash_size.to_bytes(2, \"little\") + b\"\\x00\" * 14\n            self.v = bytearray(word * self.cv_words)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.salt = bytearray(self.salt)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.total_bits = self.total_bits\n            other.v = bytearray(self.v)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                Ci = self.total_bits + self.block_size * 8\n                self.compress(block, Ci)\n                self.total_bits = Ci\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return bytes(c.v[:self.digest_size])\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            L = self.msg_len * 8\n            block_bytes = self.block_size\n            pos = len(self.buf)\n            total = self.total_bits + pos * 8\n            if total != L:\n                raise AssertionError(\"internal length mismatch\")\n\n            self.buf.append(0x80)\n            pos += 1\n\n            processed_extra = False\n            if pos > block_bytes - 18:\n                if pos < block_bytes:\n                    self.buf.extend(b\"\\x00\" * (block_bytes - pos))\n                self.compress(bytes(self.buf[:block_bytes]), total)\n                processed_extra = True\n                self.buf = bytearray()\n                pos = 0\n\n            if pos < block_bytes - 18:\n                self.buf.extend(b\"\\x00\" * (block_bytes - 18 - pos))\n\n            self.buf.extend(self.hash_size.to_bytes(2, \"little\"))\n            self.buf.extend(L.to_bytes(16, \"little\"))\n\n            if len(self.buf) != block_bytes:\n                raise AssertionError(\"final block size mismatch\")\n\n            Ci = total if (not processed_extra and L != self.total_bits) else 0\n            self.compress(bytes(self.buf), Ci)\n\n            self.buf = bytearray()\n            self.total_bits = total\n            return\n\n        def compress(self, block, Ci):\n            v_words = [list(self.v[i * 16:(i + 1) * 16]) for i in range(self.cv_words)]\n            m_words = [list(block[i * 16:(i + 1) * 16]) for i in range(self.msg_words)]\n\n            w = [None] * 16\n            for i in range(self.cv_words):\n                w[i] = v_words[i][:]\n            for i in range(self.msg_words):\n                w[self.cv_words + i] = m_words[i][:]\n\n            counter = (Ci & 0xffff_ffff_ffff_ffff) if Ci else 0\n\n            for _ in range(self.rounds):\n                counter = self.sub_words(w, counter)\n                self.shift_rows_words(w)\n                self.mix_columns_words(w)\n\n            out_words = []\n            if self.cv_words == 4:\n                for r in range(4):\n                    tmp = [0] * 16\n                    for j in range(16):\n                        tmp[j] = (\n                            v_words[r][j] ^\n                            m_words[r][j] ^\n                            m_words[r + 4][j] ^\n                            m_words[r + 8][j] ^\n                            w[r][j] ^\n                            w[r + 4][j] ^\n                            w[r + 8][j] ^\n                            w[r + 12][j]\n                        ) & 0xff\n                    out_words.append(tmp)\n            else:\n                for r in range(8):\n                    tmp = [0] * 16\n                    for j in range(16):\n                        tmp[j] = (\n                            v_words[r][j] ^\n                            m_words[r][j] ^\n                            w[r][j] ^\n                            w[r + 8][j]\n                        ) & 0xff\n                    out_words.append(tmp)\n\n            self.v = bytearray(sum(out_words, []))\n            return\n\n        def sub_words(self, w, counter):\n            k = counter & 0xffff_ffff_ffff_ffff\n            salt_key = list(self.salt)\n            for i in range(16):\n                k1 = list(k.to_bytes(8, \"little\") + b\"\\x00\" * 8)\n                w[i] = self.aes_round(w[i], k1)\n                w[i] = self.aes_round(w[i], salt_key)\n                k = (k + 1) & 0xffff_ffff_ffff_ffff\n            return k\n\n        def aes_round(self, state, rk):\n            t0 = self.T0\n            t1 = self.T1\n            t2 = self.T2\n            t3 = self.T3\n            v0 = t0[state[0]]\n            v1 = t1[state[5]]\n            v2 = t2[state[10]]\n            v3 = t3[state[15]]\n            c0 = v0[0] ^ v1[0] ^ v2[0] ^ v3[0] ^ rk[0]\n            c1 = v0[1] ^ v1[1] ^ v2[1] ^ v3[1] ^ rk[1]\n            c2 = v0[2] ^ v1[2] ^ v2[2] ^ v3[2] ^ rk[2]\n            c3 = v0[3] ^ v1[3] ^ v2[3] ^ v3[3] ^ rk[3]\n            v0 = t0[state[4]]\n            v1 = t1[state[9]]\n            v2 = t2[state[14]]\n            v3 = t3[state[3]]\n            c4 = v0[0] ^ v1[0] ^ v2[0] ^ v3[0] ^ rk[4]\n            c5 = v0[1] ^ v1[1] ^ v2[1] ^ v3[1] ^ rk[5]\n            c6 = v0[2] ^ v1[2] ^ v2[2] ^ v3[2] ^ rk[6]\n            c7 = v0[3] ^ v1[3] ^ v2[3] ^ v3[3] ^ rk[7]\n            v0 = t0[state[8]]\n            v1 = t1[state[13]]\n            v2 = t2[state[2]]\n            v3 = t3[state[7]]\n            c8 = v0[0] ^ v1[0] ^ v2[0] ^ v3[0] ^ rk[8]\n            c9 = v0[1] ^ v1[1] ^ v2[1] ^ v3[1] ^ rk[9]\n            c10 = v0[2] ^ v1[2] ^ v2[2] ^ v3[2] ^ rk[10]\n            c11 = v0[3] ^ v1[3] ^ v2[3] ^ v3[3] ^ rk[11]\n            v0 = t0[state[12]]\n            v1 = t1[state[1]]\n            v2 = t2[state[6]]\n            v3 = t3[state[11]]\n            c12 = v0[0] ^ v1[0] ^ v2[0] ^ v3[0] ^ rk[12]\n            c13 = v0[1] ^ v1[1] ^ v2[1] ^ v3[1] ^ rk[13]\n            c14 = v0[2] ^ v1[2] ^ v2[2] ^ v3[2] ^ rk[14]\n            c15 = v0[3] ^ v1[3] ^ v2[3] ^ v3[3] ^ rk[15]\n            return [c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15]\n\n        def shift_rows_words(self, w):\n            w[1], w[5], w[9], w[13] = w[5], w[9], w[13], w[1]\n            w[2], w[6], w[10], w[14] = w[10], w[14], w[2], w[6]\n            w[3], w[7], w[11], w[15] = w[15], w[3], w[7], w[11]\n            return\n\n        def mix_columns_words(self, w):\n\n            def xtime8(x):\n                return ((x << 1) ^ 0x1b) & 0xff if (x & 0x80) else (x << 1)\n\n            def mix_column4(a0, a1, a2, a3):\n                t = (a0 ^ a1 ^ a2 ^ a3) & 0xff\n                u = a0\n                return (\n                    (a0 ^ t ^ xtime8(a0 ^ a1)) & 0xff,\n                    (a1 ^ t ^ xtime8(a1 ^ a2)) & 0xff,\n                    (a2 ^ t ^ xtime8(a2 ^ a3)) & 0xff,\n                    (a3 ^ t ^ xtime8(a3 ^ u)) & 0xff,\n                )\n\n            for col in range(4):\n                base = col * 4\n                for b in range(16):\n                    r0, r1, r2, r3 = mix_column4(\n                        w[base][b], w[base + 1][b], w[base + 2][b], w[base + 3][b]\n                    )\n                    w[base][b] = r0\n                    w[base + 1][b] = r1\n                    w[base + 2][b] = r2\n                    w[base + 3][b] = r3\n            return\n\n    class ECHO224(ECHOBase):\n        block_size = 192\n        digest_size = 28\n        hash_size = 224\n        cv_words = 4\n        msg_words = 12\n        rounds = 8\n\n    class ECHO256(ECHOBase):\n        block_size = 192\n        digest_size = 32\n        hash_size = 256\n        cv_words = 4\n        msg_words = 12\n        rounds = 8\n\n    class ECHO384(ECHOBase):\n        block_size = 128\n        digest_size = 48\n        hash_size = 384\n        cv_words = 8\n        msg_words = 8\n        rounds = 10\n\n    class ECHO512(ECHOBase):\n        block_size = 128\n        digest_size = 64\n        hash_size = 512\n        cv_words = 8\n        msg_words = 8\n        rounds = 10\n\n    class FSBBase:\n        class FSBPiBin:\n            size_bytes = 0x04_2800\n            digits = size_bytes * 8\n            guard_digits = 0x20\n\n            c3_over_24 = 0x26_dd04_1d87_8000\n            a_const = 0xcf_6371\n            b_const = 0x207e_2da6\n            k_const = 0x06_8380\n            sqrt_const = 0x2715\n\n            def __init__(self):\n                self.gmpy2 = None\n                try:\n                    self.gmpy2 = __import__(\"gmpy2\")\n                except Exception:\n                    self.gmpy2 = None\n                return\n\n            def enable_unlimited_int_to_str(self):\n                try:\n                    sys.set_int_max_str_digits(0)\n                except Exception:\n                    pass\n                return\n\n            def make_int(self, x):\n                if self.gmpy2 is None:\n                    return int(x)\n                return self.gmpy2.mpz(int(x))\n\n            def isqrt(self, x):\n                if self.gmpy2 is None:\n                    import math\n                    return math.isqrt(int(x))\n                return self.gmpy2.isqrt(x)\n\n            def pow10(self, n):\n                if self.gmpy2 is None:\n                    return 10 ** int(n)\n                return self.gmpy2.mpz(10) ** int(n)\n\n            def bs(self, a, b):\n                if b - a == 1:\n                    if a == 0:\n                        P = self.make_int(1)\n                        Q = self.make_int(1)\n                    else:\n                        k = self.make_int(a)\n                        P = (self.make_int(6) * k - self.make_int(5)) * \\\n                            (self.make_int(2) * k - self.make_int(1)) * \\\n                            (self.make_int(6) * k - self.make_int(1))\n                        Q = k * k * k * self.make_int(self.c3_over_24)\n                    T = P * (self.make_int(self.a_const) + self.make_int(self.b_const) * self.make_int(a))\n                    if a & 1:\n                        T = -T\n                    return P, Q, T\n\n                m = (a + b) // 2\n                P1, Q1, T1 = self.bs(a, m)\n                P2, Q2, T2 = self.bs(m, b)\n                P = P1 * P2\n                Q = Q1 * Q2\n                T = T1 * Q2 + T2 * P1\n                return P, Q, T\n\n            def pi_scaled(self, digits):\n                digits = int(digits)\n                n_terms = digits // 14 + 1\n                P, Q, T = self.bs(0, n_terms)\n\n                one = self.pow10(digits)\n                sqrt_10005 = self.isqrt(self.make_int(self.sqrt_const) * one * one)\n                pi_scaled = (self.make_int(self.k_const) * sqrt_10005 * Q) // T\n                return pi_scaled\n\n            def pi_fractional_digits(self, n_digits):\n                self.enable_unlimited_int_to_str()\n\n                n_digits = int(n_digits)\n                guard = int(self.guard_digits)\n                digits_total = n_digits + guard\n\n                x = self.pi_scaled(digits_total)\n                if guard:\n                    x = x // self.pow10(guard)\n\n                s = str(int(x)) if self.gmpy2 is not None else str(x)\n                need = n_digits + 1\n                if len(s) < need:\n                    s = (\"0\" * (need - len(s))) + s\n\n                frac = s[1:1 + n_digits]\n                return frac\n\n            def pack_parity_stream(self, frac_digits):\n                digit_bytes = frac_digits.encode(\"ascii\")\n                out = bytearray(self.size_bytes)\n\n                pos = 0\n                for i in range(self.size_bytes):\n                    b0 = (digit_bytes[pos + 0] & 1) << 7\n                    b1 = (digit_bytes[pos + 1] & 1) << 6\n                    b2 = (digit_bytes[pos + 2] & 1) << 5\n                    b3 = (digit_bytes[pos + 3] & 1) << 4\n                    b4 = (digit_bytes[pos + 4] & 1) << 3\n                    b5 = (digit_bytes[pos + 5] & 1) << 2\n                    b6 = (digit_bytes[pos + 6] & 1) << 1\n                    b7 = (digit_bytes[pos + 7] & 1) << 0\n                    out[i] = b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7\n                    pos += 8\n\n                return bytes(out)\n\n            def make_pi_bin(self):\n                cache_path = os.path.join(GEF_TEMP_DIR, \"FSB_hash_pi.bin\")\n                try:\n                    st = os.stat(cache_path)\n                    if st.st_size == self.size_bytes:\n                        with open(cache_path, \"rb\") as f:\n                            data = f.read()\n                        if len(data) == self.size_bytes:\n                            return data\n                except Exception:\n                    pass\n\n                frac = self.pi_fractional_digits(self.digits)\n                data = self.pack_parity_stream(frac)\n\n                try:\n                    with open(cache_path, \"wb\") as f:\n                        f.write(data)\n                except Exception:\n                    pass\n                return data\n\n        def __init__(self, data=b\"\"):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.init_state()\n            self.h = bytearray(self.output_bytes)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def init_state(self):\n            self.pi_data = self.FSBPiBin().make_pi_bin()\n\n            if self.block_size is None or self.digest_size is None:\n                raise RuntimeError(\"invalid parameters\")\n            if self.n is None or self.w is None or self.r is None or self.p is None or self.s is None:\n                raise RuntimeError(\"invalid parameters\")\n\n            if (self.r % 8) != 0:\n                raise RuntimeError(\"r must be multiple of 8\")\n            if (self.p <= self.r) is False:\n                pass\n            if (self.s - self.r) <= 0:\n                raise RuntimeError(\"s must be greater than r\")\n            if ((self.s - self.r) % self.w) != 0:\n                raise RuntimeError(\"(s-r) must be divisible by w\")\n            if (self.r % self.w) != 0:\n                raise RuntimeError(\"r must be divisible by w\")\n\n            self.output_bytes = self.r // 8\n            self.shift_message = self.r // self.w\n            self.batch_size = (self.s - self.r) // self.w\n            self.batch_mask = (1 << self.batch_size) - 1\n            self.n_div_w = self.n // self.w\n\n            self.p_extra_bits = 8 - (self.p % 8)\n            if self.p_extra_bits == 0:\n                self.p_extra_bits = 8\n            self.p_mask = (1 << self.p) - 1\n            self.p_shift_prefix = self.p - self.r\n\n            size_vectors = (self.p // 8) + 1\n            vectors_count = self.n // self.r\n            need = vectors_count * size_vectors\n            if len(self.pi_data) < need:\n                raise RuntimeError(\"FSB_hash_pi.bin is too short for this variant\")\n\n            vecs = []\n            for i in range(vectors_count):\n                start = i * size_vectors\n                end = start + size_vectors\n                chunk = self.pi_data[start:end]\n                v = int.from_bytes(chunk, \"big\") >> self.p_extra_bits\n                vecs.append(v)\n            self.vectors = vecs\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = bytearray(self.h)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n\n            bs = self.block_size\n            while len(self.buf) >= bs:\n                block = bytes(self.buf[:bs])\n                del self.buf[:bs]\n                self.compress(block)\n            return self\n\n        def finalize(self):\n            bs = self.block_size\n\n            bit_len = (self.msg_len * 8) & 0xffff_ffff_ffff_ffff\n            self.buf.append(0x80)\n            while (len(self.buf) % bs) != (bs - 8):\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\">Q\", bit_len))\n\n            while len(self.buf) >= bs:\n                block = bytes(self.buf[:bs])\n                del self.buf[:bs]\n                self.compress(block)\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            wh = Hash.Whirlpool(bytes(c.h))\n            full = wh.digest()\n            return full[: self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def compress(self, block):\n            if len(block) != self.block_size:\n                raise ValueError(\"invalid block length\")\n\n            msg_int = int.from_bytes(block, \"big\")\n            divided = [0] * self.w\n            for i in range(self.w):\n                shift = (self.w - 1 - i) * self.batch_size\n                divided[i] = (msg_int >> shift) & self.batch_mask\n\n            state = self.h\n            acc = 0\n            for i in range(self.w):\n                w_index = (i * self.n_div_w) + state[i] + (divided[i] << self.shift_message)\n                chosen_vec = w_index // self.r\n                shift_value = w_index % self.r\n\n                v = self.vectors[chosen_vec]\n                if shift_value != 0:\n                    v = ((v >> shift_value) | (v << (self.p - shift_value))) & self.p_mask\n                prefix = v >> self.p_shift_prefix\n                acc ^= prefix\n\n            self.h = bytearray(acc.to_bytes(self.output_bytes, \"big\"))\n            return\n\n    class FSB160(FSBBase):\n        block_size = 0x3c\n        digest_size = 0x14\n        n = 0x14_0000\n        w = 0x50\n        r = 0x280\n        p = 0x28d\n        s = 0x460\n\n    class FSB224(FSBBase):\n        block_size = 0x54\n        digest_size = 0x1c\n        n = 0x1c_0000\n        w = 0x70\n        r = 0x380\n        p = 0x38b\n        s = 0x620\n\n    class FSB256(FSBBase):\n        block_size = 0x60\n        digest_size = 0x20\n        n = 0x20_0000\n        w = 0x80\n        r = 0x400\n        p = 0x425\n        s = 0x700\n\n    class FSB384(FSBBase):\n        block_size = 0x73\n        digest_size = 0x30\n        n = 0x17_0000\n        w = 0xb8\n        r = 0x5c0\n        p = 0x5cb\n        s = 0x958\n\n    class FSB512(FSBBase):\n        block_size = 0x9b\n        digest_size = 0x40\n        n = 0x1f_0000\n        w = 0xf8\n        r = 0x7c0\n        p = 0x7c3\n        s = 0xc98\n\n    class SHAvite3Base:\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        def __init__(self, data=b\"\", salt=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if salt != 0:\n                raise ValueError(\"only salt=0 is supported\")\n            self.h = list(self.iv)\n            self.buf = bytearray(self.block_size)\n            self.ptr = 0\n            self.count0 = 0\n            self.count1 = 0\n            if self.block_size != 0x40:\n                self.count2 = 0\n                self.count3 = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.ptr = self.ptr\n            other.count0 = self.count0\n            other.count1 = self.count1\n            if self.block_size != 0x40:\n                other.count2 = self.count2\n                other.count3 = self.count3\n            return other\n\n        def rol32(self, x, n):\n            x &= 0xffff_ffff\n            return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n        def swap32(self, x):\n            x &= 0xffff_ffff\n            return ((x & 0x0000_00ff) << 0x18) | ((x & 0x0000_ff00) << 0x08) | \\\n                   ((x & 0x00ff_0000) >> 0x08) | ((x & 0xff00_0000) >> 0x18)\n\n        def dec32le(self, b, off):\n            return b[off] | (b[off + 1] << 0x08) | (b[off + 2] << 0x10) | (b[off + 3] << 0x18)\n\n        def enc32le(self, x):\n            return (x & 0xffff_ffff).to_bytes(4, \"little\")\n\n        def xtime(self, x):\n            x &= 0xff\n            return ((x << 1) ^ (0x1b if (x & 0x80) else 0)) & 0xff\n\n        def not32(self, x):\n            return x ^ 0xffff_ffff\n\n        def init_aes_tables(self):\n            if hasattr(self, \"aes0\"):\n                return\n            te0 = [0] * 256\n            for i in range(256):\n                s = self.sbox[i]\n                s2 = self.xtime(s)\n                s3 = s2 ^ s\n                te0[i] = ((s2 << 0x18) | (s << 0x10) | (s << 0x08) | s3) & 0xffff_ffff\n            te1 = [self.rol32(x, 0x08) for x in te0]\n            te2 = [self.rol32(x, 0x10) for x in te0]\n            te3 = [self.rol32(x, 0x18) for x in te0]\n            Hash.SHAvite3Base.aes0 = [self.swap32(x) for x in te0]\n            Hash.SHAvite3Base.aes1 = [self.swap32(x) for x in te3]\n            Hash.SHAvite3Base.aes2 = [self.swap32(x) for x in te2]\n            Hash.SHAvite3Base.aes3 = [self.swap32(x) for x in te1]\n            return\n\n        def aes_round_nokey(self, x0, x1, x2, x3):\n            self.init_aes_tables()\n            a0 = self.aes0\n            a1 = self.aes1\n            a2 = self.aes2\n            a3 = self.aes3\n            y0 = a0[(x0 >> 0x00) & 0xff] ^ a1[(x1 >> 0x08) & 0xff] ^ a2[(x2 >> 0x10) & 0xff] ^ a3[(x3 >> 0x18) & 0xff]\n            y1 = a0[(x1 >> 0x00) & 0xff] ^ a1[(x2 >> 0x08) & 0xff] ^ a2[(x3 >> 0x10) & 0xff] ^ a3[(x0 >> 0x18) & 0xff]\n            y2 = a0[(x2 >> 0x00) & 0xff] ^ a1[(x3 >> 0x08) & 0xff] ^ a2[(x0 >> 0x10) & 0xff] ^ a3[(x1 >> 0x18) & 0xff]\n            y3 = a0[(x3 >> 0x00) & 0xff] ^ a1[(x0 >> 0x08) & 0xff] ^ a2[(x1 >> 0x10) & 0xff] ^ a3[(x2 >> 0x18) & 0xff]\n            return y0, y1, y2, y3\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            off = 0\n            length = len(data)\n            while length > 0:\n                c_len = self.block_size - self.ptr\n                if c_len > length:\n                    c_len = length\n                self.buf[self.ptr:self.ptr + c_len] = data[off:off + c_len]\n                self.ptr += c_len\n                off += c_len\n                length -= c_len\n                if self.ptr == self.block_size:\n                    if self.block_size == 64:\n                        self.count0 = (self.count0 + 0x200) & 0xffff_ffff\n                        if self.count0 == 0:\n                            self.count1 = (self.count1 + 1) & 0xffff_ffff\n                        self.c256(bytes(self.buf))\n                    else:\n                        self.count0 = (self.count0 + 0x400) & 0xffff_ffff\n                        if self.count0 == 0:\n                            self.count1 = (self.count1 + 1) & 0xffff_ffff\n                            if self.count1 == 0:\n                                self.count2 = (self.count2 + 1) & 0xffff_ffff\n                                if self.count2 == 0:\n                                    self.count3 = (self.count3 + 1) & 0xffff_ffff\n                        self.c512(bytes(self.buf))\n                    self.ptr = 0\n            return self\n\n        def c256(self, block):\n            rk = [0] * 0x90\n            for i in range(16):\n                rk[i] = self.dec32le(block, i * 4)\n\n            count_injections = {\n                0x10: ((0, self.count0), (1, self.not32(self.count1))),\n                0x38: ((1, self.count1), (2, self.not32(self.count0))),\n                0x54: ((2, self.count1), (3, self.not32(self.count0))),\n                0x7c: ((0, self.count0), (3, self.not32(self.count1))),\n            }\n\n            # Key schedule\n            u = 0x10\n            for _ in range(4):\n                for _ in range(4):\n                    x0 = rk[u - 15]\n                    x1 = rk[u - 14]\n                    x2 = rk[u - 13]\n                    x3 = rk[u - 16]\n                    x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                    rk[u + 0] = x0 ^ rk[u - 4]\n                    rk[u + 1] = x1 ^ rk[u - 3]\n                    rk[u + 2] = x2 ^ rk[u - 2]\n                    rk[u + 3] = x3 ^ rk[u - 1]\n                    for off, val in count_injections.get(u, ()):\n                        rk[u + off] ^= val\n                    u += 4\n                for _ in range(4):\n                    rk[u + 0] = rk[u - 16] ^ rk[u - 3]\n                    rk[u + 1] = rk[u - 15] ^ rk[u - 2]\n                    rk[u + 2] = rk[u - 14] ^ rk[u - 1]\n                    rk[u + 3] = rk[u - 13] ^ rk[u - 0]\n                    u += 4\n\n            # Compression\n            p = list(self.h)\n            u = 0\n            for _ in range(6):\n                for lo, hi in ((4, 0), (0, 4)):\n                    x0 = p[lo] ^ rk[u]\n                    x1 = p[lo + 1] ^ rk[u + 1]\n                    x2 = p[lo + 2] ^ rk[u + 2]\n                    x3 = p[lo + 3] ^ rk[u + 3]\n                    u += 4\n                    for _ in range(2):\n                        x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                        x0 ^= rk[u]\n                        x1 ^= rk[u + 1]\n                        x2 ^= rk[u + 2]\n                        x3 ^= rk[u + 3]\n                        u += 4\n                    x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                    p[hi] ^= x0\n                    p[hi + 1] ^= x1\n                    p[hi + 2] ^= x2\n                    p[hi + 3] ^= x3\n\n            for i in range(8):\n                self.h[i] ^= p[i]\n            return\n\n        def c512(self, block):\n            rk = [0] * 0x1c0\n            for i in range(32):\n                rk[i] = self.dec32le(block, i * 4)\n\n            count_injections = {\n                0x020: ((0, self.count0), (1, self.count1), (2, self.count2), (3, self.not32(self.count3))),\n                0x0a4: ((0, self.count3), (1, self.count2), (2, self.count1), (3, self.not32(self.count0))),\n                0x13c: ((0, self.count2), (1, self.count3), (2, self.count0), (3, self.not32(self.count1))),\n                0x1b8: ((0, self.count1), (1, self.count0), (2, self.count3), (3, self.not32(self.count2))),\n            }\n\n            # Key schedule\n            u = 0x20\n            while True:\n                for _ in range(4):\n                    for _ in range(2):\n                        x0 = rk[u - 31]\n                        x1 = rk[u - 30]\n                        x2 = rk[u - 29]\n                        x3 = rk[u - 32]\n                        x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                        rk[u + 0] = x0 ^ rk[u - 4]\n                        rk[u + 1] = x1 ^ rk[u - 3]\n                        rk[u + 2] = x2 ^ rk[u - 2]\n                        rk[u + 3] = x3 ^ rk[u - 1]\n                        for off, val in count_injections.get(u, ()):\n                            rk[u + off] ^= val\n                        u += 4\n                if u == 0x1c0:\n                    break\n                for _ in range(8):\n                    rk[u + 0] = rk[u - 32] ^ rk[u - 7]\n                    rk[u + 1] = rk[u - 31] ^ rk[u - 6]\n                    rk[u + 2] = rk[u - 30] ^ rk[u - 5]\n                    rk[u + 3] = rk[u - 29] ^ rk[u - 4]\n                    u += 4\n\n            # Compression\n            p = list(self.h)\n            u = 0\n            for _ in range(14):\n                for lo, hi in ((4, 0), (12, 8)):\n                    x0 = p[lo + 0] ^ rk[u + 0]\n                    x1 = p[lo + 1] ^ rk[u + 1]\n                    x2 = p[lo + 2] ^ rk[u + 2]\n                    x3 = p[lo + 3] ^ rk[u + 3]\n                    u += 4\n                    for _ in range(3):\n                        x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                        x0 ^= rk[u + 0]\n                        x1 ^= rk[u + 1]\n                        x2 ^= rk[u + 2]\n                        x3 ^= rk[u + 3]\n                        u += 4\n                    x0, x1, x2, x3 = self.aes_round_nokey(x0, x1, x2, x3)\n                    p[hi + 0] ^= x0\n                    p[hi + 1] ^= x1\n                    p[hi + 2] ^= x2\n                    p[hi + 3] ^= x3\n                for j in range(4):\n                    p[j], p[j + 4], p[j + 8], p[j + 12] = p[j + 12], p[j], p[j + 4], p[j + 8]\n\n            for i in range(16):\n                self.h[i] ^= p[i]\n            return\n\n        def finalize(self):\n            buf = self.buf\n            ptr = self.ptr\n            if self.block_size == 64:\n                self.count0 = (self.count0 + (ptr << 3)) & 0xffff_ffff\n                count0 = self.count0\n                count1 = self.count1\n                if ptr == 0:\n                    buf[0] = 0x80\n                    for i in range(1, 54):\n                        buf[i] = 0\n                    self.count0 = 0\n                    self.count1 = 0\n                elif ptr < 54:\n                    buf[ptr] = 0x80\n                    ptr += 1\n                    for i in range(ptr, 54):\n                        buf[i] = 0\n                else:\n                    buf[ptr] = 0x80\n                    ptr += 1\n                    for i in range(ptr, 64):\n                        buf[i] = 0\n                    self.c256(bytes(buf))\n                    for i in range(54):\n                        buf[i] = 0\n                    self.count0 = 0\n                    self.count1 = 0\n                buf[54:58] = self.enc32le(count0)\n                buf[58:62] = self.enc32le(count1)\n                out_w = self.digest_size // 4\n                buf[62] = (out_w << 5) & 0xff\n                buf[63] = (out_w >> 3) & 0xff\n                self.c256(bytes(buf))\n                out = bytearray()\n                for u in range(out_w):\n                    out.extend(self.enc32le(self.h[u]))\n                return bytes(out)\n            self.count0 = (self.count0 + (ptr << 3)) & 0xffff_ffff\n            count0 = self.count0\n            count1 = self.count1\n            count2 = self.count2\n            count3 = self.count3\n            if ptr == 0:\n                buf[0] = 0x80\n                for i in range(1, 110):\n                    buf[i] = 0\n                self.count0 = 0\n                self.count1 = 0\n                self.count2 = 0\n                self.count3 = 0\n            elif ptr < 110:\n                buf[ptr] = 0x80\n                ptr += 1\n                for i in range(ptr, 110):\n                    buf[i] = 0\n            else:\n                buf[ptr] = 0x80\n                ptr += 1\n                for i in range(ptr, 0x80):\n                    buf[i] = 0\n                self.c512(bytes(buf))\n                for i in range(110):\n                    buf[i] = 0\n                self.count0 = 0\n                self.count1 = 0\n                self.count2 = 0\n                self.count3 = 0\n            buf[110:114] = self.enc32le(count0)\n            buf[114:118] = self.enc32le(count1)\n            buf[118:122] = self.enc32le(count2)\n            buf[122:126] = self.enc32le(count3)\n            out_w = self.digest_size // 4\n            buf[126] = (out_w << 5) & 0xff\n            buf[127] = (out_w >> 3) & 0xff\n            self.c512(bytes(buf))\n            out = bytearray()\n            for u in range(out_w):\n                out.extend(self.enc32le(self.h[u]))\n            return bytes(out)\n\n        def digest(self):\n            c = self.copy()\n            return c.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class SHAvite3_224(SHAvite3Base):\n        block_size = 0x40\n        digest_size = 0x1c\n        iv = (\n            0x6774_f31c, 0x990a_e210, 0xc87d_4274, 0xc954_6371, 0x62b2_aea8, 0x4b58_01d8, 0x1b70_2860, 0x842f_3017,\n        )\n\n    class SHAvite3_256(SHAvite3Base):\n        block_size = 0x40\n        digest_size = 0x20\n        iv = (\n            0x49bb_3e47, 0x2674_860d, 0xa8b3_92ac, 0x021a_c4e6, 0x4092_83cf, 0x620e_5d86, 0x6d92_9dcb, 0x96cc_2a8b,\n        )\n\n    class SHAvite3_384(SHAvite3Base):\n        block_size = 0x80\n        digest_size = 0x30\n        iv = (\n            0x83df_1545, 0xf9aa_ec13, 0xf480_3cb0, 0x11fe_1f47, 0xda6c_d269, 0x4f53_fcd7, 0x9505_29a2, 0x9790_8147,\n            0xb0a4_d7af, 0x2b91_32bf, 0x226e_607d, 0x3c0f_8d7c, 0x487b_3f0f, 0x0436_3e22, 0x0155_c99c, 0xec2e_20d3,\n        )\n\n    class SHAvite3_512(SHAvite3Base):\n        block_size = 0x80\n        digest_size = 0x40\n        iv = (\n            0x72fc_cdd8, 0x79ca_4727, 0x128a_077b, 0x40d5_5aec, 0xd190_1a06, 0x430a_e307, 0xb29f_5cd1, 0xdf07_fbfc,\n            0x8e45_d73d, 0x681a_b538, 0xbde8_6578, 0xdd57_7e47, 0xe275_eade, 0x502d_9fcd, 0xb935_7178, 0x022a_4b9a,\n        )\n\n    class LaneBase:\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        @classmethod\n        def ensure_tables(self):\n            if hasattr(Hash.LaneBase, \"k_table\"):\n                return\n\n            k = [0] * 768\n            k[0] = 0x07fc_703d\n            for i in range(1, 768):\n                prev = k[i - 1]\n                v = prev >> 1\n                if prev & 1:\n                    v ^= 0xd000_0001\n                k[i] = v & 0xffff_ffff\n            Hash.LaneBase.k_table = tuple(k)\n\n            kb = [0] * (768 * 4)\n            p = 0\n            for word in k:\n                kb[p] = (word >> 24) & 0xff\n                kb[p + 1] = (word >> 16) & 0xff\n                kb[p + 2] = (word >> 8) & 0xff\n                kb[p + 3] = word & 0xff\n                p += 4\n            Hash.LaneBase.k_bytes = tuple(kb)\n\n            m2 = [0] * 256\n            m3 = [0] * 256\n            for a in range(256):\n                b = a << 1\n                if a & 0x80:\n                    b ^= 0x11b\n                b &= 0xff\n                m2[a] = b\n                m3[a] = b ^ a\n            Hash.LaneBase.mul2_table = tuple(m2)\n            Hash.LaneBase.mul3_table = tuple(m3)\n            return\n\n        def __init__(self, data=b''):\n            self.hashbitlen = self.digest_size * 8\n            self.databitcount = 0\n            self.finalized = False\n            self.final_digest = None\n            self.ensure_tables()\n            self.initialize()\n            if data:\n                self.update(data)\n            return\n\n        def initialize(self):\n            self.hash = bytearray(64)\n            self.buffer = bytearray(128)\n            self.buffer[0] = 2\n            self.buffer[1] = (self.hashbitlen >> 24) & 0xff\n            self.buffer[2] = (self.hashbitlen >> 16) & 0xff\n            self.buffer[3] = (self.hashbitlen >> 8) & 0xff\n            self.buffer[4] = (self.hashbitlen >> 0) & 0xff\n            if self.hashbitlen <= 256:\n                self.lane256_transform(self.buffer, 0)\n            else:\n                self.lane512_transform(self.buffer, 0)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.databitcount = self.databitcount\n            other.buffer[:] = self.buffer\n            other.hash[:] = self.hash\n            other.finalized = self.finalized\n            other.final_digest = self.final_digest\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            mv = data if isinstance(data, memoryview) else memoryview(data)\n            blocksize = self.block_size\n            total = len(mv)\n            offset = 0\n            buffill = (self.databitcount >> 3) & (blocksize - 1)\n\n            if buffill:\n                n = blocksize - buffill\n                if n > total:\n                    n = total\n                self.buffer[buffill:buffill + n] = mv[:n]\n                self.databitcount += n << 3\n                if buffill + n == blocksize:\n                    if blocksize == 64:\n                        self.lane256_transform(self.buffer, self.databitcount)\n                    else:\n                        self.lane512_transform(self.buffer, self.databitcount)\n                offset = n\n\n            remain = total - offset\n            while remain >= blocksize:\n                self.databitcount += blocksize << 3\n                block = mv[offset:offset + blocksize]\n                if blocksize == 64:\n                    self.lane256_transform(block, self.databitcount)\n                else:\n                    self.lane512_transform(block, self.databitcount)\n                offset += blocksize\n                remain -= blocksize\n\n            if remain:\n                self.buffer[:remain] = mv[offset:offset + remain]\n                self.databitcount += remain << 3\n            return\n\n        def digest(self):\n            if self.finalized:\n                return self.final_digest\n            tmp = self.copy()\n            tmp.finalize()\n            return tmp.final_digest\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            blocksize = self.block_size\n            used = (self.databitcount >> 3) & (blocksize - 1)\n\n            if used:\n                self.buffer[used:blocksize] = b'\\x00' * (blocksize - used)\n                if blocksize == 64:\n                    self.lane256_transform(self.buffer, self.databitcount)\n                else:\n                    self.lane512_transform(self.buffer, self.databitcount)\n\n            self.buffer[:blocksize] = b'\\x00' * blocksize\n            counter = self.databitcount & 0xffff_ffff_ffff_ffff\n            self.buffer[1] = (counter >> 56) & 0xff\n            self.buffer[2] = (counter >> 48) & 0xff\n            self.buffer[3] = (counter >> 40) & 0xff\n            self.buffer[4] = (counter >> 32) & 0xff\n            self.buffer[5] = (counter >> 24) & 0xff\n            self.buffer[6] = (counter >> 16) & 0xff\n            self.buffer[7] = (counter >> 8) & 0xff\n            self.buffer[8] = counter & 0xff\n\n            if blocksize == 64:\n                self.lane256_transform(self.buffer, 0)\n            else:\n                self.lane512_transform(self.buffer, 0)\n\n            self.final_digest = bytes(self.hash[:self.digest_size])\n            self.finalized = True\n            return\n\n        def lane256_transform(self, buffer, counter):\n\n            def add_constants_2(r, a):\n                kb = self.k_bytes\n                base = 32 * r\n                for block in range(2):\n                    a_base = block * 16\n                    w_base = base + block * 16\n                    for col in range(4):\n                        w = w_base + col * 4\n                        a[a_base + col] ^= kb[w]\n                        a[a_base + col + 4] ^= kb[w + 1]\n                        a[a_base + col + 8] ^= kb[w + 2]\n                        a[a_base + col + 12] ^= kb[w + 3]\n                return\n\n            def sub_shift_mix_2(a):\n                s = self.sbox\n                m2 = self.mul2_table\n                m3 = self.mul3_table\n                shifted = (0, 1, 2, 3, 5, 6, 7, 4, 10, 11, 8, 9, 15, 12, 13, 14)\n                for p in (0, 16):\n                    x = [s[a[p + i]] for i in shifted]\n                    for col in range(4):\n                        x0 = x[col]\n                        x1 = x[4 + col]\n                        x2 = x[8 + col]\n                        x3 = x[12 + col]\n                        a[p + col] = m2[x0] ^ m3[x1] ^ x2 ^ x3\n                        a[p + 4 + col] = m2[x1] ^ m3[x2] ^ x3 ^ x0\n                        a[p + 8 + col] = m2[x2] ^ m3[x3] ^ x0 ^ x1\n                        a[p + 12 + col] = m2[x3] ^ m3[x0] ^ x1 ^ x2\n                return\n\n            def swap_columns256(a):\n                p0, p1 = 0, 16\n                for row in range(0, 16, 4):\n                    for col0, col1 in ((2, 0), (3, 1)):\n                        a[p0 + row + col0], a[p1 + row + col1] = a[p1 + row + col1], a[p0 + row + col0]\n                return\n\n            def xor_state_2(a, b):\n                for i in range(32):\n                    a[i] ^= b[i]\n                return\n\n            def expand_message256(hashval, buffer, w0, w1, w2, w3, w4, w5):\n                for col in range(4):\n                    bc = col * 4\n                    for row in range(4):\n                        idx = bc + row\n                        pos = row * 4 + col\n                        h0, h1 = hashval[idx], hashval[idx + 16]\n                        b0, b1, b2, b3 = buffer[idx], buffer[idx + 16], buffer[idx + 32], buffer[idx + 48]\n                        w0[pos], w0[pos + 16] = h0 ^ b0 ^ b1 ^ b2 ^ b3, h1 ^ b0 ^ b2\n                        w1[pos], w1[pos + 16] = h0 ^ h1 ^ b0 ^ b2 ^ b3, h0 ^ b1 ^ b2\n                        w2[pos], w2[pos + 16] = h0 ^ h1 ^ b0 ^ b1 ^ b2, h0 ^ b0 ^ b3\n                        w3[pos], w3[pos + 16] = h0, h1\n                        w4[pos], w4[pos + 16] = b0, b1\n                        w5[pos], w5[pos + 16] = b2, b3\n                return\n\n            def store_hash256(hashval, w0):\n                for col in range(4):\n                    bc = col * 4\n                    for row in range(4):\n                        pos = row * 4 + col\n                        hashval[bc + row] = w0[pos]\n                        hashval[16 + bc + row] = w0[16 + pos]\n                return\n\n            def permute_p256(j, a, c0, c1, c2, c3, c4, c5, c6, c7):\n                for i in range(5):\n                    r = 5 * j + i\n                    sub_shift_mix_2(a)\n                    add_constants_2(r, a)\n                    if r & 1:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c4, a[7] ^ c5, a[11] ^ c6, a[15] ^ c7\n                    else:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c0, a[7] ^ c1, a[11] ^ c2, a[15] ^ c3\n                    swap_columns256(a)\n                sub_shift_mix_2(a)\n                swap_columns256(a)\n                return\n\n            def permute_q256(j, a, c0, c1, c2, c3, c4, c5, c6, c7):\n                for i in range(2):\n                    r = 30 + 2 * j + i\n                    sub_shift_mix_2(a)\n                    add_constants_2(r, a)\n                    if r & 1:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c4, a[7] ^ c5, a[11] ^ c6, a[15] ^ c7\n                    else:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c0, a[7] ^ c1, a[11] ^ c2, a[15] ^ c3\n                    swap_columns256(a)\n                sub_shift_mix_2(a)\n                swap_columns256(a)\n                return\n\n            w0 = [0] * 32\n            w1 = [0] * 32\n            w2 = [0] * 32\n            w3 = [0] * 32\n            w4 = [0] * 32\n            w5 = [0] * 32\n\n            expand_message256(self.hash, buffer, w0, w1, w2, w3, w4, w5)\n\n            c0 = (counter >> 56) & 0xff\n            c1 = (counter >> 48) & 0xff\n            c2 = (counter >> 40) & 0xff\n            c3 = (counter >> 32) & 0xff\n            c4 = (counter >> 24) & 0xff\n            c5 = (counter >> 16) & 0xff\n            c6 = (counter >> 8) & 0xff\n            c7 = counter & 0xff\n\n            permute_p256(0, w0, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p256(1, w1, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p256(2, w2, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p256(3, w3, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p256(4, w4, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p256(5, w5, c0, c1, c2, c3, c4, c5, c6, c7)\n\n            xor_state_2(w0, w1)\n            xor_state_2(w0, w2)\n            xor_state_2(w3, w4)\n            xor_state_2(w3, w5)\n\n            permute_q256(0, w0, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_q256(1, w3, c0, c1, c2, c3, c4, c5, c6, c7)\n\n            xor_state_2(w0, w3)\n            store_hash256(self.hash, w0)\n            return\n\n        def lane512_transform(self, buffer, counter):\n\n            def add_constants_4(r, a):\n                kb = self.k_bytes\n                base = 64 * r\n                for part in range(4):\n                    a_base = part * 16\n                    w_base = base + part * 16\n                    for col in range(4):\n                        w = w_base + col * 4\n                        a[a_base + col] ^= kb[w]\n                        a[a_base + col + 4] ^= kb[w + 1]\n                        a[a_base + col + 8] ^= kb[w + 2]\n                        a[a_base + col + 12] ^= kb[w + 3]\n                return\n\n            def sub_shift_mix_4(a):\n                s = self.sbox\n                m2 = self.mul2_table\n                m3 = self.mul3_table\n                shifted = (0, 1, 2, 3, 5, 6, 7, 4, 10, 11, 8, 9, 15, 12, 13, 14)\n                for part in range(4):\n                    p = part * 16\n                    x = [s[a[p + i]] for i in shifted]\n                    for col in range(4):\n                        x0 = x[col]\n                        x1 = x[4 + col]\n                        x2 = x[8 + col]\n                        x3 = x[12 + col]\n                        a[p + col] = m2[x0] ^ m3[x1] ^ x2 ^ x3\n                        a[p + 4 + col] = m2[x1] ^ m3[x2] ^ x3 ^ x0\n                        a[p + 8 + col] = m2[x2] ^ m3[x3] ^ x0 ^ x1\n                        a[p + 12 + col] = m2[x3] ^ m3[x0] ^ x1 ^ x2\n                return\n\n            def swap_columns512(a):\n                bases = (0, 16, 32, 48)\n                for row_base in range(0, 16, 4):\n                    for src_block in range(4):\n                        for dst_block in range(src_block + 1, 4):\n                            src_index = bases[src_block] + row_base + dst_block\n                            dst_index = bases[dst_block] + row_base + src_block\n                            a[src_index], a[dst_index] = a[dst_index], a[src_index]\n                return\n\n            def xor_state_4(a, b):\n                for i in range(64):\n                    a[i] ^= b[i]\n                return\n\n            def expand_message512(hashval, buffer, w0, w1, w2, w3, w4, w5):\n                for col in range(4):\n                    bc = col * 4\n                    for row in range(4):\n                        idx = bc + row\n                        pos = row * 4 + col\n                        h0, h1, h2, h3 = hashval[idx], hashval[idx + 16], hashval[idx + 32], hashval[idx + 48]\n                        b0, b1, b2, b3 = buffer[idx], buffer[idx + 16], buffer[idx + 32], buffer[idx + 48]\n                        b4, b5, b6, b7 = buffer[idx + 64], buffer[idx + 80], buffer[idx + 96], buffer[idx + 112]\n                        w0[pos], w0[pos + 16] = h0 ^ b0 ^ b2 ^ b4 ^ b6, h1 ^ b1 ^ b3 ^ b5 ^ b7\n                        w1[pos], w1[pos + 16] = h0 ^ h2 ^ b0 ^ b4 ^ b6, h1 ^ h3 ^ b1 ^ b5 ^ b7\n                        w2[pos], w2[pos + 16] = h0 ^ h2 ^ b0 ^ b2 ^ b4, h1 ^ h3 ^ b1 ^ b3 ^ b5\n                        w3[pos], w3[pos + 16] = h0, h1\n                        w4[pos], w4[pos + 16] = b0, b1\n                        w5[pos], w5[pos + 16] = b4, b5\n                        w0[pos + 32], w0[pos + 48] = h2 ^ b0 ^ b4, h3 ^ b1 ^ b5\n                        w1[pos + 32], w1[pos + 48] = h0 ^ b2 ^ b4, h1 ^ b3 ^ b5\n                        w2[pos + 32], w2[pos + 48] = h0 ^ b0 ^ b6, h1 ^ b1 ^ b7\n                        w3[pos + 32], w3[pos + 48] = h2, h3\n                        w4[pos + 32], w4[pos + 48] = b2, b3\n                        w5[pos + 32], w5[pos + 48] = b6, b7\n                return\n\n            def store_hash512(hashval, w0):\n                for col in range(4):\n                    bc = col * 4\n                    for row in range(4):\n                        pos = row * 4 + col\n                        hashval[bc + row] = w0[pos]\n                        hashval[16 + bc + row] = w0[16 + pos]\n                        hashval[32 + bc + row] = w0[32 + pos]\n                        hashval[48 + bc + row] = w0[48 + pos]\n                return\n\n            def permute_p512(j, a, c0, c1, c2, c3, c4, c5, c6, c7):\n                for i in range(7):\n                    r = 7 * j + i\n                    sub_shift_mix_4(a)\n                    add_constants_4(r, a)\n                    if r & 1:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c4, a[7] ^ c5, a[11] ^ c6, a[15] ^ c7\n                    else:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c0, a[7] ^ c1, a[11] ^ c2, a[15] ^ c3\n                    swap_columns512(a)\n                sub_shift_mix_4(a)\n                swap_columns512(a)\n                return\n\n            def permute_q512(j, a, c0, c1, c2, c3, c4, c5, c6, c7):\n                for i in range(3):\n                    r = 42 + 3 * j + i\n                    sub_shift_mix_4(a)\n                    add_constants_4(r, a)\n                    if r & 1:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c4, a[7] ^ c5, a[11] ^ c6, a[15] ^ c7\n                    else:\n                        a[3], a[7], a[11], a[15] = a[3] ^ c0, a[7] ^ c1, a[11] ^ c2, a[15] ^ c3\n                    swap_columns512(a)\n                sub_shift_mix_4(a)\n                swap_columns512(a)\n                return\n\n            w0 = [0] * 64\n            w1 = [0] * 64\n            w2 = [0] * 64\n            w3 = [0] * 64\n            w4 = [0] * 64\n            w5 = [0] * 64\n\n            expand_message512(self.hash, buffer, w0, w1, w2, w3, w4, w5)\n\n            c0 = (counter >> 56) & 0xff\n            c1 = (counter >> 48) & 0xff\n            c2 = (counter >> 40) & 0xff\n            c3 = (counter >> 32) & 0xff\n            c4 = (counter >> 24) & 0xff\n            c5 = (counter >> 16) & 0xff\n            c6 = (counter >> 8) & 0xff\n            c7 = counter & 0xff\n\n            permute_p512(0, w0, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p512(1, w1, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p512(2, w2, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p512(3, w3, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p512(4, w4, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_p512(5, w5, c0, c1, c2, c3, c4, c5, c6, c7)\n\n            xor_state_4(w0, w1)\n            xor_state_4(w0, w2)\n            xor_state_4(w3, w4)\n            xor_state_4(w3, w5)\n\n            permute_q512(0, w0, c0, c1, c2, c3, c4, c5, c6, c7)\n            permute_q512(1, w3, c0, c1, c2, c3, c4, c5, c6, c7)\n\n            xor_state_4(w0, w3)\n            store_hash512(self.hash, w0)\n            return\n\n    class Lane224(LaneBase):\n        digest_size = 0x1c\n        block_size = 0x40\n\n    class Lane256(LaneBase):\n        digest_size = 0x20\n        block_size = 0x40\n\n    class Lane384(LaneBase):\n        digest_size = 0x30\n        block_size = 0x80\n\n    class Lane512(LaneBase):\n        digest_size = 0x40\n        block_size = 0x80\n\n    class FastHashBase:\n        block_size = 8\n\n        def __init__(self, data=b\"\", seed=0):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.seed = seed\n            self.value = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.value = self.value\n            return other\n\n        def fasthash64(self, message, seed):\n\n            def mix64(h):\n                mix_const = 0x2127_599b_f432_5c37\n                h &= 0xffff_ffff_ffff_ffff\n                h ^= (h >> 23)\n                h = (h * mix_const) & 0xffff_ffff_ffff_ffff\n                h ^= (h >> 47)\n                return h\n\n            m = 0x8803_55f2_1e6d_1965\n            length = len(message)\n\n            h = (seed & 0xffff_ffff_ffff_ffff) ^ ((length * m) & 0xffff_ffff_ffff_ffff)\n\n            index = 0\n            end = length & ~7\n            while index < end:\n                v = struct.unpack_from(\"<Q\", message, index)[0]\n                index += 8\n                h ^= mix64(v)\n                h = (h * m) & 0xffff_ffff_ffff_ffff\n\n            rem = length & 7\n            if rem:\n                tail = message[end:end + rem]\n                v = 0\n                for i in range(rem):\n                    v ^= tail[i] << (8 * i)\n                h ^= mix64(v)\n                h = (h * m) & 0xffff_ffff_ffff_ffff\n\n            h = mix64(h)\n            return h\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            return self\n\n        def finalize(self):\n            message = bytes(self.buf)\n            self.value = self.compute_value(message, self.seed)\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return struct.pack(self.pack_format, c.value)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class FastHash64(FastHashBase):\n        digest_size = 8\n        pack_format = \"<Q\"\n\n        def compute_value(self, message, seed):\n            return self.fasthash64(message, seed)\n\n    class FastHash32(FastHashBase):\n        digest_size = 4\n        pack_format = \"<I\"\n\n        def compute_value(self, message, seed):\n            h = self.fasthash64(message, seed)\n            v = (h - (h >> 32)) & 0xffff_ffff\n            return v\n\n    class SuperFastHash:\n        block_size = 4\n        digest_size = 4\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.value = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.value = self.value\n            return other\n\n        def u32(self, x):\n            x &= 0xffff_ffff\n            return x\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            return self\n\n        def finalize(self):\n            message = bytes(self.buf)\n            length = len(message)\n\n            index = 0\n            digest = self.u32(length)\n\n            for _ in range(length >> 2):\n                w1 = message[index] | (message[index + 1] << 8)\n                w2 = message[index + 2] | (message[index + 3] << 8)\n                index += 4\n\n                digest = self.u32(digest + w1)\n                digest ^= self.u32(digest << 16) ^ self.u32(w2 << 11)\n                digest = self.u32(digest + (digest >> 11))\n\n            rem = length & 3\n            if rem == 3:\n                digest = self.u32(digest + (message[index] | (message[index + 1] << 8)))\n                digest ^= self.u32(digest << 16)\n                digest ^= self.u32(message[index + 2] << 18)\n                digest = self.u32(digest + (digest >> 11))\n            elif rem == 2:\n                digest = self.u32(digest + (message[index] | (message[index + 1] << 8)))\n                digest ^= self.u32(digest << 11)\n                digest = self.u32(digest + (digest >> 17))\n            elif rem == 1:\n                digest = self.u32(digest + message[index])\n                digest ^= self.u32(digest << 10)\n                digest = self.u32(digest + (digest >> 1))\n\n            digest ^= self.u32(digest << 3)\n            digest = self.u32(digest + (digest >> 5))\n            digest ^= self.u32(digest << 4)\n            digest = self.u32(digest + (digest >> 17))\n            digest ^= self.u32(digest << 25)\n            digest = self.u32(digest + (digest >> 6))\n\n            self.value = digest\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return struct.pack(\"<I\", c.value)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class BuzHash:\n        digest_size = 4\n        block_size = 0\n\n        bytehash = (\n            0x12bd_9527, 0xf414_0cea, 0x987b_d6e1, 0x7907_9850, 0xafbf_d539, 0xd350_ce0a, 0x8297_3931, 0x9fc3_2b9c,\n            0x2800_3b88, 0xc30c_13aa, 0x6b67_8c34, 0x5844_ef1d, 0xaa55_2c18, 0x4a77_d3e8, 0xd1f6_2ea0, 0x6599_417c,\n            0xfbe3_0e7a, 0xf9e2_d5ee, 0xa1fc_a42e, 0x4154_8969, 0x116d_5b59, 0xaeda_1e1a, 0xc519_1c17, 0x54b9_a3cb,\n            0x727e_492a, 0x5c43_2f91, 0x31a5_0bce, 0xc269_6af6, 0x217c_8020, 0x1262_aefc, 0xace7_5924, 0x9876_a04f,\n            0xaf30_0bc2, 0x3ffc_e3f6, 0xd668_0fb5, 0xd0b1_ced8, 0x6651_f842, 0x736f_adef, 0xbc2d_3429, 0xb03d_2904,\n            0x7e63_4ba4, 0xdfd8_7d8c, 0x7988_d63a, 0x4be4_d933, 0x6a8d_0382, 0x9e13_2d62, 0x3ee9_c95f, 0xfec0_5b97,\n            0x6907_ad34, 0x8616_cfcc, 0xa6aa_bf24, 0x8ad1_c92e, 0x4f2a_ffc0, 0xb875_19db, 0x6576_eaf6, 0x15db_e00a,\n            0x63e1_dd82, 0xa36b_6a81, 0xeead_99b3, 0xbc6a_4309, 0x3478_d1a7, 0x2182_bcc0, 0xdd50_cfce, 0x7cb2_5580,\n            0x7307_5483, 0x503b_7f42, 0x4cd5_0d63, 0x3f4d_94c9, 0x385f_cbb7, 0x90da_f16c, 0xece1_0b8e, 0x11c1_cb04,\n            0x816a_899b, 0x69a2_9d06, 0xfb09_0b37, 0xf98e_f13c, 0x0765_3435, 0x9f15_dc42, 0x3b43_abdf, 0x1334_283f,\n            0x93f3_d9af, 0x0cbd_fe71, 0xa788_a614, 0x4f54_d2f0, 0xd437_4fc7, 0x7055_7ce7, 0xf741_fce8, 0xe4b6_f661,\n            0xc630_cb98, 0x387a_6366, 0x72f4_28fd, 0x5390_09db, 0xc53e_3810, 0x1e1a_52e5, 0x7d68_16b0, 0x040f_9b81,\n            0x9c99_c9fb, 0x9f3a_f3d2, 0x774d_1061, 0xd5c8_40ea, 0x8e14_80fe, 0x6ee4_023c, 0x2fbd_a535, 0xd88e_ff7a,\n            0xd863_2a2a, 0x43c4_e024, 0x3ef2_7971, 0xc728_66fd, 0xe35c_c630, 0x46d9_6220, 0x437a_8384, 0xe92c_af0c,\n            0x6290_a47e, 0xa7bb_9238, 0x0e10_00f9, 0x49e7_6bdc, 0x3acf_b4b8, 0x0358_2b8e, 0x6ea2_de4e, 0x2ec1_008d,\n            0xfcc8_df69, 0x91c2_fe0a, 0xb471_c7d9, 0x778b_e812, 0x70d2_9ad1, 0x7641_1cbf, 0xc302_e81c, 0x4e44_5194,\n            0x22e3_aa72, 0xb657_62e9, 0xa280_db05, 0x827a_a70e, 0x4c53_1a9d, 0x7a60_bf4a, 0x8fd9_5a44, 0x2289_aef0,\n            0xcd50_ddc4, 0x639a_ae69, 0x5fe8_5ed6, 0x4ed7_24ff, 0x00f0_4f7d, 0x95a5_fcb0, 0x8825_5d15, 0xa603_d2c9,\n            0xf695_6a5b, 0x53ea_7f3e, 0xb570_f225, 0x2b3b_e203, 0xa181_e40e, 0xc413_cdce, 0xa7cb_1ebb, 0xcf25_8b1f,\n            0x516e_b016, 0xca20_4586, 0xd1e6_9894, 0xe85a_73d3, 0x7db2_d382, 0xae73_b463, 0x3598_d643, 0x5087_c864,\n            0xd91f_30b6, 0xe1d4_d1e7, 0x73b3_b337, 0xceac_1233, 0x8edf_7845, 0xa69c_45c9, 0xdb5d_b3ab, 0x28cf_ade8,\n            0xebfa_49e7, 0xcbc2_a659, 0x59cc_e971, 0x959a_01af, 0x8ee9_aae7, 0xfb2f_01c6, 0x5a75_2836, 0x9ed1_2981,\n            0x618d_05b6, 0x93ec_12b3, 0x4590_c779, 0xed13_17a2, 0x03fe_5835, 0x7ad3_c6f7, 0xd4aa_d5b5, 0x1a99_5ed7,\n            0x247b_faa4, 0x69c2_c799, 0x745f_a405, 0xc5b9_f239, 0xc3d9_aebc, 0xa6f6_0e0b, 0xdf1e_91d7, 0xab8e_041c,\n            0xee31_88c6, 0x3737_7a9e, 0xc0e1_a3bf, 0x19a5_a9e4, 0x56cb_9556, 0xc4d3_3d3f, 0xfb1e_b03e, 0xf955_7057,\n            0x1be3_1d37, 0xd1fa_65f1, 0xf518_d714, 0x570a_c722, 0xf26c_f66a, 0x2479_4d47, 0x8ba2_e402, 0x3f51_37e6,\n            0x35be_1453, 0x4335_0478, 0x9f05_ee88, 0x364c_f9cf, 0x39a2_3ee7, 0xa4db_8d49, 0xc2eb_b3d2, 0xc6fb_99d5,\n            0xe014_dfb0, 0x7156_d425, 0xe090_a87a, 0x4cc1_2f78, 0x1b30_f503, 0x0669_4a7a, 0x6819_8cd1, 0x2f83_45bd,\n            0x9d79_198e, 0xd871_943f, 0x22ef_6cf4, 0xe81b_1c15, 0x067b_61d8, 0xfc4e_a4f5, 0xfe6d_ab57, 0x1bf7_44ba,\n            0xa70b_6a25, 0xafe6_e412, 0xc6c1_a05c, 0x8ffb_e3ce, 0xc427_0af1, 0xf3f3_6373, 0xc450_7dd8, 0x5e6f_d1e2,\n            0x58cd_9739, 0x47d3_c5b5, 0xe1d5_a343, 0x3d4d_ea4a, 0x893d_91ae, 0xbb2a_5e2a, 0x0d57_b800, 0x652a_7cc9,\n            0x6a68_ccfd, 0x6252_9f0b, 0xec5f_36d6, 0x766c_ceda, 0x96ca_63ef, 0xa049_9838, 0xd903_0f59, 0x8185_f4d2,\n        )\n\n        def __init__(self, n=64, data=b\"\"):\n            if not isinstance(n, int) or n <= 0:\n                raise ValueError(\"n must be a positive int\")\n            self.n = n\n            self.block_size = n\n            self.bshiftn = n % 32\n            self.buf = bytearray(n)\n            self.state = 0\n            self.bufpos = 0\n            self.overflow = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(self.n)\n            other.state = self.state\n            other.buf = bytearray(self.buf)\n            other.bufpos = self.bufpos\n            other.overflow = self.overflow\n            return other\n\n        def update_byte(self, data):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                n &= 31\n                if n == 0:\n                    return x\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if len(data) != 1:\n                raise ValueError(\"data must be exactly 1 byte\")\n            b = data[0]\n\n            if self.bufpos == self.n:\n                self.overflow = True\n                self.bufpos = 0\n\n            state = self.state\n            state = rol32(state, 1)\n\n            if self.overflow:\n                toshift = self.bytehash[self.buf[self.bufpos]]\n                state ^= rol32(toshift, self.bshiftn)\n\n            self.buf[self.bufpos] = b\n            self.bufpos += 1\n\n            state ^= self.bytehash[b]\n            self.state = state\n            return state\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            for b in data:\n                self.update_byte(bytes([b]))\n            return self\n\n        def finalize(self):\n            return\n\n        def digest(self):\n            return self.state.to_bytes(4, \"little\")\n\n        def hexdigest(self):\n            h = self.digest().hex()\n            return h\n\n    class NHash:\n        digest_size = 0\n        block_size = 1\n\n        primes = (\n            0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, 0x3b,\n            0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71,\n        )\n\n        def __init__(self, data=b\"\", divisors=None):\n            self.total = 0\n            self.i = 0\n            if divisors is None:\n                self.divisors = []\n            else:\n                self.divisors = list(divisors)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.total = self.total\n            other.i = self.i\n            other.divisors = list(self.divisors)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            for b in data:\n                self.i = (self.i + 0x1c) % 0x1d\n                self.total += self.primes[self.i] * b\n            return self\n\n        def finalize(self):\n            return\n\n        def digest(self):\n\n            def moddiv_list():\n                if not self.divisors:\n                    return []\n                tmp = self.total\n                ret = []\n                for div in reversed(self.divisors):\n                    if not isinstance(div, int) or div <= 0:\n                        raise ValueError(\"all divisors must be positive int\")\n                    ret.append(tmp % div)\n                    tmp //= div\n                ret.reverse()\n                return ret\n\n            def moddiv_string():\n                if not self.divisors:\n                    s = str(self.total)\n                    return s\n                parts = [str(x) for x in self.moddiv_list()]\n                s = \"/\".join(parts)\n                return s\n\n            if self.divisors:\n                return moddiv_string().encode(\"ascii\")\n            v = self.total\n            nbytes = (v.bit_length() + 7) // 8\n            if nbytes == 0:\n                nbytes = 1\n            return v.to_bytes(nbytes, \"big\")\n\n        def hexdigest(self):\n            h = self.digest().hex()\n            return h\n\n    class LSHBase:\n        tau = (0x03, 0x02, 0x00, 0x01, 0x07, 0x04, 0x05, 0x06, 0x0b, 0x0a, 0x08, 0x09, 0x0f, 0x0c, 0x0d, 0x0e)\n        sigma = (0x06, 0x04, 0x05, 0x07, 0x0c, 0x0f, 0x0e, 0x0d, 0x02, 0x00, 0x01, 0x03, 0x08, 0x0b, 0x0a, 0x09)\n\n        gamma32 = (0x00, 0x08, 0x10, 0x18, 0x18, 0x10, 0x08, 0x00)\n        gamma64 = (0x00, 0x10, 0x20, 0x30, 0x08, 0x18, 0x28, 0x38)\n\n        sc0_32 = (\n            0x917c_af90, 0x6c1b_10a2, 0x6f35_2943, 0xcf77_8243, 0x2ceb_7472, 0x29e9_6ff2, 0x8a9b_a428, 0x2eeb_2642,\n        )\n        sc0_64 = (\n            0x9788_4283_c938_982a, 0xba1f_ca93_533e_2355, 0xc519_a2e8_7aeb_1c03, 0x9a0f_c954_62af_17b1,\n            0xfc3d_da8a_b019_a82b, 0x0282_5d07_9a89_5407, 0x79f2_d0a7_ee06_a6f7, 0xd76d_15ee_d9fd_f5fe,\n        )\n\n        def __init__(self, data=b\"\"):\n            if self.word_bits not in (32, 64):\n                raise ValueError(\"invalid word_bits\")\n            if self.ns not in (26, 28):\n                raise ValueError(\"invalid ns\")\n            if self.block_size not in (128, 256):\n                raise ValueError(\"invalid block_size\")\n            if self.digest_size not in (28, 32, 48, 64):\n                raise ValueError(\"invalid digest_size\")\n            if not isinstance(self.iv, (list, tuple)) or len(self.iv) != 16:\n                raise ValueError(\"invalid iv\")\n            self.word_bytes = self.word_bits // 8\n            self.mask = (1 << self.word_bits) - 1\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.cv = list(self.iv)\n            self.sc = self.make_step_constants()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = object.__new__(self.__class__)\n            other.word_bits = self.word_bits\n            other.ns = self.ns\n            other.block_size = self.block_size\n            other.digest_size = self.digest_size\n            other.iv = self.iv\n            other.word_bytes = self.word_bytes\n            other.mask = self.mask\n            other.sc = self.sc\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.cv = list(self.cv)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            h = [(c.cv[i] ^ c.cv[i + 8]) & c.mask for i in range(8)]\n            out = b\"\".join(int(x).to_bytes(c.word_bytes, \"little\") for x in h)\n            return out[:c.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # One-zeros padding\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != 0:\n                self.buf.append(0x00)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return\n\n        def rol(self, x, n):\n            x &= self.mask\n            if n == 0:\n                return x\n            return ((x << n) | (x >> (self.word_bits - n))) & self.mask\n\n        def make_step_constants(self):\n            if self.word_bits == 32:\n                sc0 = self.sc0_32\n            else:\n                sc0 = self.sc0_64\n\n            sc = [list(sc0)]\n            for j in range(1, self.ns):\n                prev = sc[j - 1]\n                sc.append([(prev[l] + self.rol(prev[l], 8)) & self.mask for l in range(8)])  # noqa: E741\n            return sc\n\n        def compress(self, block):\n\n            def msg_add(x, y):\n                return [x[i] ^ y[i] for i in range(16)]\n\n            def alpha_beta(j):\n                if self.word_bits == 32:\n                    if (j & 1) == 0:\n                        return 0x1d, 0x01\n                    return 0x05, 0x11\n                if (j & 1) == 0:\n                    return 0x17, 0x3b\n                return 0x07, 0x03\n\n            def gamma(l):  # noqa: E741\n                if self.word_bits == 32:\n                    return self.gamma32[l]\n                return self.gamma64[l]\n\n            def mix_pair(j, l, x, y):  # noqa: E741\n                alpha, beta = alpha_beta(j)\n                g = gamma(l)\n\n                x = (x + y) & self.mask\n                x = self.rol(x, alpha)\n                x ^= self.sc[j][l]\n\n                y = (x + y) & self.mask\n                y = self.rol(y, beta)\n\n                x = (x + y) & self.mask\n                y = self.rol(y, g)\n                return x, y\n\n            def mix(j, t):\n                t = list(t)\n                for l in range(8):  # noqa: E741\n                    x, y = mix_pair(j, l, t[l], t[l + 8])\n                    t[l] = x\n                    t[l + 8] = y\n                return t\n\n            def word_perm(x):\n                return [x[self.sigma[i]] for i in range(16)]\n\n            def step(j, t, mj):\n                t = msg_add(t, mj)\n                t = mix(j, t)\n                t = word_perm(t)\n                return t\n\n            def msg_expand(m32):\n                sub = [m32[:16], m32[16:32]]\n                for j in range(2, self.ns + 1):\n                    prev1 = sub[j - 1]\n                    prev2 = sub[j - 2]\n                    sub.append([(prev1[l] + prev2[self.tau[l]]) & self.mask for l in range(16)])  # noqa: E741\n                return sub\n\n            if self.word_bits == 32:\n                fmt = \"<32I\"\n            else:\n                fmt = \"<32Q\"\n            m = list(struct.unpack(fmt, block))\n\n            sub = msg_expand(m)\n            t = list(self.cv)\n            for j in range(self.ns):\n                t = step(j, t, sub[j])\n            self.cv = msg_add(t, sub[self.ns])\n            return\n\n    class LSH256_224(LSHBase):\n        word_bits = 32\n        ns = 26\n        block_size = 128\n        digest_size = 28\n        iv = (\n            0x0686_08d3, 0x62d8_f7a7, 0xd766_52ab, 0x4c60_0a43, 0xbdc4_0aa8, 0x1eca_0b68, 0xda1a_89be, 0x3147_d354,\n            0x707e_b4f9, 0xf65b_3862, 0x6b0b_2abe, 0x56b8_ec0a, 0xcf23_7286, 0xee0d_1727, 0x3363_6595, 0x8bb8_d05f,\n        )\n\n    class LSH256_256(LSHBase):\n        word_bits = 32\n        ns = 26\n        block_size = 128\n        digest_size = 32\n        iv = (\n            0x46a1_0f1f, 0xfddc_e486, 0xb414_43a8, 0x198e_6b9d, 0x3304_388d, 0xb0f5_a3c7, 0xb360_61c4, 0x7adb_d553,\n            0x105d_5378, 0x2f74_de54, 0x5c2f_2d95, 0xf255_3fbe, 0x8051_357a, 0x1386_68c8, 0x47aa_4484, 0xe01a_fb41,\n        )\n\n    class LSH512_224(LSHBase):\n        word_bits = 64\n        ns = 28\n        block_size = 256\n        digest_size = 28\n        iv = (\n            0x0c40_1e9f_e881_3a55, 0x4a5f_4462_68fd_3d35, 0xff13_e452_334f_612a, 0xf822_7661_037e_354a,\n            0xa5f2_2372_3c9c_a29d, 0x95d9_65a1_1aed_3979, 0x01e2_3835_b9ab_02cc, 0x52d4_9cba_d5b3_0616,\n            0x9e5c_2027_773f_4ed3, 0x66a5_c880_1925_b701, 0x22bb_c85b_4c67_79d9, 0xc131_71a4_2c55_9c23,\n            0x31e2_b67d_25be_3813, 0xd522_c4de_ed8e_4d83, 0xa79f_5509_b43f_bafe, 0xe00d_2cd8_8b4b_6c6a,\n        )\n\n    class LSH512_256(LSHBase):\n        word_bits = 64\n        ns = 28\n        block_size = 256\n        digest_size = 32\n        iv = (\n            0x6dc5_7c33_df98_9423, 0xd8ea_7f6e_8342_c199, 0x76df_8356_f860_3ac4, 0x40f1_b44d_e838_223a,\n            0x39ff_e7cf_c314_84cd, 0x39c4_326c_c528_1548, 0x8a2f_f85a_3460_45d8, 0xff20_2aa4_6dbd_d61e,\n            0xcf78_5b3c_d5fc_db8b, 0x1f03_23b6_4a81_50bf, 0xff75_d972_f29e_a355, 0x2e56_7f30_bf1c_a9e1,\n            0xb596_875b_f8ff_6dba, 0xfcca_39b0_89ef_4615, 0xecff_4017_d020_b4b6, 0x7e77_384c_772e_d802,\n        )\n\n    class LSH512_384(LSHBase):\n        word_bits = 64\n        ns = 28\n        block_size = 256\n        digest_size = 48\n        iv = (\n            0x5315_6a66_2928_08f6, 0xb2c4_f362_b204_c2bc, 0xb84b_7213_bfa0_5c4e, 0x976c_eb7c_1b29_9f73,\n            0xdf0c_c63c_0570_ae97, 0xda44_41ba_a486_ce3f, 0x6559_f5d9_b5f2_acc2, 0x22da_cf19_b4b5_2a16,\n            0xbbcd_acef_de80_953a, 0xc989_1a28_7972_5b3e, 0x7c9f_e633_0237_e440, 0xa30b_a550_553f_7431,\n            0xbb08_043f_b34e_3e30, 0xa0de_c48d_5461_8ead, 0x1503_1726_7464_bc57, 0x32d1_501f_de63_dc93,\n        )\n\n    class LSH512_512(LSHBase):\n        word_bits = 64\n        ns = 28\n        block_size = 256\n        digest_size = 64\n        iv = (\n            0xadd5_0f3c_7f07_094e, 0xe3f3_cee8_f941_8a4f, 0xb527_ecde_5b3d_0ae9, 0x2ef6_dec6_8076_f501,\n            0x8cb9_94ca_e5ac_a216, 0xfbb9_eae4_bba4_8cc7, 0x650a_5261_7472_5fea, 0x1f9a_61a7_3f8d_8085,\n            0xb660_7378_173b_539b, 0x1bc9_9853_b0c0_b9ed, 0xdf72_7fc1_9b18_2d47, 0xdbef_360c_f893_a457,\n            0x4981_f5e5_7014_7e80, 0xd00c_4490_ca7d_3e30, 0x5d73_940c_0e4a_e1ec, 0x8940_85e2_edb2_d819,\n        )\n\n    class FugueBase:\n        state_words = 36  # Fugue-384/512: 36, Fugue-224/256: 30\n\n        @classmethod\n        def ensure_tables(cls):\n            if hasattr(Hash.FugueBase, \"T\"):\n                return\n\n            def rol8(x, n):\n                x &= 0xff\n                n &= 7\n                return ((x << n) | (x >> (8 - n))) & 0xff\n\n            def gf_mul(a, b):\n                a &= 0xff\n                b &= 0xff\n                res = 0\n                for _ in range(8):\n                    if b & 1:\n                        res ^= a\n                    hi = a & 0x80\n                    a = (a << 1) & 0xff\n                    if hi:\n                        a ^= 0x1b\n                    b >>= 1\n                return res & 0xff\n\n            def gf_pow(a, e):\n                res = 1\n                base = a & 0xff\n                while e:\n                    if e & 1:\n                        res = gf_mul(res, base)\n                    base = gf_mul(base, base)\n                    e >>= 1\n                return res & 0xff\n\n            def linear_map(U):\n                M = ((1, 4, 7, 1), (1, 1, 4, 7), (7, 1, 1, 4), (4, 7, 1, 1))\n                V = [[0] * 4 for _ in range(4)]\n                for i in range(4):\n                    for j in range(4):\n                        acc = 0\n                        for k in range(4):\n                            coeff = M[i][k]\n                            if coeff == 1:\n                                acc ^= U[k][j]\n                            else:\n                                acc ^= gf_mul(U[k][j], coeff)\n                        V[i][j] = acc & 0xff\n                d = [0] * 4\n                for i in range(4):\n                    acc = 0\n                    for j in range(4):\n                        if j != i:\n                            acc ^= U[i][j]\n                    d[i] = acc & 0xff\n                W = [[0] * 4 for _ in range(4)]\n                for i in range(4):\n                    for j in range(4):\n                        coeff = M[j][i]\n                        add = d[i] if coeff == 1 else gf_mul(d[i], coeff)\n                        W[i][j] = (V[i][j] ^ add) & 0xff\n                for i in range(4):\n                    n = i & 3\n                    if n:\n                        W[i] = W[i][n:] + W[i][:n]\n                y0 = ((W[0][0] << 24) | (W[1][0] << 16) | (W[2][0] << 8) | W[3][0]) & 0xffff_ffff\n                y1 = ((W[0][1] << 24) | (W[1][1] << 16) | (W[2][1] << 8) | W[3][1]) & 0xffff_ffff\n                y2 = ((W[0][2] << 24) | (W[1][2] << 16) | (W[2][2] << 8) | W[3][2]) & 0xffff_ffff\n                y3 = ((W[0][3] << 24) | (W[1][3] << 16) | (W[2][3] << 8) | W[3][3]) & 0xffff_ffff\n                return y0, y1, y2, y3\n\n            sbox = [0] * 256\n            for x in range(256):\n                inv = 0 if x == 0 else gf_pow(x, 254)\n                y = inv & 0xff\n                sb = (y ^ rol8(y, 1) ^ rol8(y, 2) ^ rol8(y, 3) ^ rol8(y, 4) ^ 0x63)\n                sbox[x] = sb & 0xff\n\n            Hash.FugueBase.sbox = sbox\n\n            T = [[[0 for _ in range(256)] for _ in range(4)] for _ in range(4)]\n            for c in range(4):\n                for r in range(4):\n                    for val in range(256):\n                        U = [[0]*4 for _ in range(4)]\n                        U[r][c] = sbox[val]\n                        y0, y1, y2, y3 = linear_map(U)\n                        T[c][r][val] = (y0 << 96) | (y1 << 64) | (y2 << 32) | y3\n\n            Hash.FugueBase.T = T\n            return\n\n        def __init__(self, data=b\"\"):\n            self.ensure_tables()\n            self.S = [0] * 36\n            self.bit_count = 0\n            self.partial = 0\n            self.partial_len = 0\n            self.rshift = 0\n            iv = self.init_val\n            if iv:\n                n = self.state_words\n                off = n - len(iv)\n                for i, v in enumerate(iv):\n                    self.S[off + i] = v & 0xffff_ffff\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.S = list(self.S)\n            other.bit_count = self.bit_count\n            other.partial = self.partial\n            other.partial_len = self.partial_len\n            other.rshift = self.rshift\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.bit_count = (\n                self.bit_count + ((len(data) & 0xffff_ffff_ffff_ffff) << 3)\n            ) & 0xffff_ffff_ffff_ffff\n            for b in data:\n                self.partial = ((self.partial << 8) | (b & 0xff)) & 0xffff_ffff\n                self.partial_len += 1\n                if self.partial_len == 4:\n                    self.process(self.partial)\n                    self.partial = 0\n                    self.partial_len = 0\n            return self\n\n        def finalize(self):\n            if self.partial_len != 0:\n                while self.partial_len < 4:\n                    self.partial = (self.partial << 8) & 0xffff_ffff\n                    self.partial_len += 1\n                self.process(self.partial)\n                self.partial = 0\n                self.partial_len = 0\n            high = (self.bit_count >> 32) & 0xffff_ffff\n            low = self.bit_count & 0xffff_ffff\n            self.process(high)\n            self.process(low)\n            out = bytearray(self.digest_size)\n            self.process_final(out)\n            return bytes(out)\n\n        def digest(self):\n            c = self.copy()\n            return c.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def ror(self, rc, length):\n            rc %= length\n            if rc == 0:\n                return\n            tmp = self.S[length - rc:length]\n            self.S[rc:length] = self.S[0:length - rc]\n            self.S[0:rc] = tmp\n            return\n\n        def cmix30(self):\n            S = self.S\n            S[0] ^= S[4]\n            S[1] ^= S[5]\n            S[2] ^= S[6]\n            S[15] ^= S[4]\n            S[16] ^= S[5]\n            S[17] ^= S[6]\n            for i in (0, 1, 2, 15, 16, 17):\n                S[i] &= 0xffff_ffff\n            return\n\n        def cmix36(self):\n            S = self.S\n            S[0] ^= S[4]\n            S[1] ^= S[5]\n            S[2] ^= S[6]\n            S[18] ^= S[4]\n            S[19] ^= S[5]\n            S[20] ^= S[6]\n            for i in (0, 1, 2, 18, 19, 20):\n                S[i] &= 0xffff_ffff\n            return\n\n        def smix(self, i0, i1, i2, i3):\n            S = self.S\n            x0 = S[i0]\n            x1 = S[i1]\n            x2 = S[i2]\n            x3 = S[i3]\n\n            Tp = self.T\n\n            out = Tp[0][0][(x0 >> 24) & 0xff]\n            out ^= Tp[0][1][(x0 >> 16) & 0xff]\n            out ^= Tp[0][2][(x0 >> 8) & 0xff]\n            out ^= Tp[0][3][x0 & 0xff]\n\n            out ^= Tp[1][0][(x1 >> 24) & 0xff]\n            out ^= Tp[1][1][(x1 >> 16) & 0xff]\n            out ^= Tp[1][2][(x1 >> 8) & 0xff]\n            out ^= Tp[1][3][x1 & 0xff]\n\n            out ^= Tp[2][0][(x2 >> 24) & 0xff]\n            out ^= Tp[2][1][(x2 >> 16) & 0xff]\n            out ^= Tp[2][2][(x2 >> 8) & 0xff]\n            out ^= Tp[2][3][x2 & 0xff]\n\n            out ^= Tp[3][0][(x3 >> 24) & 0xff]\n            out ^= Tp[3][1][(x3 >> 16) & 0xff]\n            out ^= Tp[3][2][(x3 >> 8) & 0xff]\n            out ^= Tp[3][3][x3 & 0xff]\n\n            S[i0] = (out >> 96) & 0xffff_ffff\n            S[i1] = (out >> 64) & 0xffff_ffff\n            S[i2] = (out >> 32) & 0xffff_ffff\n            S[i3] = out & 0xffff_ffff\n            return\n\n        def process_final_common(self, out, state_len, init_rot_mul, cmix_fn, pre_rounds, loop_steps, final_xors, out_words):\n\n            def xor_from_zero(indices):\n                s0 = self.S[0]\n                for idx in indices:\n                    self.S[idx] ^= s0\n                return\n\n            def encode_words(out, indices):\n                for pos, idx in enumerate(indices):\n                    off = pos * 4\n                    if off >= len(out):\n                        break\n                    x = self.S[idx]\n                    out[off + 0] = (x >> 24) & 0xff\n                    out[off + 1] = (x >> 16) & 0xff\n                    out[off + 2] = (x >> 8) & 0xff\n                    out[off + 3] = x & 0xff\n                return\n\n            self.ror(init_rot_mul * self.rshift, state_len)\n\n            for _ in range(pre_rounds):\n                self.ror(3, state_len)\n                cmix_fn()\n                self.smix(0, 1, 2, 3)\n\n            for _ in range(13):\n                for xor_indices, rot in loop_steps:\n                    xor_from_zero(xor_indices)\n                    self.ror(rot, state_len)\n                    self.smix(0, 1, 2, 3)\n\n            xor_from_zero(final_xors)\n            encode_words(out, out_words)\n            return\n\n    class FugueCore30(FugueBase):\n        state_words = 30\n\n        def process(self, w):\n            S = self.S\n            w &= 0xffff_ffff\n            rs = self.rshift\n\n            if rs == 1:\n                S[4] ^= S[24]\n                S[24] = w\n                S[2] ^= S[24]\n                S[25] ^= S[18]\n                S[21] ^= S[25]\n                S[22] ^= S[26]\n                S[23] ^= S[27]\n                S[6] ^= S[25]\n                S[7] ^= S[26]\n                S[8] ^= S[27]\n                self.smix(21, 22, 23, 24)\n                S[18] ^= S[22]\n                S[19] ^= S[23]\n                S[20] ^= S[24]\n                S[3] ^= S[22]\n                S[4] ^= S[23]\n                S[5] ^= S[24]\n                self.smix(18, 19, 20, 21)\n                self.rshift = 2\n\n            elif rs == 2:\n                S[28] ^= S[18]\n                S[18] = w\n                S[26] ^= S[18]\n                S[19] ^= S[12]\n                S[15] ^= S[19]\n                S[16] ^= S[20]\n                S[17] ^= S[21]\n                S[0] ^= S[19]\n                S[1] ^= S[20]\n                S[2] ^= S[21]\n                self.smix(15, 16, 17, 18)\n                S[12] ^= S[16]\n                S[13] ^= S[17]\n                S[14] ^= S[18]\n                S[27] ^= S[16]\n                S[28] ^= S[17]\n                S[29] ^= S[18]\n                self.smix(12, 13, 14, 15)\n                self.rshift = 3\n\n            elif rs == 3:\n                S[22] ^= S[12]\n                S[12] = w\n                S[20] ^= S[12]\n                S[13] ^= S[6]\n                S[9] ^= S[13]\n                S[10] ^= S[14]\n                S[11] ^= S[15]\n                S[24] ^= S[13]\n                S[25] ^= S[14]\n                S[26] ^= S[15]\n                self.smix(9, 10, 11, 12)\n                S[6] ^= S[10]\n                S[7] ^= S[11]\n                S[8] ^= S[12]\n                S[21] ^= S[10]\n                S[22] ^= S[11]\n                S[23] ^= S[12]\n                self.smix(6, 7, 8, 9)\n                self.rshift = 4\n\n            elif rs == 4:\n                S[16] ^= S[6]\n                S[6] = w\n                S[14] ^= S[6]\n                S[7] ^= S[0]\n                S[3] ^= S[7]\n                S[4] ^= S[8]\n                S[5] ^= S[9]\n                S[18] ^= S[7]\n                S[19] ^= S[8]\n                S[20] ^= S[9]\n                self.smix(3, 4, 5, 6)\n                S[0] ^= S[4]\n                S[1] ^= S[5]\n                S[2] ^= S[6]\n                S[15] ^= S[4]\n                S[16] ^= S[5]\n                S[17] ^= S[6]\n                self.smix(0, 1, 2, 3)\n                self.rshift = 0\n\n            else:\n                S[10] ^= S[0]\n                S[0] = w\n                S[8] ^= S[0]\n                S[1] ^= S[24]\n                S[27] ^= S[1]\n                S[28] ^= S[2]\n                S[29] ^= S[3]\n                S[12] ^= S[1]\n                S[13] ^= S[2]\n                S[14] ^= S[3]\n                self.smix(27, 28, 29, 0)\n                S[24] ^= S[28]\n                S[25] ^= S[29]\n                S[26] ^= S[0]\n                S[9] ^= S[28]\n                S[10] ^= S[29]\n                S[11] ^= S[0]\n                self.smix(24, 25, 26, 27)\n                self.rshift = 1\n            return\n\n        FINAL_LOOP_STEPS = (\n            ((4, 15), 15),\n            ((4, 16), 14),\n        )\n        FINAL_XORS = (4, 15)\n        FINAL_OUT_WORDS = (1, 2, 3, 4, 15, 16, 17, 18)\n\n        def process_final(self, out):\n            self.process_final_common(\n                out=out,\n                state_len=30,\n                init_rot_mul=6,\n                cmix_fn=self.cmix30,\n                pre_rounds=10,\n                loop_steps=self.FINAL_LOOP_STEPS,\n                final_xors=self.FINAL_XORS,\n                out_words=self.FINAL_OUT_WORDS,\n            )\n            return\n\n    class Fugue224(FugueCore30):\n        block_size = 28\n        digest_size = 28\n        init_val = (\n            0xf4c9_120d, 0x6286_f757, 0xee39_e01c, 0xe074_e3cb, 0xa112_7c62, 0x9a43_d215, 0xbd8d_679a,\n        )\n\n    class Fugue256(FugueCore30):\n        block_size = 32\n        digest_size = 32\n        init_val = (\n            0xe952_bdde, 0x6671_135f, 0xe0d4_f668, 0xd2b0_b594, 0xf96c_621d, 0xfbf9_29de, 0x9149_e899, 0x34f8_c248,\n        )\n\n    class Fugue384(FugueBase):\n        block_size = 48\n        digest_size = 48\n        init_val = (\n            0xaa61_ec0d, 0x3125_2e1f, 0xa01d_b4c7, 0x0060_0985, 0x215e_f44a, 0x741b_5e9c, 0xfa69_3e9a, 0x473e_b040,\n            0xe502_ae8a, 0xa99c_25e0, 0xbc95_517c, 0x5c10_95a1,\n        )\n\n        def process(self, w):\n            S = self.S\n            w &= 0xffff_ffff\n            rs = self.rshift\n\n            if rs == 1:\n                S[7] ^= S[27]\n                S[27] = w\n                S[35] ^= S[27]\n                S[28] ^= S[18]\n                S[31] ^= S[21]\n                S[24] ^= S[28]\n                S[25] ^= S[29]\n                S[26] ^= S[30]\n                S[6] ^= S[28]\n                S[7] ^= S[29]\n                S[8] ^= S[30]\n                self.smix(24, 25, 26, 27)\n                S[21] ^= S[25]\n                S[22] ^= S[26]\n                S[23] ^= S[27]\n                S[3] ^= S[25]\n                S[4] ^= S[26]\n                S[5] ^= S[27]\n                self.smix(21, 22, 23, 24)\n                S[18] ^= S[22]\n                S[19] ^= S[23]\n                S[20] ^= S[24]\n                S[0] ^= S[22]\n                S[1] ^= S[23]\n                S[2] ^= S[24]\n                self.smix(18, 19, 20, 21)\n                self.rshift = 2\n\n            elif rs == 2:\n                S[34] ^= S[18]\n                S[18] = w\n                S[26] ^= S[18]\n                S[19] ^= S[9]\n                S[22] ^= S[12]\n                S[15] ^= S[19]\n                S[16] ^= S[20]\n                S[17] ^= S[21]\n                S[33] ^= S[19]\n                S[34] ^= S[20]\n                S[35] ^= S[21]\n                self.smix(15, 16, 17, 18)\n                S[12] ^= S[16]\n                S[13] ^= S[17]\n                S[14] ^= S[18]\n                S[30] ^= S[16]\n                S[31] ^= S[17]\n                S[32] ^= S[18]\n                self.smix(12, 13, 14, 15)\n                S[9] ^= S[13]\n                S[10] ^= S[14]\n                S[11] ^= S[15]\n                S[27] ^= S[13]\n                S[28] ^= S[14]\n                S[29] ^= S[15]\n                self.smix(9, 10, 11, 12)\n                self.rshift = 3\n\n            elif rs == 3:\n                S[25] ^= S[9]\n                S[9] = w\n                S[17] ^= S[9]\n                S[10] ^= S[0]\n                S[13] ^= S[3]\n                S[6] ^= S[10]\n                S[7] ^= S[11]\n                S[8] ^= S[12]\n                S[24] ^= S[10]\n                S[25] ^= S[11]\n                S[26] ^= S[12]\n                self.smix(6, 7, 8, 9)\n                S[3] ^= S[7]\n                S[4] ^= S[8]\n                S[5] ^= S[9]\n                S[21] ^= S[7]\n                S[22] ^= S[8]\n                S[23] ^= S[9]\n                self.smix(3, 4, 5, 6)\n                S[0] ^= S[4]\n                S[1] ^= S[5]\n                S[2] ^= S[6]\n                S[18] ^= S[4]\n                S[19] ^= S[5]\n                S[20] ^= S[6]\n                self.smix(0, 1, 2, 3)\n                self.rshift = 0\n\n            else:\n                S[16] ^= S[0]\n                S[0] = w\n                S[8] ^= S[0]\n                S[1] ^= S[27]\n                S[4] ^= S[30]\n                S[33] ^= S[1]\n                S[34] ^= S[2]\n                S[35] ^= S[3]\n                S[15] ^= S[1]\n                S[16] ^= S[2]\n                S[17] ^= S[3]\n                self.smix(33, 34, 35, 0)\n                S[30] ^= S[34]\n                S[31] ^= S[35]\n                S[32] ^= S[0]\n                S[12] ^= S[34]\n                S[13] ^= S[35]\n                S[14] ^= S[0]\n                self.smix(30, 31, 32, 33)\n                S[27] ^= S[31]\n                S[28] ^= S[32]\n                S[29] ^= S[33]\n                S[9] ^= S[31]\n                S[10] ^= S[32]\n                S[11] ^= S[33]\n                self.smix(27, 28, 29, 30)\n                self.rshift = 1\n            return\n\n        FINAL_LOOP_STEPS = (\n            ((4, 12, 24), 12),\n            ((4, 13, 24), 12),\n            ((4, 13, 25), 11),\n        )\n        FINAL_XORS = (4, 12, 24)\n        FINAL_OUT_WORDS = (1, 2, 3, 4, 12, 13, 14, 15, 24, 25, 26, 27)\n\n        def process_final(self, out):\n            self.process_final_common(\n                out=out,\n                state_len=36,\n                init_rot_mul=9,\n                cmix_fn=self.cmix36,\n                pre_rounds=18,\n                loop_steps=self.FINAL_LOOP_STEPS,\n                final_xors=self.FINAL_XORS,\n                out_words=self.FINAL_OUT_WORDS,\n            )\n            return\n\n    class Fugue512(FugueBase):\n        block_size = 64\n        digest_size = 64\n        init_val = (\n            0x8807_a57e, 0xe616_af75, 0xc5d3_e4db, 0xac9a_b027, 0xd915_f117, 0xb6ee_cc54, 0x06e8_020b, 0x4a92_efd1,\n            0xaac6_e2c9, 0xddb2_1398, 0xcae6_5838, 0x437f_203f, 0x25ea_78e7, 0x951f_ddd6, 0xda6e_d11d, 0xe13e_3567,\n        )\n\n        def process(self, w):\n            S = self.S\n            w &= 0xffff_ffff\n            rs = self.rshift\n\n            if rs == 1:\n                S[10] ^= S[24]\n                S[24] = w\n                S[32] ^= S[24]\n                S[25] ^= S[12]\n                S[28] ^= S[15]\n                S[31] ^= S[18]\n                S[21] ^= S[25]\n                S[22] ^= S[26]\n                S[23] ^= S[27]\n                S[3] ^= S[25]\n                S[4] ^= S[26]\n                S[5] ^= S[27]\n                self.smix(21, 22, 23, 24)\n                S[18] ^= S[22]\n                S[19] ^= S[23]\n                S[20] ^= S[24]\n                S[0] ^= S[22]\n                S[1] ^= S[23]\n                S[2] ^= S[24]\n                self.smix(18, 19, 20, 21)\n                S[15] ^= S[19]\n                S[16] ^= S[20]\n                S[17] ^= S[21]\n                S[33] ^= S[19]\n                S[34] ^= S[20]\n                S[35] ^= S[21]\n                self.smix(15, 16, 17, 18)\n                S[12] ^= S[16]\n                S[13] ^= S[17]\n                S[14] ^= S[18]\n                S[30] ^= S[16]\n                S[31] ^= S[17]\n                S[32] ^= S[18]\n                self.smix(12, 13, 14, 15)\n                self.rshift = 2\n\n            elif rs == 2:\n                S[34] ^= S[12]\n                S[12] = w\n                S[20] ^= S[12]\n                S[13] ^= S[0]\n                S[16] ^= S[3]\n                S[19] ^= S[6]\n                S[9] ^= S[13]\n                S[10] ^= S[14]\n                S[11] ^= S[15]\n                S[27] ^= S[13]\n                S[28] ^= S[14]\n                S[29] ^= S[15]\n                self.smix(9, 10, 11, 12)\n                S[6] ^= S[10]\n                S[7] ^= S[11]\n                S[8] ^= S[12]\n                S[24] ^= S[10]\n                S[25] ^= S[11]\n                S[26] ^= S[12]\n                self.smix(6, 7, 8, 9)\n                S[3] ^= S[7]\n                S[4] ^= S[8]\n                S[5] ^= S[9]\n                S[21] ^= S[7]\n                S[22] ^= S[8]\n                S[23] ^= S[9]\n                self.smix(3, 4, 5, 6)\n                S[0] ^= S[4]\n                S[1] ^= S[5]\n                S[2] ^= S[6]\n                S[18] ^= S[4]\n                S[19] ^= S[5]\n                S[20] ^= S[6]\n                self.smix(0, 1, 2, 3)\n                self.rshift = 0\n\n            else:\n                S[22] ^= S[0]\n                S[0] = w\n                S[8] ^= S[0]\n                S[1] ^= S[24]\n                S[4] ^= S[27]\n                S[7] ^= S[30]\n                S[33] ^= S[1]\n                S[34] ^= S[2]\n                S[35] ^= S[3]\n                S[15] ^= S[1]\n                S[16] ^= S[2]\n                S[17] ^= S[3]\n                self.smix(33, 34, 35, 0)\n                S[30] ^= S[34]\n                S[31] ^= S[35]\n                S[32] ^= S[0]\n                S[12] ^= S[34]\n                S[13] ^= S[35]\n                S[14] ^= S[0]\n                self.smix(30, 31, 32, 33)\n                S[27] ^= S[31]\n                S[28] ^= S[32]\n                S[29] ^= S[33]\n                S[9] ^= S[31]\n                S[10] ^= S[32]\n                S[11] ^= S[33]\n                self.smix(27, 28, 29, 30)\n                S[24] ^= S[28]\n                S[25] ^= S[29]\n                S[26] ^= S[30]\n                S[6] ^= S[28]\n                S[7] ^= S[29]\n                S[8] ^= S[30]\n                self.smix(24, 25, 26, 27)\n                self.rshift = 1\n            return\n\n        FINAL_LOOP_STEPS = (\n            ((4, 9, 18, 27), 9),\n            ((4, 10, 18, 27), 9),\n            ((4, 10, 19, 27), 9),\n            ((4, 10, 19, 28), 8),\n        )\n        FINAL_XORS = (4, 9, 18, 27)\n        FINAL_OUT_WORDS = (1, 2, 3, 4, 9, 10, 11, 12, 18, 19, 20, 21, 27, 28, 29, 30)\n\n        def process_final(self, out):\n            self.process_final_common(\n                out=out,\n                state_len=36,\n                init_rot_mul=12,\n                cmix_fn=self.cmix36,\n                pre_rounds=32,\n                loop_steps=self.FINAL_LOOP_STEPS,\n                final_xors=self.FINAL_XORS,\n                out_words=self.FINAL_OUT_WORDS,\n            )\n            return\n\n    class HamsiBase:\n        alpha_n = (\n            0xff00_f0f0, 0xcccc_aaaa, 0xf0f0_cccc, 0xff00_aaaa, 0xcccc_aaaa, 0xf0f0_ff00, 0xaaaa_cccc, 0xf0f0_ff00,\n            0xf0f0_cccc, 0xaaaa_ff00, 0xcccc_ff00, 0xaaaa_f0f0, 0xaaaa_f0f0, 0xff00_cccc, 0xcccc_f0f0, 0xff00_aaaa,\n            0xcccc_aaaa, 0xff00_f0f0, 0xff00_aaaa, 0xf0f0_cccc, 0xf0f0_ff00, 0xcccc_aaaa, 0xf0f0_ff00, 0xaaaa_cccc,\n            0xaaaa_ff00, 0xf0f0_cccc, 0xaaaa_f0f0, 0xcccc_ff00, 0xff00_cccc, 0xaaaa_f0f0, 0xff00_aaaa, 0xcccc_f0f0,\n        )\n        alpha_f = (\n            0xcaf9_639c, 0x0ff0_f9c0, 0x639c_0ff0, 0xcaf9_f9c0, 0x0ff0_f9c0, 0x639c_caf9, 0xf9c0_0ff0, 0x639c_caf9,\n            0x639c_0ff0, 0xf9c0_caf9, 0x0ff0_caf9, 0xf9c0_639c, 0xf9c0_639c, 0xcaf9_0ff0, 0x0ff0_639c, 0xcaf9_f9c0,\n            0x0ff0_f9c0, 0xcaf9_639c, 0xcaf9_f9c0, 0x639c_0ff0, 0x639c_caf9, 0x0ff0_f9c0, 0x639c_caf9, 0xf9c0_0ff0,\n            0xf9c0_caf9, 0x639c_0ff0, 0xf9c0_639c, 0x0ff0_caf9, 0xcaf9_0ff0, 0xf9c0_639c, 0xcaf9_f9c0, 0x0ff0_639c,\n        )\n        t256 = (\n            0x7495_1000, 0x5a2b_467e, 0x88fd_1d2b, 0x1ee6_8292, 0xcba9_0000, 0x9027_3769, 0xbbdc_f407, 0xd0f4_af61,\n            0xcba9_0000, 0x9027_3769, 0xbbdc_f407, 0xd0f4_af61, 0xbf3c_1000, 0xca0c_7117, 0x3321_e92c, 0xce12_2df3,\n            0xe92a_2000, 0xb457_8cfc, 0x11fa_3a57, 0x3dc9_0524, 0x9753_0000, 0x204f_6ed3, 0x77b9_e80f, 0xa1ec_5ec1,\n            0x9753_0000, 0x204f_6ed3, 0x77b9_e80f, 0xa1ec_5ec1, 0x7e79_2000, 0x9418_e22f, 0x6643_d258, 0x9c25_5be5,\n            0x121b_4000, 0x5b17_d9e8, 0x8dfa_cfab, 0xce36_cc72, 0xe657_0000, 0x4bb3_3a25, 0x8485_98ba, 0x1041_003e,\n            0xe657_0000, 0x4bb3_3a25, 0x8485_98ba, 0x1041_003e, 0xf44c_4000, 0x10a4_e3cd, 0x097f_5711, 0xde77_cc4c,\n            0xe478_8000, 0x8596_73c1, 0xb5fb_2452, 0x29cc_5edf, 0x045f_0000, 0x9c4a_93c9, 0x62fc_79d0, 0x731e_bdc2,\n            0x045f_0000, 0x9c4a_93c9, 0x62fc_79d0, 0x731e_bdc2, 0xe027_8000, 0x19dc_e008, 0xd707_5d82, 0x5ad2_e31d,\n            0xb7a4_0100, 0x8a1f_31d8, 0x8589_d8ab, 0xe6c4_6464, 0x734c_0000, 0x956f_a7d6, 0xa29d_1297, 0x6ee5_6854,\n            0x734c_0000, 0x956f_a7d6, 0xa29d_1297, 0x6ee5_6854, 0xc4e8_0100, 0x1f70_960e, 0x2714_ca3c, 0x8821_0c30,\n            0xa7b8_0200, 0x1f12_8433, 0x60e5_f9f2, 0x9e14_7576, 0xee26_0000, 0x124b_683e, 0x80c2_d68f, 0x3bf3_ab2c,\n            0xee26_0000, 0x124b_683e, 0x80c2_d68f, 0x3bf3_ab2c, 0x499e_0200, 0x0d59_ec0d, 0xe027_2f7d, 0xa5e7_de5a,\n            0x8f3e_0400, 0x0d9d_c877, 0x6fc5_48e1, 0x898d_2cd6, 0x14bd_0000, 0x2fba_37ff, 0x6a72_e5bb, 0x247f_ebe6,\n            0x14bd_0000, 0x2fba_37ff, 0x6a72_e5bb, 0x247f_ebe6, 0x9b83_0400, 0x2227_ff88, 0x05b7_ad5a, 0xadf2_c730,\n            0xde32_0800, 0x2883_50fe, 0x7185_2ac7, 0xa6bf_9f96, 0xe18b_0000, 0x5459_887d, 0xbf12_83d3, 0x1b66_6a73,\n            0xe18b_0000, 0x5459_887d, 0xbf12_83d3, 0x1b66_6a73, 0x3fb9_0800, 0x7cda_d883, 0xce97_a914, 0xbdd9_f5e5,\n            0x515c_0010, 0x40f3_72fb, 0xfce7_2602, 0x7157_5061, 0x2e39_0000, 0x64dd_6689, 0x3cd4_06fc, 0xb1f4_90bc,\n            0x2e39_0000, 0x64dd_6689, 0x3cd4_06fc, 0xb1f4_90bc, 0x7f65_0010, 0x242e_1472, 0xc033_20fe, 0xc0a3_c0dd,\n            0xa2b8_0020, 0x81e7_e5f6, 0xf9ce_4c04, 0xe2af_a0c0, 0x5c72_0000, 0xc9ba_cd12, 0x79a9_0df9, 0x63e9_2178,\n            0x5c72_0000, 0xc9ba_cd12, 0x79a9_0df9, 0x63e9_2178, 0xfeca_0020, 0x485d_28e4, 0x8067_41fd, 0x8146_81b8,\n            0x4dce_0040, 0x3b5b_ec7e, 0x3665_6ba8, 0x2363_3a05, 0x78ab_0000, 0xa0cd_5a34, 0x5d5c_a0f7, 0x7277_84cb,\n            0x78ab_0000, 0xa0cd_5a34, 0x5d5c_a0f7, 0x7277_84cb, 0x3565_0040, 0x9b96_b64a, 0x6b39_cb5f, 0x5114_bece,\n            0x5bd2_0080, 0x450f_18ec, 0xc2c4_6c55, 0xf362_b233, 0x39a6_0000, 0x4ab7_53eb, 0xd14e_094b, 0xb772_b42b,\n            0x39a6_0000, 0x4ab7_53eb, 0xd14e_094b, 0xb772_b42b, 0x6274_0080, 0x0fb8_4b07, 0x138a_651e, 0x4410_0618,\n            0xc04e_0001, 0x33b9_c010, 0xae0e_bb05, 0xb5a4_c63b, 0xc8f1_0000, 0x0b2d_e782, 0x6bf6_48a4, 0x539c_bdbf,\n            0xc8f1_0000, 0x0b2d_e782, 0x6bf6_48a4, 0x539c_bdbf, 0x08bf_0001, 0x3894_2792, 0xc5f8_f3a1, 0xe638_7b84,\n            0x8823_0002, 0x5fe7_a7b3, 0x99e5_85aa, 0x8d75_f7f1, 0x51ac_0000, 0x25e3_0f14, 0x79e2_2a4c, 0x1298_bd46,\n            0x51ac_0000, 0x25e3_0f14, 0x79e2_2a4c, 0x1298_bd46, 0xd98f_0002, 0x7a04_a8a7, 0xe007_afe6, 0x9fed_4ab7,\n            0xd008_0004, 0x8c76_8f77, 0x9dc5_b050, 0xaf4a_29da, 0x6ba9_0000, 0x40eb_f9aa, 0x9832_1c3d, 0x76ac_c733,\n            0x6ba9_0000, 0x40eb_f9aa, 0x9832_1c3d, 0x76ac_c733, 0xbba1_0004, 0xcc9d_76dd, 0x05f7_ac6d, 0xd9e6_eee9,\n            0xa8ae_0008, 0x2079_397d, 0xfe73_9301, 0xb8a9_2831, 0x171c_0000, 0xb26e_3344, 0x9e6a_837e, 0x58f8_485f,\n            0x171c_0000, 0xb26e_3344, 0x9e6a_837e, 0x58f8_485f, 0xbfb2_0008, 0x9217_0a39, 0x6019_107f, 0xe051_606e,\n        )\n        t512 = (\n            0xef0b_0270, 0x3afd_0000, 0x5dae_0000, 0x6949_0000, 0x9b0f_3c06, 0x4405_b5f9, 0x6614_0a51, 0x924f_5d0a,\n            0xc96b_0030, 0xe725_0000, 0x2f84_0000, 0x264f_0000, 0x0869_5bf9, 0x6dfc_f137, 0x509f_6984, 0x9e69_af68,\n            0xc96b_0030, 0xe725_0000, 0x2f84_0000, 0x264f_0000, 0x0869_5bf9, 0x6dfc_f137, 0x509f_6984, 0x9e69_af68,\n            0x2660_0240, 0xddd8_0000, 0x722a_0000, 0x4f06_0000, 0x9366_67ff, 0x29f9_44ce, 0x368b_63d5, 0x0c26_f262,\n            0x145a_3c00, 0xb9e9_0000, 0x6127_0000, 0xf161_0000, 0xce61_3d6c, 0xb049_3d78, 0x47a9_6720, 0xe18e_24c5,\n            0x2367_1400, 0xc8b9_0000, 0xf4c7_0000, 0xfb75_0000, 0x73cd_2465, 0xf8a6_a549, 0x02c4_0a3f, 0xdc24_e61f,\n            0x2367_1400, 0xc8b9_0000, 0xf4c7_0000, 0xfb75_0000, 0x73cd_2465, 0xf8a6_a549, 0x02c4_0a3f, 0xdc24_e61f,\n            0x373d_2800, 0x7150_0000, 0x95e0_0000, 0x0a14_0000, 0xbdac_1909, 0x48ef_9831, 0x456d_6d1f, 0x3daa_c2da,\n            0x5428_5c00, 0xeaed_0000, 0xc5d6_0000, 0xa1c5_0000, 0xb3a2_6770, 0x94a5_c4e1, 0x6bb0_419d, 0x551b_3782,\n            0x9cbb_1800, 0xb0d3_0000, 0x9251_0000, 0xed93_0000, 0x593a_4345, 0xe114_d5f4, 0x4306_33da, 0x78ca_ce29,\n            0x9cbb_1800, 0xb0d3_0000, 0x9251_0000, 0xed93_0000, 0x593a_4345, 0xe114_d5f4, 0x4306_33da, 0x78ca_ce29,\n            0xc893_4400, 0x5a3e_0000, 0x5787_0000, 0x4c56_0000, 0xea98_2435, 0x75b1_1115, 0x28b6_7247, 0x2dd1_f9ab,\n            0x2944_9c00, 0x64e7_0000, 0xf24b_0000, 0xc2f3_0000, 0x0ede_4e8f, 0x56c2_3745, 0xf3e0_4259, 0x8d0d_9ec4,\n            0x466d_0c00, 0x0862_0000, 0xdd5d_0000, 0xbadd_0000, 0x6a92_7942, 0x441f_2b93, 0x218a_ce6f, 0xbf2c_0be2,\n            0x466d_0c00, 0x0862_0000, 0xdd5d_0000, 0xbadd_0000, 0x6a92_7942, 0x441f_2b93, 0x218a_ce6f, 0xbf2c_0be2,\n            0x6f29_9000, 0x6c85_0000, 0x2f16_0000, 0x782e_0000, 0x644c_37cd, 0x12dd_1cd6, 0xd26a_8c36, 0x3221_9526,\n            0xf680_0005, 0x3443_c000, 0x2407_0000, 0x8f3d_0000, 0x2137_3bfb, 0x0ab8_d5ae, 0xcdc5_8b19, 0xd795_ba31,\n            0xa67f_0001, 0x7137_8000, 0x19fc_0000, 0x96db_0000, 0x3a8b_6dfd, 0xebca_aef3, 0x2c6d_478f, 0xac8e_6c88,\n            0xa67f_0001, 0x7137_8000, 0x19fc_0000, 0x96db_0000, 0x3a8b_6dfd, 0xebca_aef3, 0x2c6d_478f, 0xac8e_6c88,\n            0x50ff_0004, 0x4574_4000, 0x3dfb_0000, 0x19e6_0000, 0x1bbc_5606, 0xe172_7b5d, 0xe1a8_cc96, 0x7b1b_d6b9,\n            0xf775_0009, 0xcf3c_c000, 0xc3d6_0000, 0x0492_0000, 0x0295_19a9, 0xf8e8_36ba, 0x7a87_f14e, 0x9e16_981a,\n            0xd46a_0000, 0x8dc8_c000, 0xa5af_0000, 0x4a29_0000, 0xfc4e_427a, 0xc9b4_866c, 0x9836_9604, 0xf746_c320,\n            0xd46a_0000, 0x8dc8_c000, 0xa5af_0000, 0x4a29_0000, 0xfc4e_427a, 0xc9b4_866c, 0x9836_9604, 0xf746_c320,\n            0x231f_0009, 0x42f4_0000, 0x6679_0000, 0x4ebb_0000, 0xfedb_5bd3, 0x315c_b0d6, 0xe2b1_674a, 0x6950_5b3a,\n            0x7744_00f0, 0xf15a_0000, 0xf5b2_0000, 0x3414_0000, 0x8937_7e8c, 0x5a8b_ec25, 0x0bc3_cd1e, 0xcf37_75cb,\n            0xf46c_0050, 0x9618_0000, 0x14a5_0000, 0x031f_0000, 0x4294_7eb8, 0x66bf_7e19, 0x9ca4_70d2, 0x8a34_1574,\n            0xf46c_0050, 0x9618_0000, 0x14a5_0000, 0x031f_0000, 0x4294_7eb8, 0x66bf_7e19, 0x9ca4_70d2, 0x8a34_1574,\n            0x8328_00a0, 0x6742_0000, 0xe117_0000, 0x370b_0000, 0xcba3_0034, 0x3c34_923c, 0x9767_bdcc, 0x4503_60bf,\n            0xe887_0170, 0x9d72_0000, 0x12db_0000, 0xd422_0000, 0xf288_6b27, 0xa921_e543, 0x4ef8_b518, 0x6188_13b1,\n            0xb437_0060, 0x0c4c_0000, 0x56c2_0000, 0x5cae_0000, 0x9454_1f3f, 0x3b3e_f825, 0x1b36_5f3d, 0xf3d4_5758,\n            0xb437_0060, 0x0c4c_0000, 0x56c2_0000, 0x5cae_0000, 0x9454_1f3f, 0x3b3e_f825, 0x1b36_5f3d, 0xf3d4_5758,\n            0x5cb0_0110, 0x913e_0000, 0x4419_0000, 0x888c_0000, 0x66dc_7418, 0x921f_1d66, 0x55ce_ea25, 0x925c_44e9,\n            0x0c72_0000, 0x49e5_0f00, 0x4279_0000, 0x5cea_0000, 0x33aa_301a, 0x1582_2514, 0x95a3_4b7b, 0xb44b_0090,\n            0xfe22_0000, 0xa758_0500, 0x25d1_0000, 0xf760_0000, 0x8931_78da, 0x1fd4_f860, 0x4ed0_a315, 0xa123_ff9f,\n            0xfe22_0000, 0xa758_0500, 0x25d1_0000, 0xf760_0000, 0x8931_78da, 0x1fd4_f860, 0x4ed0_a315, 0xa123_ff9f,\n            0xf250_0000, 0xeebd_0a00, 0x67a8_0000, 0xab8a_0000, 0xba9b_48c0, 0x0a56_dd74, 0xdb73_e86e, 0x1568_ff0f,\n            0x4518_0000, 0xa5b5_1700, 0xf96a_0000, 0x3b48_0000, 0x1ecc_142c, 0x2313_95d6, 0x16bc_a6b0, 0xdf33_f4df,\n            0xb83d_0000, 0x1671_0600, 0x379a_0000, 0xf5b1_0000, 0x2281_61ac, 0xae48_f145, 0x6624_1616, 0xc5c1_eb3e,\n            0xb83d_0000, 0x1671_0600, 0x379a_0000, 0xf5b1_0000, 0x2281_61ac, 0xae48_f145, 0x6624_1616, 0xc5c1_eb3e,\n            0xfd25_0000, 0xb3c4_1100, 0xcef0_0000, 0xcef9_0000, 0x3c4d_7580, 0x8d5b_6493, 0x7098_b0a6, 0x1af2_1fe1,\n            0x75a4_0000, 0xc28b_2700, 0x94a4_0000, 0x90f5_0000, 0xfb78_57e0, 0x49ce_0bae, 0x1767_c483, 0xaedf_667e,\n            0xd166_0000, 0x1bbc_0300, 0x9eec_0000, 0xf694_0000, 0x0302_4527, 0xcf70_fcf2, 0xb443_1b17, 0x857f_3c2b,\n            0xd166_0000, 0x1bbc_0300, 0x9eec_0000, 0xf694_0000, 0x0302_4527, 0xcf70_fcf2, 0xb443_1b17, 0x857f_3c2b,\n            0xa4c2_0000, 0xd937_2400, 0x0a48_0000, 0x6661_0000, 0xf87a_12c7, 0x86be_f75c, 0xa324_df94, 0x2ba0_5a55,\n            0x75c9_0003, 0x0e10_c000, 0xd120_0000, 0xbaea_0000, 0x8bc4_2f3e, 0x8758_b757, 0xbb28_761d, 0x00b7_2e2b,\n            0xeecf_0001, 0x6f56_4000, 0xf33e_0000, 0xa79e_0000, 0xbdb5_7219, 0xb711_ebc5, 0x4a3b_40ba, 0xfeab_f254,\n            0xeecf_0001, 0x6f56_4000, 0xf33e_0000, 0xa79e_0000, 0xbdb5_7219, 0xb711_ebc5, 0x4a3b_40ba, 0xfeab_f254,\n            0x9b06_0002, 0x6146_8000, 0x221e_0000, 0x1d74_0000, 0x3671_5d27, 0x3049_5c92, 0xf113_36a7, 0xfe1c_dc7f,\n            0x8679_0000, 0x3f39_0002, 0xe19a_e000, 0x9856_0000, 0x9565_670e, 0x4e88_c8ea, 0xd3dd_4944, 0x161d_dab9,\n            0x30b7_0000, 0xe5d0_0000, 0xf4f4_6000, 0x42c4_0000, 0x63b8_3d6a, 0x78ba_9460, 0x21af_a1ea, 0xb0a5_1834,\n            0x30b7_0000, 0xe5d0_0000, 0xf4f4_6000, 0x42c4_0000, 0x63b8_3d6a, 0x78ba_9460, 0x21af_a1ea, 0xb0a5_1834,\n            0xb6ce_0000, 0xdae9_0002, 0x156e_8000, 0xda92_0000, 0xf6dd_5a64, 0x3632_5c8a, 0xf272_e8ae, 0xa6b8_c28d,\n            0x1419_0000, 0x23ca_003c, 0x50df_0000, 0x44b6_0000, 0x1b6c_67b0, 0x3cf3_ac75, 0x61e6_10b0, 0xdbca_db80,\n            0xe343_0000, 0x3a4e_0014, 0xf2c6_0000, 0xaa4e_0000, 0xdb1e_42a6, 0x256b_be15, 0x123d_b156, 0x3a4e_99d7,\n            0xe343_0000, 0x3a4e_0014, 0xf2c6_0000, 0xaa4e_0000, 0xdb1e_42a6, 0x256b_be15, 0x123d_b156, 0x3a4e_99d7,\n            0xf75a_0000, 0x1984_0028, 0xa219_0000, 0xeef8_0000, 0xc072_2516, 0x1998_1260, 0x73db_a1e6, 0xe184_4257,\n            0x5450_0000, 0x0671_005c, 0x25ae_0000, 0x6a1e_0000, 0x2ea5_4edf, 0x664e_8512, 0xbfba_18c3, 0x7e71_5d17,\n            0xbc8d_0000, 0xfc3b_0018, 0x1983_0000, 0xd10b_0000, 0xae18_78c4, 0x42a6_9856, 0x0012_da37, 0x2c3b_504e,\n            0xbc8d_0000, 0xfc3b_0018, 0x1983_0000, 0xd10b_0000, 0xae18_78c4, 0x42a6_9856, 0x0012_da37, 0x2c3b_504e,\n            0xe8dd_0000, 0xfa4a_0044, 0x3c2d_0000, 0xbb15_0000, 0x80bd_361b, 0x24e8_1d44, 0xbfa8_c2f4, 0x524a_0d59,\n            0x6951_0000, 0xd4e1_009c, 0xc323_0000, 0xac2f_0000, 0xe495_0bae, 0xcea4_15dc, 0x87ec_287c, 0xbce1_a3ce,\n            0xc673_0000, 0xaf8d_000c, 0xa4c1_0000, 0x218d_0000, 0x2311_1587, 0x7913_512f, 0x1d28_ac88, 0x378d_d173,\n            0xc673_0000, 0xaf8d_000c, 0xa4c1_0000, 0x218d_0000, 0x2311_1587, 0x7913_512f, 0x1d28_ac88, 0x378d_d173,\n            0xaf22_0000, 0x7b6c_0090, 0x67e2_0000, 0x8da2_0000, 0xc784_1e29, 0xb7b7_44f3, 0x9ac4_84f4, 0x8b6c_72bd,\n            0xcc14_0000, 0xa563_0000, 0x5ab9_0780, 0x3b50_0000, 0x4bd0_13ff, 0x879b_3418, 0x6943_48c1, 0xca5a_87fe,\n            0x819e_0000, 0xec57_0000, 0x6632_0280, 0x95f3_0000, 0x5da9_2802, 0x48f4_3cbc, 0xe65a_a22d, 0x8e67_b7fa,\n            0x819e_0000, 0xec57_0000, 0x6632_0280, 0x95f3_0000, 0x5da9_2802, 0x48f4_3cbc, 0xe65a_a22d, 0x8e67_b7fa,\n            0x4d8a_0000, 0x4934_0000, 0x3c8b_0500, 0xaea3_0000, 0x1679_3bfd, 0xcf6f_08a4, 0x8f19_eaec, 0x443d_3004,\n            0x7823_0000, 0x12fc_0000, 0xa93a_0b80, 0x90a5_0000, 0x713e_2879, 0x7ee9_8924, 0xf08c_a062, 0x636f_8bab,\n            0x02af_0000, 0xb728_0000, 0xba1c_0300, 0x5698_0000, 0xba8d_45d3, 0x8048_c667, 0xa95c_149a, 0xf4f6_ea7b,\n            0x02af_0000, 0xb728_0000, 0xba1c_0300, 0x5698_0000, 0xba8d_45d3, 0x8048_c667, 0xa95c_149a, 0xf4f6_ea7b,\n            0x7a8c_0000, 0xa5d4_0000, 0x1326_0880, 0xc63d_0000, 0xcbb3_6daa, 0xfea1_4f43, 0x59d0_b4f8, 0x9799_61d0,\n            0xac48_0000, 0x1ba6_0000, 0x45fb_1380, 0x0343_0000, 0x5a85_316a, 0x1fb2_50b6, 0xfe72_c7fe, 0x91e4_78f6,\n            0x1e4e_0000, 0xdecf_0000, 0x6df8_0180, 0x7724_0000, 0xec47_079e, 0xf4a0_694e, 0xcda3_1812, 0x98aa_496e,\n            0x1e4e_0000, 0xdecf_0000, 0x6df8_0180, 0x7724_0000, 0xec47_079e, 0xf4a0_694e, 0xcda3_1812, 0x98aa_496e,\n            0xb206_0000, 0xc569_0000, 0x2803_1200, 0x7467_0000, 0xb6c2_36f4, 0xeb12_39f8, 0x33d1_dfec, 0x094e_3198,\n            0xaec3_0000, 0x9c4f_0001, 0x79d1_e000, 0x2c15_0000, 0x45cc_75b3, 0x6650_b736, 0xab92_f78f, 0xa312_567b,\n            0xdb25_0000, 0x0929_0000, 0x49aa_c000, 0x81e1_0000, 0xcafe_6b59, 0x4279_3431, 0x4356_6b76, 0xe86c_ba2e,\n            0xdb25_0000, 0x0929_0000, 0x49aa_c000, 0x81e1_0000, 0xcafe_6b59, 0x4279_3431, 0x4356_6b76, 0xe86c_ba2e,\n            0x75e6_0000, 0x9566_0001, 0x307b_2000, 0xadf4_0000, 0x8f32_1eea, 0x2429_8307, 0xe8c4_9cf9, 0x4b7e_ec55,\n            0x5843_0000, 0x807e_0000, 0x7833_0001, 0xc66b_3800, 0xe737_5cdc, 0x79ad_3fdd, 0xac73_fe6f, 0x3a44_79b1,\n            0x1d5a_0000, 0x2b72_0000, 0x488d_0000, 0xaf61_1800, 0x25cb_2ec5, 0xc879_bfd0, 0x81a2_0429, 0x1e75_36a6,\n            0x1d5a_0000, 0x2b72_0000, 0x488d_0000, 0xaf61_1800, 0x25cb_2ec5, 0xc879_bfd0, 0x81a2_0429, 0x1e75_36a6,\n            0x4519_0000, 0xab0c_0000, 0x30be_0001, 0x690a_2000, 0xc2fc_7219, 0xb1d4_800d, 0x2dd1_fa46, 0x2431_4f17,\n            0xa53b_0000, 0x1426_0000, 0x4e30_001e, 0x7cae_0000, 0x8f9e_0dd5, 0x78df_aa3d, 0xf731_68d8, 0x0b1b_4946,\n            0x07ed_0000, 0xb250_0000, 0x8774_000a, 0x970d_0000, 0x4372_23ae, 0x48c7_6ea4, 0xf478_6222, 0x9075_b1ce,\n            0x07ed_0000, 0xb250_0000, 0x8774_000a, 0x970d_0000, 0x4372_23ae, 0x48c7_6ea4, 0xf478_6222, 0x9075_b1ce,\n            0xa2d6_0000, 0xa676_0000, 0xc944_0014, 0xeba3_0000, 0xccec_2e7b, 0x3018_c499, 0x0349_0afa, 0x9b6e_f888,\n            0x8898_0000, 0x1f94_0000, 0x7fcf_002e, 0xfb4e_0000, 0xf158_079a, 0x61ae_9167, 0xa895_706c, 0xe610_7494,\n            0x0bc2_0000, 0xdb63_0000, 0x7e88_000c, 0x1586_0000, 0x91fd_48f3, 0x7581_bb43, 0xf460_449e, 0xd8b6_1463,\n            0x0bc2_0000, 0xdb63_0000, 0x7e88_000c, 0x1586_0000, 0x91fd_48f3, 0x7581_bb43, 0xf460_449e, 0xd8b6_1463,\n            0x835a_0000, 0xc4f7_0000, 0x0147_0022, 0xeec8_0000, 0x60a5_4f69, 0x142f_2a24, 0x5cf5_34f2, 0x3ea6_60f7,\n            0x5250_0000, 0x2954_0000, 0x6a61_004e, 0xf0ff_0000, 0x9a31_7eec, 0x4523_41ce, 0xcf56_8fe5, 0x5303_130f,\n            0x538d_0000, 0xa9fc_0000, 0x9ef7_0006, 0x56ff_0000, 0x0ae4_004e, 0x92c5_cdf9, 0xa944_4018, 0x7f97_5691,\n            0x538d_0000, 0xa9fc_0000, 0x9ef7_0006, 0x56ff_0000, 0x0ae4_004e, 0x92c5_cdf9, 0xa944_4018, 0x7f97_5691,\n            0x01dd_0000, 0x80a8_0000, 0xf496_0048, 0xa600_0000, 0x90d5_7ea2, 0xd7e6_8c37, 0x6612_cffd, 0x2c94_459e,\n            0xe628_0000, 0x4c4b_0000, 0xa855_0000, 0xd3d0_02e0, 0xd861_30b8, 0x98a7_b0da, 0x2895_06b4, 0xd75a_4897,\n            0xf0c5_0000, 0x5923_0000, 0x4582_0000, 0xe18d_00c0, 0x3b6d_0631, 0xc2ed_5699, 0xcbe0_fe1c, 0x56a7_b19f,\n            0xf0c5_0000, 0x5923_0000, 0x4582_0000, 0xe18d_00c0, 0x3b6d_0631, 0xc2ed_5699, 0xcbe0_fe1c, 0x56a7_b19f,\n            0x16ed_0000, 0x1568_0000, 0xedd7_0000, 0x325d_0220, 0xe30c_3689, 0x5a4a_e643, 0xe375_f8a8, 0x81fd_f908,\n            0xb431_0000, 0x7733_0000, 0xb15d_0000, 0x7fd0_04e0, 0x78a2_6138, 0xd116_c35d, 0xd256_d489, 0x4e6f_74de,\n            0xe306_0000, 0xbdc1_0000, 0x8713_0000, 0xbff2_0060, 0x2eba_0a1a, 0x8db5_3751, 0x73c5_ab06, 0x5bd6_1539,\n            0xe306_0000, 0xbdc1_0000, 0x8713_0000, 0xbff2_0060, 0x2eba_0a1a, 0x8db5_3751, 0x73c5_ab06, 0x5bd6_1539,\n            0x5737_0000, 0xcaf2_0000, 0x364e_0000, 0xc022_0480, 0x5618_6b22, 0x5ca3_f40c, 0xa193_7f8f, 0x15b9_61e7,\n            0x02f2_0000, 0xa281_0000, 0x873f_0000, 0xe36c_7800, 0x1e1d_74ef, 0x073d_2bd6, 0xc4c2_3237, 0x7f32_259e,\n            0xbadd_0000, 0x13ad_0000, 0xb7e7_0000, 0xf728_2800, 0xdf45_144d, 0x361a_c33a, 0xea5a_8d14, 0x2a2c_18f0,\n            0xbadd_0000, 0x13ad_0000, 0xb7e7_0000, 0xf728_2800, 0xdf45_144d, 0x361a_c33a, 0xea5a_8d14, 0x2a2c_18f0,\n            0xb82f_0000, 0xb12c_0000, 0x30d8_0000, 0x1444_5000, 0xc158_60a2, 0x3127_e8ec, 0x2e98_bf23, 0x551e_3d6e,\n            0x1e6c_0000, 0xc442_0000, 0x8a2e_0000, 0xbcb6_b800, 0x2c44_13b6, 0x8bfd_d3da, 0x6a0c_1bc8, 0xb99d_c2eb,\n            0x9256_0000, 0x1eda_0000, 0xea51_0000, 0xe8b1_3000, 0xa935_56a5, 0xebfb_6199, 0xb15c_2254, 0x33c5_244f,\n            0x9256_0000, 0x1eda_0000, 0xea51_0000, 0xe8b1_3000, 0xa935_56a5, 0xebfb_6199, 0xb15c_2254, 0x33c5_244f,\n            0x8c3a_0000, 0xda98_0000, 0x607f_0000, 0x5407_8800, 0x8571_4513, 0x6006_b243, 0xdb50_399c, 0x8a58_e6a4,\n            0x033d_0000, 0x08b3_0000, 0xf33a_0000, 0x3ac2_0007, 0x5129_8a50, 0x6b6e_661f, 0x0ea5_cfe3, 0xe6da_7ffe,\n            0xa8da_0000, 0x96be_0000, 0x5c1d_0000, 0x07da_0002, 0x7d66_9583, 0x1f98_708a, 0xbb66_8808, 0xda87_8000,\n            0xa8da_0000, 0x96be_0000, 0x5c1d_0000, 0x07da_0002, 0x7d66_9583, 0x1f98_708a, 0xbb66_8808, 0xda87_8000,\n            0xabe7_0000, 0x9e0d_0000, 0xaf27_0000, 0x3d18_0005, 0x2c4f_1fd3, 0x74f6_1695, 0xb5c3_47eb, 0x3c5d_fffe,\n            0x0193_0000, 0xe782_0000, 0xedfb_0000, 0xcf0c_000b, 0x8dd0_8d58, 0xbca3_b42e, 0x0636_61e1, 0x536f_9e7b,\n            0x9228_0000, 0xdc85_0000, 0x57fa_0000, 0x56dc_0003, 0xbae9_2316, 0x5aef_a30c, 0x90ce_f752, 0x7b16_75d7,\n            0x9228_0000, 0xdc85_0000, 0x57fa_0000, 0x56dc_0003, 0xbae9_2316, 0x5aef_a30c, 0x90ce_f752, 0x7b16_75d7,\n            0x93bb_0000, 0x3b07_0000, 0xba01_0000, 0x99d0_0008, 0x3739_ae4e, 0xe64c_1722, 0x96f8_96b3, 0x2879_ebac,\n            0x5fa8_0000, 0x5603_0000, 0x43ae_0000, 0x64f3_0013, 0x257e_86bf, 0x1311_944e, 0x541e_95bf, 0x8ea4_db69,\n            0x0044_0000, 0x7f48_0000, 0xda7c_0000, 0x2a23_0001, 0x3bad_c9cc, 0xa9b6_9c87, 0x030a_9e60, 0xbe0a_679e,\n            0x0044_0000, 0x7f48_0000, 0xda7c_0000, 0x2a23_0001, 0x3bad_c9cc, 0xa9b6_9c87, 0x030a_9e60, 0xbe0a_679e,\n            0x5fec_0000, 0x294b_0000, 0x99d2_0000, 0x4ed0_0012, 0x1ed3_4f73, 0xbaa7_08c9, 0x5714_0bdf, 0x30ae_bcf7,\n            0xee93_0000, 0xd607_0000, 0x92c1_0000, 0x2b98_01e0, 0x9451_287c, 0x3b6c_fb57, 0x4531_2374, 0x201f_6a64,\n            0x7b28_0000, 0x5742_0000, 0xa9e5_0000, 0x6343_00a0, 0x9edb_442f, 0x6d99_95bb, 0x27f8_3b03, 0xc7ff_60f0,\n            0x7b28_0000, 0x5742_0000, 0xa9e5_0000, 0x6343_00a0, 0x9edb_442f, 0x6d99_95bb, 0x27f8_3b03, 0xc7ff_60f0,\n            0x95bb_0000, 0x8145_0000, 0x3b24_0000, 0x48db_0140, 0x0a8a_6c53, 0x56f5_6eec, 0x62c9_1877, 0xe7e0_0a94,\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n        #include <string.h>\n\n        static inline void sbox(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)\n        {\n            uint32_t t = *a;\n            *a = (*a & *c) ^ *d;\n            *c ^= *b;\n            *c ^= *a;\n            *d = (*d | t) ^ *b;\n            t ^= *c;\n            *b = *d;\n            *d = (*d | t) ^ *a;\n            *a &= *b;\n            t ^= *a;\n            *b ^= *d;\n            *b ^= t;\n            *a = *c;\n            *c = *b;\n            *b = *d;\n            *d = (~t) & 0xffffffffu;\n        }\n\n        static inline void linear(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)\n        {\n            *a = ((*a << 13) | (*a >> 19)) & 0xffffffffu;\n            *c = ((*c <<  3) | (*c >> 29)) & 0xffffffffu;\n            *b ^= *a ^ *c;\n            *d ^= *c ^ ((*a << 3) & 0xffffffffu);\n            *b = ((*b <<  1) | (*b >> 31)) & 0xffffffffu;\n            *d = ((*d <<  7) | (*d >> 25)) & 0xffffffffu;\n            *a ^= *b ^ *d;\n            *c ^= *d ^ ((*b << 7) & 0xffffffffu);\n            *a = ((*a <<  5) | (*a >> 27)) & 0xffffffffu;\n            *c = ((*c << 22) | (*c >> 10)) & 0xffffffffu;\n        }\n        void compress_small(\n            uint32_t *h, const uint8_t *block, int final_round, const uint32_t *alpha, const uint32_t *tables)\n        {\n            const uint32_t *t0 = tables + (size_t)block[0] * 8;\n            const uint32_t *t1 = tables + 256*8 + (size_t)block[1] * 8;\n            const uint32_t *t2 = tables + 512*8 + (size_t)block[2] * 8;\n            const uint32_t *t3 = tables + 768*8 + (size_t)block[3] * 8;\n            uint32_t m[8];\n            for (int i = 0; i < 8; i++)\n                m[i] = t0[i] ^ t1[i] ^ t2[i] ^ t3[i];\n\n            uint32_t s0  = m[0], s1  = m[1], s2  = h[0], s3  = h[1];\n            uint32_t s4  = h[2], s5  = h[3], s6  = m[2], s7  = m[3];\n            uint32_t s8  = m[4], s9  = m[5], s10 = h[4], s11 = h[5];\n            uint32_t s12 = h[6], s13 = h[7], s14 = m[6], s15 = m[7];\n\n            int rounds = final_round ? 6 : 3;\n\n            for (int rc = 0; rc < rounds; rc++) {\n                s0  ^= alpha[0x00]; s1  ^= alpha[0x01] ^ (uint32_t)rc;\n                s2  ^= alpha[0x02]; s3  ^= alpha[0x03];\n                s4  ^= alpha[0x08]; s5  ^= alpha[0x09];\n                s6  ^= alpha[0x0a]; s7  ^= alpha[0x0b];\n                s8  ^= alpha[0x10]; s9  ^= alpha[0x11];\n                s10 ^= alpha[0x12]; s11 ^= alpha[0x13];\n                s12 ^= alpha[0x18]; s13 ^= alpha[0x19];\n                s14 ^= alpha[0x1a]; s15 ^= alpha[0x1b];\n\n                sbox(&s0, &s4, &s8,  &s12);\n                sbox(&s1, &s5, &s9,  &s13);\n                sbox(&s2, &s6, &s10, &s14);\n                sbox(&s3, &s7, &s11, &s15);\n\n                linear(&s0, &s5, &s10, &s15);\n                linear(&s1, &s6, &s11, &s12);\n                linear(&s2, &s7, &s8,  &s13);\n                linear(&s3, &s4, &s9,  &s14);\n            }\n\n            h[0] ^= s0;\n            h[1] ^= s1;\n            h[2] ^= s2;\n            h[3] ^= s3;\n            h[4] ^= s8;\n            h[5] ^= s9;\n            h[6] ^= s10;\n            h[7] ^= s11;\n        }\n\n        void compress_big(\n            uint32_t *h, const uint8_t *block, int final_round, const uint32_t *alpha, const uint32_t *tables)\n        {\n            const size_t stride = 256 * 16;\n            const uint32_t *tt[8];\n            for (int i = 0; i < 8; i++)\n                tt[i] = tables + i * stride + (size_t)block[i] * 16;\n\n            uint32_t m[16];\n            for (int i = 0; i < 16; i++)\n                m[i] = tt[0][i] ^ tt[1][i] ^ tt[2][i] ^ tt[3][i]\n                     ^ tt[4][i] ^ tt[5][i] ^ tt[6][i] ^ tt[7][i];\n\n            uint32_t s00=m[0],  s01=m[1],  s02=h[0],  s03=h[1];\n            uint32_t s04=m[2],  s05=m[3],  s06=h[2],  s07=h[3];\n            uint32_t s08=h[4],  s09=h[5],  s0a=m[4],  s0b=m[5];\n            uint32_t s0c=h[6],  s0d=h[7],  s0e=m[6],  s0f=m[7];\n            uint32_t s10=m[8],  s11=m[9],  s12=h[8],  s13=h[9];\n            uint32_t s14=m[10], s15=m[11], s16=h[10], s17=h[11];\n            uint32_t s18=h[12], s19=h[13], s1a=m[12], s1b=m[13];\n            uint32_t s1c=h[14], s1d=h[15], s1e=m[14], s1f=m[15];\n\n            int rounds = final_round ? 12 : 6;\n\n            for (int rc = 0; rc < rounds; rc++) {\n                s00 ^= alpha[0x00]; s01 ^= alpha[0x01] ^ (uint32_t)rc;\n                s02 ^= alpha[0x02]; s03 ^= alpha[0x03];\n                s04 ^= alpha[0x04]; s05 ^= alpha[0x05];\n                s06 ^= alpha[0x06]; s07 ^= alpha[0x07];\n                s08 ^= alpha[0x08]; s09 ^= alpha[0x09];\n                s0a ^= alpha[0x0a]; s0b ^= alpha[0x0b];\n                s0c ^= alpha[0x0c]; s0d ^= alpha[0x0d];\n                s0e ^= alpha[0x0e]; s0f ^= alpha[0x0f];\n                s10 ^= alpha[0x10]; s11 ^= alpha[0x11];\n                s12 ^= alpha[0x12]; s13 ^= alpha[0x13];\n                s14 ^= alpha[0x14]; s15 ^= alpha[0x15];\n                s16 ^= alpha[0x16]; s17 ^= alpha[0x17];\n                s18 ^= alpha[0x18]; s19 ^= alpha[0x19];\n                s1a ^= alpha[0x1a]; s1b ^= alpha[0x1b];\n                s1c ^= alpha[0x1c]; s1d ^= alpha[0x1d];\n                s1e ^= alpha[0x1e]; s1f ^= alpha[0x1f];\n\n                sbox(&s00,&s08,&s10,&s18); sbox(&s01,&s09,&s11,&s19);\n                sbox(&s02,&s0a,&s12,&s1a); sbox(&s03,&s0b,&s13,&s1b);\n                sbox(&s04,&s0c,&s14,&s1c); sbox(&s05,&s0d,&s15,&s1d);\n                sbox(&s06,&s0e,&s16,&s1e); sbox(&s07,&s0f,&s17,&s1f);\n\n                linear(&s00,&s09,&s12,&s1b); linear(&s01,&s0a,&s13,&s1c);\n                linear(&s02,&s0b,&s14,&s1d); linear(&s03,&s0c,&s15,&s1e);\n                linear(&s04,&s0d,&s16,&s1f); linear(&s05,&s0e,&s17,&s18);\n                linear(&s06,&s0f,&s10,&s19); linear(&s07,&s08,&s11,&s1a);\n\n                linear(&s00,&s02,&s05,&s07);\n                linear(&s10,&s13,&s15,&s16);\n                linear(&s09,&s0b,&s0c,&s0e);\n                linear(&s19,&s1a,&s1c,&s1f);\n            }\n\n            h[0]  ^= s00; h[1]  ^= s01; h[2]  ^= s02; h[3]  ^= s03;\n            h[4]  ^= s04; h[5]  ^= s05; h[6]  ^= s06; h[7]  ^= s07;\n            h[8]  ^= s10; h[9]  ^= s11; h[10] ^= s12; h[11] ^= s13;\n            h[12] ^= s14; h[13] ^= s15; h[14] ^= s16; h[15] ^= s17;\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void compress_small(uint32_t *h, const uint8_t *block, int final_round,\n            const uint32_t *alpha, const uint32_t *tables);\n        void compress_big(uint32_t *h, const uint8_t *block, int final_round,\n            const uint32_t *alpha, const uint32_t *tables);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.HamsiBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            def pack_alpha(alpha_seq):\n                buf = ffi.new(\"uint32_t[]\", len(alpha_seq))\n                for i, v in enumerate(alpha_seq):\n                    buf[i] = v & 0xffff_ffff\n                return buf\n\n            def pack_tables(tables, size):\n                total_words = size * 256 * (size * 2)\n                buf = ffi.new(\"uint32_t[]\", total_words)\n                pos = 0\n                for t in tables:\n                    for row in t:\n                        for v in row:\n                            buf[pos] = v & 0xffff_ffff\n                            pos += 1\n                return buf\n            try:\n                alpha_n = pack_alpha(self.alpha_n)\n                alpha_f = pack_alpha(self.alpha_f)\n                if self.block_size == 4:\n                    tables = pack_tables(self.expand_small_tables, 4)\n                elif self.block_size == 8:\n                    tables = pack_tables(self.expand_big_tables, 8)\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib alpha_n alpha_f tables\")(\n                ffi, lib, alpha_n, alpha_f, tables,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def build_expand_small_tables(cls):\n            if hasattr(Hash.HamsiBase, \"expand_small_tables\"):\n                return\n\n            tables = []\n            t = cls.t256\n            for u in range(4):\n                pos = []\n                base_u = u * 64\n                for byte in range(256):\n                    acc = [0] * 8\n                    db = byte\n                    off = base_u\n                    for _ in range(8):\n                        if db & 1:\n                            for i in range(8):\n                                acc[i] ^= t[off + i]\n                        db >>= 1\n                        off += 8\n                    pos.append(tuple(acc))\n                tables.append(tuple(pos))\n            Hash.HamsiBase.expand_small_tables = tuple(tables)\n            return\n\n        @classmethod\n        def build_expand_big_tables(cls):\n            if hasattr(Hash.HamsiBase, \"expand_big_tables\"):\n                return\n\n            tables = []\n            t = cls.t512\n            for u in range(8):\n                pos = []\n                base_u = u * 128\n                for byte in range(256):\n                    acc = [0] * 16\n                    db = byte\n                    off = base_u\n                    for _ in range(8):\n                        if db & 1:\n                            for i in range(16):\n                                acc[i] ^= t[off + i]\n                        db >>= 1\n                        off += 16\n                    pos.append(tuple(acc))\n                tables.append(tuple(pos))\n            Hash.HamsiBase.expand_big_tables = tuple(tables)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.h = list(self.iv)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if self.block_size == 4:\n                self.build_expand_small_tables()\n                self.compress = self.compress_small\n            elif self.block_size == 8:\n                self.build_expand_big_tables()\n                self.compress = self.compress_big\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not data:\n                return self\n            mv = memoryview(data)\n            self.msg_len += len(mv)\n            if self.buf:\n                need = self.block_size - len(self.buf)\n                if len(mv) < need:\n                    self.buf.extend(mv)\n                    return self\n                self.buf.extend(mv[:need])\n                self.compress(self.buf, False)\n                self.buf.clear()\n                mv = mv[need:]\n            full = (len(mv) // self.block_size) * self.block_size\n            for off in range(0, full, self.block_size):\n                self.compress(mv[off:off + self.block_size], False)\n            if full < len(mv):\n                self.buf.extend(mv[full:])\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            if self.block_size == 4:\n                pad = self.buf + b\"\\x80\" + (b\"\\x00\" * (3 - len(self.buf))) + bit_len.to_bytes(8, \"big\")\n                self.compress(pad[0:4], False)\n                self.compress(pad[4:8], False)\n                self.compress(pad[8:12], True)\n            elif self.block_size == 8:\n                pad = self.buf + b\"\\x80\" + (b\"\\x00\" * (7 - len(self.buf)))\n                self.compress(pad, False)\n                self.compress(bit_len.to_bytes(8, \"big\"), True)\n            else:\n                raise ValueError(\"invalid block_size\")\n            self.buf = bytearray()\n            return\n\n        def output(self):\n            if self.block_size == 4:\n                words = self.h[:self.digest_size >> 2]\n            elif self.digest_size == 48:\n                h = self.h\n                words = [h[0], h[1], h[3], h[4], h[5], h[6], h[8], h[9], h[10], h[12], h[13], h[15]]\n            else:\n                words = self.h\n            return struct.pack(\">\" + (\"I\" * len(words)), *words)\n\n        def sbox(self, a, b, c, d):\n            t = a\n            a = (a & c) ^ d\n            c ^= b\n            c ^= a\n            d = (d | t) ^ b\n            t ^= c\n            b = d\n            d = (d | t) ^ a\n            a &= b\n            t ^= a\n            b ^= d\n            b ^= t\n            a = c\n            c = b\n            b = d\n            d = (~t) & 0xffff_ffff\n            return a, b, c, d\n\n        def linear(self, a, b, c, d):\n            a = (((a << 13) | (a >> 19)) & 0xffff_ffff)\n            c = (((c << 3) | (c >> 29)) & 0xffff_ffff)\n            b ^= a ^ c\n            d ^= c ^ ((a << 3) & 0xffff_ffff)\n            b = (((b << 1) | (b >> 31)) & 0xffff_ffff)\n            d = (((d << 7) | (d >> 25)) & 0xffff_ffff)\n            a ^= b ^ d\n            c ^= d ^ ((b << 7) & 0xffff_ffff)\n            a = (((a << 5) | (a >> 27)) & 0xffff_ffff)\n            c = (((c << 22) | (c >> 10)) & 0xffff_ffff)\n            return a, b, c, d\n\n        def compress_small(self, block, final_round):\n            if self.USE_CFFI:\n                hbuf = self.cffi.ffi.new(\"uint32_t[]\", len(self.h))\n                for i, v in enumerate(self.h):\n                    hbuf[i] = v\n                blk = self.cffi.ffi.new(\"uint8_t[]\", bytes(block))\n                alpha = self.cffi.alpha_f if final_round else self.cffi.alpha_n\n                self.cffi.lib.compress_small(hbuf, blk, int(final_round), alpha, self.cffi.tables)\n                for i in range(len(self.h)):\n                    self.h[i] = hbuf[i]\n                return\n\n            # --- pure Python ---\n            t0, t1, t2, t3 = self.expand_small_tables\n            a0, a1, a2, a3 = t0[block[0]], t1[block[1]], t2[block[2]], t3[block[3]]\n            m = [x0 ^ x1 ^ x2 ^ x3 for x0, x1, x2, x3 in zip(a0, a1, a2, a3)]\n            h = self.h\n\n            s0, s1, s2, s3 = m[0], m[1], h[0], h[1]\n            s4, s5, s6, s7 = h[2], h[3], m[2], m[3]\n            s8, s9, s10, s11 = m[4], m[5], h[4], h[5]\n            s12, s13, s14, s15 = h[6], h[7], m[6], m[7]\n\n            alpha = self.alpha_f if final_round else self.alpha_n\n            rounds = 6 if final_round else 3\n\n            for rc in range(rounds):\n                s0 ^= alpha[0x00]\n                s1 ^= alpha[0x01] ^ rc\n                s2 ^= alpha[0x02]\n                s3 ^= alpha[0x03]\n                s4 ^= alpha[0x08]\n                s5 ^= alpha[0x09]\n                s6 ^= alpha[0x0a]\n                s7 ^= alpha[0x0b]\n                s8 ^= alpha[0x10]\n                s9 ^= alpha[0x11]\n                s10 ^= alpha[0x12]\n                s11 ^= alpha[0x13]\n                s12 ^= alpha[0x18]\n                s13 ^= alpha[0x19]\n                s14 ^= alpha[0x1a]\n                s15 ^= alpha[0x1b]\n\n                s0, s4, s8, s12 = self.sbox(s0, s4, s8, s12)\n                s1, s5, s9, s13 = self.sbox(s1, s5, s9, s13)\n                s2, s6, s10, s14 = self.sbox(s2, s6, s10, s14)\n                s3, s7, s11, s15 = self.sbox(s3, s7, s11, s15)\n\n                s0, s5, s10, s15 = self.linear(s0, s5, s10, s15)\n                s1, s6, s11, s12 = self.linear(s1, s6, s11, s12)\n                s2, s7, s8, s13 = self.linear(s2, s7, s8, s13)\n                s3, s4, s9, s14 = self.linear(s3, s4, s9, s14)\n\n            h[7] ^= s11\n            h[6] ^= s10\n            h[5] ^= s9\n            h[4] ^= s8\n            h[3] ^= s3\n            h[2] ^= s2\n            h[1] ^= s1\n            h[0] ^= s0\n            return\n\n        def compress_big(self, block, final_round):\n            if self.USE_CFFI:\n                hbuf = self.cffi.ffi.new(\"uint32_t[]\", len(self.h))\n                for i, v in enumerate(self.h):\n                    hbuf[i] = v\n                blk = self.cffi.ffi.new(\"uint8_t[]\", bytes(block))\n                alpha = self.cffi.alpha_f if final_round else self.cffi.alpha_n\n                self.cffi.lib.compress_big(hbuf, blk, int(final_round), alpha, self.cffi.tables)\n                for i in range(len(self.h)):\n                    self.h[i] = hbuf[i]\n                return\n\n            # --- pure Python ---\n            t0, t1, t2, t3, t4, t5, t6, t7 = self.expand_big_tables\n            a0, a1, a2, a3 = t0[block[0]], t1[block[1]], t2[block[2]], t3[block[3]]\n            a4, a5, a6, a7 = t4[block[4]], t5[block[5]], t6[block[6]], t7[block[7]]\n            m = [x0 ^ x1 ^ x2 ^ x3 ^ x4 ^ x5 ^ x6 ^ x7 for x0, x1, x2, x3, x4, x5, x6, x7 in zip(a0, a1, a2, a3, a4, a5, a6, a7)]\n            h = self.h\n\n            s00, s01, s02, s03 = m[0], m[1], h[0], h[1]\n            s04, s05, s06, s07 = m[2], m[3], h[2], h[3]\n            s08, s09, s0a, s0b = h[4], h[5], m[4], m[5]\n            s0c, s0d, s0e, s0f = h[6], h[7], m[6], m[7]\n            s10, s11, s12, s13 = m[8], m[9], h[8], h[9]\n            s14, s15, s16, s17 = m[10], m[11], h[10], h[11]\n            s18, s19, s1a, s1b = h[12], h[13], m[12], m[13]\n            s1c, s1d, s1e, s1f = h[14], h[15], m[14], m[15]\n\n            alpha = self.alpha_f if final_round else self.alpha_n\n            rounds = 12 if final_round else 6\n\n            for rc in range(rounds):\n                s00 ^= alpha[0x00]\n                s01 ^= alpha[0x01] ^ rc\n                s02 ^= alpha[0x02]\n                s03 ^= alpha[0x03]\n                s04 ^= alpha[0x04]\n                s05 ^= alpha[0x05]\n                s06 ^= alpha[0x06]\n                s07 ^= alpha[0x07]\n                s08 ^= alpha[0x08]\n                s09 ^= alpha[0x09]\n                s0a ^= alpha[0x0a]\n                s0b ^= alpha[0x0b]\n                s0c ^= alpha[0x0c]\n                s0d ^= alpha[0x0d]\n                s0e ^= alpha[0x0e]\n                s0f ^= alpha[0x0f]\n                s10 ^= alpha[0x10]\n                s11 ^= alpha[0x11]\n                s12 ^= alpha[0x12]\n                s13 ^= alpha[0x13]\n                s14 ^= alpha[0x14]\n                s15 ^= alpha[0x15]\n                s16 ^= alpha[0x16]\n                s17 ^= alpha[0x17]\n                s18 ^= alpha[0x18]\n                s19 ^= alpha[0x19]\n                s1a ^= alpha[0x1a]\n                s1b ^= alpha[0x1b]\n                s1c ^= alpha[0x1c]\n                s1d ^= alpha[0x1d]\n                s1e ^= alpha[0x1e]\n                s1f ^= alpha[0x1f]\n\n                s00, s08, s10, s18 = self.sbox(s00, s08, s10, s18)\n                s01, s09, s11, s19 = self.sbox(s01, s09, s11, s19)\n                s02, s0a, s12, s1a = self.sbox(s02, s0a, s12, s1a)\n                s03, s0b, s13, s1b = self.sbox(s03, s0b, s13, s1b)\n                s04, s0c, s14, s1c = self.sbox(s04, s0c, s14, s1c)\n                s05, s0d, s15, s1d = self.sbox(s05, s0d, s15, s1d)\n                s06, s0e, s16, s1e = self.sbox(s06, s0e, s16, s1e)\n                s07, s0f, s17, s1f = self.sbox(s07, s0f, s17, s1f)\n\n                s00, s09, s12, s1b = self.linear(s00, s09, s12, s1b)\n                s01, s0a, s13, s1c = self.linear(s01, s0a, s13, s1c)\n                s02, s0b, s14, s1d = self.linear(s02, s0b, s14, s1d)\n                s03, s0c, s15, s1e = self.linear(s03, s0c, s15, s1e)\n                s04, s0d, s16, s1f = self.linear(s04, s0d, s16, s1f)\n                s05, s0e, s17, s18 = self.linear(s05, s0e, s17, s18)\n                s06, s0f, s10, s19 = self.linear(s06, s0f, s10, s19)\n                s07, s08, s11, s1a = self.linear(s07, s08, s11, s1a)\n\n                s00, s02, s05, s07 = self.linear(s00, s02, s05, s07)\n                s10, s13, s15, s16 = self.linear(s10, s13, s15, s16)\n                s09, s0b, s0c, s0e = self.linear(s09, s0b, s0c, s0e)\n                s19, s1a, s1c, s1f = self.linear(s19, s1a, s1c, s1f)\n\n            h[15] ^= s17\n            h[14] ^= s16\n            h[13] ^= s15\n            h[12] ^= s14\n            h[11] ^= s13\n            h[10] ^= s12\n            h[9] ^= s11\n            h[8] ^= s10\n            h[7] ^= s07\n            h[6] ^= s06\n            h[5] ^= s05\n            h[4] ^= s04\n            h[3] ^= s03\n            h[2] ^= s02\n            h[1] ^= s01\n            h[0] ^= s00\n            return\n\n    class Hamsi224(HamsiBase):\n        block_size = 4\n        digest_size = 28\n        iv = (\n            0xc396_7a67, 0xc3bc_6c20, 0x4bc3_bcc3, 0xa7c3_bc6b, 0x2c20_4b61, 0x7468_6f6c, 0x6965_6b65, 0x2055_6e69,\n        )\n\n    class Hamsi256(HamsiBase):\n        block_size = 4\n        digest_size = 32\n        iv = (\n            0x7665_7273, 0x6974_6569, 0x7420_4c65, 0x7576_656e, 0x2c20_4465, 0x7061_7274, 0x656d_656e, 0x7420_456c,\n        )\n\n    class Hamsi384(HamsiBase):\n        block_size = 8\n        digest_size = 48\n        iv = (\n            0x656b_7472, 0x6f74_6563, 0x686e_6965, 0x6b2c_2043, 0x6f6d_7075, 0x7465_7220, 0x5365_6375, 0x7269_7479,\n            0x2061_6e64, 0x2049_6e64, 0x7573_7472, 0x6961_6c20, 0x4372_7970, 0x746f_6772, 0x6170_6879, 0x2c20_4b61,\n        )\n\n    class Hamsi512(HamsiBase):\n        block_size = 8\n        digest_size = 64\n        iv = (\n            0x7374_6565, 0x6c70_6172, 0x6b20_4172, 0x656e_6265, 0x7267_2031, 0x302c_2062, 0x7573_2032, 0x3434_362c,\n            0x2042_2d33, 0x3030_3120, 0x4c65_7576, 0x656e_2d48, 0x6576_6572, 0x6c65_652c, 0x2042_656c, 0x6769_756d,\n        )\n\n    class LuffaBase:\n        block_size = 0x20  # 256 bits\n        # Appendix A: Starting Variables\n        V = (\n            (0x6d25_1e69, 0x44b0_51e0, 0x4eaa_6fb4, 0xdbf7_8465, 0x6e29_2011, 0x9015_2df4, 0xee05_8139, 0xdef6_10bb),\n            (0xc3b4_4b95, 0xd9d2_f256, 0x70ee_e9a0, 0xde09_9fa3, 0x5d9b_0557, 0x8fc9_44b3, 0xcf1c_cf0e, 0x746c_d581),\n            (0xf7ef_c89d, 0x5dba_5781, 0x0401_6ce5, 0xad65_9c05, 0x0306_194f, 0x666d_1836, 0x24aa_230a, 0x8b26_4ae7),\n            (0x8580_75d5, 0x36d7_9cce, 0xe571_f7d7, 0x204b_1f67, 0x3587_0c6a, 0x57e9_e923, 0x14bc_b808, 0x7cde_72ce),\n            (0x6c68_e9be, 0x5ec4_1e22, 0xc825_b7c7, 0xaffb_4363, 0xf5df_3999, 0x0fc6_88f1, 0xb072_24cc, 0x03e8_6cea),\n        )\n        # Appendix B-1: Constant generator initial values (c^(0)_{j,L}, c^(0)_{j,R})\n        C_INIT = (\n            (0x181c_ca53, 0x380c_de06),\n            (0x5b6f_0876, 0xf16f_8594),\n            (0x7e10_6ce9, 0x3897_9cb0),\n            (0xbb62_f364, 0x92e9_3c29),\n            (0x9a02_5047, 0xcff2_a940),\n        )\n        # Section 3.2.1: Message Injection matrices (coefficients in GF(2^8))\n        MI_MAT = {\n            0x03: (\n                (0x03, 0x02, 0x02, 0x01),\n                (0x02, 0x03, 0x02, 0x02),\n                (0x02, 0x02, 0x03, 0x04),\n            ),\n            0x04: (\n                (0x04, 0x06, 0x06, 0x07, 0x01),\n                (0x07, 0x04, 0x06, 0x06, 0x02),\n                (0x06, 0x07, 0x04, 0x06, 0x04),\n                (0x06, 0x06, 0x07, 0x04, 0x08),\n            ),\n            0x05: (\n                (0x0f, 0x08, 0x0a, 0x0a, 0x08, 0x01),\n                (0x08, 0x0f, 0x08, 0x0a, 0x0a, 0x02),\n                (0x0a, 0x08, 0x0f, 0x08, 0x0a, 0x04),\n                (0x0a, 0x0a, 0x08, 0x0f, 0x08, 0x08),\n                (0x08, 0x0a, 0x0a, 0x08, 0x0f, 0x10),\n            ),\n        }\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        static uint32_t rol32(uint32_t x, int n)\n        {\n            return ((x << n) | (x >> (32 - n))) & 0xffffffffU;\n        }\n\n        static void scalar_mul(const uint32_t *vec, unsigned int coeff, uint32_t *out)\n        {\n            uint32_t tmp[8];\n            uint32_t res[8];\n            int i, k;\n\n            coeff &= 0xffU;\n            for (k = 0; k < 8; k++) {\n                tmp[k] = vec[k];\n                res[k] = 0;\n            }\n            if (coeff == 0) {\n                for (k = 0; k < 8; k++) {\n                    out[k] = 0;\n                }\n                return;\n            }\n            if (coeff == 1) {\n                for (k = 0; k < 8; k++) {\n                    out[k] = vec[k];\n                }\n                return;\n            }\n            for (i = 0; i < 8; i++) {\n                if ((coeff >> i) & 1U) {\n                    for (k = 0; k < 8; k++) {\n                        res[k] ^= tmp[k];\n                    }\n                }\n                {\n                    uint32_t a0 = tmp[0];\n                    uint32_t a1 = tmp[1];\n                    uint32_t a2 = tmp[2];\n                    uint32_t a3 = tmp[3];\n                    uint32_t a4 = tmp[4];\n                    uint32_t a5 = tmp[5];\n                    uint32_t a6 = tmp[6];\n                    uint32_t a7 = tmp[7];\n                    uint32_t t = a7;\n                    tmp[0] = t;\n                    tmp[1] = a0 ^ t;\n                    tmp[2] = a1;\n                    tmp[3] = a2 ^ t;\n                    tmp[4] = a3 ^ t;\n                    tmp[5] = a4;\n                    tmp[6] = a5;\n                    tmp[7] = a6;\n                }\n            }\n            for (k = 0; k < 8; k++) {\n                out[k] = res[k];\n            }\n        }\n\n        static void subcrumb(uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3)\n        {\n            uint32_t t4 = *r0;\n            *r0 |= *r1;\n            *r2 ^= *r3;\n            *r1 = (~(*r1)) & 0xffffffffU;\n            *r0 ^= *r3;\n            *r3 &= t4;\n            *r1 ^= *r3;\n            *r3 ^= *r2;\n            *r2 &= *r0;\n            *r0 = (~(*r0)) & 0xffffffffU;\n            *r2 ^= *r1;\n            *r1 |= *r3;\n            t4 ^= *r1;\n            *r3 ^= *r2;\n            *r2 &= *r1;\n            *r1 ^= *r0;\n            *r0 = t4;\n        }\n\n        static void mixword(uint32_t *xk, uint32_t *xk4)\n        {\n            uint32_t yk4 = *xk4 ^ *xk;\n            uint32_t yk = rol32(*xk, 2);\n            yk ^= yk4;\n            yk4 = rol32(yk4, 14);\n            yk4 ^= yk;\n            yk = rol32(yk, 10);\n            yk ^= yk4;\n            yk4 = rol32(yk4, 1);\n            *xk = yk;\n            *xk4 = yk4;\n        }\n\n        void luffa_round(uint32_t *state, const uint32_t *m, int w, const uint32_t *step_const, const uint8_t *mi_mat)\n        {\n            uint32_t xs[5][8];\n            uint32_t term[8];\n            int j, k, idx, r;\n            int input_count = w + 1;\n\n            for (j = 0; j < w; j++) {\n                for (k = 0; k < 8; k++) {\n                    xs[j][k] = 0;\n                }\n                for (idx = 0; idx < input_count; idx++) {\n                    unsigned int coeff = mi_mat[j * input_count + idx];\n                    const uint32_t *vec;\n                    if (coeff == 0) {\n                        continue;\n                    }\n                    if (idx < w) {\n                        vec = state + (idx * 8);\n                    } else {\n                        vec = m;\n                    }\n                    if (coeff == 1) {\n                        for (k = 0; k < 8; k++) {\n                            xs[j][k] ^= vec[k];\n                        }\n                    } else {\n                        scalar_mul(vec, coeff, term);\n                        for (k = 0; k < 8; k++) {\n                            xs[j][k] ^= term[k];\n                        }\n                    }\n                }\n            }\n\n            for (j = 0; j < w; j++) {\n                uint32_t a[8];\n                for (k = 0; k < 8; k++) {\n                    a[k] = xs[j][k] & 0xffffffffU;\n                }\n                for (k = 4; k < 8; k++) {\n                    if (j != 0) {\n                        a[k] = rol32(a[k], j);\n                    }\n                }\n                for (r = 0; r < 8; r++) {\n                    uint32_t t0, t1, t2, t3;\n\n                    subcrumb(&a[0], &a[1], &a[2], &a[3]);\n                    t0 = a[5];\n                    t1 = a[6];\n                    t2 = a[7];\n                    t3 = a[4];\n                    subcrumb(&t0, &t1, &t2, &t3);\n                    a[5] = t0;\n                    a[6] = t1;\n                    a[7] = t2;\n                    a[4] = t3;\n\n                    for (k = 0; k < 4; k++) {\n                        mixword(&a[k], &a[k + 4]);\n                    }\n                    a[0] ^= step_const[j * 16 + (r * 2) + 0];\n                    a[4] ^= step_const[j * 16 + (r * 2) + 1];\n                }\n                for (k = 0; k < 8; k++) {\n                    state[j * 8 + k] = a[k];\n                }\n            }\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void luffa_round(uint32_t *state, const uint32_t *m, int w, const uint32_t *step_const, const uint8_t *mi_mat);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.LuffaBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            try:\n                step_const = ffi.new(\"uint32_t[]\", self.step_const_flat)\n                mi_mat = ffi.new(\"uint8_t[]\", self.mi_mat_flat)\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib step_const mi_mat\")(\n                ffi, lib, step_const, mi_mat,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def prepare_constants(cls):\n            if not hasattr(cls, \"step_const\"):\n                # Section 4.4: generates (c_{j,0}, c_{j,4}) for r=0..7 using the constant generator\n                out = []\n                for j in range(cls.w):\n                    tl, tr = cls.C_INIT[j]\n                    jconst = []\n                    for _ in range(8):\n                        # Section 4.4: one step of constant generator (pseudo code in the spec)\n                        c = (tl >> 31) & 1\n                        tl2 = ((tl << 1) | (tr >> 31)) & 0xffff_ffff\n                        tr2 = (tr << 1) & 0xffff_ffff\n                        if c == 1:\n                            tl2 ^= 0xc4d6_496c\n                            tr2 ^= 0x55c6_1c8d\n                        tl, tr = tr2, tl2\n                        c0 = tr\n\n                        c = (tl >> 31) & 1\n                        tl2 = ((tl << 1) | (tr >> 31)) & 0xffff_ffff\n                        tr2 = (tr << 1) & 0xffff_ffff\n                        if c == 1:\n                            tl2 ^= 0xc4d6_496c\n                            tr2 ^= 0x55c6_1c8d\n                        tl, tr = tr2, tl2\n                        c4 = tr\n                        jconst.append((c0, c4))\n                    out.append(tuple(jconst))\n                cls.step_const = tuple(out)\n\n            if not hasattr(cls, \"step_const_flat\"):\n                step_const_flat = []\n                for j in range(cls.w):\n                    for r in range(8):\n                        c0, c4 = cls.step_const[j][r]\n                        step_const_flat.append(c0)\n                        step_const_flat.append(c4)\n                cls.step_const_flat = tuple(step_const_flat)\n\n            if not hasattr(cls, \"mi_mat_flat\"):\n                mi_mat_flat = []\n                for row in cls.MI_MAT[cls.w]:\n                    mi_mat_flat.extend(row)\n                cls.mi_mat_flat = bytes(mi_mat_flat)\n            return\n\n        def __init__(self, data=b\"\"):\n            if self.w is None or self.digest_size is None:\n                raise ValueError(\"LuffaBase must be subclassed with w and digest_size\")\n            self.H = [list(self.V[i]) for i in range(self.w)]\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.prepare_constants()\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.H = [list(block) for block in self.H]\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output_digest_bytes()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            # Section 3.1: append '1' bit then '0' until length is multiple of 256 bits\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != 0:\n                self.buf.append(0x00)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return\n\n        def compress(self, block):\n            if not isinstance(block, (bytes, bytearray, memoryview)):\n                raise TypeError(\"block must be bytes-like\")\n            block = bytes(block)\n            if len(block) != self.block_size:\n                raise ValueError(\"block must be 32 bytes\")\n            m = list(struct.unpack(\">8I\", block))\n            self.round_function(m)\n            return\n\n        def output_digest_bytes(self):\n            # Section 3.3: finalization (blank round + OF, then additional rounds with 0 as needed)\n            zero_m = [0] * 8\n            self.round_function(zero_m)\n            z0 = self.output_function()\n            words = []\n            if self.digest_size == 0x1c:\n                words.extend(z0[:7])\n            elif self.digest_size == 0x20:\n                words.extend(z0[:8])\n            elif self.digest_size == 0x30:\n                words.extend(z0[:8])\n                self.round_function(zero_m)\n                z1 = self.output_function()\n                words.extend(z1[:4])\n            elif self.digest_size == 0x40:\n                words.extend(z0[:8])\n                self.round_function(zero_m)\n                z1 = self.output_function()\n                words.extend(z1[:8])\n            else:\n                raise ValueError(\"unsupported digest size\")\n            out = b\"\".join(struct.pack(\">I\", w) for w in words)\n            return out\n\n        def output_function(self):\n            z = [0] * 8\n            for j in range(self.w):\n                for k in range(8):\n                    z[k] ^= self.H[j][k]\n            return z\n\n        def round_function(self, m):\n            if self.USE_CFFI:\n                state_flat = []\n                for j in range(self.w):\n                    state_flat.extend(self.H[j])\n                state_buf = self.cffi.ffi.new(\"uint32_t[]\", state_flat)\n                m_buf = self.cffi.ffi.new(\"uint32_t[]\", m)\n                self.cffi.lib.luffa_round(state_buf, m_buf, self.w, self.cffi.step_const, self.cffi.mi_mat)\n                for j in range(self.w):\n                    base = j * 8\n                    self.H[j] = [int(state_buf[base + k]) for k in range(8)]\n                return\n\n            # --- pure Python ---\n            xs = self.message_injection(m)\n            for j in range(self.w):\n                self.H[j] = self.permute(xs[j], j)\n            return\n\n        def message_injection(self, m):\n            mat = self.MI_MAT[self.w]\n            inputs = [self.H[j] for j in range(self.w)] + [m]\n            outs = []\n            for row in mat:\n                acc = [0] * 8\n                for coeff, vec in zip(row, inputs):\n                    if coeff == 0:\n                        continue\n                    if coeff == 1:\n                        term = vec\n                    else:\n                        term = self.scalar_mul(vec, coeff)\n                    for k in range(8):\n                        acc[k] ^= term[k]\n                outs.append(acc)\n            return outs\n\n        def scalar_mul(self, vec, coeff):\n            coeff &= 0xff\n            if coeff == 0:\n                return [0] * 8\n            if coeff == 1:\n                return list(vec)\n            res = [0] * 8\n            tmp = list(vec)\n            for i in range(8):\n                if (coeff >> i) & 1:\n                    for k in range(8):\n                        res[k] ^= tmp[k]\n                # Appendix E: multiplication by x in GF(2^8)^32 (phi(x)=x^8+x^4+x^3+x+1)\n                t = tmp[7]\n                tmp = [t, tmp[0] ^ t, tmp[1], tmp[2] ^ t, tmp[3] ^ t, tmp[4], tmp[5], tmp[6]]\n            return res\n\n        def permute(self, words, j):\n\n            def rol32(x, n):\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            def mixword(xk, xk4):\n                # Section 4.3 (sigma1=2,sigma2=14,sigma3=10,sigma4=1), rotations\n                yk4 = xk4 ^ xk\n                yk = rol32(xk, 2)\n                yk ^= yk4\n                yk4 = rol32(yk4, 14)\n                yk4 ^= yk\n                yk = rol32(yk, 10)\n                yk ^= yk4\n                yk4 = rol32(yk4, 1)\n                return yk, yk4\n\n            def subcrumb(r0, r1, r2, r3):\n                # Appendix D Table 4: bit-sliced Sbox schedule\n                r4 = r0\n                r0 |= r1\n                r2 ^= r3\n                r1 = (~r1) & 0xffff_ffff\n                r0 ^= r3\n                r3 &= r4\n                r1 ^= r3\n                r3 ^= r2\n                r2 &= r0\n                r0 = (~r0) & 0xffff_ffff\n                r2 ^= r1\n                r1 |= r3\n                r4 ^= r1\n                r3 ^= r2\n                r2 &= r1\n                r1 ^= r0\n                return r4, r1, r2, r3\n\n            # Section 4.1: Permute(a, j) = Q_j\n            a = [w & 0xffff_ffff for w in words]\n            # Section 4.5: tweak (rotate least significant four words by j bits to the left)\n            for k in range(4, 8):\n                a[k] = rol32(a[k], j)\n            for r in range(8):\n                a[0], a[1], a[2], a[3] = subcrumb(a[0], a[1], a[2], a[3])\n                # IMPORTANT: the latter four words are input to SubCrumb in different order\n                a[5], a[6], a[7], a[4] = subcrumb(a[5], a[6], a[7], a[4])\n                for k in range(4):\n                    a[k], a[k + 4] = mixword(a[k], a[k + 4])\n                c0, c4 = self.step_const[j][r]\n                a[0] ^= c0\n                a[4] ^= c4\n            return a\n\n    class Luffa224(LuffaBase):\n        digest_size = 0x1c\n        w = 0x03\n\n    class Luffa256(LuffaBase):\n        digest_size = 0x20\n        w = 0x03\n\n    class Luffa384(LuffaBase):\n        digest_size = 0x30\n        w = 0x04\n\n    class Luffa512(LuffaBase):\n        digest_size = 0x40\n        w = 0x05\n\n    class ESCHBase:\n        rcon = (\n            0xb7e1_5162, 0xbf71_5880, 0x38b4_da56, 0x324e_7738, 0xbb11_85eb, 0x4f7c_7b57, 0xcfbf_a1c8, 0xc2b3_293d,\n        )\n        const_m0 = 0x01_00_00_00\n        const_m1 = 0x02_00_00_00\n        pack4 = struct.Struct(\"<4I\")\n        unpack4 = struct.Struct(\"<4I\")\n\n        def __init__(self, data=b\"\"):\n            self.state = [0] * (2 * self.branches)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            mv = memoryview(data)\n            data_len = len(mv)\n            self.msg_len += data_len\n            block_size = self.block_size\n            off = 0\n            if self.buf:\n                need = block_size - len(self.buf)\n                if data_len <= need:\n                    self.buf.extend(mv)\n                    return self\n                self.buf.extend(mv[:need])\n                self.absorb_block(self.buf)\n                self.buf.clear()\n                off = need\n            limit = data_len - block_size\n            while off < limit:\n                self.absorb_block(mv[off:off + block_size])\n                off += block_size\n            if off < data_len:\n                self.buf.extend(mv[off:])\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.squeeze()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if len(self.buf) == self.block_size:\n                last = self.buf\n                const_m = self.const_m1\n            else:\n                self.buf.append(0x80)\n                pad_len = self.block_size - len(self.buf)\n                if pad_len:\n                    self.buf.extend(b\"\\x00\" * pad_len)\n                last = self.buf\n                const_m = self.const_m0\n            self.absorb_last_block(last, const_m)\n            self.buf.clear()\n            return\n\n        def squeeze(self):\n            out = bytearray()\n            need = self.digest_size\n            pack4 = self.pack4.pack\n            state = self.state\n            out.extend(pack4(state[0], state[1], state[2], state[3]))\n            while len(out) < need:\n                self.sparkle(self.slim_steps)\n                state = self.state\n                out.extend(pack4(state[0], state[1], state[2], state[3]))\n            return bytes(out[:need])\n\n        def alzette(self, x, y, c):\n            x = (x + ((y >> 31) | ((y << 1) & 0xffff_ffff))) & 0xffff_ffff\n            y ^= ((x >> 24) | ((x << 8) & 0xffff_ffff))\n            x ^= c\n\n            x = (x + ((y >> 17) | ((y << 15) & 0xffff_ffff))) & 0xffff_ffff\n            y ^= ((x >> 17) | ((x << 15) & 0xffff_ffff))\n            x ^= c\n\n            x = (x + y) & 0xffff_ffff\n            y ^= ((x >> 31) | ((x << 1) & 0xffff_ffff))\n            x ^= c\n\n            x = (x + ((y >> 24) | ((y << 8) & 0xffff_ffff))) & 0xffff_ffff\n            y ^= ((x >> 16) | ((x << 16) & 0xffff_ffff))\n            x ^= c\n            return x, y\n\n        def inject_block_xor(self, block):\n            w0, w1, w2, w3 = self.unpack4.unpack(block)\n            state = self.state\n\n            tx = w0 ^ w2\n            ty = w1 ^ w3\n            tx ^= (tx << 16) & 0xffff_ffff\n            ty ^= (ty << 16) & 0xffff_ffff\n            lx = ((tx >> 16) | ((tx << 16) & 0xffff_ffff)) & 0xffff_ffff\n            ly = ((ty >> 16) | ((ty << 16) & 0xffff_ffff)) & 0xffff_ffff\n\n            state[0] ^= w0 ^ ly\n            state[1] ^= w1 ^ lx\n            state[2] ^= w2 ^ ly\n            state[3] ^= w3 ^ lx\n            state[4] ^= ly\n            state[5] ^= lx\n\n            if self.m_w == 4:\n                state[6] ^= ly\n                state[7] ^= lx\n            return\n\n        def absorb_block(self, block):\n            self.inject_block_xor(block)\n            self.sparkle(self.slim_steps)\n            return\n\n        def absorb_last_block(self, block, const_m_word):\n            self.inject_block_xor(block)\n            self.state[2 * self.m_w - 1] ^= const_m_word\n            self.sparkle(self.big_steps)\n            return\n\n        def sparkle_6(self, steps):\n            state = self.state\n            rcon = self.rcon\n\n            for s in range(steps):\n                state[1] ^= rcon[s & 7]\n                state[3] ^= s\n\n                for i in range(6):\n                    state[i * 2], state[i * 2 + 1] = self.alzette(state[i * 2], state[i * 2 + 1], rcon[i])\n\n                tx = state[0] ^ state[2] ^ state[4]\n                ty = state[1] ^ state[3] ^ state[5]\n                tx ^= (tx << 16) & 0xffff_ffff\n                ty ^= (ty << 16) & 0xffff_ffff\n                tx = ((tx >> 16) | ((tx << 16) & 0xffff_ffff)) & 0xffff_ffff\n                ty = ((ty >> 16) | ((ty << 16) & 0xffff_ffff)) & 0xffff_ffff\n\n                s0 = state[0]\n                s1 = state[1]\n                s2 = state[2]\n                s3 = state[3]\n                s4 = state[4]\n                s5 = state[5]\n                s6 = state[6] ^ s0 ^ ty\n                s7 = state[7] ^ s1 ^ tx\n                s8 = state[8] ^ s2 ^ ty\n                s9 = state[9] ^ s3 ^ tx\n                s10 = state[10] ^ s4 ^ ty\n                s11 = state[11] ^ s5 ^ tx\n\n                state[0] = s8\n                state[1] = s9\n                state[2] = s10\n                state[3] = s11\n                state[4] = s6\n                state[5] = s7\n                state[6] = s0\n                state[7] = s1\n                state[8] = s2\n                state[9] = s3\n                state[10] = s4\n                state[11] = s5\n            return\n\n        def sparkle_8(self, steps):\n            state = self.state\n            rcon = self.rcon\n\n            for s in range(steps):\n                state[1] ^= rcon[s & 7]\n                state[3] ^= s\n\n                for i in range(8):\n                    state[i * 2], state[i * 2 + 1] = self.alzette(state[i * 2], state[i * 2 + 1], rcon[i])\n\n                tx = state[0] ^ state[2] ^ state[4] ^ state[6]\n                ty = state[1] ^ state[3] ^ state[5] ^ state[7]\n                tx ^= (tx << 16) & 0xffff_ffff\n                ty ^= (ty << 16) & 0xffff_ffff\n                tx = ((tx >> 16) | ((tx << 16) & 0xffff_ffff)) & 0xffff_ffff\n                ty = ((ty >> 16) | ((ty << 16) & 0xffff_ffff)) & 0xffff_ffff\n\n                s0 = state[0]\n                s1 = state[1]\n                s2 = state[2]\n                s3 = state[3]\n                s4 = state[4]\n                s5 = state[5]\n                s6 = state[6]\n                s7 = state[7]\n                s8 = state[8] ^ s0 ^ ty\n                s9 = state[9] ^ s1 ^ tx\n                s10 = state[10] ^ s2 ^ ty\n                s11 = state[11] ^ s3 ^ tx\n                s12 = state[12] ^ s4 ^ ty\n                s13 = state[13] ^ s5 ^ tx\n                s14 = state[14] ^ s6 ^ ty\n                s15 = state[15] ^ s7 ^ tx\n\n                state[0] = s10\n                state[1] = s11\n                state[2] = s12\n                state[3] = s13\n                state[4] = s14\n                state[5] = s15\n                state[6] = s8\n                state[7] = s9\n                state[8] = s0\n                state[9] = s1\n                state[10] = s2\n                state[11] = s3\n                state[12] = s4\n                state[13] = s5\n                state[14] = s6\n                state[15] = s7\n            return\n\n        def sparkle(self, steps):\n            if self.branches == 6:\n                self.sparkle_6(steps)\n            else:\n                self.sparkle_8(steps)\n            return\n\n    class ESCH256(ESCHBase):\n        block_size = 16\n        digest_size = 32\n        branches = 6\n        slim_steps = 7\n        big_steps = 11\n        m_w = 3\n\n    class ESCH384(ESCHBase):\n        block_size = 16\n        digest_size = 48\n        branches = 8\n        slim_steps = 8\n        big_steps = 12\n        m_w = 4\n\n    class SIMDBase:\n        P = (\n            0x04, 0x06, 0x00, 0x02, 0x07, 0x05, 0x03, 0x01, 0x0f, 0x0b, 0x0c, 0x08, 0x09, 0x0d, 0x0a, 0x0e,\n            0x11, 0x12, 0x17, 0x14, 0x16, 0x15, 0x10, 0x13, 0x1e, 0x18, 0x19, 0x1f, 0x1b, 0x1d, 0x1c, 0x1a,\n        )\n        round_pis = (\n            (0x03, 0x17, 0x11, 0x1b),\n            (0x1c, 0x13, 0x16, 0x07),\n            (0x1d, 0x09, 0x0f, 0x05),\n            (0x04, 0x0d, 0x0a, 0x19),\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        static uint32_t rol32(uint32_t x, int n)\n        {\n            return ((x << n) | (x >> (32 - n))) & 0xffffffffU;\n        }\n\n        static int lift257(int v)\n        {\n            if (v > 0x80)\n                return v - 0x101;\n            return v;\n        }\n\n        static uint32_t pack_code(int x, int y, int c)\n        {\n            uint32_t lo = ((uint32_t)(c * lift257(x))) & 0xffffU;\n            uint32_t hi = ((uint32_t)(c * lift257(y))) & 0xffffU;\n            return lo | (hi << 16);\n        }\n\n        static const uint8_t perm_table[32] = {\n            0x04, 0x06, 0x00, 0x02, 0x07, 0x05, 0x03, 0x01, 0x0f, 0x0b, 0x0c, 0x08, 0x09, 0x0d, 0x0a, 0x0e,\n            0x11, 0x12, 0x17, 0x14, 0x16, 0x15, 0x10, 0x13, 0x1e, 0x18, 0x19, 0x1f, 0x1b, 0x1d, 0x1c, 0x1a,\n        };\n\n        static const uint8_t round_pis[4][4] = {\n            {0x03, 0x17, 0x11, 0x1b}, {0x1c, 0x13, 0x16, 0x07}, {0x1d, 0x09, 0x0f, 0x05}, {0x04, 0x0d, 0x0a, 0x19},\n        };\n\n        static void step_if(\n            uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, const uint32_t *w_vec, int lanes, int r, int s, int p)\n        {\n            uint32_t new_a[8], new_b[8], new_c[8], new_d[8];\n            int j;\n\n            for (j = 0; j < lanes; j++) {\n                uint32_t phi = c[j] ^ (a[j] & (b[j] ^ c[j]));\n                uint32_t t = (d[j] + w_vec[j] + phi) & 0xffffffffU;\n                uint32_t u = 0;\n\n                t = rol32(t, s);\n                u = rol32(a[j ^ p], r);\n\n                new_a[j] = (t + u) & 0xffffffffU;\n                new_b[j] = rol32(a[j], r);\n                new_c[j] = b[j];\n                new_d[j] = c[j];\n            }\n\n            for (j = 0; j < lanes; j++) {\n                a[j] = new_a[j];\n                b[j] = new_b[j];\n                c[j] = new_c[j];\n                d[j] = new_d[j];\n            }\n        }\n\n        static void step_maj(\n            uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, const uint32_t *w_vec, int lanes, int r, int s, int p)\n        {\n            uint32_t new_a[8];\n            uint32_t new_b[8];\n            uint32_t new_c[8];\n            uint32_t new_d[8];\n            int j;\n\n            for (j = 0; j < lanes; j++) {\n                uint32_t phi = (a[j] & b[j]) | (c[j] & (a[j] | b[j]));\n                uint32_t t = (d[j] + w_vec[j] + phi) & 0xffffffffU;\n                uint32_t u = 0;\n\n                t = rol32(t, s);\n                u = rol32(a[j ^ p], r);\n\n                new_a[j] = (t + u) & 0xffffffffU;\n                new_b[j] = rol32(a[j], r);\n                new_c[j] = b[j];\n                new_d[j] = c[j];\n            }\n\n            for (j = 0; j < lanes; j++) {\n                a[j] = new_a[j];\n                b[j] = new_b[j];\n                c[j] = new_c[j];\n                d[j] = new_d[j];\n            }\n        }\n\n        static void compress_generic(\n            uint32_t *state, const uint8_t *block, int final_flag, const uint16_t *rows_normal,\n            const uint16_t *rows_final, const uint8_t *p_xor_table, int lanes, int block_size, int ntt_n, int z_stride)\n        {\n            const uint16_t *rows = final_flag ? rows_final : rows_normal;\n            int row_stride = block_size + 1;\n            int half_n = ntt_n / 2;\n            int offset0 = ntt_n + half_n - 1;\n            int offset1 = ntt_n - 1;\n\n            int y[256];\n            uint32_t z[32][8];\n            uint32_t w[32][8];\n            uint32_t m_words[32];\n            uint32_t a[8], b[8], c[8], d[8];\n\n            int i = 0;\n            int j = 0;\n\n            for (i = 0; i < ntt_n; i++) {\n                int acc = rows[i * row_stride + block_size];\n                for (j = 0; j < block_size; j++) {\n                    acc += ((int)block[j]) * ((int)rows[i * row_stride + j]);\n                }\n                y[i] = acc % 0x101;\n            }\n\n            for (i = 0; i < 32; i++) {\n                int base = z_stride * i;\n                for (j = 0; j < lanes; j++) {\n                    int idx = base + 2 * j;\n\n                    if (i <= 15) {\n                        z[i][j] = pack_code(y[idx], y[idx + 1], 0xb9);\n                    } else if (i <= 23) {\n                        z[i][j] = pack_code(y[idx - ntt_n], y[idx - half_n], 0xe9);\n                    } else {\n                        z[i][j] = pack_code(y[idx - offset0], y[idx - offset1], 0xe9);\n                    }\n                }\n            }\n\n            for (i = 0; i < 32; i++) {\n                int src = perm_table[i];\n                for (j = 0; j < lanes; j++) {\n                    w[i][j] = z[src][j];\n                }\n            }\n\n            for (i = 0; i < lanes * 4; i++) {\n                int off = i * 4;\n                m_words[i] = (\n                    ((uint32_t)block[off + 0]) |\n                    ((uint32_t)block[off + 1] << 8) |\n                    ((uint32_t)block[off + 2] << 16) |\n                    ((uint32_t)block[off + 3] << 24)\n                );\n            }\n\n            for (j = 0; j < lanes; j++) {\n                a[j] = state[j] ^ m_words[j];\n                b[j] = state[lanes + j] ^ m_words[lanes + j];\n                c[j] = state[(lanes * 2) + j] ^ m_words[(lanes * 2) + j];\n                d[j] = state[(lanes * 3) + j] ^ m_words[(lanes * 3) + j];\n            }\n\n            {\n                int step_index = 0;\n\n                for (i = 0; i < 4; i++) {\n                    int pi0 = round_pis[i][0];\n                    int pi1 = round_pis[i][1];\n                    int pi2 = round_pis[i][2];\n                    int pi3 = round_pis[i][3];\n\n                    step_if(a, b, c, d, w[step_index], lanes, pi0, pi1, p_xor_table[step_index]);\n                    step_index++;\n                    step_if(a, b, c, d, w[step_index], lanes, pi1, pi2, p_xor_table[step_index]);\n                    step_index++;\n                    step_if(a, b, c, d, w[step_index], lanes, pi2, pi3, p_xor_table[step_index]);\n                    step_index++;\n                    step_if(a, b, c, d, w[step_index], lanes, pi3, pi0, p_xor_table[step_index]);\n                    step_index++;\n\n                    step_maj(a, b, c, d, w[step_index], lanes, pi0, pi1, p_xor_table[step_index]);\n                    step_index++;\n                    step_maj(a, b, c, d, w[step_index], lanes, pi1, pi2, p_xor_table[step_index]);\n                    step_index++;\n                    step_maj(a, b, c, d, w[step_index], lanes, pi2, pi3, p_xor_table[step_index]);\n                    step_index++;\n                    step_maj(a, b, c, d, w[step_index], lanes, pi3, pi0, p_xor_table[step_index]);\n                    step_index++;\n                }\n\n                step_if(a, b, c, d, state, lanes, 0x04, 0x0d, p_xor_table[step_index]);\n                step_index++;\n                step_if(a, b, c, d, state + lanes, lanes, 0x0d, 0x0a, p_xor_table[step_index]);\n                step_index++;\n                step_if(a, b, c, d, state + (lanes * 2), lanes, 0x0a, 0x19, p_xor_table[step_index]);\n                step_index++;\n                step_if(a, b, c, d, state + (lanes * 3), lanes, 0x19, 0x04, p_xor_table[step_index]);\n            }\n\n            for (j = 0; j < lanes; j++) {\n                state[j] = a[j];\n                state[lanes + j] = b[j];\n                state[(lanes * 2) + j] = c[j];\n                state[(lanes * 3) + j] = d[j];\n            }\n        }\n\n        void compress_small(\n            uint32_t *state, const uint8_t *block, int final_flag, const uint16_t *rows_normal,\n            const uint16_t *rows_final, const uint8_t *p_xor_table)\n        {\n            compress_generic(state, block, final_flag, rows_normal, rows_final, p_xor_table, 4, 64, 128, 8);\n        }\n\n        void compress_big(\n            uint32_t *state, const uint8_t *block, int final_flag, const uint16_t *rows_normal,\n            const uint16_t *rows_final, const uint8_t *p_xor_table)\n        {\n            compress_generic(state, block, final_flag, rows_normal, rows_final, p_xor_table, 8, 128, 256, 16);\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void compress_small(\n            uint32_t *state, const uint8_t *block, int final_flag, const uint16_t *rows_normal,\n            const uint16_t *rows_final, const uint8_t  *p_xor_table);\n        void compress_big(\n            uint32_t *state, const uint8_t *block, int final_flag, const uint16_t *rows_normal,\n            const uint16_t *rows_final, const uint8_t *p_xor_table);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.SIMDBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            def flatten_ntt_rows(rows):\n                flat = []\n                for coeffs, add_const in rows:\n                    flat.extend(coeffs)\n                    flat.append(add_const)\n                return tuple(flat)\n\n            try:\n                if self.lanes == 4:\n                    rows_normal = ffi.new(\"uint16_t[]\", flatten_ntt_rows(self.ntt_rows_normal))\n                    rows_final = ffi.new(\"uint16_t[]\", flatten_ntt_rows(self.ntt_rows_final))\n                    p_xor_table = ffi.new(\"uint8_t[]\", tuple(self.p_xor_table))\n                elif self.lanes == 8:\n                    rows_normal = ffi.new(\"uint16_t[]\", flatten_ntt_rows(self.ntt_rows_normal))\n                    rows_final = ffi.new(\"uint16_t[]\", flatten_ntt_rows(self.ntt_rows_final))\n                    p_xor_table = ffi.new(\"uint8_t[]\", tuple(self.p_xor_table))\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib rows_normal rows_final p_xor_table\")(\n                ffi, lib, rows_normal, rows_final, p_xor_table,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        def prepare_constants(self):\n            cls = self.__class__\n            if not hasattr(cls, \"root_pows\"):\n                root_pows = [1] * self.order\n                for i in range(1, self.order):\n                    root_pows[i] = (root_pows[i - 1] * self.root) % 0x101\n                cls.root_pows = root_pows\n            if not hasattr(cls, \"ntt_rows_normal\"):\n                root_pows = self.root_pows\n                ntt_rows_normal = [None] * self.ntt_n\n                ntt_rows_final = [None] * self.ntt_n\n                for i in range(self.ntt_n):\n                    row = [0] * self.block_size\n                    for j in range(self.block_size):\n                        row[j] = root_pows[(i * j) % self.order]\n                    add_normal = root_pows[(self.const_exps[0] * i) % self.order]\n                    add_final = add_normal + root_pows[(self.const_exps[1] * i) % self.order]\n                    ntt_rows_normal[i] = (tuple(row), add_normal)\n                    ntt_rows_final[i] = (tuple(row), add_final)\n                cls.ntt_rows_normal = tuple(ntt_rows_normal)\n                cls.ntt_rows_final = tuple(ntt_rows_final)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.state = list(self.iv_words)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.prepare_constants()\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block, 0)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            words = c.state[: c.lanes * 2][: c.out_words]\n            out = b\"\".join(struct.pack(\"<I\", w) for w in words)\n            return out\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if len(self.buf) != 0:\n                if len(self.buf) < self.block_size:\n                    self.buf.extend(b\"\\x00\" * (self.block_size - len(self.buf)))\n                block = self.buf[:self.block_size]\n                del self.buf[:self.block_size]\n                self.compress(block, 0)\n            bit_len = self.msg_len * 8\n            bit_len = bit_len % (1 << (self.block_size * 8))\n            length_block = bit_len.to_bytes(self.block_size, \"little\")\n            self.compress(length_block, 1)\n            return\n\n        def compress(self, block, final_flag):\n\n            def ntt(block, rows):\n                y = [0] * self.ntt_n\n                for i in range(self.ntt_n):\n                    coeffs, add_const = rows[i]\n                    acc = add_const\n                    for j in range(self.block_size):\n                        acc += block[j] * coeffs[j]\n                    y[i] = acc % 0x101\n                return y\n\n            def lift257(v):\n                if v > 0x80:\n                    return v - 0x101\n                return v\n\n            def pack_code(x, y, c):\n                lo = (c * lift257(x)) & 0xffff\n                hi = (c * lift257(y)) & 0xffff\n                return lo | (hi << 0x10)\n\n            def message_expansion(block, final_flag):\n                if final_flag:\n                    y = ntt(block, self.ntt_rows_final)\n                else:\n                    y = ntt(block, self.ntt_rows_normal)\n                z = [None] * 32\n                lanes = self.lanes\n                z_stride = self.z_stride\n                ntt_n = self.ntt_n\n                half_n = ntt_n // 2\n\n                for i in range(32):\n                    row = [0] * lanes\n                    base = z_stride * i\n\n                    if i <= 15:\n                        for j in range(lanes):\n                            idx = base + 2 * j\n                            row[j] = pack_code(y[idx], y[idx + 1], 0xb9)\n                    elif i <= 23:\n                        for j in range(lanes):\n                            idx = base + 2 * j\n                            row[j] = pack_code(y[idx - ntt_n], y[idx - half_n], 0xe9)\n                    else:\n                        offset0 = ntt_n + half_n - 1\n                        offset1 = ntt_n - 1\n                        for j in range(lanes):\n                            idx = base + 2 * j\n                            row[j] = pack_code(y[idx - offset0], y[idx - offset1], 0xe9)\n                    z[i] = row\n\n                w = [None] * 32\n                for i in range(32):\n                    w[i] = z[self.P[i]]\n                return w\n\n            def rol32(x, n):\n                return ((x << n) | (x >> (0x20 - n))) & 0xffff_ffff\n\n            def step_if(a, b, c, d, w_vec, r, s, p):\n                new_a = [0] * self.lanes\n                new_b = [0] * self.lanes\n                new_c = [0] * self.lanes\n                new_d = [0] * self.lanes\n                for j in range(self.lanes):\n                    phi = c[j] ^ (a[j] & (b[j] ^ c[j]))\n                    t = (d[j] + w_vec[j] + phi) & 0xffff_ffff\n                    t = rol32(t, s)\n                    u = rol32(a[j ^ p], r)\n                    new_a[j] = (t + u) & 0xffff_ffff\n                    new_b[j] = rol32(a[j], r)\n                    new_c[j] = b[j]\n                    new_d[j] = c[j]\n                return new_a, new_b, new_c, new_d\n\n            def step_maj(a, b, c, d, w_vec, r, s, p):\n                new_a = [0] * self.lanes\n                new_b = [0] * self.lanes\n                new_c = [0] * self.lanes\n                new_d = [0] * self.lanes\n                for j in range(self.lanes):\n                    phi = (a[j] & b[j]) | (c[j] & (a[j] | b[j]))\n                    t = (d[j] + w_vec[j] + phi) & 0xffff_ffff\n                    t = rol32(t, s)\n                    u = rol32(a[j ^ p], r)\n                    new_a[j] = (t + u) & 0xffff_ffff\n                    new_b[j] = rol32(a[j], r)\n                    new_c[j] = b[j]\n                    new_d[j] = c[j]\n                return new_a, new_b, new_c, new_d\n\n            if len(block) != self.block_size:\n                raise ValueError(\"invalid block size\")\n\n            if self.USE_CFFI:\n                state_buf = self.cffi.ffi.new(\"uint32_t[]\", self.state)\n                block_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(block))\n                if self.lanes == 4:\n                    clib_compress = self.cffi.lib.compress_small\n                else:\n                    clib_compress = self.cffi.lib.compress_big\n                clib_compress(\n                    state_buf, block_buf, int(final_flag),\n                    self.cffi.rows_normal, self.cffi.rows_final, self.cffi.p_xor_table,\n                )\n                self.state = [state_buf[i] for i in range(self.lanes * 4)]\n                return\n\n            w = message_expansion(block, final_flag)\n            m_words = struct.unpack(\"<\" + \"I\" * (self.lanes * 4), block)\n            s_words = [0] * (self.lanes * 4)\n            for i in range(self.lanes * 4):\n                s_words[i] = self.state[i] ^ m_words[i]\n            lanes = self.lanes\n\n            a = list(s_words[0 : lanes])\n            b = list(s_words[lanes : lanes * 2])\n            c = list(s_words[lanes * 2 : lanes * 3])\n            d = list(s_words[lanes * 3 : lanes * 4])\n            ptab = self.p_xor_table\n            step_index = 0\n            for rnd in range(4):\n                pi0, pi1, pi2, pi3 = self.round_pis[rnd]\n\n                a, b, c, d = step_if(a, b, c, d, w[step_index], pi0, pi1, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_if(a, b, c, d, w[step_index], pi1, pi2, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_if(a, b, c, d, w[step_index], pi2, pi3, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_if(a, b, c, d, w[step_index], pi3, pi0, ptab[step_index])\n                step_index += 1\n\n                a, b, c, d = step_maj(a, b, c, d, w[step_index], pi0, pi1, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_maj(a, b, c, d, w[step_index], pi1, pi2, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_maj(a, b, c, d, w[step_index], pi2, pi3, ptab[step_index])\n                step_index += 1\n                a, b, c, d = step_maj(a, b, c, d, w[step_index], pi3, pi0, ptab[step_index])\n                step_index += 1\n\n            iv_a = self.state[0 : lanes]\n            iv_b = self.state[lanes : lanes * 2]\n            iv_c = self.state[lanes * 2 : lanes * 3]\n            iv_d = self.state[lanes * 3 : lanes * 4]\n\n            a, b, c, d = step_if(a, b, c, d, iv_a, 0x04, 0x0d, ptab[step_index])\n            step_index += 1\n            a, b, c, d = step_if(a, b, c, d, iv_b, 0x0d, 0x0a, ptab[step_index])\n            step_index += 1\n            a, b, c, d = step_if(a, b, c, d, iv_c, 0x0a, 0x19, ptab[step_index])\n            step_index += 1\n            a, b, c, d = step_if(a, b, c, d, iv_d, 0x19, 0x04, ptab[step_index])\n            self.state = list(a + b + c + d)\n            return\n\n    class SIMD224(SIMDBase):\n        block_size = 0x40\n        digest_size = 28\n        lanes = 4\n\n        ntt_n = 0x80\n        order = 0x80\n        z_stride = 0x08\n        root = 0x8b\n        const_exps = [0x7f, 0x7d]\n\n        out_words = 7\n        p_xor_table = (\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n        )\n        iv_words = (\n            0x3358_6e9f, 0x12ff_f033, 0xb2d9_f64d, 0x6f8f_ea53, 0xde94_3106, 0x2742_e439, 0x4fba_b5ac, 0x62b9_ff96,\n            0x22e7_b0af, 0xc862_b3a8, 0x33e0_0cdc, 0x236b_86a6, 0xf64a_e77c, 0xfa37_3b76, 0x7dc1_ee5b, 0x7fb2_9ce8,\n        )\n\n    class SIMD256(SIMDBase):\n        block_size = 0x40\n        digest_size = 32\n        lanes = 4\n\n        ntt_n = 0x80\n        order = 0x80\n        z_stride = 0x08\n        root = 0x8b\n        const_exps = [0x7f, 0x7d]\n\n        out_words = 8\n        p_xor_table = (\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n            0x01, 0x02, 0x03, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03,\n        )\n        iv_words = (\n            0x4d56_7983, 0x0719_0ba9, 0x8474_577b, 0x39d7_26e9, 0xaaf3_d925, 0x3ee2_0b03, 0xafd5_e751, 0xc960_06d3,\n            0xc2c2_ba14, 0x49b3_bcb4, 0xf67c_af46, 0x6686_26c9, 0xe2ea_a8d2, 0x1ff4_7833, 0xd0c6_61a5, 0x5569_3de1,\n        )\n\n    class SIMD384(SIMDBase):\n        block_size = 0x80\n        digest_size = 48\n        lanes = 8\n\n        ntt_n = 0x100\n        order = 0x100\n        z_stride = 0x10\n        root = 0x29\n        const_exps = [0xff, 0xfd]\n\n        out_words = 12\n        p_xor_table = (\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01,\n        )\n        iv_words = (\n            0x8a36_eebc, 0x94a3_bd90, 0xd153_7b83, 0xb25b_070b, 0xf463_f1b5, 0xb6f8_1e20, 0x0055_c339, 0xb4d1_44d1,\n            0x7360_ca61, 0x1836_1a03, 0x17dc_b4b9, 0x3414_c45a, 0xa699_a9d2, 0xe39e_9664, 0x468b_fe77, 0x51d0_62f8,\n            0xb9e3_bfe8, 0x63be_ce2a, 0x8fe5_06b9, 0xf8cc_4ac2, 0x7ae1_1542, 0xb1aa_dda1, 0x64b0_6794, 0x28d2_f462,\n            0xe640_71ec, 0x1deb_91a8, 0x8ac8_db23, 0x3f78_2ab5, 0x039b_5cb8, 0x71dd_d962, 0xfade_2cea, 0x1416_df71,\n        )\n\n    class SIMD512(SIMDBase):\n        block_size = 0x80\n        digest_size = 64\n        lanes = 8\n\n        ntt_n = 0x100\n        order = 0x100\n        z_stride = 0x10\n        root = 0x29\n        const_exps = [0xff, 0xfd]\n\n        out_words = 16\n        p_xor_table = (\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01, 0x06, 0x02, 0x03, 0x05, 0x07, 0x04,\n            0x01,\n        )\n        iv_words = (\n            0x0ba1_6b95, 0x72f9_99ad, 0x9fec_c2ae, 0xba32_64fc, 0x5e89_4929, 0x8e9f_30e5, 0x2f1d_aa37, 0xf0f2_c558,\n            0xac50_6643, 0xa906_35a5, 0xe25b_878b, 0xaab7_878f, 0x8881_7f7a, 0x0a02_892b, 0x559a_7550, 0x598f_657e,\n            0x7eef_60a1, 0x6b70_e3e8, 0x9c17_14d1, 0xb958_e2a8, 0xab02_675e, 0xed1c_014f, 0xcd8d_65bb, 0xfdb7_a257,\n            0x0925_4899, 0xd699_c7bc, 0x9019_b6dc, 0x2b90_22e4, 0x8fa1_4956, 0x21bf_9bd3, 0xb94d_0943, 0x6ffd_dc22,\n        )\n\n    class BMWHBase:\n        W_SCHEDULE = (\n            (5, \"-\", 7, \"+\", 10, \"+\", 13, \"+\", 14),\n            (6, \"-\", 8, \"+\", 11, \"+\", 14, \"-\", 15),\n            (0, \"+\", 7, \"+\", 9, \"-\", 12, \"+\", 15),\n            (0, \"-\", 1, \"+\", 8, \"-\", 10, \"+\", 13),\n            (1, \"+\", 2, \"+\", 9, \"-\", 11, \"-\", 14),\n            (3, \"-\", 2, \"+\", 10, \"-\", 12, \"+\", 15),\n            (4, \"-\", 0, \"-\", 3, \"-\", 11, \"+\", 13),\n            (1, \"-\", 4, \"-\", 5, \"-\", 12, \"-\", 14),\n            (2, \"-\", 5, \"-\", 6, \"+\", 13, \"-\", 15),\n            (0, \"-\", 3, \"+\", 6, \"-\", 7, \"+\", 14),\n            (8, \"-\", 1, \"-\", 4, \"-\", 7, \"+\", 15),\n            (8, \"-\", 0, \"-\", 2, \"-\", 5, \"+\", 9),\n            (1, \"+\", 3, \"-\", 6, \"-\", 9, \"+\", 10),\n            (2, \"+\", 4, \"+\", 7, \"+\", 10, \"+\", 11),\n            (3, \"-\", 5, \"+\", 8, \"-\", 11, \"-\", 12),\n            (12, \"-\", 4, \"-\", 6, \"-\", 9, \"+\", 13),\n        )\n        # For i16=16..31: (j0m, j1m, j3m, j4m, j7m, j10m, j11m)\n        # j1m/j4m/j11m are rotation amounts.\n        M16_TABLE = (\n            (0, 1, 3, 4, 7, 10, 11),\n            (1, 2, 4, 5, 8, 11, 12),\n            (2, 3, 5, 6, 9, 12, 13),\n            (3, 4, 6, 7, 10, 13, 14),\n            (4, 5, 7, 8, 11, 14, 15),\n            (5, 6, 8, 9, 12, 15, 16),\n            (6, 7, 9, 10, 13, 0, 1),\n            (7, 8, 10, 11, 14, 1, 2),\n            (8, 9, 11, 12, 15, 2, 3),\n            (9, 10, 12, 13, 0, 3, 4),\n            (10, 11, 13, 14, 1, 4, 5),\n            (11, 12, 14, 15, 2, 5, 6),\n            (12, 13, 15, 16, 3, 6, 7),\n            (13, 14, 0, 1, 4, 7, 8),\n            (14, 15, 1, 2, 5, 8, 9),\n            (15, 16, 2, 3, 6, 9, 10),\n        )\n\n        def __init__(self, data=b\"\"):\n            if self.word_bits not in (32, 64):\n                raise ValueError(\"invalid word_bits\")\n            if len(self.iv) != 16:\n                raise ValueError(\"iv missing/invalid\")\n            if len(self.final_const) != 16:\n                raise ValueError(\"final_const missing/invalid\")\n            self.H = list(self.iv)\n            self.buf = bytearray()\n            self.msg_len = 0  # in bytes\n            self.result_bytes = b\"\"\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.H = list(self.H)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.result_bytes = self.result_bytes\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.H = self.compress(block, self.H)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.result_bytes\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != (self.block_size - 8):\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\"<Q\", bit_len & 0xffff_ffff_ffff_ffff))\n\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.H = self.compress(block, self.H)\n\n            block2 = bytearray(self.block_size)\n            if self.word_bits == 32:\n                for i, w in enumerate(self.H):\n                    struct.pack_into(\"<I\", block2, i * 4, w)\n            else:\n                for i, w in enumerate(self.H):\n                    struct.pack_into(\"<Q\", block2, i * 8, w)\n\n            h1 = self.compress(bytes(block2), list(self.final_const))\n            start = 16 - self.out_words\n            out = bytearray()\n            if self.word_bits == 32:\n                for w in h1[start:]:\n                    out.extend(struct.pack(\"<I\", w))\n            else:\n                for w in h1[start:]:\n                    out.extend(struct.pack(\"<Q\", w))\n\n            self.result_bytes = bytes(out[:self.digest_size])\n            return\n\n        def compress(self, block, H):\n\n            def align(x):\n                if self.word_bits == 32:\n                    return x & 0xffff_ffff\n                return x & 0xffff_ffff_ffff_ffff\n\n            def rol(x, n):\n                if self.word_bits == 32:\n                    n &= 31\n                    x &= 0xffff_ffff\n                    return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n                n &= 63\n                x &= 0xffff_ffff_ffff_ffff\n                return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n            def add_elt(M, H, i16):\n                j0m, j1m, j3m, j4m, j7m, j10m, j11m = self.M16_TABLE[i16 - 16]\n                if self.word_bits == 32:\n                    k = align(i16 * 0x0555_5555)\n                else:\n                    k = align(i16 * 0x0555_5555_5555_5555)\n                v = align(rol(M[j0m], j1m) + rol(M[j3m], j4m) - rol(M[j10m], j11m) + k)\n                return v ^ H[j7m]\n\n            def make_w(M, H, entry):\n                i0, op01, i1, op12, i2, op23, i3, op34, i4 = entry\n                res = M[i0] ^ H[i0]\n                for op, val in [(op01, M[i1] ^ H[i1]), (op12, M[i2] ^ H[i2]), (op23, M[i3] ^ H[i3]), (op34, M[i4] ^ H[i4])]:\n                    if op == \"+\":\n                        res = res + val\n                    else:\n                        res = res - val\n                return align(res)\n\n            def expand1(Q, M, H, i16):\n                base = i16 - 16\n                if self.word_bits == 32:\n                    funcs = [ss1, ss2, ss3, ss0] * 4\n                else:\n                    funcs = [sb1, sb2, sb3, sb0] * 4\n                s = 0\n                for k in range(16):\n                    s += funcs[k](Q[base + k])\n                s += add_elt(M, H, i16)\n                return align(s)\n\n            def expand2(Q, M, H, i16):\n                base = i16 - 16\n                if self.word_bits == 32:\n                    s = (\n                        Q[base + 0] + rol(Q[base + 1], 3) + Q[base + 2] + rol(Q[base + 3], 7)\n                        + Q[base + 4] + rol(Q[base + 5], 13) + Q[base + 6] + rol(Q[base + 7], 16)\n                        + Q[base + 8] + rol(Q[base + 9], 19) + Q[base + 10] + rol(Q[base + 11], 23)\n                        + Q[base + 12] + rol(Q[base + 13], 27) + ((Q[base + 14] >> 1) ^ Q[base + 14])\n                        + ((Q[base + 15] >> 2) ^ Q[base + 15]) + add_elt(M, H, i16)\n                    )\n                else:\n                    s = (\n                        Q[base + 0] + rol(Q[base + 1], 5) + Q[base + 2] + rol(Q[base + 3], 11)\n                        + Q[base + 4] + rol(Q[base + 5], 27) + Q[base + 6] + rol(Q[base + 7], 32)\n                        + Q[base + 8] + rol(Q[base + 9], 37) + Q[base + 10] + rol(Q[base + 11], 43)\n                        + Q[base + 12] + rol(Q[base + 13], 53) + ((Q[base + 14] >> 1) ^ Q[base + 14])\n                        + ((Q[base + 15] >> 2) ^ Q[base + 15]) + add_elt(M, H, i16)\n                    )\n                return align(s)\n\n            def ss0(x):\n                return align((x >> 1) ^ (x << 3) ^ rol(x, 4) ^ rol(x, 19))\n\n            def ss1(x):\n                return align((x >> 1) ^ (x << 2) ^ rol(x, 8) ^ rol(x, 23))\n\n            def ss2(x):\n                return align((x >> 2) ^ (x << 1) ^ rol(x, 12) ^ rol(x, 25))\n\n            def ss3(x):\n                return align((x >> 2) ^ (x << 2) ^ rol(x, 15) ^ rol(x, 29))\n\n            def ss4(x):\n                return align((x >> 1) ^ x)\n\n            def sb0(x):\n                return align((x >> 1) ^ (x << 3) ^ rol(x, 4) ^ rol(x, 37))\n\n            def sb1(x):\n                return align((x >> 1) ^ (x << 2) ^ rol(x, 13) ^ rol(x, 43))\n\n            def sb2(x):\n                return align((x >> 2) ^ (x << 1) ^ rol(x, 19) ^ rol(x, 53))\n\n            def sb3(x):\n                return align((x >> 2) ^ (x << 2) ^ rol(x, 28) ^ rol(x, 59))\n\n            def sb4(x):\n                return align((x >> 1) ^ x)\n\n            if self.word_bits == 32:\n                init_funcs = [ss0, ss1, ss2, ss3, ss4]\n                M = list(struct.unpack(\"<16I\", block))\n            else:\n                init_funcs = [sb0, sb1, sb2, sb3, sb4]\n                M = list(struct.unpack(\"<16Q\", block))\n\n            Q = [0] * 32\n            W = [make_w(M, H, e) for e in self.W_SCHEDULE]\n            for j in range(15):\n                Q[j] = align(init_funcs[j % 5](W[j]) + H[(j + 1) & 15])\n            Q[15] = align(init_funcs[0](W[15]) + H[0])\n            Q[16] = expand1(Q, M, H, 16)\n            Q[17] = expand1(Q, M, H, 17)\n            for j in range(18, 32):\n                Q[j] = expand2(Q, M, H, j)\n\n            xl = Q[16] ^ Q[17] ^ Q[18] ^ Q[19] ^ Q[20] ^ Q[21] ^ Q[22] ^ Q[23]\n            xh = xl ^ Q[24] ^ Q[25] ^ Q[26] ^ Q[27] ^ Q[28] ^ Q[29] ^ Q[30] ^ Q[31]\n\n            dh = [0] * 16\n            dh[0] = align(((xh << 5) ^ (Q[16] >> 5) ^ M[0]) + (xl ^ Q[24] ^ Q[0]))\n            dh[1] = align(((xh >> 7) ^ (Q[17] << 8) ^ M[1]) + (xl ^ Q[25] ^ Q[1]))\n            dh[2] = align(((xh >> 5) ^ (Q[18] << 5) ^ M[2]) + (xl ^ Q[26] ^ Q[2]))\n            dh[3] = align(((xh >> 1) ^ (Q[19] << 5) ^ M[3]) + (xl ^ Q[27] ^ Q[3]))\n            dh[4] = align(((xh >> 3) ^ (Q[20] << 0) ^ M[4]) + (xl ^ Q[28] ^ Q[4]))\n            dh[5] = align(((xh << 6) ^ (Q[21] >> 6) ^ M[5]) + (xl ^ Q[29] ^ Q[5]))\n            dh[6] = align(((xh >> 4) ^ (Q[22] << 6) ^ M[6]) + (xl ^ Q[30] ^ Q[6]))\n            dh[7] = align(((xh >> 11) ^ (Q[23] << 2) ^ M[7]) + (xl ^ Q[31] ^ Q[7]))\n            dh[8] = align(rol(dh[4], 9) + (xh ^ Q[24] ^ M[8]) + ((xl << 8) ^ Q[23] ^ Q[8]))\n            dh[9] = align(rol(dh[5], 10) + (xh ^ Q[25] ^ M[9]) + ((xl >> 6) ^ Q[16] ^ Q[9]))\n            dh[10] = align(rol(dh[6], 11) + (xh ^ Q[26] ^ M[10]) + ((xl << 6) ^ Q[17] ^ Q[10]))\n            dh[11] = align(rol(dh[7], 12) + (xh ^ Q[27] ^ M[11]) + ((xl << 4) ^ Q[18] ^ Q[11]))\n            dh[12] = align(rol(dh[0], 13) + (xh ^ Q[28] ^ M[12]) + ((xl >> 3) ^ Q[19] ^ Q[12]))\n            dh[13] = align(rol(dh[1], 14) + (xh ^ Q[29] ^ M[13]) + ((xl >> 4) ^ Q[20] ^ Q[13]))\n            dh[14] = align(rol(dh[2], 15) + (xh ^ Q[30] ^ M[14]) + ((xl >> 7) ^ Q[21] ^ Q[14]))\n            dh[15] = align(rol(dh[3], 16) + (xh ^ Q[31] ^ M[15]) + ((xl >> 2) ^ Q[22] ^ Q[15]))\n            return dh\n\n    class BMW224(BMWHBase):\n        block_size = 64\n        digest_size = 28\n        word_bits = 32\n        out_words = 7\n        iv = (\n            0x0001_0203, 0x0405_0607, 0x0809_0a0b, 0x0c0d_0e0f, 0x1011_1213, 0x1415_1617, 0x1819_1a1b, 0x1c1d_1e1f,\n            0x2021_2223, 0x2425_2627, 0x2829_2a2b, 0x2c2d_2e2f, 0x3031_3233, 0x3435_3637, 0x3839_3a3b, 0x3c3d_3e3f,\n        )\n        final_const = (\n            0xaaaa_aaa0, 0xaaaa_aaa1, 0xaaaa_aaa2, 0xaaaa_aaa3, 0xaaaa_aaa4, 0xaaaa_aaa5, 0xaaaa_aaa6, 0xaaaa_aaa7,\n            0xaaaa_aaa8, 0xaaaa_aaa9, 0xaaaa_aaaa, 0xaaaa_aaab, 0xaaaa_aaac, 0xaaaa_aaad, 0xaaaa_aaae, 0xaaaa_aaaf,\n        )\n\n    class BMW256(BMWHBase):\n        block_size = 64\n        digest_size = 32\n        word_bits = 32\n        out_words = 8\n        iv = (\n            0x4041_4243, 0x4445_4647, 0x4849_4a4b, 0x4c4d_4e4f, 0x5051_5253, 0x5455_5657, 0x5859_5a5b, 0x5c5d_5e5f,\n            0x6061_6263, 0x6465_6667, 0x6869_6a6b, 0x6c6d_6e6f, 0x7071_7273, 0x7475_7677, 0x7879_7a7b, 0x7c7d_7e7f,\n        )\n        final_const = (\n            0xaaaa_aaa0, 0xaaaa_aaa1, 0xaaaa_aaa2, 0xaaaa_aaa3, 0xaaaa_aaa4, 0xaaaa_aaa5, 0xaaaa_aaa6, 0xaaaa_aaa7,\n            0xaaaa_aaa8, 0xaaaa_aaa9, 0xaaaa_aaaa, 0xaaaa_aaab, 0xaaaa_aaac, 0xaaaa_aaad, 0xaaaa_aaae, 0xaaaa_aaaf,\n        )\n\n    class BMW384(BMWHBase):\n        block_size = 128\n        digest_size = 48\n        word_bits = 64\n        out_words = 6\n        iv = (\n            0x0001_0203_0405_0607, 0x0809_0a0b_0c0d_0e0f, 0x1011_1213_1415_1617, 0x1819_1a1b_1c1d_1e1f,\n            0x2021_2223_2425_2627, 0x2829_2a2b_2c2d_2e2f, 0x3031_3233_3435_3637, 0x3839_3a3b_3c3d_3e3f,\n            0x4041_4243_4445_4647, 0x4849_4a4b_4c4d_4e4f, 0x5051_5253_5455_5657, 0x5859_5a5b_5c5d_5e5f,\n            0x6061_6263_6465_6667, 0x6869_6a6b_6c6d_6e6f, 0x7071_7273_7475_7677, 0x7879_7a7b_7c7d_7e7f,\n        )\n        final_const = (\n            0xaaaa_aaaa_aaaa_aaa0, 0xaaaa_aaaa_aaaa_aaa1, 0xaaaa_aaaa_aaaa_aaa2, 0xaaaa_aaaa_aaaa_aaa3,\n            0xaaaa_aaaa_aaaa_aaa4, 0xaaaa_aaaa_aaaa_aaa5, 0xaaaa_aaaa_aaaa_aaa6, 0xaaaa_aaaa_aaaa_aaa7,\n            0xaaaa_aaaa_aaaa_aaa8, 0xaaaa_aaaa_aaaa_aaa9, 0xaaaa_aaaa_aaaa_aaaa, 0xaaaa_aaaa_aaaa_aaab,\n            0xaaaa_aaaa_aaaa_aaac, 0xaaaa_aaaa_aaaa_aaad, 0xaaaa_aaaa_aaaa_aaae, 0xaaaa_aaaa_aaaa_aaaf,\n        )\n\n    class BMW512(BMWHBase):\n        block_size = 128\n        digest_size = 64\n        word_bits = 64\n        out_words = 8\n        iv = (\n            0x8081_8283_8485_8687, 0x8889_8a8b_8c8d_8e8f, 0x9091_9293_9495_9697, 0x9899_9a9b_9c9d_9e9f,\n            0xa0a1_a2a3_a4a5_a6a7, 0xa8a9_aaab_acad_aeaf, 0xb0b1_b2b3_b4b5_b6b7, 0xb8b9_babb_bcbd_bebf,\n            0xc0c1_c2c3_c4c5_c6c7, 0xc8c9_cacb_cccd_cecf, 0xd0d1_d2d3_d4d5_d6d7, 0xd8d9_dadb_dcdd_dedf,\n            0xe0e1_e2e3_e4e5_e6e7, 0xe8e9_eaeb_eced_eeef, 0xf0f1_f2f3_f4f5_f6f7, 0xf8f9_fafb_fcfd_feff,\n        )\n        final_const = (\n            0xaaaa_aaaa_aaaa_aaa0, 0xaaaa_aaaa_aaaa_aaa1, 0xaaaa_aaaa_aaaa_aaa2, 0xaaaa_aaaa_aaaa_aaa3,\n            0xaaaa_aaaa_aaaa_aaa4, 0xaaaa_aaaa_aaaa_aaa5, 0xaaaa_aaaa_aaaa_aaa6, 0xaaaa_aaaa_aaaa_aaa7,\n            0xaaaa_aaaa_aaaa_aaa8, 0xaaaa_aaaa_aaaa_aaa9, 0xaaaa_aaaa_aaaa_aaaa, 0xaaaa_aaaa_aaaa_aaab,\n            0xaaaa_aaaa_aaaa_aaac, 0xaaaa_aaaa_aaaa_aaad, 0xaaaa_aaaa_aaaa_aaae, 0xaaaa_aaaa_aaaa_aaaf,\n        )\n\n    class RadioGatunBase:\n        digest_size = 0x20\n        blank_rounds = 0x10\n\n        def __init__(self, data=b\"\"):\n            if self.word_bits is None or self.rotate is None:\n                raise ValueError(\"word_bits and rotate must be set in subclasses\")\n            self.word_bytes = self.word_bits // 8\n            if self.block_size is None:\n                self.block_size = self.word_bytes * 3\n            self.word_mask = (1 << self.word_bits) - 1\n            self.mill = [0] * 0x13\n            self.belt = [0] * (13 * 3)\n            self.buf = bytearray()\n            self.is_finalized = False\n            self.phase = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.mill = list(self.mill)\n            other.belt = list(self.belt)\n            other.buf = bytearray(self.buf)\n            other.is_finalized = self.is_finalized\n            other.phase = self.phase\n            return other\n\n        def update(self, data):\n            if self.is_finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[: self.block_size])\n                del self.buf[: self.block_size]\n                self.absorb_block(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.squeeze(self.digest_size)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.is_finalized:\n                return\n            data = bytes(self.buf) + b\"\\x01\"\n            self.buf = bytearray()\n            rem = len(data) % self.block_size\n            if rem != 0:\n                data += b\"\\x00\" * (self.block_size - rem)\n            for off in range(0, len(data), self.block_size):\n                self.absorb_block(data[off : off + self.block_size])\n            for _ in range(self.blank_rounds):\n                self.beltmill()\n            self.is_finalized = True\n            self.phase = 0\n            return\n\n        def squeeze(self, nbytes):\n\n            def get_word():\n                if self.phase == 0:\n                    self.beltmill()\n                    self.phase = 1\n                out = self.mill[self.phase]\n                self.phase += 1\n                if self.phase > 2:\n                    self.phase = 0\n                return out\n\n            if not self.is_finalized:\n                self.finalize()\n            out = bytearray()\n            while len(out) < nbytes:\n                w = get_word()\n                out.extend(w.to_bytes(self.word_bytes, \"little\"))\n            return bytes(out[:nbytes])\n\n        def beltmill(self):\n\n            def ror(x, r):\n                if r == 0:\n                    return x\n                return ((x >> r) | (x << (self.word_bits - r))) & self.word_mask\n\n            def mill_func(mill):\n                A = [0] * 19\n                for i in range(19):\n                    A[i] = mill[i] ^ (mill[(i + 1) % 19] | (mill[(i + 2) % 19] ^ self.word_mask))\n                a = [0] * 19\n                for i in range(19):\n                    a[i] = ror(A[(7 * i) % 19], self.rotate[i])\n                for i in range(19):\n                    A[i] = a[i] ^ a[(i + 1) % 19] ^ a[(i + 4) % 19]\n                A[0] ^= 1\n                return A\n\n            old_belt = self.belt\n            old_mill = self.mill\n            new_belt = [0] * (13 * 3)\n            for i in range(13):\n                src = (i - 1) % 13\n                new_belt[i * 3 : (i + 1) * 3] = old_belt[src * 3 : (src + 1) * 3]\n            for i in range(12):\n                stage = i + 1\n                word = i % 3\n                new_belt[stage * 3 + word] ^= old_mill[i + 1]\n            new_mill = mill_func(old_mill)\n            base = 12 * 3\n            new_mill[13] ^= old_belt[base + 0]\n            new_mill[14] ^= old_belt[base + 1]\n            new_mill[15] ^= old_belt[base + 2]\n            self.belt = new_belt\n            self.mill = new_mill\n            return\n\n        def absorb_block(self, block):\n            w = self.word_bytes\n            p0 = int.from_bytes(block[0 * w:1 * w], \"little\")\n            p1 = int.from_bytes(block[1 * w:2 * w], \"little\")\n            p2 = int.from_bytes(block[2 * w:3 * w], \"little\")\n            self.belt[0] ^= p0\n            self.belt[1] ^= p1\n            self.belt[2] ^= p2\n            self.mill[16] ^= p0\n            self.mill[17] ^= p1\n            self.mill[18] ^= p2\n            self.beltmill()\n            return\n\n    class RadioGatun32(RadioGatunBase):\n        block_size = 0x0c\n        word_bits = 0x20\n        rotate = (\n            0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c, 0x04, 0x0d,\n            0x17, 0x02, 0x0e, 0x1b, 0x09, 0x18, 0x08, 0x19, 0x0b,\n        )\n\n    class RadioGatun64(RadioGatunBase):\n        block_size = 0x18\n        word_bits = 0x40\n        rotate = (\n            0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c, 0x24, 0x2d,\n            0x37, 0x02, 0x0e, 0x1b, 0x29, 0x38, 0x08, 0x19, 0x2b,\n        )\n\n    class ED2KBase:\n        block_size = 64\n        digest_size = 16\n        chunk_size = 9_728_000\n\n        def __init__(self, data=b\"\"):\n            self.chunk_hasher = Hash.MD4()\n            self.chunk_len = 0\n            self.list_hasher = Hash.MD4()\n            self.chunk_count = 0\n            self.first_chunk_hash = b\"\\x00\" * 16\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.chunk_hasher = self.chunk_hasher.copy()\n            other.chunk_len = self.chunk_len\n            other.list_hasher = self.list_hasher.copy()\n            other.chunk_count = self.chunk_count\n            other.first_chunk_hash = bytes(self.first_chunk_hash)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            pos = 0\n            total = len(data)\n            while pos < total:\n                free = self.chunk_size - self.chunk_len\n                take = total - pos\n                if take > free:\n                    take = free\n                part = data[pos:pos + take]\n                self.chunk_hasher.update(part)\n                self.chunk_len += take\n                pos += take\n                if self.chunk_len == self.chunk_size:\n                    self.hash_chunk()\n            return self\n\n        def digest(self):\n            c = self.copy()\n            return c.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.variant_name == \"red\":\n                return self.finalize_red()\n            if self.variant_name == \"blue\":\n                return self.finalize_blue()\n            if self.variant_name == \"redblue\":\n                return self.finalize_redblue()\n            raise ValueError(\"unknown ED2K variant\")\n\n        def hash_chunk(self):\n            chunk_hash = self.chunk_hasher.digest()\n            self.chunk_hasher = Hash.MD4()\n            self.chunk_len = 0\n            if self.chunk_count == 0:\n                self.first_chunk_hash = bytes(chunk_hash)\n            self.chunk_count += 1\n            self.list_hasher.update(chunk_hash)\n            return\n\n        def list_digest(self):\n            return self.list_hasher.digest()\n\n        def finalize_red(self):\n            if self.chunk_count == 0:\n                self.hash_chunk()\n                return bytes(self.first_chunk_hash)\n            self.hash_chunk()\n            return self.list_digest()\n\n        def finalize_blue(self):\n            if self.chunk_count == 0:\n                self.hash_chunk()\n                return bytes(self.first_chunk_hash)\n            if self.chunk_len != 0:\n                self.hash_chunk()\n                return self.list_digest()\n            if self.chunk_count == 1:\n                return bytes(self.first_chunk_hash)\n            return self.list_digest()\n\n        def finalize_redblue(self):\n            if self.chunk_count == 0:\n                self.hash_chunk()\n                one = bytes(self.first_chunk_hash)\n                return one + one\n            if self.chunk_len != 0:\n                self.hash_chunk()\n                one = self.list_digest()\n                return one + one\n            if self.chunk_count == 1:\n                blue = bytes(self.first_chunk_hash)\n            else:\n                blue = self.list_digest()\n            self.hash_chunk()\n            red = self.list_digest()\n            return red + blue\n\n    class ED2KRed(ED2KBase):\n        digest_size = 16\n        variant_name = \"red\"\n\n    class ED2KBlue(ED2KBase):\n        digest_size = 16\n        variant_name = \"blue\"\n\n    class ED2KRedBlue(ED2KBase):\n        digest_size = 32\n        variant_name = \"redblue\"\n\n    class MDC2:\n        block_size = 8\n        digest_size = 16\n        IP = (\n            0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, 0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04,\n            0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08,\n            0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3b, 0x33, 0x2b, 0x23, 0x1b, 0x13, 0x0b, 0x03,\n            0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05, 0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07,\n        )\n        FP = (\n            0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20, 0x27, 0x07, 0x2f, 0x0f, 0x37, 0x17, 0x3f, 0x1f,\n            0x26, 0x06, 0x2e, 0x0e, 0x36, 0x16, 0x3e, 0x1e, 0x25, 0x05, 0x2d, 0x0d, 0x35, 0x15, 0x3d, 0x1d,\n            0x24, 0x04, 0x2c, 0x0c, 0x34, 0x14, 0x3c, 0x1c, 0x23, 0x03, 0x2b, 0x0b, 0x33, 0x13, 0x3b, 0x1b,\n            0x22, 0x02, 0x2a, 0x0a, 0x32, 0x12, 0x3a, 0x1a, 0x21, 0x01, 0x29, 0x09, 0x31, 0x11, 0x39, 0x19,\n        )\n        E = (\n            0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x08, 0x09, 0x0a, 0x0b,\n            0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x14, 0x15,\n            0x16, 0x17, 0x18, 0x19, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x01,\n        )\n        P = (\n            0x10, 0x07, 0x14, 0x15, 0x1d, 0x0c, 0x1c, 0x11, 0x01, 0x0f, 0x17, 0x1a, 0x05, 0x12, 0x1f, 0x0a,\n            0x02, 0x08, 0x18, 0x0e, 0x20, 0x1b, 0x03, 0x09, 0x13, 0x0d, 0x1e, 0x06, 0x16, 0x0b, 0x04, 0x19,\n        )\n        PC1 = (\n            0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,\n            0x3b, 0x33, 0x2b, 0x23, 0x1b, 0x13, 0x0b, 0x03, 0x3c, 0x34, 0x2c, 0x24, 0x3f, 0x37, 0x2f, 0x27,\n            0x1f, 0x17, 0x0f, 0x07, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06, 0x3d, 0x35, 0x2d, 0x25,\n            0x1d, 0x15, 0x0d, 0x05, 0x1c, 0x14, 0x0c, 0x04,\n        )\n        PC2 = (\n            0x0e, 0x11, 0x0b, 0x18, 0x01, 0x05, 0x03, 0x1c, 0x0f, 0x06, 0x15, 0x0a, 0x17, 0x13, 0x0c, 0x04,\n            0x1a, 0x08, 0x10, 0x07, 0x1b, 0x14, 0x0d, 0x02, 0x29, 0x34, 0x1f, 0x25, 0x2f, 0x37, 0x1e, 0x28,\n            0x33, 0x2d, 0x21, 0x30, 0x2c, 0x31, 0x27, 0x38, 0x22, 0x35, 0x2e, 0x2a, 0x32, 0x24, 0x1d, 0x20,\n        )\n        SHIFTS = (\n            0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,\n        )\n        SBOX = (\n            (\n                (0x0e, 0x04, 0x0d, 0x01, 0x02, 0x0f, 0x0b, 0x08, 0x03, 0x0a, 0x06, 0x0c, 0x05, 0x09, 0x00, 0x07),\n                (0x00, 0x0f, 0x07, 0x04, 0x0e, 0x02, 0x0d, 0x01, 0x0a, 0x06, 0x0c, 0x0b, 0x09, 0x05, 0x03, 0x08),\n                (0x04, 0x01, 0x0e, 0x08, 0x0d, 0x06, 0x02, 0x0b, 0x0f, 0x0c, 0x09, 0x07, 0x03, 0x0a, 0x05, 0x00),\n                (0x0f, 0x0c, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0b, 0x03, 0x0e, 0x0a, 0x00, 0x06, 0x0d),\n            ),\n            (\n                (0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04, 0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a),\n                (0x03, 0x0d, 0x04, 0x07, 0x0f, 0x02, 0x08, 0x0e, 0x0c, 0x00, 0x01, 0x0a, 0x06, 0x09, 0x0b, 0x05),\n                (0x00, 0x0e, 0x07, 0x0b, 0x0a, 0x04, 0x0d, 0x01, 0x05, 0x08, 0x0c, 0x06, 0x09, 0x03, 0x02, 0x0f),\n                (0x0d, 0x08, 0x0a, 0x01, 0x03, 0x0f, 0x04, 0x02, 0x0b, 0x06, 0x07, 0x0c, 0x00, 0x05, 0x0e, 0x09),\n            ),\n            (\n                (0x0a, 0x00, 0x09, 0x0e, 0x06, 0x03, 0x0f, 0x05, 0x01, 0x0d, 0x0c, 0x07, 0x0b, 0x04, 0x02, 0x08),\n                (0x0d, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0a, 0x02, 0x08, 0x05, 0x0e, 0x0c, 0x0b, 0x0f, 0x01),\n                (0x0d, 0x06, 0x04, 0x09, 0x08, 0x0f, 0x03, 0x00, 0x0b, 0x01, 0x02, 0x0c, 0x05, 0x0a, 0x0e, 0x07),\n                (0x01, 0x0a, 0x0d, 0x00, 0x06, 0x09, 0x08, 0x07, 0x04, 0x0f, 0x0e, 0x03, 0x0b, 0x05, 0x02, 0x0c),\n            ),\n            (\n                (0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05, 0x0b, 0x0c, 0x04, 0x0f),\n                (0x0d, 0x08, 0x0b, 0x05, 0x06, 0x0f, 0x00, 0x03, 0x04, 0x07, 0x02, 0x0c, 0x01, 0x0a, 0x0e, 0x09),\n                (0x0a, 0x06, 0x09, 0x00, 0x0c, 0x0b, 0x07, 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x05, 0x02, 0x08, 0x04),\n                (0x03, 0x0f, 0x00, 0x06, 0x0a, 0x01, 0x0d, 0x08, 0x09, 0x04, 0x05, 0x0b, 0x0c, 0x07, 0x02, 0x0e),\n            ),\n            (\n                (0x02, 0x0c, 0x04, 0x01, 0x07, 0x0a, 0x0b, 0x06, 0x08, 0x05, 0x03, 0x0f, 0x0d, 0x00, 0x0e, 0x09),\n                (0x0e, 0x0b, 0x02, 0x0c, 0x04, 0x07, 0x0d, 0x01, 0x05, 0x00, 0x0f, 0x0a, 0x03, 0x09, 0x08, 0x06),\n                (0x04, 0x02, 0x01, 0x0b, 0x0a, 0x0d, 0x07, 0x08, 0x0f, 0x09, 0x0c, 0x05, 0x06, 0x03, 0x00, 0x0e),\n                (0x0b, 0x08, 0x0c, 0x07, 0x01, 0x0e, 0x02, 0x0d, 0x06, 0x0f, 0x00, 0x09, 0x0a, 0x04, 0x05, 0x03),\n            ),\n            (\n                (0x0c, 0x01, 0x0a, 0x0f, 0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b),\n                (0x0a, 0x0f, 0x04, 0x02, 0x07, 0x0c, 0x09, 0x05, 0x06, 0x01, 0x0d, 0x0e, 0x00, 0x0b, 0x03, 0x08),\n                (0x09, 0x0e, 0x0f, 0x05, 0x02, 0x08, 0x0c, 0x03, 0x07, 0x00, 0x04, 0x0a, 0x01, 0x0d, 0x0b, 0x06),\n                (0x04, 0x03, 0x02, 0x0c, 0x09, 0x05, 0x0f, 0x0a, 0x0b, 0x0e, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0d),\n            ),\n            (\n                (0x04, 0x0b, 0x02, 0x0e, 0x0f, 0x00, 0x08, 0x0d, 0x03, 0x0c, 0x09, 0x07, 0x05, 0x0a, 0x06, 0x01),\n                (0x0d, 0x00, 0x0b, 0x07, 0x04, 0x09, 0x01, 0x0a, 0x0e, 0x03, 0x05, 0x0c, 0x02, 0x0f, 0x08, 0x06),\n                (0x01, 0x04, 0x0b, 0x0d, 0x0c, 0x03, 0x07, 0x0e, 0x0a, 0x0f, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02),\n                (0x06, 0x0b, 0x0d, 0x08, 0x01, 0x04, 0x0a, 0x07, 0x09, 0x05, 0x00, 0x0f, 0x0e, 0x02, 0x03, 0x0c),\n            ),\n            (\n                (0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01, 0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07),\n                (0x01, 0x0f, 0x0d, 0x08, 0x0a, 0x03, 0x07, 0x04, 0x0c, 0x05, 0x06, 0x0b, 0x00, 0x0e, 0x09, 0x02),\n                (0x07, 0x0b, 0x04, 0x01, 0x09, 0x0c, 0x0e, 0x02, 0x00, 0x06, 0x0a, 0x0d, 0x0f, 0x03, 0x05, 0x08),\n                (0x02, 0x01, 0x0e, 0x07, 0x04, 0x0a, 0x08, 0x0d, 0x0f, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0b),\n            ),\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        static uint64_t fast_permute64(uint64_t value, const uint64_t *tables)\n        {\n            return (\n                tables[(0 * 256) + ((value >> 56) & 0xffULL)] ^\n                tables[(1 * 256) + ((value >> 48) & 0xffULL)] ^\n                tables[(2 * 256) + ((value >> 40) & 0xffULL)] ^\n                tables[(3 * 256) + ((value >> 32) & 0xffULL)] ^\n                tables[(4 * 256) + ((value >> 24) & 0xffULL)] ^\n                tables[(5 * 256) + ((value >> 16) & 0xffULL)] ^\n                tables[(6 * 256) + ((value >> 8) & 0xffULL)] ^\n                tables[(7 * 256) + (value & 0xffULL)]\n            );\n        }\n\n        static uint64_t fast_permute56(uint64_t value, const uint64_t *tables)\n        {\n            return (\n                tables[(0 * 256) + ((value >> 48) & 0xffULL)] ^\n                tables[(1 * 256) + ((value >> 40) & 0xffULL)] ^\n                tables[(2 * 256) + ((value >> 32) & 0xffULL)] ^\n                tables[(3 * 256) + ((value >> 24) & 0xffULL)] ^\n                tables[(4 * 256) + ((value >> 16) & 0xffULL)] ^\n                tables[(5 * 256) + ((value >> 8) & 0xffULL)] ^\n                tables[(6 * 256) + (value & 0xffULL)]\n            );\n        }\n\n        static uint64_t fast_permute32(uint32_t value, const uint64_t *tables)\n        {\n            return (\n                tables[(0 * 256) + ((value >> 24) & 0xffU)] ^\n                tables[(1 * 256) + ((value >> 16) & 0xffU)] ^\n                tables[(2 * 256) + ((value >> 8) & 0xffU)] ^\n                tables[(3 * 256) + (value & 0xffU)]\n            );\n        }\n\n        static uint32_t rol28(uint32_t x, int n)\n        {\n            return ((x << n) | (x >> (28 - n))) & 0x0fffffffU;\n        }\n\n        static uint8_t set_odd_parity_byte(uint8_t value)\n        {\n            uint8_t x = value & 0xfeU;\n            uint8_t y = x;\n            int ones = 0;\n\n            while (y != 0) {\n                ones += (y & 0x01U);\n                y >>= 1;\n            }\n\n            if ((ones & 1) == 0)\n                x |= 0x01U;\n            return x;\n        }\n\n        static void set_odd_parity(uint8_t *data, int size)\n        {\n            int i = 0;\n\n            for (i = 0; i < size; i++) {\n                data[i] = set_odd_parity_byte(data[i]);\n            }\n        }\n\n        static void des_subkeys(\n            const uint8_t *key, const uint64_t *pc1_tables, const uint64_t *pc2_tables, uint64_t *subkeys)\n        {\n            uint8_t shift_table[16] = {\n                0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\n                0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,\n            };\n            uint64_t k = 0;\n            uint64_t k56 = 0;\n            uint32_t c = 0;\n            uint32_t d = 0;\n            int i = 0;\n\n            for (i = 0; i < 8; i++) {\n                k = (k << 8) | (uint64_t)key[i];\n            }\n\n            k56 = fast_permute64(k, pc1_tables);\n            c = (uint32_t)(k56 >> 28);\n            d = (uint32_t)(k56 & 0x0fffffffU);\n\n            for (i = 0; i < 16; i++) {\n                uint64_t cd = 0;\n                c = rol28(c, shift_table[i]);\n                d = rol28(d, shift_table[i]);\n                cd = (((uint64_t)c) << 28) | (uint64_t)d;\n                subkeys[i] = fast_permute56(cd, pc2_tables);\n            }\n        }\n\n        static uint32_t des_f(uint32_t r, uint64_t subkey, const uint64_t *e_tables, const uint32_t *sp_tables)\n        {\n            uint64_t x = fast_permute32(r, e_tables) ^ subkey;\n\n            return (\n                sp_tables[(0 * 64) + ((x >> 42) & 0x3fULL)] ^\n                sp_tables[(1 * 64) + ((x >> 36) & 0x3fULL)] ^\n                sp_tables[(2 * 64) + ((x >> 30) & 0x3fULL)] ^\n                sp_tables[(3 * 64) + ((x >> 24) & 0x3fULL)] ^\n                sp_tables[(4 * 64) + ((x >> 18) & 0x3fULL)] ^\n                sp_tables[(5 * 64) + ((x >> 12) & 0x3fULL)] ^\n                sp_tables[(6 * 64) + ((x >> 6) & 0x3fULL)] ^\n                sp_tables[(7 * 64) + (x & 0x3fULL)]\n            );\n        }\n\n        static void des_encrypt_block(\n            const uint8_t *block, const uint8_t *key, const uint64_t *ip_tables, const uint64_t *fp_tables,\n            const uint64_t *pc1_tables, const uint64_t *pc2_tables, const uint64_t *e_tables,\n            const uint32_t *sp_tables, uint8_t *out)\n        {\n            uint64_t subkeys[16];\n            uint64_t x = 0;\n            uint64_t y = 0;\n            uint32_t l = 0;\n            uint32_t r = 0;\n            int i = 0;\n\n            des_subkeys(key, pc1_tables, pc2_tables, subkeys);\n\n            for (i = 0; i < 8; i++) {\n                x = (x << 8) | (uint64_t)block[i];\n            }\n\n            x = fast_permute64(x, ip_tables);\n            l = (uint32_t)(x >> 32);\n            r = (uint32_t)(x & 0xffffffffU);\n\n            for (i = 0; i < 16; i++) {\n                uint32_t nl = r;\n                uint32_t nr = l ^ des_f(r, subkeys[i], e_tables, sp_tables);\n                l = nl;\n                r = nr;\n            }\n\n            y = (((uint64_t)r) << 32) | (uint64_t)l;\n            y = fast_permute64(y, fp_tables);\n\n            for (i = 7; i >= 0; i--) {\n                out[i] = (uint8_t)(y & 0xffULL);\n                y >>= 8;\n            }\n        }\n\n        void compress(\n            uint8_t *h, uint8_t *hh, const uint8_t *block, const uint64_t *ip_tables, const uint64_t *fp_tables,\n            const uint64_t *pc1_tables, const uint64_t *pc2_tables, const uint64_t *e_tables,\n            const uint32_t *sp_tables)\n        {\n            uint8_t h_key[8];\n            uint8_t hh_key[8];\n            uint8_t d[8];\n            uint8_t dd[8];\n            int i = 0;\n\n            for (i = 0; i < 8; i++) {\n                h_key[i] = h[i];\n                hh_key[i] = hh[i];\n            }\n\n            h_key[0] = (uint8_t)((h_key[0] & 0x9fU) | 0x40U);\n            hh_key[0] = (uint8_t)((hh_key[0] & 0x9fU) | 0x20U);\n\n            set_odd_parity(h_key, 8);\n            set_odd_parity(hh_key, 8);\n\n            des_encrypt_block(block, h_key, ip_tables, fp_tables, pc1_tables, pc2_tables, e_tables, sp_tables, d);\n            des_encrypt_block(block, hh_key, ip_tables, fp_tables, pc1_tables, pc2_tables, e_tables, sp_tables, dd);\n\n            for (i = 0; i < 4; i++) {\n                h[i] = (uint8_t)(block[i] ^ d[i]);\n                hh[i] = (uint8_t)(block[i] ^ dd[i]);\n            }\n\n            for (i = 4; i < 8; i++) {\n                h[i] = (uint8_t)(block[i] ^ dd[i]);\n                hh[i] = (uint8_t)(block[i] ^ d[i]);\n            }\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void compress(\n            uint8_t *h, uint8_t *hh, const uint8_t *block, const uint64_t *ip_tables, const uint64_t *fp_tables,\n            const uint64_t *pc1_tables, const uint64_t *pc2_tables, const uint64_t *e_tables,\n            const uint32_t *sp_tables);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.MDC2\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            def flatten_tables(tables):\n                flat = []\n                for row in tables:\n                    flat.extend(row)\n                return tuple(flat)\n\n            try:\n                ip_tables = ffi.new(\"uint64_t[]\", flatten_tables(self.IP_tables))\n                fp_tables = ffi.new(\"uint64_t[]\", flatten_tables(self.FP_tables))\n                pc1_tables = ffi.new(\"uint64_t[]\", flatten_tables(self.PC1_tables))\n                pc2_tables = ffi.new(\"uint64_t[]\", flatten_tables(self.PC2_tables))\n                e_tables = ffi.new(\"uint64_t[]\", flatten_tables(self.E_tables))\n                sp_tables = ffi.new(\"uint32_t[]\", flatten_tables(self.SP_tables))\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib ip_tables fp_tables pc1_tables pc2_tables e_tables sp_tables\")(\n                ffi, lib, ip_tables, fp_tables, pc1_tables, pc2_tables, e_tables, sp_tables,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n            if hasattr(cls, \"IP_tables\"):\n                return\n\n            def build_perm_tables(table, in_bits):\n                num_chunks = in_bits // 8\n                tables = [[0] * 256 for _ in range(num_chunks)]\n                out_bits = len(table)\n                for chunk in range(num_chunks):\n                    for val in range(256):\n                        out = 0\n                        for i, pos in enumerate(table):\n                            bit_idx = pos - 1\n                            if (bit_idx // 8) == chunk:\n                                bit = (val >> (7 - (bit_idx % 8))) & 1\n                                out |= (bit << (out_bits - 1 - i))\n                        tables[chunk][val] = out\n                return tables\n\n            cls.IP_tables = build_perm_tables(cls.IP, 64)\n            cls.FP_tables = build_perm_tables(cls.FP, 64)\n            cls.PC1_tables = build_perm_tables(cls.PC1, 64)\n            cls.PC2_tables = build_perm_tables(cls.PC2, 56)\n            cls.E_tables = build_perm_tables(cls.E, 32)\n\n            SP_tables = [[0] * 64 for _ in range(8)]\n            for i in range(8):\n                for val in range(64):\n                    row = ((val & 0x20) >> 4) | (val & 0x1)\n                    col = (val >> 1) & 0x0f\n                    sval = cls.SBOX[i][row][col]\n                    out = 0\n                    for b in range(4):\n                        bit_val = (sval >> (3 - b)) & 1\n                        in_pos = i * 4 + b + 1\n                        out_idx = cls.P.index(in_pos)\n                        out |= (bit_val << (31 - out_idx))\n                    SP_tables[i][val] = out\n            cls.SP_tables = SP_tables\n            return\n\n        def __init__(self, data=b\"\"):\n            self.h = bytearray([0x52] * 8)\n            self.hh = bytearray([0x25] * 8)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.pad_type = 1\n            self.ensure_tables()\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = bytearray(self.h)\n            other.hh = bytearray(self.hh)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.pad_type = self.pad_type\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 8:\n                block = bytes(self.buf[:8])\n                del self.buf[:8]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return bytes(c.h + c.hh)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if (len(self.buf) > 0) or (self.pad_type == 2):\n                if self.pad_type == 2:\n                    self.buf.append(0x80)\n                while len(self.buf) < 8:\n                    self.buf.append(0x00)\n                self.compress(bytes(self.buf[:8]))\n                del self.buf[:8]\n            return\n\n        def compress(self, block):\n            if len(block) != 8:\n                raise ValueError(\"invalid block size\")\n\n            if self.USE_CFFI:\n                h_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(self.h))\n                hh_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(self.hh))\n                block_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(block))\n                self.cffi.lib.compress(\n                    h_buf, hh_buf, block_buf,\n                    self.cffi.ip_tables, self.cffi.fp_tables,\n                    self.cffi.pc1_tables, self.cffi.pc2_tables, self.cffi.e_tables,\n                    self.cffi.sp_tables,\n                )\n                self.h = bytearray(bytes(self.cffi.ffi.buffer(h_buf, 8)))\n                self.hh = bytearray(bytes(self.cffi.ffi.buffer(hh_buf, 8)))\n                return\n\n            def set_odd_parity(data):\n                for i in range(len(data)):\n                    data[i] = set_odd_parity_byte(data[i])\n                return\n\n            def set_odd_parity_byte(value):\n                x = value & 0xfe\n                ones = 0\n                y = x\n                while y != 0:\n                    ones += y & 0x1\n                    y >>= 1\n                if (ones % 2) == 0:\n                    x |= 0x1\n                return x\n\n            self.h[0] = (self.h[0] & 0x9f) | 0x40\n            self.hh[0] = (self.hh[0] & 0x9f) | 0x20\n            set_odd_parity(self.h)\n            set_odd_parity(self.hh)\n            d = self.des_encrypt_block(block, bytes(self.h))\n            dd = self.des_encrypt_block(block, bytes(self.hh))\n            h = bytearray(8)\n            hh = bytearray(8)\n            for i in range(4):\n                h[i] = block[i] ^ d[i]\n                hh[i] = block[i] ^ dd[i]\n            for i in range(4, 8):\n                h[i] = block[i] ^ dd[i]\n                hh[i] = block[i] ^ d[i]\n            self.h = h\n            self.hh = hh\n            return\n\n        def des_encrypt_block(self, block, key):\n\n            def fast_permute64(value, tables):\n                return (\n                    tables[0][(value >> 56) & 0xff] ^\n                    tables[1][(value >> 48) & 0xff] ^\n                    tables[2][(value >> 40) & 0xff] ^\n                    tables[3][(value >> 32) & 0xff] ^\n                    tables[4][(value >> 24) & 0xff] ^\n                    tables[5][(value >> 16) & 0xff] ^\n                    tables[6][(value >> 8) & 0xff] ^\n                    tables[7][value & 0xff]\n                )\n\n            def fast_permute56(value, tables):\n                return (\n                    tables[0][(value >> 48) & 0xff] ^\n                    tables[1][(value >> 40) & 0xff] ^\n                    tables[2][(value >> 32) & 0xff] ^\n                    tables[3][(value >> 24) & 0xff] ^\n                    tables[4][(value >> 16) & 0xff] ^\n                    tables[5][(value >> 8) & 0xff] ^\n                    tables[6][value & 0xff]\n                )\n\n            def fast_permute32(value, tables):\n                return (\n                    tables[0][(value >> 24) & 0xff] ^\n                    tables[1][(value >> 16) & 0xff] ^\n                    tables[2][(value >> 8) & 0xff] ^\n                    tables[3][value & 0xff]\n                )\n\n            def rol28(x, n):\n                return ((x << n) | (x >> (28 - n))) & 0x0fff_ffff\n\n            def des_subkeys(key):\n                k = int.from_bytes(key, \"big\")\n                k56 = fast_permute64(k, self.PC1_tables)\n                c = k56 >> 28\n                d = k56 & 0x0fff_ffff\n                subkeys = []\n                for shift in self.SHIFTS:\n                    c = rol28(c, shift)\n                    d = rol28(d, shift)\n                    cd = (c << 28) | d\n                    subkeys.append(fast_permute56(cd, self.PC2_tables))\n                return subkeys\n\n            def des_f(r, subkey):\n                x = fast_permute32(r, self.E_tables) ^ subkey\n                SP = self.SP_tables\n                return (\n                    SP[0][(x >> 42) & 0x3f] ^\n                    SP[1][(x >> 36) & 0x3f] ^\n                    SP[2][(x >> 30) & 0x3f] ^\n                    SP[3][(x >> 24) & 0x3f] ^\n                    SP[4][(x >> 18) & 0x3f] ^\n                    SP[5][(x >> 12) & 0x3f] ^\n                    SP[6][(x >> 6) & 0x3f] ^\n                    SP[7][x & 0x3f]\n                )\n\n            subkeys = des_subkeys(key)\n            x = int.from_bytes(block, \"big\")\n            x = fast_permute64(x, self.IP_tables)\n            l = x >> 32  # noqa: E741\n            r = x & 0xffff_ffff\n            for subkey in subkeys:\n                nl = r\n                nr = l ^ des_f(r, subkey)\n                l = nl  # noqa: E741\n                r = nr\n            y = (r << 32) | l\n            y = fast_permute64(y, self.FP_tables)\n            return y.to_bytes(8, \"big\")\n\n    class MarsupilamiFourteen:\n        block_size = 0x88\n        digest_size = 64\n        node_block_size = 0x2000\n        single = bytes([0x07])\n        intermediate = bytes([0x0b])\n        final = bytes([0xff, 0xff, 0x06])\n        first = bytes([0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])\n        round_constants = (\n            0x0000_0000_0000_0001, 0x0000_0000_0000_8082, 0x8000_0000_0000_808a, 0x8000_0000_8000_8000,\n            0x0000_0000_0000_808b, 0x0000_0000_8000_0001, 0x8000_0000_8000_8081, 0x8000_0000_0000_8009,\n            0x0000_0000_0000_008a, 0x0000_0000_0000_0088, 0x0000_0000_8000_8009, 0x0000_0000_8000_000a,\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n\n        class KangarooSponge:\n            def __init__(self, strength, rounds, round_constants):\n                self.strength = strength\n                self.rounds = rounds\n                self.round_constants = round_constants\n                self.rate_bytes = (1600 - (strength << 1)) >> 3\n                self.state = [0] * 25\n                self.queue = bytearray(self.rate_bytes)\n                self.bytes_in_queue = 0\n                self.squeezing = False\n                self.init_sponge()\n                return\n\n            def copy(self):\n                other = self.__class__(self.strength, self.rounds, self.round_constants)\n                other.state = self.state[:]\n                other.queue = bytearray(self.queue)\n                other.bytes_in_queue = self.bytes_in_queue\n                other.squeezing = self.squeezing\n                return other\n\n            def init_sponge(self):\n                for i in range(25):\n                    self.state[i] = 0\n                for i in range(self.rate_bytes):\n                    self.queue[i] = 0\n                self.bytes_in_queue = 0\n                self.squeezing = False\n                return\n\n            def absorb(self, data, off, length):\n                if self.squeezing:\n                    raise ValueError(\"attempt to absorb while squeezing\")\n                count = 0\n                while count < length:\n                    if self.bytes_in_queue == 0 and count <= (length - self.rate_bytes):\n                        while True:\n                            self.kangaroo_absorb(data, off + count)\n                            count += self.rate_bytes\n                            if count > (length - self.rate_bytes):\n                                break\n                    else:\n                        partial_block = min(self.rate_bytes - self.bytes_in_queue, length - count)\n                        self.queue[self.bytes_in_queue:self.bytes_in_queue + partial_block] = \\\n                            data[off + count:off + count + partial_block]\n                        self.bytes_in_queue += partial_block\n                        count += partial_block\n                        if self.bytes_in_queue == self.rate_bytes:\n                            self.kangaroo_absorb(self.queue, 0)\n                            self.bytes_in_queue = 0\n                return\n\n            def pad_and_switch_to_squeezing_phase(self):\n                for i in range(self.bytes_in_queue, self.rate_bytes):\n                    self.queue[i] = 0\n                self.queue[self.rate_bytes - 1] ^= 0x80\n                self.kangaroo_absorb(self.queue, 0)\n                self.kangaroo_extract()\n                self.bytes_in_queue = self.rate_bytes\n                self.squeezing = True\n                return\n\n            def squeeze(self, out, off, output_length):\n                if not self.squeezing:\n                    self.pad_and_switch_to_squeezing_phase()\n                i = 0\n                while i < output_length:\n                    if self.bytes_in_queue == 0:\n                        self.kangaroo_permutation()\n                        self.kangaroo_extract()\n                        self.bytes_in_queue = self.rate_bytes\n                    partial_block = min(self.bytes_in_queue, output_length - i)\n                    src = self.rate_bytes - self.bytes_in_queue\n                    out[off + i:off + i + partial_block] = self.queue[src:src + partial_block]\n                    self.bytes_in_queue -= partial_block\n                    i += partial_block\n                return\n\n            def kangaroo_absorb(self, data, off):\n                count = self.rate_bytes >> 3\n                off_set = off\n                for i in range(count):\n                    lane = int.from_bytes(data[off_set:off_set + 8], \"little\")\n                    self.state[i] ^= lane\n                    off_set += 8\n                self.kangaroo_permutation()\n                return\n\n            def kangaroo_extract(self):\n                count = self.rate_bytes >> 3\n                off = 0\n                for i in range(count):\n                    self.queue[off:off + 8] = self.state[i].to_bytes(8, \"little\")\n                    off += 8\n                return\n\n            def kangaroo_permutation(self):\n\n                def rol64(x, n):\n                    return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n                rc = (\n                    (10, 1, 1), (1, 6, 44), (6, 9, 20), (9, 22, 61), (22, 14, 39), (14, 20, 18), (20, 2, 62), (2, 12, 43),\n                    (12, 13, 25), (13, 19, 8), (19, 23, 56), (23, 15, 41), (15, 4, 27), (4, 24, 14), (24, 21, 2), (21, 8, 55),\n                    (8, 16, 45), (16, 5, 36), (5, 3, 28), (3, 18, 21), (18, 17, 15), (17, 11, 10), (11, 7, 6), (7, 10, 3),\n                )\n                a = self.state\n                base = len(self.round_constants) - self.rounds\n                for i in range(self.rounds):\n                    c = [0] * 5\n                    for j in range(5):\n                        c[j] = a[j] ^ a[j + 5] ^ a[j + 10] ^ a[j + 15] ^ a[j + 20]\n                    d = [0] * 5\n                    for j in range(5):\n                        d[(j + 1) % 5] = rol64(c[(j + 1) % 5], 1) ^ c[(j + 4) % 5]\n                    for j in range(5):\n                        a[j] ^= d[(j + 1) % 5]\n                        a[j + 5] ^= d[(j + 1) % 5]\n                        a[j + 10] ^= d[(j + 1) % 5]\n                        a[j + 15] ^= d[(j + 1) % 5]\n                        a[j + 20] ^= d[(j + 1) % 5]\n                    new_a = a[::]\n                    for dst, src, ri in rc:\n                        new_a[dst] = rol64(a[src], ri)\n                    a = new_a\n                    new_a = [0] * 25\n                    for k in [0, 5, 10, 15, 20]:\n                        for j in range(5):\n                            new_a[k + j] = a[k + j] ^ ((a[k + (j + 1) % 5] ^ 0xffff_ffff_ffff_ffff) & a[k + (j + 2) % 5])\n                    a = new_a\n                    a[0] ^= self.round_constants[base + i]\n\n                self.state = a\n                return\n\n        def __init__(self, data=b\"\", digest_size=64, personal=b\"\"):\n            self.strength = 256\n            self.rounds = 14\n            self.output_size = digest_size\n            self.tree = self.KangarooSponge(self.strength, self.rounds, self.round_constants)\n            self.leaf = self.KangarooSponge(self.strength, self.rounds, self.round_constants)\n            self.chain_len = self.strength >> 2\n            self.personal = b\"\"\n            self.squeezing = False\n            self.curr_node = 0\n            self.processed = 0\n            self.msg_len = 0\n            self.build_personal(personal)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(b\"\", self.output_size)\n            other.tree = self.tree.copy()\n            other.leaf = self.leaf.copy()\n            other.chain_len = self.chain_len\n            other.personal = bytes(self.personal)\n            other.squeezing = self.squeezing\n            other.curr_node = self.curr_node\n            other.processed = self.processed\n            other.msg_len = self.msg_len\n            return other\n\n        def build_personal(self, personal):\n            if personal is None:\n                personal = b\"\"\n            if not isinstance(personal, (bytes, bytearray, memoryview)):\n                raise TypeError(\"personal must be bytes-like\")\n            personal = bytes(personal)\n            encoded = self.length_encode(len(personal))\n            self.personal = personal + encoded\n            return\n\n        def length_encode(self, value):\n            n = 0\n            v = value\n            if v != 0:\n                n = 1\n                while True:\n                    v >>= 8\n                    if v == 0:\n                        break\n                    n += 1\n\n            out = bytearray(n + 1)\n            out[n] = n\n            for i in range(n):\n                shift = 8 * (n - i - 1)\n                out[i] = (value >> shift) & 0xff\n            return bytes(out)\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.squeezing:\n                raise ValueError(\"attempt to absorb while squeezing\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.process_data(data, 0, len(data))\n            return self\n\n        def process_data(self, data, off, length):\n            if self.squeezing:\n                raise ValueError(\"attempt to absorb while squeezing\")\n            sponge = self.tree if self.curr_node == 0 else self.leaf\n            space = self.node_block_size - self.processed\n            if space >= length:\n                sponge.absorb(data, off, length)\n                self.processed += length\n                return\n            if space > 0:\n                sponge.absorb(data, off, space)\n                self.processed += space\n            processed = space\n            while processed < length:\n                if self.processed == self.node_block_size:\n                    self.switch_leaf(True)\n                data_len = min(length - processed, self.node_block_size)\n                self.leaf.absorb(data, off + processed, data_len)\n                self.processed += data_len\n                processed += data_len\n            return\n\n        def switch_leaf(self, more_to_come):\n            if self.curr_node == 0:\n                self.tree.absorb(self.first, 0, len(self.first))\n            else:\n                self.leaf.absorb(self.intermediate, 0, len(self.intermediate))\n                chain_value = bytearray(self.chain_len)\n                self.leaf.squeeze(chain_value, 0, self.chain_len)\n                self.tree.absorb(chain_value, 0, self.chain_len)\n                self.leaf.init_sponge()\n\n            if more_to_come:\n                self.curr_node += 1\n            self.processed = 0\n            return\n\n        def switch_to_squeezing(self):\n            self.process_data(self.personal, 0, len(self.personal))\n            if self.curr_node == 0:\n                self.tree.absorb(self.single, 0, len(self.single))\n                self.tree.pad_and_switch_to_squeezing_phase()\n            else:\n                self.switch_leaf(False)\n                node_count_encoded = self.length_encode(self.curr_node)\n                self.tree.absorb(node_count_encoded, 0, len(node_count_encoded))\n                self.tree.absorb(self.final, 0, len(self.final))\n                self.tree.pad_and_switch_to_squeezing_phase()\n            self.squeezing = True\n            return\n\n        def finalize(self):\n            if not self.squeezing:\n                self.switch_to_squeezing()\n            return\n\n        def read(self, length):\n            if length < 0:\n                raise ValueError(\"invalid output length\")\n            if not self.squeezing:\n                self.switch_to_squeezing()\n            out = bytearray(length)\n            self.tree.squeeze(out, 0, length)\n            return bytes(out)\n\n        def digest(self, length=None):\n            c = self.copy()\n            if length is None:\n                length = c.output_size\n            return c.read(length)\n\n        def hexdigest(self, length=None):\n            return self.digest(length).hex()\n\n    class Panama:\n        block_size = 32\n        digest_size = 32\n\n        def __init__(self, data=b\"\"):\n            self.state = [0] * 17\n            self.buffer = [[0] * 8 for _ in range(32)]\n            self.buffer_ptr = 0\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buffer = [list(row) for row in self.buffer]\n            other.buffer_ptr = self.buffer_ptr\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 32:\n                block = bytes(self.buf[:32])\n                del self.buf[:32]\n                self.push(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytearray()\n            for i in range(8):\n                out.extend(struct.pack(\"<I\", c.state[i + 9]))\n            return bytes(out)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            block = bytearray(32)\n            n = len(self.buf)\n            if n:\n                block[:n] = self.buf\n            block[n] = 0x01\n            self.push(bytes(block))\n            self.pull(32)\n            self.buf.clear()\n            return\n\n        def step(self, inw1, inw2):\n\n            def rol32(x, n):\n                x &= 0xffff_ffff\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            def gamma(a):\n                g = [0] * 17\n                for i in range(17):\n                    g[i] = (a[i] ^ (a[(i + 1) % 17] | (~a[(i + 2) % 17]))) & 0xffff_ffff\n                return g\n\n            def pi(g):\n                p = [0] * 17\n                p[0] = g[0]\n                p[1] = rol32(g[7], 1)\n                p[2] = rol32(g[14], 3)\n                p[3] = rol32(g[4], 6)\n                p[4] = rol32(g[11], 10)\n                p[5] = rol32(g[1], 15)\n                p[6] = rol32(g[8], 21)\n                p[7] = rol32(g[15], 28)\n                p[8] = rol32(g[5], 4)\n                p[9] = rol32(g[12], 13)\n                p[10] = rol32(g[2], 23)\n                p[11] = rol32(g[9], 2)\n                p[12] = rol32(g[16], 14)\n                p[13] = rol32(g[6], 27)\n                p[14] = rol32(g[13], 9)\n                p[15] = rol32(g[3], 24)\n                p[16] = rol32(g[10], 8)\n                return p\n\n            def theta(p):\n                t = [0] * 17\n                for i in range(17):\n                    t[i] = p[i] ^ p[(i + 1) % 17] ^ p[(i + 4) % 17]\n                return t\n\n            a = list(self.state)\n            ptr0 = self.buffer_ptr\n            ptr24 = (ptr0 - 8) & 31\n            ptr31 = (ptr0 - 1) & 31\n\n            pairs = ((0, 2), (1, 3), (2, 4), (3, 5), (4, 6), (5, 7), (6, 0), (7, 1))\n            for n0, n2 in pairs:\n                self.buffer[ptr24][n0] ^= self.buffer[ptr31][n2]\n                self.buffer[ptr31][n2] ^= inw1[n2]\n\n            g = gamma(a)\n            p = pi(g)\n            t = theta(p)\n\n            ptr16 = ptr0 ^ 16\n            next_state = [0] * 17\n            next_state[0] = t[0] ^ 1\n            for i in range(8):\n                next_state[i + 1] = t[i + 1] ^ inw2[i]\n            for i in range(8):\n                next_state[i + 9] = t[i + 9] ^ self.buffer[ptr16][i]\n\n            self.state = next_state\n            self.buffer_ptr = ptr31\n            return\n\n        def push(self, block):\n            x = list(struct.unpack(\"<8I\", block))\n            self.step(x, x)\n            return\n\n        def pull(self, num):\n            for _ in range(num):\n                a = self.state\n                inw1 = [a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]]\n                ptr4 = (self.buffer_ptr + 4) & 31\n                inw2 = list(self.buffer[ptr4])\n                self.step(inw1, inw2)\n            return\n\n    class PhotonBeetle:\n        block_size = 4\n        digest_size = 32\n        sbox = (\n            0x0c, 0x05, 0x06, 0x0b, 0x09, 0x00, 0x0a, 0x0d, 0x03, 0x0e, 0x0f, 0x08, 0x04, 0x07, 0x01, 0x02,\n        )\n        rc = (\n            (0x01, 0x00, 0x02, 0x06, 0x0e, 0x0f, 0x0d, 0x09),\n            (0x03, 0x02, 0x00, 0x04, 0x0c, 0x0d, 0x0f, 0x0b),\n            (0x07, 0x06, 0x04, 0x00, 0x08, 0x09, 0x0b, 0x0f),\n            (0x0e, 0x0f, 0x0d, 0x09, 0x01, 0x00, 0x02, 0x06),\n            (0x0d, 0x0c, 0x0e, 0x0a, 0x02, 0x03, 0x01, 0x05),\n            (0x0b, 0x0a, 0x08, 0x0c, 0x04, 0x05, 0x07, 0x03),\n            (0x06, 0x07, 0x05, 0x01, 0x09, 0x08, 0x0a, 0x0e),\n            (0x0c, 0x0d, 0x0f, 0x0b, 0x03, 0x02, 0x00, 0x04),\n            (0x09, 0x08, 0x0a, 0x0e, 0x06, 0x07, 0x05, 0x01),\n            (0x02, 0x03, 0x01, 0x05, 0x0d, 0x0c, 0x0e, 0x0a),\n            (0x05, 0x04, 0x06, 0x02, 0x0a, 0x0b, 0x09, 0x0d),\n            (0x0a, 0x0b, 0x09, 0x0d, 0x05, 0x04, 0x06, 0x02),\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stddef.h>\n        #include <stdint.h>\n\n        static int mix_pair_index(int r, int pair_index, int a, int b)\n        {\n            return ((((r * 4) + pair_index) * 16 + a) * 16) + b;\n        }\n\n        static uint8_t mix_pair_at(const uint8_t *mix_pair, int r, int pair_index, int a, int b)\n        {\n            return mix_pair[mix_pair_index(r, pair_index, a, b)];\n        }\n\n        static void photon256(uint8_t *state, const uint8_t *sbox, const uint8_t *rc, const uint8_t *mix_pair)\n        {\n            uint8_t m[64];\n            uint8_t n[64];\n            int i = 0;\n            int j = 0;\n            int rnd = 0;\n\n            for (i = 0, j = 0; i < 32; i++, j += 2) {\n                m[j] = (uint8_t)(state[i] & 0x0f);\n                m[j + 1] = (uint8_t)(state[i] >> 4);\n            }\n\n            for (rnd = 0; rnd < 12; rnd++) {\n                const uint8_t *rc_row = rc + (rnd * 8);\n                int r = 0;\n                int c = 0;\n\n                m[0] ^= rc_row[0];\n                m[8] ^= rc_row[1];\n                m[16] ^= rc_row[2];\n                m[24] ^= rc_row[3];\n                m[32] ^= rc_row[4];\n                m[40] ^= rc_row[5];\n                m[48] ^= rc_row[6];\n                m[56] ^= rc_row[7];\n\n                for (r = 0; r < 8; r++) {\n                    int base = r << 3;\n                    int shift = r;\n\n                    for (c = 0; c < 8; c++) {\n                        n[base + c] = sbox[m[base + ((c + shift) & 7)]];\n                    }\n                }\n\n                for (c = 0; c < 8; c++) {\n                    int p0a = n[c];\n                    int p0b = n[8 + c];\n                    int p1a = n[16 + c];\n                    int p1b = n[24 + c];\n                    int p2a = n[32 + c];\n                    int p2b = n[40 + c];\n                    int p3a = n[48 + c];\n                    int p3b = n[56 + c];\n\n                    m[c] =\n                        mix_pair_at(mix_pair, 0, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 0, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 0, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 0, 3, p3a, p3b);\n                    m[8 + c] =\n                        mix_pair_at(mix_pair, 1, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 1, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 1, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 1, 3, p3a, p3b);\n                    m[16 + c] =\n                        mix_pair_at(mix_pair, 2, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 2, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 2, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 2, 3, p3a, p3b);\n                    m[24 + c] =\n                        mix_pair_at(mix_pair, 3, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 3, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 3, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 3, 3, p3a, p3b);\n                    m[32 + c] =\n                        mix_pair_at(mix_pair, 4, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 4, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 4, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 4, 3, p3a, p3b);\n                    m[40 + c] =\n                        mix_pair_at(mix_pair, 5, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 5, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 5, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 5, 3, p3a, p3b);\n                    m[48 + c] =\n                        mix_pair_at(mix_pair, 6, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 6, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 6, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 6, 3, p3a, p3b);\n                    m[56 + c] =\n                        mix_pair_at(mix_pair, 7, 0, p0a, p0b) ^\n                        mix_pair_at(mix_pair, 7, 1, p1a, p1b) ^\n                        mix_pair_at(mix_pair, 7, 2, p2a, p2b) ^\n                        mix_pair_at(mix_pair, 7, 3, p3a, p3b);\n                }\n            }\n\n            for (i = 0, j = 0; i < 32; i++, j += 2) {\n                state[i] = (uint8_t)(m[j] | (m[j + 1] << 4));\n            }\n        }\n\n        static void gen_tag(uint8_t *state, uint8_t *out, const uint8_t *sbox, const uint8_t *rc, const uint8_t *mix_pair)\n        {\n            int i = 0;\n\n            photon256(state, sbox, rc, mix_pair);\n            for (i = 0; i < 16; i++) {\n                out[i] = state[i];\n            }\n\n            photon256(state, sbox, rc, mix_pair);\n            for (i = 0; i < 16; i++) {\n                out[16 + i] = state[i];\n            }\n        }\n\n        static void absorb4(\n            uint8_t *state, const uint8_t *msg, size_t msg_len, int c0, const uint8_t *sbox, const uint8_t *rc,\n            const uint8_t *mix_pair)\n        {\n            size_t off = 0;\n            size_t full = (msg_len / 4) * 4;\n            size_t rem = 0;\n            size_t i = 0;\n\n            while (off < full) {\n                photon256(state, sbox, rc, mix_pair);\n                state[0] ^= msg[off];\n                state[1] ^= msg[off + 1];\n                state[2] ^= msg[off + 2];\n                state[3] ^= msg[off + 3];\n                off += 4;\n            }\n\n            rem = msg_len - off;\n            if (rem > 0) {\n                photon256(state, sbox, rc, mix_pair);\n                for (i = 0; i < rem; i++) {\n                    state[i] ^= msg[off + i];\n                }\n                state[rem] ^= 0x01;\n            }\n\n            state[31] ^= (uint8_t)(c0 << 5);\n        }\n\n        void hash_bytes(\n            const uint8_t *msg, size_t msg_len, uint8_t *out, const uint8_t *sbox, const uint8_t *rc,\n            const uint8_t *mix_pair)\n        {\n            uint8_t state[32];\n            size_t i = 0;\n\n            for (i = 0; i < 32; i++) {\n                state[i] = 0;\n            }\n\n            if (msg_len == 0) {\n                state[31] ^= (uint8_t)(0x01 << 5);\n                gen_tag(state, out, sbox, rc, mix_pair);\n                return;\n            }\n\n            if (msg_len <= 16) {\n                for (i = 0; i < msg_len; i++) {\n                    state[i] = msg[i];\n                }\n                if (msg_len < 16) {\n                    state[msg_len] ^= 0x01;\n                    state[31] ^= (uint8_t)(0x01 << 5);\n                } else {\n                    state[31] ^= (uint8_t)(0x02 << 5);\n                }\n                gen_tag(state, out, sbox, rc, mix_pair);\n                return;\n            }\n\n            for (i = 0; i < 16; i++) {\n                state[i] = msg[i];\n            }\n\n            if (((msg_len - 16) % 4) == 0) {\n                absorb4(state, msg + 16, msg_len - 16, 0x01, sbox, rc, mix_pair);\n            } else {\n                absorb4(state, msg + 16, msg_len - 16, 0x02, sbox, rc, mix_pair);\n            }\n            gen_tag(state, out, sbox, rc, mix_pair);\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void hash_bytes(\n            const uint8_t *msg, size_t msg_len, uint8_t *out, const uint8_t *sbox, const uint8_t *rc,\n            const uint8_t *mix_pair);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.PhotonBeetle\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            if base_class in base_class.cffi_cache:\n                ffi, lib = base_class.cffi_cache[base_class]\n            else:\n                try:\n                    with warnings.catch_warnings():\n                        warnings.filterwarnings(\n                            \"ignore\",\n                            message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                            category=UserWarning,\n                            module=r\"cffi\\.vengine_cpy\",\n                        )\n                        ffi = cffi.FFI()\n                        ffi.cdef(base_class.DEF_TEMPLATE)\n                        lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n                    base_class.cffi_cache[base_class] = (ffi, lib)\n                except Exception:\n                    self.USE_CFFI = False\n                    return\n\n            # Different for each class\n            def flatten_mix_pair(mix_pair):\n                flat = []\n                for r in mix_pair:\n                    for pair_tab in r:\n                        for row in pair_tab:\n                            flat.extend(row)\n                return tuple(flat)\n\n            def flatten_rc(rc):\n                flat = []\n                for row in rc:\n                    flat.extend(row)\n                return tuple(flat)\n\n            try:\n                sbox = ffi.new(\"uint8_t[]\", tuple(self.sbox))\n                rc = ffi.new(\"uint8_t[]\", flatten_rc(self.rc))\n                mix_pair = ffi.new(\"uint8_t[]\", flatten_mix_pair(self.MIX_PAIR))\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib sbox rc mix_pair\")(\n                ffi, lib, sbox, rc, mix_pair,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n\n            def gf16_mul(a, b):\n                x = a\n                y = b\n                z = 0\n                for _ in range(4):\n                    if (y & 0x01) != 0:\n                        z ^= x\n                    carry = x & 0x08\n                    x = (x << 1) & 0x0f\n                    if carry != 0:\n                        x ^= 0x03\n                    y >>= 1\n                return z\n\n            def gf16_matrix_mul(tab, a, b):\n                out = [[0 for j in range(8)] for i in range(8)]\n                for i in range(8):\n                    for j in range(8):\n                        v = 0\n                        for k in range(8):\n                            v ^= tab[a[i][k]][b[k][j]]\n                        out[i][j] = v\n                return out\n\n            if not hasattr(cls, \"gf16_mul_table\"):\n                tab = []\n                for a in range(16):\n                    row = []\n                    for b in range(16):\n                        row.append(gf16_mul(a, b))\n                    tab.append(tuple(row))\n                cls.gf16_mul_table = tuple(tab)\n\n            if not hasattr(cls, \"m8\"):\n                m = (\n                    (0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\n                    (0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00),\n                    (0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00),\n                    (0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),\n                    (0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00),\n                    (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00),\n                    (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01),\n                    (0x02, 0x04, 0x02, 0x0b, 0x02, 0x08, 0x05, 0x06),\n                )\n                m2 = gf16_matrix_mul(cls.gf16_mul_table, m, m)\n                m4 = gf16_matrix_mul(cls.gf16_mul_table, m2, m2)\n                m8 = gf16_matrix_mul(cls.gf16_mul_table, m4, m4)\n                cls.m8 = m8\n\n            if not hasattr(cls, \"MIX_VAL\"):\n                tab = cls.gf16_mul_table\n                m8 = cls.m8\n                mix_val = []\n                for r in range(8):\n                    row = []\n                    for k in range(8):\n                        mul_row = []\n                        coeff = m8[r][k]\n                        for v in range(16):\n                            mul_row.append(tab[coeff][v])\n                        row.append(tuple(mul_row))\n                    mix_val.append(tuple(row))\n                cls.MIX_VAL = tuple(mix_val)\n\n            if not hasattr(cls, \"MIX_PAIR\"):\n                mix_val = cls.MIX_VAL\n                mix_pair = []\n                for r in range(8):\n                    row = []\n                    for pair_idx in range(4):\n                        pair_tab = []\n                        k0 = pair_idx << 1\n                        k1 = k0 + 1\n                        mv0 = mix_val[r][k0]\n                        mv1 = mix_val[r][k1]\n                        for a in range(16):\n                            pair_row = []\n                            v0 = mv0[a]\n                            for b in range(16):\n                                pair_row.append(v0 ^ mv1[b])\n                            pair_tab.append(tuple(pair_row))\n                        row.append(tuple(pair_tab))\n                    mix_pair.append(tuple(row))\n                cls.MIX_PAIR = tuple(mix_pair)\n\n            if not hasattr(cls, \"NIBBLE_SPLIT\"):\n                split = []\n                for b in range(256):\n                    split.append((b & 0x0f, b >> 4))\n                cls.NIBBLE_SPLIT = tuple(split)\n\n            if not hasattr(cls, \"NIBBLE_PACK\"):\n                pack = []\n                for lo in range(16):\n                    row = []\n                    for hi in range(16):\n                        row.append(lo | (hi << 4))\n                    pack.append(tuple(row))\n                cls.NIBBLE_PACK = tuple(pack)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            self.result = b\"\"\n            self.ensure_tables()\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            other.result = bytes(self.result)\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash already finalized\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return bytes(c.result)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n            self.result = self.hash_bytes(bytes(self.buf))\n            self.finalized = True\n            return\n\n        def hash_bytes(self, msg):\n            if self.USE_CFFI:\n                if len(msg) != 0:\n                    msg_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(msg))\n                else:\n                    msg_buf = self.cffi.ffi.NULL\n                out_buf = self.cffi.ffi.new(\"uint8_t[]\", self.digest_size)\n                self.cffi.lib.hash_bytes(\n                    msg_buf, len(msg), out_buf, self.cffi.sbox, self.cffi.rc, self.cffi.mix_pair,\n                )\n                return bytes(self.cffi.ffi.buffer(out_buf, self.digest_size))\n\n            def photon256(state):\n                split = self.NIBBLE_SPLIT\n                pack = self.NIBBLE_PACK\n                mix_pair = self.MIX_PAIR\n                rc = self.rc\n                sbox = self.sbox\n\n                m = [0] * 64\n                n = [0] * 64\n\n                i = 0\n                j = 0\n                while i < 32:\n                    lo, hi = split[state[i]]\n                    m[j] = lo\n                    m[j + 1] = hi\n                    i += 1\n                    j += 2\n\n                rnd = 0\n                while rnd < 12:\n                    rc_r = rc[rnd]\n                    m[0] ^= rc_r[0]\n                    m[8] ^= rc_r[1]\n                    m[16] ^= rc_r[2]\n                    m[24] ^= rc_r[3]\n                    m[32] ^= rc_r[4]\n                    m[40] ^= rc_r[5]\n                    m[48] ^= rc_r[6]\n                    m[56] ^= rc_r[7]\n\n                    r = 0\n                    while r < 8:\n                        base = r << 3\n                        shift = r\n                        c = 0\n                        while c < 8:\n                            n[base + c] = sbox[m[base + ((c + shift) & 7)]]\n                            c += 1\n                        r += 1\n\n                    row0 = mix_pair[0]\n                    row1 = mix_pair[1]\n                    row2 = mix_pair[2]\n                    row3 = mix_pair[3]\n                    row4 = mix_pair[4]\n                    row5 = mix_pair[5]\n                    row6 = mix_pair[6]\n                    row7 = mix_pair[7]\n\n                    c = 0\n                    while c < 8:\n                        p0a = n[c]\n                        p0b = n[8 + c]\n                        p1a = n[16 + c]\n                        p1b = n[24 + c]\n                        p2a = n[32 + c]\n                        p2b = n[40 + c]\n                        p3a = n[48 + c]\n                        p3b = n[56 + c]\n\n                        m[c] = row0[0][p0a][p0b] ^ row0[1][p1a][p1b] ^ row0[2][p2a][p2b] ^ row0[3][p3a][p3b]\n                        m[8 + c] = row1[0][p0a][p0b] ^ row1[1][p1a][p1b] ^ row1[2][p2a][p2b] ^ row1[3][p3a][p3b]\n                        m[16 + c] = row2[0][p0a][p0b] ^ row2[1][p1a][p1b] ^ row2[2][p2a][p2b] ^ row2[3][p3a][p3b]\n                        m[24 + c] = row3[0][p0a][p0b] ^ row3[1][p1a][p1b] ^ row3[2][p2a][p2b] ^ row3[3][p3a][p3b]\n                        m[32 + c] = row4[0][p0a][p0b] ^ row4[1][p1a][p1b] ^ row4[2][p2a][p2b] ^ row4[3][p3a][p3b]\n                        m[40 + c] = row5[0][p0a][p0b] ^ row5[1][p1a][p1b] ^ row5[2][p2a][p2b] ^ row5[3][p3a][p3b]\n                        m[48 + c] = row6[0][p0a][p0b] ^ row6[1][p1a][p1b] ^ row6[2][p2a][p2b] ^ row6[3][p3a][p3b]\n                        m[56 + c] = row7[0][p0a][p0b] ^ row7[1][p1a][p1b] ^ row7[2][p2a][p2b] ^ row7[3][p3a][p3b]\n                        c += 1\n\n                    rnd += 1\n\n                i = 0\n                j = 0\n                while i < 32:\n                    state[i] = pack[m[j]][m[j + 1]]\n                    i += 1\n                    j += 2\n                return\n\n            def gen_tag(state):\n                photon256(state)\n                out = bytearray(32)\n                out[0:16] = state[0:16]\n                photon256(state)\n                out[16:32] = state[0:16]\n                return bytes(out)\n\n            def absorb4(state, msg, c0):\n                off = 0\n                full = (len(msg) // 4) * 4\n                while off < full:\n                    photon256(state)\n                    state[0] ^= msg[off]\n                    state[1] ^= msg[off + 1]\n                    state[2] ^= msg[off + 2]\n                    state[3] ^= msg[off + 3]\n                    off += 4\n                rem = len(msg) - off\n                if rem > 0:\n                    photon256(state)\n                    i = 0\n                    while i < rem:\n                        state[i] ^= msg[off + i]\n                        i += 1\n                    state[rem] ^= 0x01\n                state[31] ^= (c0 << 5)\n                return\n\n            state = bytearray(32)\n            mlen = len(msg)\n\n            if mlen == 0:\n                state[31] ^= (0x01 << 5)\n                out = gen_tag(state)\n                return out\n\n            if mlen <= 16:\n                state[0:mlen] = msg\n                if mlen < 16:\n                    state[mlen] ^= 0x01\n                c0 = 0x01 if mlen < 16 else 0x02\n                state[31] ^= (c0 << 5)\n                out = gen_tag(state)\n                return out\n\n            state[0:16] = msg[0:16]\n            rem = msg[16:]\n            c0 = 0x01 if (len(rem) % 4) == 0 else 0x02\n            absorb4(state, rem, c0)\n            out = gen_tag(state)\n            return out\n\n    class VSH1024:\n        block_size = 0x83\n        digest_size = 0x80\n        n = int(\n            \"1350664108659952233496032162788059699388814756056670275244851438515\"\n            \"265106048595338339402871505719094417982072821644715513736804197039641917430464965\"\n            \"892742562393410208643832021103729587257623585096431105640735015081875106765946292\"\n            \"05563685529475213500852879416377328533906109750544334999811150056977236890927563\"\n        )\n        primes = (\n            0x2, 0x3, 0x5, 0x7, 0xb, 0xd, 0x11, 0x13, 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, 0x3b,\n            0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83, 0x89,\n            0x8b, 0x95, 0x97, 0x9d, 0xa3, 0xa7, 0xad, 0xb3, 0xb5, 0xbf, 0xc1, 0xc5, 0xc7, 0xd3, 0xdf, 0xe3,\n            0xe5, 0xe9, 0xef, 0xf1, 0xfb, 0x101, 0x107, 0x10d, 0x10f, 0x115, 0x119, 0x11b, 0x125, 0x133, 0x137,\n            0x139, 0x13d, 0x14b, 0x151, 0x15b, 0x15d, 0x161, 0x167, 0x16f, 0x175, 0x17b, 0x17f, 0x185, 0x18d,\n            0x191, 0x199, 0x1a3, 0x1a5, 0x1af, 0x1b1, 0x1b7, 0x1bb, 0x1c1, 0x1c9, 0x1cd, 0x1cf, 0x1d3, 0x1df,\n            0x1e7, 0x1eb, 0x1f3, 0x1f7, 0x1fd, 0x209, 0x20b, 0x21d, 0x223, 0x22d, 0x233, 0x239, 0x23b, 0x241,\n            0x24b, 0x251, 0x257, 0x259, 0x25f, 0x265, 0x269, 0x26b, 0x277, 0x281, 0x283, 0x287, 0x28d, 0x293,\n            0x295, 0x2a1, 0x2a5, 0x2ab, 0x2b3, 0x2bd, 0x2c5, 0x2cf, 0x2d7, 0x2dd, 0x2e3,\n        )\n        k = 0x83\n        block_size = 0x83\n\n        def __init__(self, data=b\"\"):\n            self.x = 0x1\n            self.bit_buf = []\n            self.msg_len_bits = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.x = self.x\n            other.bit_buf = list(self.bit_buf)\n            other.msg_len_bits = self.msg_len_bits\n            return other\n\n        def update(self, data):\n            data = bytes(data)\n            for b in data:\n                bit = 0x80\n                while bit != 0:\n                    if b & bit:\n                        self.bit_buf.append(1)\n                    else:\n                        self.bit_buf.append(0)\n                    self.msg_len_bits += 1\n                    bit >>= 1\n                    if len(self.bit_buf) >= self.k:\n                        block_bits = self.bit_buf[:self.k]\n                        del self.bit_buf[:self.k]\n                        self.compress(block_bits)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.x.to_bytes(self.digest_size, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if len(self.bit_buf) != 0:\n                block_bits = list(self.bit_buf)\n                while len(block_bits) < self.k:\n                    block_bits.append(0x0)\n                self.compress(block_bits)\n                self.bit_buf = []\n            length_bits = []\n            value = self.msg_len_bits\n            i = 0\n            while i < self.k:\n                length_bits.append(value & 0x1)\n                value >>= 0x1\n                i += 0x1\n            self.compress(length_bits)\n            return\n\n        def compress(self, block_bits):\n            mul = 1\n            i = 0\n            while i < self.k:\n                if block_bits[i]:\n                    mul *= self.primes[i]\n                i += 1\n            self.x = (self.x * self.x * mul) % self.n\n            return\n\n    class Xoodyak:\n        block_size = 16\n        digest_size = 32\n        round_constants = (\n            0x0058, 0x0038, 0x03c0, 0x00d0, 0x0120, 0x0014, 0x0060, 0x002c, 0x0380, 0x00f0, 0x01a0, 0x0012,\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n\n        static uint32_t rol32(uint32_t x, int n)\n        {\n            return ((x << n) | (x >> (32 - n))) & 0xffffffffU;\n        }\n\n        static void plane_shift(const uint32_t *plane, uint32_t *out, int t, int v)\n        {\n            int x = 0;\n\n            for (x = 0; x < 4; x++) {\n                out[x] = rol32(plane[(x - t) & 3], v);\n            }\n        }\n\n        void xoodoo_permute(uint8_t *state)\n        {\n            static const uint32_t round_constants[12] = {\n                0x00000058U, 0x00000038U, 0x000003c0U, 0x000000d0U,\n                0x00000120U, 0x00000014U, 0x00000060U, 0x0000002cU,\n                0x00000380U, 0x000000f0U, 0x000001a0U, 0x00000012U,\n            };\n\n            uint32_t a[12];\n            uint32_t p[4];\n            uint32_t e[4];\n            uint32_t e2[4];\n            uint32_t a1[4];\n            uint32_t a2[4];\n            uint32_t b0[4];\n            uint32_t b1[4];\n            uint32_t b2[4];\n            int i = 0;\n            int x = 0;\n\n            for (i = 0; i < 12; i++) {\n                int start = i * 4;\n                a[i] = (\n                    ((uint32_t)state[start + 0]) |\n                    ((uint32_t)state[start + 1] << 8) |\n                    ((uint32_t)state[start + 2] << 16) |\n                    ((uint32_t)state[start + 3] << 24)\n                );\n            }\n\n            for (i = 0; i < 12; i++) {\n                uint32_t rc = round_constants[i];\n\n                for (x = 0; x < 4; x++) {\n                    p[x] = a[x] ^ a[4 + x] ^ a[8 + x];\n                }\n\n                plane_shift(p, e, 1, 5);\n                plane_shift(p, e2, 1, 14);\n\n                for (x = 0; x < 4; x++) {\n                    e[x] ^= e2[x];\n                }\n\n                for (x = 0; x < 4; x++) {\n                    a[x] ^= e[x];\n                    a[4 + x] ^= e[x];\n                    a[8 + x] ^= e[x];\n                }\n\n                plane_shift(a + 4, a1, 1, 0);\n                plane_shift(a + 8, a2, 0, 11);\n\n                for (x = 0; x < 4; x++) {\n                    a[4 + x] = a1[x];\n                    a[8 + x] = a2[x];\n                }\n\n                a[0] ^= rc;\n\n                for (x = 0; x < 4; x++) {\n                    b0[x] = (a[4 + x] ^ 0xffffffffU) & a[8 + x];\n                    b1[x] = (a[8 + x] ^ 0xffffffffU) & a[x];\n                    b2[x] = (a[x] ^ 0xffffffffU) & a[4 + x];\n                }\n\n                for (x = 0; x < 4; x++) {\n                    a[x] ^= b0[x];\n                    a[4 + x] ^= b1[x];\n                    a[8 + x] ^= b2[x];\n                }\n\n                plane_shift(a + 4, a1, 0, 1);\n                plane_shift(a + 8, a2, 2, 8);\n\n                for (x = 0; x < 4; x++) {\n                    a[4 + x] = a1[x];\n                    a[8 + x] = a2[x];\n                }\n            }\n\n            for (i = 0; i < 12; i++) {\n                int start = i * 4;\n                uint32_t word = a[i];\n\n                state[start + 0] = word & 0xffU;\n                state[start + 1] = (word >> 8) & 0xffU;\n                state[start + 2] = (word >> 16) & 0xffU;\n                state[start + 3] = (word >> 24) & 0xffU;\n            }\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void xoodoo_permute(uint8_t *state);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.Xoodyak\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            try:\n                with warnings.catch_warnings():\n                    warnings.filterwarnings(\n                        \"ignore\",\n                        message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                        category=UserWarning,\n                        module=r\"cffi\\.vengine_cpy\",\n                    )\n                    ffi = cffi.FFI()\n                    ffi.cdef(base_class.DEF_TEMPLATE)\n                    lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib\")(\n                ffi, lib,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        def __init__(self, data=b\"\"):\n            self.state = bytearray(48)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.phase = \"up\"\n            self.absorb_started = False\n            self.finalized = False\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = bytearray(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.phase = self.phase\n            other.absorb_started = self.absorb_started\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                chunk = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.absorb_chunk(chunk)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.squeeze_any(self.digest_size, 0x40)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n            if len(self.buf) != 0 or not self.absorb_started:\n                chunk = bytes(self.buf)\n                self.buf.clear()\n                self.absorb_chunk(chunk)\n            self.finalized = True\n            return\n\n        def absorb_chunk(self, chunk):\n            if self.phase != \"up\":\n                self.up(0, 0x00)\n            if self.absorb_started:\n                self.down(chunk, 0x00)\n            else:\n                self.down(chunk, 0x03)\n                self.absorb_started = True\n            return\n\n        def squeeze_any(self, length, c_u):\n            y = bytearray(self.up(min(length, self.block_size), c_u))\n            while len(y) < length:\n                self.down(b\"\", 0x00)\n                y.extend(self.up(min(length - len(y), self.block_size), 0x00))\n            return bytes(y)\n\n        def down(self, xi, c_d):\n            n = len(xi)\n            i = 0\n            while i < n:\n                self.state[i] ^= xi[i]\n                i += 1\n            self.state[n] ^= 0x01\n            self.state[47] ^= (c_d & 0x01)\n            self.phase = \"down\"\n            return\n\n        def up(self, yi_len, c_u):\n            if self.USE_CFFI:\n                state_buf = self.cffi.ffi.new(\"uint8_t[]\", bytes(self.state))\n                self.cffi.lib.xoodoo_permute(state_buf)\n                self.state = bytearray(state_buf[i] for i in range(48))\n                self.phase = \"up\"\n                return bytes(self.state[:yi_len])\n\n            def rol32(x, n):\n                return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n            def plane_shift(plane, t, v):\n                out = [0, 0, 0, 0]\n                x = 0\n                while x < 4:\n                    out[x] = rol32(plane[(x - t) & 3], v)\n                    x += 1\n                return out\n\n            a = []\n            i = 0\n            while i < 12:\n                start = i * 4\n                a.append(int.from_bytes(self.state[start:start + 4], \"little\"))\n                i += 1\n            for rc in self.round_constants:\n                p = [0, 0, 0, 0]\n                x = 0\n                while x < 4:\n                    p[x] = a[x] ^ a[4 + x] ^ a[8 + x]\n                    x += 1\n                e = plane_shift(p, 1, 5)\n                e2 = plane_shift(p, 1, 14)\n                x = 0\n                while x < 4:\n                    e[x] ^= e2[x]\n                    x += 1\n                x = 0\n                while x < 4:\n                    a[x] ^= e[x]\n                    a[4 + x] ^= e[x]\n                    a[8 + x] ^= e[x]\n                    x += 1\n                a1 = plane_shift(a[4:8], 1, 0)\n                a2 = plane_shift(a[8:12], 0, 11)\n                x = 0\n                while x < 4:\n                    a[4 + x] = a1[x]\n                    a[8 + x] = a2[x]\n                    x += 1\n                a[0] ^= rc\n                b0 = [0, 0, 0, 0]\n                b1 = [0, 0, 0, 0]\n                b2 = [0, 0, 0, 0]\n                x = 0\n                while x < 4:\n                    b0[x] = (a[4 + x] ^ 0xffff_ffff) & a[8 + x]\n                    b1[x] = (a[8 + x] ^ 0xffff_ffff) & a[x]\n                    b2[x] = (a[x] ^ 0xffff_ffff) & a[4 + x]\n                    x += 1\n                x = 0\n                while x < 4:\n                    a[x] ^= b0[x]\n                    a[4 + x] ^= b1[x]\n                    a[8 + x] ^= b2[x]\n                    x += 1\n                a1 = plane_shift(a[4:8], 0, 1)\n                a2 = plane_shift(a[8:12], 2, 8)\n                x = 0\n                while x < 4:\n                    a[4 + x] = a1[x]\n                    a[8 + x] = a2[x]\n                    x += 1\n            i = 0\n            while i < 12:\n                start = i * 4\n                self.state[start:start + 4] = a[i].to_bytes(4, \"little\")\n                i += 1\n\n            self.phase = \"up\"\n            return bytes(self.state[:yi_len])\n\n    class GxHashBase:\n        block_size = 16\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n        keys = (\n            (0x42, 0x45, 0x78, 0xf2, 0x21, 0x3e, 0x9d, 0xb0, 0xe5, 0x22, 0xc2, 0x89, 0x8e, 0xc2, 0x3b, 0xfc),\n            (0x79, 0xe2, 0xfc, 0x03, 0x9b, 0x2e, 0x6b, 0xcb, 0x58, 0xdc, 0x61, 0xb3, 0xd9, 0x2b, 0x13, 0x39),\n            (0x32, 0x2e, 0x01, 0xd0, 0x7d, 0x2b, 0x9d, 0x68, 0xb7, 0xb1, 0x44, 0x55, 0x2b, 0x12, 0x8b, 0xc7),\n        )\n\n        def __init__(self, data=b\"\", seed=0):\n            self.seed = int(seed)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.final_state = None\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            if self.final_state is None:\n                other.final_state = None\n            else:\n                other.final_state = bytes(self.final_state)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            self.final_state = None\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.final_state[:self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            self.final_state = self.gxhash_state(bytes(self.buf), self.seed)\n            return\n\n        def gxhash_state(self, data, seed):\n\n            def create_seed(seed):\n                seed64 = int(seed) & 0xffff_ffff_ffff_ffff\n                lane = list(struct.pack(\"<Q\", seed64))\n                return lane + lane\n\n            state = self.compress_all(data)\n            state = self.aes_encrypt(state, create_seed(seed))\n            state = self.aes_encrypt(state, self.keys[0])\n            state = self.aes_encrypt(state, self.keys[1])\n            state = self.aes_encrypt_last(state, self.keys[2])\n            return bytes(state)\n\n        def xor_bytes(self, a, b):\n            out = []\n            for i in range(16):\n                out.append(a[i] ^ b[i])\n            return out\n\n        def sub_bytes(self, state):\n            out = []\n            for x in state:\n                out.append(self.sbox[x])\n            return out\n\n        def shift_rows(self, state):\n            out = [0] * 16\n            for row in range(4):\n                for col in range(4):\n                    src_col = (col + row) % 4\n                    out[4 * col + row] = state[4 * src_col + row]\n            return out\n\n        def mix_columns(self, state):\n\n            def xtime(x):\n                x = x << 1\n                if x & 0x100:\n                    x ^= 0x11b\n                return x & 0xff\n\n            out = [0] * 16\n            for col in range(4):\n                i = col * 4\n                a0 = state[i + 0]\n                a1 = state[i + 1]\n                a2 = state[i + 2]\n                a3 = state[i + 3]\n                m2a0 = xtime(a0)\n                m2a1 = xtime(a1)\n                m2a2 = xtime(a2)\n                m2a3 = xtime(a3)\n                m3a0 = m2a0 ^ a0\n                m3a1 = m2a1 ^ a1\n                m3a2 = m2a2 ^ a2\n                m3a3 = m2a3 ^ a3\n                out[i + 0] = m2a0 ^ m3a1 ^ a2 ^ a3\n                out[i + 1] = a0 ^ m2a1 ^ m3a2 ^ a3\n                out[i + 2] = a0 ^ a1 ^ m2a2 ^ m3a3\n                out[i + 3] = m3a0 ^ a1 ^ a2 ^ m2a3\n            return out\n\n        def aes_encrypt(self, data, keys):\n            state = self.sub_bytes(data)\n            state = self.shift_rows(state)\n            state = self.mix_columns(state)\n            state = self.xor_bytes(state, keys)\n            return state\n\n        def aes_encrypt_last(self, data, keys):\n            state = self.sub_bytes(data)\n            state = self.shift_rows(state)\n            state = self.xor_bytes(state, keys)\n            return state\n\n        def compress_many(self, data, ptr, end_address, hash_vector, length):\n\n            def add_epi8(a, b):\n                out = []\n                for i in range(16):\n                    out.append((a[i] + b[i]) & 0xff)\n                return out\n\n            def compress_8(data, ptr, end_address, hash_vector, length):\n                t1 = [0] * 16\n                t2 = [0] * 16\n                lane1 = hash_vector[:]\n                lane2 = hash_vector[:]\n                k0 = self.keys[0]\n                k1 = self.keys[1]\n                while ptr < end_address:\n                    v0 = list(data[ptr + 0x00:ptr + 0x10])\n                    v1 = list(data[ptr + 0x10:ptr + 0x20])\n                    v2 = list(data[ptr + 0x20:ptr + 0x30])\n                    v3 = list(data[ptr + 0x30:ptr + 0x40])\n                    v4 = list(data[ptr + 0x40:ptr + 0x50])\n                    v5 = list(data[ptr + 0x50:ptr + 0x60])\n                    v6 = list(data[ptr + 0x60:ptr + 0x70])\n                    v7 = list(data[ptr + 0x70:ptr + 0x80])\n                    ptr += 0x80\n                    tmp1 = self.aes_encrypt(v0, v2)\n                    tmp2 = self.aes_encrypt(v1, v3)\n                    tmp1 = self.aes_encrypt(tmp1, v4)\n                    tmp2 = self.aes_encrypt(tmp2, v5)\n                    tmp1 = self.aes_encrypt(tmp1, v6)\n                    tmp2 = self.aes_encrypt(tmp2, v7)\n                    t1 = add_epi8(t1, k0)\n                    t2 = add_epi8(t2, k1)\n                    lane1 = self.aes_encrypt_last(self.aes_encrypt(tmp1, t1), lane1)\n                    lane2 = self.aes_encrypt_last(self.aes_encrypt(tmp2, t2), lane2)\n                len_vec = list(struct.pack(\"<I\", length & 0xffff_ffff)) * 4\n                lane1 = add_epi8(lane1, len_vec)\n                lane2 = add_epi8(lane2, len_vec)\n                return self.aes_encrypt(lane1, lane2)\n\n            unroll_factor = 8\n            remaining_bytes = end_address - ptr\n            unrollable_blocks_count = (remaining_bytes // (self.block_size * unroll_factor)) * unroll_factor\n            remaining_bytes = remaining_bytes - unrollable_blocks_count * self.block_size\n            stop_ptr = ptr + remaining_bytes\n            state = hash_vector[:]\n            while ptr < stop_ptr:\n                v0 = list(data[ptr:ptr + 0x10])\n                ptr += self.block_size\n                state = self.aes_encrypt(state, v0)\n            state = compress_8(data, ptr, end_address, state, length)\n            return state\n\n        def compress_all(self, data):\n\n            def get_partial(data):\n                length = len(data)\n                vector = list(data[:16]) + [0] * (16 - length)\n                out = []\n                for x in vector:\n                    out.append((x + length) & 0xff)\n                return out\n\n            length = len(data)\n            if length == 0:\n                return [0] * 16\n            if length <= self.block_size:\n                return get_partial(data)\n            end_address = length\n            extra_bytes_count = length % self.block_size\n            if extra_bytes_count == 0:\n                hash_vector = list(data[:0x10])\n                ptr = self.block_size\n            else:\n                hash_vector = get_partial(data[:extra_bytes_count])\n                ptr = extra_bytes_count\n            v0 = list(data[ptr:ptr + 0x10])\n            ptr += self.block_size\n            if length > self.block_size * 2:\n                v = list(data[ptr:ptr + 0x10])\n                ptr += self.block_size\n                v0 = self.aes_encrypt(v0, v)\n                if length > self.block_size * 3:\n                    v = list(data[ptr:ptr + 0x10])\n                    ptr += self.block_size\n                    v0 = self.aes_encrypt(v0, v)\n                    if length > self.block_size * 4:\n                        hash_vector = self.compress_many(data, ptr, end_address, hash_vector, length)\n            mixed = self.aes_encrypt(self.aes_encrypt(v0, self.keys[0]), self.keys[1])\n            return self.aes_encrypt_last(hash_vector, mixed)\n\n    class GxHash32(GxHashBase):\n        digest_size = 4\n\n    class GxHash64(GxHashBase):\n        digest_size = 8\n\n    class GxHash128(GxHashBase):\n        digest_size = 16\n\n    class KomiHash:\n        block_size = 64\n        digest_size = 8\n        ival1 = 0x243f_6a88_85a3_08d3\n        ival2 = 0x1319_8a2e_0370_7344\n        ival3 = 0xa409_3822_299f_31d0\n        ival4 = 0x082e_fa98_ec4e_6c89\n        ival5 = 0x4528_21e6_38d0_1377\n        ival6 = 0xbe54_66cf_34e9_0c6c\n        ival7 = 0xc0ac_29b7_c97c_50dd\n        ival8 = 0x3f84_d5b5_b547_0917\n        val01 = 0x5555_5555_5555_5555\n        val10 = 0xaaaa_aaaa_aaaa_aaaa\n\n        def __init__(self, data=b\"\", seed=0):\n            if not isinstance(seed, int):\n                raise TypeError(\"seed must be int\")\n            self.seed = seed\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(seed=self.seed)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(data)\n            self.msg_len += len(data)\n            return self\n\n        def digest(self):\n            h = self.hash_bytes(bytes(self.buf), self.seed)\n            return struct.pack(\">Q\", h)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def hash_bytes(self, data, use_seed=0):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(use_seed, int):\n                raise TypeError(\"use_seed must be int\")\n\n            def u32le(data, pos):\n                return int.from_bytes(data[pos:pos + 4], \"little\")\n\n            def u64le(data, pos):\n                return int.from_bytes(data[pos:pos + 8], \"little\")\n\n            def m128(u, v, rha):\n                prod = u * v\n                rl = prod & 0xffff_ffff_ffff_ffff\n                rha = (rha + (prod >> 64)) & 0xffff_ffff_ffff_ffff\n                return rl, rha\n\n            def hash16(data, pos, seed1, seed5):\n                u = u64le(data, pos) ^ seed1\n                v = u64le(data, pos + 8) ^ seed5\n                seed1, seed5 = m128(u, v, seed5)\n                seed1 ^= seed5\n                return seed1, seed5\n\n            def hash_round(seed1, seed5):\n                seed1, seed5 = m128(seed1, seed5, seed5)\n                seed1 ^= seed5\n                return seed1, seed5\n\n            def hash_fin(r1h, r2h, seed1, seed5):\n                seed1, seed5 = m128(r1h, r2h, seed5)\n                seed1 ^= seed5\n                seed1, seed5 = hash_round(seed1, seed5)\n                return seed1\n\n            def epi(data, pos, msg_len, seed1, seed5):\n                if msg_len > 31:\n                    seed1, seed5 = hash16(data, pos, seed1, seed5)\n                    seed1, seed5 = hash16(data, pos + 16, seed1, seed5)\n                    msg_len -= 32\n                    pos += 32\n                if msg_len > 15:\n                    seed1, seed5 = hash16(data, pos, seed1, seed5)\n                    msg_len -= 16\n                    pos += 16\n                ml8 = msg_len * 8\n                if msg_len < 8:\n                    ml8 ^= 56\n                    r1h = (u64le(data, pos + msg_len - 8) >> 8) | (1 << 56)\n                    r2h = seed5\n                    r1h = (r1h >> ml8) ^ seed1\n                else:\n                    r2h = (u64le(data, pos + msg_len - 8) >> 8) | (1 << 56)\n                    ml8 ^= 120\n                    r1h = u64le(data, pos) ^ seed1\n                    r2h = (r2h >> ml8) ^ seed5\n                return hash_fin(r1h, r2h, seed1, seed5)\n\n            data = bytes(data)\n            msg_len = len(data)\n            seed1 = self.ival1 ^ (use_seed & self.val01)\n            seed5 = self.ival5 ^ (use_seed & self.val10)\n            seed1, seed5 = hash_round(seed1, seed5)\n            if msg_len < 16:\n                r1h = seed1\n                r2h = seed5\n                if msg_len > 7:\n                    r1h ^= u64le(data, 0)\n                    if msg_len < 12:\n                        ml8 = msg_len * 8\n                        m = (data[msg_len - 3] | (data[msg_len - 2] << 8) | (data[msg_len - 1] << 16) | (1 << 24))\n                        ml8 ^= 88\n                        r2h ^= m >> ml8\n                    else:\n                        mhs = 128 - msg_len * 8\n                        mh = (u32le(data, msg_len - 4) | (1 << 32)) >> mhs\n                        ml = u32le(data, 8)\n                        r2h ^= (mh << 32) | ml\n                elif msg_len != 0:\n                    ml8 = msg_len * 8\n                    if msg_len < 4:\n                        r1h ^= 1 << ml8\n                        r1h ^= data[0]\n                        if msg_len != 1:\n                            r1h ^= data[1] << 8\n                            if msg_len != 2:\n                                r1h ^= data[2] << 16\n                    else:\n                        mhs = 64 - ml8\n                        mh = (u32le(data, msg_len - 4) | (1 << 32)) >> mhs\n                        ml = u32le(data, 0)\n                        r1h ^= (mh << 32) | ml\n                return hash_fin(r1h, r2h, seed1, seed5)\n\n            pos = 0\n            if msg_len <= 31:\n                seed1, seed5 = hash16(data, pos, seed1, seed5)\n                ml8 = msg_len * 8\n                if msg_len < 24:\n                    ml8 ^= 184\n                    r1h = (u64le(data, pos + msg_len - 8) >> 8) | (1 << 56)\n                    r2h = seed5\n                    r1h = (r1h >> ml8) ^ seed1\n                    return hash_fin(r1h, r2h, seed1, seed5)\n\n                r2h = (u64le(data, pos + msg_len - 8) >> 8) | (1 << 56)\n                ml8 ^= 248\n                r1h = u64le(data, pos + 16) ^ seed1\n                r2h = (r2h >> ml8) ^ seed5\n                return hash_fin(r1h, r2h, seed1, seed5)\n\n            if msg_len > 63:\n                seed2 = self.ival2 ^ seed1\n                seed3 = self.ival3 ^ seed1\n                seed4 = self.ival4 ^ seed1\n                seed6 = self.ival6 ^ seed5\n                seed7 = self.ival7 ^ seed5\n                seed8 = self.ival8 ^ seed5\n                while msg_len > 63:\n                    seed1, seed5 = m128(\n                        u64le(data, pos) ^ seed1,\n                        u64le(data, pos + 32) ^ seed5,\n                        seed5,\n                    )\n                    seed2, seed6 = m128(\n                        u64le(data, pos + 8) ^ seed2,\n                        u64le(data, pos + 40) ^ seed6,\n                        seed6,\n                    )\n                    seed3, seed7 = m128(\n                        u64le(data, pos + 16) ^ seed3,\n                        u64le(data, pos + 48) ^ seed7,\n                        seed7,\n                    )\n                    seed4, seed8 = m128(\n                        u64le(data, pos + 24) ^ seed4,\n                        u64le(data, pos + 56) ^ seed8,\n                        seed8,\n                    )\n                    pos += 64\n                    msg_len -= 64\n                    seed4 ^= seed7\n                    seed1 ^= seed8\n                    seed3 ^= seed6\n                    seed2 ^= seed5\n                seed5 ^= seed6 ^ seed7 ^ seed8\n                seed1 ^= seed2 ^ seed3 ^ seed4\n            return epi(data, pos, msg_len, seed1, seed5)\n\n    class ParallelHashBase:\n        keccak_round_constants = (\n            0x0000_0000_0000_0001, 0x0000_0000_0000_8082, 0x8000_0000_0000_808a, 0x8000_0000_8000_8000,\n            0x0000_0000_0000_808b, 0x0000_0000_8000_0001, 0x8000_0000_8000_8081, 0x8000_0000_0000_8009,\n            0x0000_0000_0000_008a, 0x0000_0000_0000_0088, 0x0000_0000_8000_8009, 0x0000_0000_8000_000a,\n            0x0000_0000_8000_808b, 0x8000_0000_0000_008b, 0x8000_0000_0000_8089, 0x8000_0000_0000_8003,\n            0x8000_0000_0000_8002, 0x8000_0000_0000_0080, 0x0000_0000_0000_800a, 0x8000_0000_8000_000a,\n            0x8000_0000_8000_8081, 0x8000_0000_0000_8080, 0x0000_0000_8000_0001, 0x8000_0000_8000_8008,\n        )\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n        #include <stddef.h>\n        #include <stdlib.h>\n        #include <string.h>\n\n        static uint64_t rol64(uint64_t x, int n)\n        {\n            return ((x << n) | (x >> (64 - n))) & 0xffffffffffffffffULL;\n        }\n\n        static uint64_t load64_le(const uint8_t *src)\n        {\n            return (\n                ((uint64_t)src[0]) |\n                ((uint64_t)src[1] << 8) |\n                ((uint64_t)src[2] << 16) |\n                ((uint64_t)src[3] << 24) |\n                ((uint64_t)src[4] << 32) |\n                ((uint64_t)src[5] << 40) |\n                ((uint64_t)src[6] << 48) |\n                ((uint64_t)src[7] << 56)\n            );\n        }\n\n        static void store64_le(uint8_t *dst, uint64_t value)\n        {\n            dst[0] = (uint8_t)(value & 0xffU);\n            dst[1] = (uint8_t)((value >> 8) & 0xffU);\n            dst[2] = (uint8_t)((value >> 16) & 0xffU);\n            dst[3] = (uint8_t)((value >> 24) & 0xffU);\n            dst[4] = (uint8_t)((value >> 32) & 0xffU);\n            dst[5] = (uint8_t)((value >> 40) & 0xffU);\n            dst[6] = (uint8_t)((value >> 48) & 0xffU);\n            dst[7] = (uint8_t)((value >> 56) & 0xffU);\n        }\n\n        static int encoded_length_u64(uint64_t value)\n        {\n            int n = 1;\n\n            while ((value >> (8 * n)) != 0 && n < 8) {\n                n++;\n            }\n            return n + 1;\n        }\n\n        static int write_left_encode_u64(uint8_t *dst, uint64_t value)\n        {\n            int n = 1;\n            int i = 0;\n\n            while ((value >> (8 * n)) != 0 && n < 8) {\n                n++;\n            }\n            dst[0] = (uint8_t)n;\n            for (i = 0; i < n; i++) {\n                dst[1 + i] = (uint8_t)((value >> (8 * (n - 1 - i))) & 0xffU);\n            }\n            return n + 1;\n        }\n\n        static void keccak_absorb_block(uint64_t *state, const uint8_t *block, int rate_bytes)\n        {\n            int lanes = rate_bytes / 8;\n            int i = 0;\n\n            for (i = 0; i < lanes; i++) {\n                state[i] ^= load64_le(block + (i * 8));\n            }\n        }\n\n        static void keccak_absorb_padded(\n            uint64_t *state, const uint8_t *tail, size_t tail_len, int rate_bytes, uint8_t domain_suffix)\n        {\n            uint8_t block[168];\n            size_t i = 0;\n\n            for (i = 0; i < (size_t)rate_bytes; i++) {\n                block[i] = 0;\n            }\n            for (i = 0; i < tail_len; i++) {\n                block[i] = tail[i];\n            }\n            block[tail_len] ^= domain_suffix;\n            block[rate_bytes - 1] ^= 0x80;\n            keccak_absorb_block(state, block, rate_bytes);\n        }\n\n        static void keccak_squeeze_block(const uint64_t *state, uint8_t *out, int out_len)\n        {\n            int full_lanes = out_len / 8;\n            int remain = out_len % 8;\n            int i = 0;\n\n            for (i = 0; i < full_lanes; i++) {\n                store64_le(out + (i * 8), state[i]);\n            }\n            if (remain != 0) {\n                uint8_t temp[8];\n                store64_le(temp, state[full_lanes]);\n                for (i = 0; i < remain; i++) {\n                    out[(full_lanes * 8) + i] = temp[i];\n                }\n            }\n        }\n\n        static void keccak_f1600(uint64_t *state)\n        {\n            uint64_t A00 = state[0], A01 = state[1], A02 = state[2], A03 = state[3], A04 = state[4];\n            uint64_t A05 = state[5], A06 = state[6], A07 = state[7], A08 = state[8], A09 = state[9];\n            uint64_t A10 = state[10], A11 = state[11], A12 = state[12], A13 = state[13], A14 = state[14];\n            uint64_t A15 = state[15], A16 = state[16], A17 = state[17], A18 = state[18], A19 = state[19];\n            uint64_t A20 = state[20], A21 = state[21], A22 = state[22], A23 = state[23], A24 = state[24];\n            static const uint64_t round_constants[24] = {\n                0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,\n                0x000000000000808bULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,\n                0x000000000000008aULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,\n                0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,\n                0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800aULL, 0x800000008000000aULL,\n                0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL,\n            };\n            int round_index = 0;\n\n            for (round_index = 0; round_index < 24; round_index++) {\n                uint64_t rc = round_constants[round_index];\n                uint64_t C0 = A00 ^ A05 ^ A10 ^ A15 ^ A20;\n                uint64_t C1 = A01 ^ A06 ^ A11 ^ A16 ^ A21;\n                uint64_t C2 = A02 ^ A07 ^ A12 ^ A17 ^ A22;\n                uint64_t C3 = A03 ^ A08 ^ A13 ^ A18 ^ A23;\n                uint64_t C4 = A04 ^ A09 ^ A14 ^ A19 ^ A24;\n                uint64_t D0 = C4 ^ rol64(C1, 1);\n                uint64_t D1 = C0 ^ rol64(C2, 1);\n                uint64_t D2 = C1 ^ rol64(C3, 1);\n                uint64_t D3 = C2 ^ rol64(C4, 1);\n                uint64_t D4 = C3 ^ rol64(C0, 1);\n                uint64_t B00 = 0, B01 = 0, B02 = 0, B03 = 0, B04 = 0;\n                uint64_t B05 = 0, B06 = 0, B07 = 0, B08 = 0, B09 = 0;\n                uint64_t B10 = 0, B11 = 0, B12 = 0, B13 = 0, B14 = 0;\n                uint64_t B15 = 0, B16 = 0, B17 = 0, B18 = 0, B19 = 0;\n                uint64_t B20 = 0, B21 = 0, B22 = 0, B23 = 0, B24 = 0;\n\n                A00 ^= D0;\n                A05 ^= D0;\n                A10 ^= D0;\n                A15 ^= D0;\n                A20 ^= D0;\n                A01 ^= D1;\n                A06 ^= D1;\n                A11 ^= D1;\n                A16 ^= D1;\n                A21 ^= D1;\n                A02 ^= D2;\n                A07 ^= D2;\n                A12 ^= D2;\n                A17 ^= D2;\n                A22 ^= D2;\n                A03 ^= D3;\n                A08 ^= D3;\n                A13 ^= D3;\n                A18 ^= D3;\n                A23 ^= D3;\n                A04 ^= D4;\n                A09 ^= D4;\n                A14 ^= D4;\n                A19 ^= D4;\n                A24 ^= D4;\n\n                B00 = A00;\n                B01 = rol64(A06, 44);\n                B02 = rol64(A12, 43);\n                B03 = rol64(A18, 21);\n                B04 = rol64(A24, 14);\n                B05 = rol64(A03, 28);\n                B06 = rol64(A09, 20);\n                B07 = rol64(A10, 3);\n                B08 = rol64(A16, 45);\n                B09 = rol64(A22, 61);\n                B10 = rol64(A01, 1);\n                B11 = rol64(A07, 6);\n                B12 = rol64(A13, 25);\n                B13 = rol64(A19, 8);\n                B14 = rol64(A20, 18);\n                B15 = rol64(A04, 27);\n                B16 = rol64(A05, 36);\n                B17 = rol64(A11, 10);\n                B18 = rol64(A17, 15);\n                B19 = rol64(A23, 56);\n                B20 = rol64(A02, 62);\n                B21 = rol64(A08, 55);\n                B22 = rol64(A14, 39);\n                B23 = rol64(A15, 41);\n                B24 = rol64(A21, 2);\n\n                A00 = B00 ^ ((~B01) & B02);\n                A01 = B01 ^ ((~B02) & B03);\n                A02 = B02 ^ ((~B03) & B04);\n                A03 = B03 ^ ((~B04) & B00);\n                A04 = B04 ^ ((~B00) & B01);\n                A05 = B05 ^ ((~B06) & B07);\n                A06 = B06 ^ ((~B07) & B08);\n                A07 = B07 ^ ((~B08) & B09);\n                A08 = B08 ^ ((~B09) & B05);\n                A09 = B09 ^ ((~B05) & B06);\n                A10 = B10 ^ ((~B11) & B12);\n                A11 = B11 ^ ((~B12) & B13);\n                A12 = B12 ^ ((~B13) & B14);\n                A13 = B13 ^ ((~B14) & B10);\n                A14 = B14 ^ ((~B10) & B11);\n                A15 = B15 ^ ((~B16) & B17);\n                A16 = B16 ^ ((~B17) & B18);\n                A17 = B17 ^ ((~B18) & B19);\n                A18 = B18 ^ ((~B19) & B15);\n                A19 = B19 ^ ((~B15) & B16);\n                A20 = B20 ^ ((~B21) & B22);\n                A21 = B21 ^ ((~B22) & B23);\n                A22 = B22 ^ ((~B23) & B24);\n                A23 = B23 ^ ((~B24) & B20);\n                A24 = B24 ^ ((~B20) & B21);\n\n                A00 ^= rc;\n            }\n\n            state[0] = A00; state[1] = A01; state[2] = A02; state[3] = A03; state[4] = A04;\n            state[5] = A05; state[6] = A06; state[7] = A07; state[8] = A08; state[9] = A09;\n            state[10] = A10; state[11] = A11; state[12] = A12; state[13] = A13; state[14] = A14;\n            state[15] = A15; state[16] = A16; state[17] = A17; state[18] = A18; state[19] = A19;\n            state[20] = A20; state[21] = A21; state[22] = A22; state[23] = A23; state[24] = A24;\n        }\n\n        void keccak_xof_run(\n            const uint8_t *data, size_t data_len, uint64_t out_bits, int rate_bytes, uint8_t domain_suffix, uint8_t *out)\n        {\n            uint64_t state[25];\n            size_t offset = 0;\n            size_t out_len = (size_t)((out_bits + 7) / 8);\n            size_t written = 0;\n            int i = 0;\n\n            for (i = 0; i < 25; i++) {\n                state[i] = 0;\n            }\n\n            while ((offset + (size_t)rate_bytes) <= data_len) {\n                keccak_absorb_block(state, data + offset, rate_bytes);\n                keccak_f1600(state);\n                offset += (size_t)rate_bytes;\n            }\n\n            keccak_absorb_padded(state, data + offset, data_len - offset, rate_bytes, domain_suffix);\n            keccak_f1600(state);\n\n            while (written < out_len) {\n                int chunk_len = rate_bytes;\n\n                if ((size_t)chunk_len > (out_len - written)) {\n                    chunk_len = (int)(out_len - written);\n                }\n                keccak_squeeze_block(state, out + written, chunk_len);\n                written += (size_t)chunk_len;\n                if (written < out_len) {\n                    keccak_f1600(state);\n                }\n            }\n\n            if ((out_bits & 7ULL) != 0 && out_len > 0) {\n                out[out_len - 1] &= (uint8_t)((0xffU << (8 - (out_bits & 7ULL))) & 0xffU);\n            }\n        }\n\n        int cshake_run(\n            const uint8_t *data, size_t data_len, uint64_t out_bits,\n            const uint8_t *function_name, size_t function_name_len,\n            const uint8_t *customization, size_t customization_len,\n            int security_bits, uint8_t *out)\n        {\n            int rate_bytes = 0;\n\n            if (security_bits == 128) {\n                rate_bytes = 168;\n            } else if (security_bits == 256) {\n                rate_bytes = 136;\n            } else {\n                return 0;\n            }\n\n            if (function_name_len == 0 && customization_len == 0) {\n                keccak_xof_run(data, data_len, out_bits, rate_bytes, 0x1fU, out);\n                return 1;\n            }\n\n            {\n                uint64_t function_bits = (uint64_t)function_name_len * 8ULL;\n                uint64_t customization_bits = (uint64_t)customization_len * 8ULL;\n                size_t core_len = 0;\n                size_t prefix_len = 0;\n                size_t padded_len = 0;\n                size_t total_len = 0;\n                size_t cursor = 0;\n                uint8_t *buffer = NULL;\n\n                core_len += (size_t)encoded_length_u64(function_bits) + function_name_len;\n                core_len += (size_t)encoded_length_u64(customization_bits) + customization_len;\n                prefix_len = (size_t)encoded_length_u64((uint64_t)rate_bytes) + core_len;\n                padded_len = ((prefix_len + (size_t)rate_bytes - 1) / (size_t)rate_bytes) * (size_t)rate_bytes;\n                total_len = padded_len + data_len;\n\n                buffer = (uint8_t *)malloc(total_len == 0 ? 1 : total_len);\n                if (buffer == NULL) {\n                    return 0;\n                }\n\n                cursor += (size_t)write_left_encode_u64(buffer + cursor, (uint64_t)rate_bytes);\n                cursor += (size_t)write_left_encode_u64(buffer + cursor, function_bits);\n                if (function_name_len != 0) {\n                    memcpy(buffer + cursor, function_name, function_name_len);\n                    cursor += function_name_len;\n                }\n                cursor += (size_t)write_left_encode_u64(buffer + cursor, customization_bits);\n                if (customization_len != 0) {\n                    memcpy(buffer + cursor, customization, customization_len);\n                    cursor += customization_len;\n                }\n                while ((cursor % (size_t)rate_bytes) != 0) {\n                    buffer[cursor] = 0;\n                    cursor++;\n                }\n                if (data_len != 0) {\n                    memcpy(buffer + cursor, data, data_len);\n                }\n                keccak_xof_run(buffer, total_len, out_bits, rate_bytes, 0x04U, out);\n                free(buffer);\n            }\n            return 1;\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void keccak_xof_run(\n            const uint8_t *data, size_t data_len, uint64_t out_bits, int rate_bytes, uint8_t domain_suffix, uint8_t *out);\n        int cshake_run(\n            const uint8_t *data, size_t data_len, uint64_t out_bits,\n            const uint8_t *function_name, size_t function_name_len,\n            const uint8_t *customization, size_t customization_len,\n            int security_bits, uint8_t *out);\n        \"\"\"\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.ParallelHashBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            try:\n                with warnings.catch_warnings():\n                    warnings.filterwarnings(\n                        \"ignore\",\n                        message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                        category=UserWarning,\n                        module=r\"cffi\\.vengine_cpy\",\n                    )\n                    ffi = cffi.FFI()\n                    ffi.cdef(base_class.DEF_TEMPLATE)\n                    lib = ffi.verify(base_class.C_TEMPLATE, extra_compile_args=[\"-O2\"])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\", \"ffi lib\")(\n                ffi, lib,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        def __init__(self, data=b\"\", block_size=8, digest_bits=None, customization=b\"\"):\n            if not isinstance(block_size, int):\n                raise TypeError(\"block_size must be int\")\n            if block_size <= 0:\n                raise ValueError(\"block_size must be > 0\")\n            if digest_bits is None:\n                digest_bits = self.default_digest_bits\n            if not isinstance(digest_bits, int):\n                raise TypeError(\"digest_bits must be int\")\n            if digest_bits < 0:\n                raise ValueError(\"digest_bits must be >= 0\")\n            if not isinstance(customization, (bytes, bytearray, memoryview)):\n                raise TypeError(\"customization must be bytes-like\")\n            self.block_size = block_size\n            self.digest_bits = digest_bits\n            self.digest_size = (digest_bits + 7) // 8\n            self.customization = bytes(customization)\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.n_blocks = 0\n            self.z = bytearray()\n            self.z.extend(self.left_encode(self.block_size))\n            self.init_cffi_backend()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(\n                block_size=self.block_size,\n                digest_bits=self.digest_bits,\n                customization=self.customization,\n            )\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.n_blocks = self.n_blocks\n            other.z = bytearray(self.z)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data_view = memoryview(data)\n            self.msg_len += len(data_view)\n            self.buf.extend(data_view)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.process_block(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            return c.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if len(self.buf) > 0:\n                block = bytes(self.buf)\n                self.buf.clear()\n                self.process_block(block)\n            new_x = bytearray(self.z)\n            new_x.extend(self.right_encode(self.n_blocks))\n            if self.xof_mode:\n                new_x.extend(self.right_encode(0))\n            else:\n                new_x.extend(self.right_encode(self.digest_bits))\n            out = self.cshake(bytes(new_x), self.digest_bits, b\"ParallelHash\", self.customization, self.security_bits)\n            return out\n\n        def process_block(self, block):\n\n            def inner_hash(block):\n                out_len = (self.inner_digest_bits + 7) // 8\n                if self.security_bits == 128:\n                    out = hashlib.shake_128(block).digest(out_len)\n                elif self.security_bits == 256:\n                    out = hashlib.shake_256(block).digest(out_len)\n                else:\n                    raise ValueError(\"invalid security_bits\")\n                if (self.inner_digest_bits % 8) != 0 and len(out) != 0:\n                    out_mut = bytearray(out)\n                    keep_bits = self.inner_digest_bits % 8\n                    out_mut[-1] &= (0xff << (8 - keep_bits)) & 0xff\n                    return bytes(out_mut)\n                return out\n\n            self.z.extend(inner_hash(block))\n            self.n_blocks += 1\n            return\n\n        def cshake(self, data, out_bits, function_name, customization, security_bits):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(function_name, (bytes, bytearray, memoryview)):\n                raise TypeError(\"function_name must be bytes-like\")\n            if not isinstance(customization, (bytes, bytearray, memoryview)):\n                raise TypeError(\"customization must be bytes-like\")\n\n            def encode_string(data):\n                if not isinstance(data, (bytes, bytearray, memoryview)):\n                    raise TypeError(\"data must be bytes-like\")\n                data = bytes(data)\n                return self.left_encode(len(data) * 8) + data\n\n            data = bytes(data)\n            function_name = bytes(function_name)\n            customization = bytes(customization)\n\n            if self.USE_CFFI and out_bits <= 0xffff_ffff_ffff_ffff:\n                out_len = (out_bits + 7) // 8\n                data_buf = self.cffi.ffi.NULL if len(data) == 0 else self.cffi.ffi.new(\"uint8_t[]\", data)\n                function_name_buf = self.cffi.ffi.NULL if len(function_name) == 0 else self.cffi.ffi.new(\"uint8_t[]\", function_name)\n                customization_buf = self.cffi.ffi.NULL if len(customization) == 0 else self.cffi.ffi.new(\"uint8_t[]\", customization)\n                out_buf = self.cffi.ffi.new(\"uint8_t[]\", max(out_len, 1))\n                rc = self.cffi.lib.cshake_run(\n                    data_buf, len(data), out_bits, function_name_buf,\n                    len(function_name), customization_buf, len(customization), security_bits, out_buf,\n                )\n                if rc == 0:\n                    raise ValueError(\"invalid security_bits\")\n                return bytes(self.cffi.ffi.buffer(out_buf, out_len))\n\n            if security_bits == 128:\n                rate_bytes = 168\n            elif security_bits == 256:\n                rate_bytes = 136\n            else:\n                raise ValueError(\"security_bits must be 128 or 256\")\n            if len(function_name) == 0 and len(customization) == 0:\n                return self.keccak_xof(data, out_bits, rate_bytes, 0x1f)\n            prefix = self.bytepad(encode_string(function_name) + encode_string(customization), rate_bytes)\n            return self.keccak_xof(prefix + data, out_bits, rate_bytes, 0x04)\n\n        def keccak_xof(self, data, out_bits, rate_bytes, domain_suffix):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(out_bits, int):\n                raise TypeError(\"out_bits must be int\")\n            if out_bits < 0:\n                raise ValueError(\"out_bits must be >= 0\")\n            if not isinstance(rate_bytes, int):\n                raise TypeError(\"rate_bytes must be int\")\n            if rate_bytes <= 0:\n                raise ValueError(\"rate_bytes must be > 0\")\n            if not isinstance(domain_suffix, int):\n                raise TypeError(\"domain_suffix must be int\")\n            if domain_suffix < 0 or domain_suffix > 0xff:\n                raise ValueError(\"domain_suffix must be a byte\")\n            data = bytes(data)\n\n            if self.USE_CFFI and out_bits <= 0xffff_ffff_ffff_ffff:\n                out_len = (out_bits + 7) // 8\n                data_buf = self.cffi.ffi.NULL if len(data) == 0 else self.cffi.ffi.new(\"uint8_t[]\", data)\n                out_buf = self.cffi.ffi.new(\"uint8_t[]\", max(out_len, 1))\n                self.cffi.lib.keccak_xof_run(data_buf, len(data), out_bits, rate_bytes, domain_suffix, out_buf)\n                return bytes(self.cffi.ffi.buffer(out_buf, out_len))\n\n            state = [0] * 25\n            offset = 0\n            while offset + rate_bytes <= len(data):\n                block = data[offset:offset + rate_bytes]\n                self.keccak_absorb_block(state, block, rate_bytes)\n                self.keccak_f1600(state)\n                offset += rate_bytes\n            tail = data[offset:]\n            self.keccak_absorb_padded(state, tail, rate_bytes, domain_suffix)\n            self.keccak_f1600(state)\n            out_len = (out_bits + 7) // 8\n            out = bytearray()\n            while len(out) < out_len:\n                out.extend(self.keccak_squeeze_block(state, rate_bytes))\n                if len(out) >= out_len:\n                    break\n                self.keccak_f1600(state)\n            out = out[:out_len]\n            if (out_bits % 8) != 0 and len(out) > 0:\n                keep_bits = out_bits % 8\n                out[-1] &= (0xff << (8 - keep_bits)) & 0xff\n            return bytes(out)\n\n        def keccak_absorb_block(self, state, block, rate_bytes):\n            lanes = rate_bytes // 8\n            for i in range(lanes):\n                lane = int.from_bytes(block[i * 8:(i + 1) * 8], \"little\")\n                state[i] ^= lane\n            return\n\n        def keccak_absorb_padded(self, state, tail, rate_bytes, domain_suffix):\n            block = bytearray(rate_bytes)\n            block[:len(tail)] = tail\n            block[len(tail)] ^= domain_suffix\n            block[rate_bytes - 1] ^= 0x80\n            self.keccak_absorb_block(state, bytes(block), rate_bytes)\n            return\n\n        def keccak_squeeze_block(self, state, rate_bytes):\n            lanes = rate_bytes // 8\n            out = bytearray()\n            for i in range(lanes):\n                out.extend(state[i].to_bytes(8, \"little\"))\n            return bytes(out)\n\n        def keccak_f1600(self, state):\n            A = state\n            RC = self.keccak_round_constants\n\n            # Explicitly load state into local variables\n            A00, A01, A02, A03, A04 = A[0], A[1], A[2], A[3], A[4]\n            A05, A06, A07, A08, A09 = A[5], A[6], A[7], A[8], A[9]\n            A10, A11, A12, A13, A14 = A[10], A[11], A[12], A[13], A[14]\n            A15, A16, A17, A18, A19 = A[15], A[16], A[17], A[18], A[19]\n            A20, A21, A22, A23, A24 = A[20], A[21], A[22], A[23], A[24]\n\n            for rc in RC:\n                # Theta\n                C0 = A00 ^ A05 ^ A10 ^ A15 ^ A20\n                C1 = A01 ^ A06 ^ A11 ^ A16 ^ A21\n                C2 = A02 ^ A07 ^ A12 ^ A17 ^ A22\n                C3 = A03 ^ A08 ^ A13 ^ A18 ^ A23\n                C4 = A04 ^ A09 ^ A14 ^ A19 ^ A24\n\n                # D0 = C4 ^ rol(C1, 1)\n                D0 = C4 ^ (((C1 << 1) | (C1 >> 63)) & 0xffff_ffff_ffff_ffff)\n                D1 = C0 ^ (((C2 << 1) | (C2 >> 63)) & 0xffff_ffff_ffff_ffff)\n                D2 = C1 ^ (((C3 << 1) | (C3 >> 63)) & 0xffff_ffff_ffff_ffff)\n                D3 = C2 ^ (((C4 << 1) | (C4 >> 63)) & 0xffff_ffff_ffff_ffff)\n                D4 = C3 ^ (((C0 << 1) | (C0 >> 63)) & 0xffff_ffff_ffff_ffff)\n\n                A00 ^= D0\n                A05 ^= D0\n                A10 ^= D0\n                A15 ^= D0\n                A20 ^= D0\n                A01 ^= D1\n                A06 ^= D1\n                A11 ^= D1\n                A16 ^= D1\n                A21 ^= D1\n                A02 ^= D2\n                A07 ^= D2\n                A12 ^= D2\n                A17 ^= D2\n                A22 ^= D2\n                A03 ^= D3\n                A08 ^= D3\n                A13 ^= D3\n                A18 ^= D3\n                A23 ^= D3\n                A04 ^= D4\n                A09 ^= D4\n                A14 ^= D4\n                A19 ^= D4\n                A24 ^= D4\n\n                # Rho and Pi\n                B00 = A00\n                B01 = ((A06 << 44) | (A06 >> 20)) & 0xffff_ffff_ffff_ffff\n                B02 = ((A12 << 43) | (A12 >> 21)) & 0xffff_ffff_ffff_ffff\n                B03 = ((A18 << 21) | (A18 >> 43)) & 0xffff_ffff_ffff_ffff\n                B04 = ((A24 << 14) | (A24 >> 50)) & 0xffff_ffff_ffff_ffff\n                B05 = ((A03 << 28) | (A03 >> 36)) & 0xffff_ffff_ffff_ffff\n                B06 = ((A09 << 20) | (A09 >> 44)) & 0xffff_ffff_ffff_ffff\n                B07 = ((A10 << 3) | (A10 >> 61)) & 0xffff_ffff_ffff_ffff\n                B08 = ((A16 << 45) | (A16 >> 19)) & 0xffff_ffff_ffff_ffff\n                B09 = ((A22 << 61) | (A22 >> 3)) & 0xffff_ffff_ffff_ffff\n                B10 = ((A01 << 1) | (A01 >> 63)) & 0xffff_ffff_ffff_ffff\n                B11 = ((A07 << 6) | (A07 >> 58)) & 0xffff_ffff_ffff_ffff\n                B12 = ((A13 << 25) | (A13 >> 39)) & 0xffff_ffff_ffff_ffff\n                B13 = ((A19 << 8) | (A19 >> 56)) & 0xffff_ffff_ffff_ffff\n                B14 = ((A20 << 18) | (A20 >> 46)) & 0xffff_ffff_ffff_ffff\n                B15 = ((A04 << 27) | (A04 >> 37)) & 0xffff_ffff_ffff_ffff\n                B16 = ((A05 << 36) | (A05 >> 28)) & 0xffff_ffff_ffff_ffff\n                B17 = ((A11 << 10) | (A11 >> 54)) & 0xffff_ffff_ffff_ffff\n                B18 = ((A17 << 15) | (A17 >> 49)) & 0xffff_ffff_ffff_ffff\n                B19 = ((A23 << 56) | (A23 >> 8)) & 0xffff_ffff_ffff_ffff\n                B20 = ((A02 << 62) | (A02 >> 2)) & 0xffff_ffff_ffff_ffff\n                B21 = ((A08 << 55) | (A08 >> 9)) & 0xffff_ffff_ffff_ffff\n                B22 = ((A14 << 39) | (A14 >> 25)) & 0xffff_ffff_ffff_ffff\n                B23 = ((A15 << 41) | (A15 >> 23)) & 0xffff_ffff_ffff_ffff\n                B24 = ((A21 << 2) | (A21 >> 62)) & 0xffff_ffff_ffff_ffff\n\n                # Chi\n                A00 = B00 ^ (~B01 & B02)\n                A01 = B01 ^ (~B02 & B03)\n                A02 = B02 ^ (~B03 & B04)\n                A03 = B03 ^ (~B04 & B00)\n                A04 = B04 ^ (~B00 & B01)\n                A05 = B05 ^ (~B06 & B07)\n                A06 = B06 ^ (~B07 & B08)\n                A07 = B07 ^ (~B08 & B09)\n                A08 = B08 ^ (~B09 & B05)\n                A09 = B09 ^ (~B05 & B06)\n                A10 = B10 ^ (~B11 & B12)\n                A11 = B11 ^ (~B12 & B13)\n                A12 = B12 ^ (~B13 & B14)\n                A13 = B13 ^ (~B14 & B10)\n                A14 = B14 ^ (~B10 & B11)\n                A15 = B15 ^ (~B16 & B17)\n                A16 = B16 ^ (~B17 & B18)\n                A17 = B17 ^ (~B18 & B19)\n                A18 = B18 ^ (~B19 & B15)\n                A19 = B19 ^ (~B15 & B16)\n                A20 = B20 ^ (~B21 & B22)\n                A21 = B21 ^ (~B22 & B23)\n                A22 = B22 ^ (~B23 & B24)\n                A23 = B23 ^ (~B24 & B20)\n                A24 = B24 ^ (~B20 & B21)\n\n                A00 ^= rc\n\n            state[0], state[1], state[2], state[3], state[4] = A00, A01, A02, A03, A04\n            state[5], state[6], state[7], state[8], state[9] = A05, A06, A07, A08, A09\n            state[10], state[11], state[12], state[13], state[14] = A10, A11, A12, A13, A14\n            state[15], state[16], state[17], state[18], state[19] = A15, A16, A17, A18, A19\n            state[20], state[21], state[22], state[23], state[24] = A20, A21, A22, A23, A24\n            return\n\n        def left_encode(self, value):\n            if not isinstance(value, int):\n                raise TypeError(\"value must be int\")\n            if value < 0:\n                raise ValueError(\"value must be >= 0\")\n            n = 1\n            while value >= (1 << (8 * n)):\n                n += 1\n            return bytes([n]) + value.to_bytes(n, \"big\")\n\n        def right_encode(self, value):\n            if not isinstance(value, int):\n                raise TypeError(\"value must be int\")\n            if value < 0:\n                raise ValueError(\"value must be >= 0\")\n            n = 1\n            while value >= (1 << (8 * n)):\n                n += 1\n            return value.to_bytes(n, \"big\") + bytes([n])\n\n        def bytepad(self, data, width):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if not isinstance(width, int):\n                raise TypeError(\"width must be int\")\n            if width <= 0:\n                raise ValueError(\"width must be > 0\")\n            data = bytes(data)\n            out = bytearray()\n            out.extend(self.left_encode(width))\n            out.extend(data)\n            while (len(out) % width) != 0:\n                out.append(0x00)\n            return bytes(out)\n\n    class ParallelHash128(ParallelHashBase):\n        security_bits = 128\n        default_digest_bits = 256\n        inner_digest_bits = 256\n        xof_mode = False\n\n    class ParallelHash256(ParallelHashBase):\n        security_bits = 256\n        default_digest_bits = 512\n        inner_digest_bits = 512\n        xof_mode = False\n\n    class ParallelHashXOF128(ParallelHashBase):\n        security_bits = 128\n        default_digest_bits = 256\n        inner_digest_bits = 256\n        xof_mode = True\n\n    class ParallelHashXOF256(ParallelHashBase):\n        security_bits = 256\n        default_digest_bits = 512\n        inner_digest_bits = 512\n        xof_mode = True\n\n    class AbacusBase:\n        block_size = 1\n\n        num_blank_rounds = 135\n        num_absorb_clocks = 1\n        num_squeeze_clocks = 1\n\n        ctr1_mod = 0xe9  # 233\n        ctr2_mod = 0xef  # 239\n        ctr3_mod = 0xf1  # 241\n        ctr4_mod = 0xfb  # 251\n\n        sbox = (\n            0xe3, 0x84, 0xf0, 0xd6, 0xf9, 0xf6, 0xbe, 0x90, 0x85, 0x7d, 0x28, 0x43, 0x12, 0xc0, 0xe1, 0xb4,\n            0x55, 0xc7, 0x8c, 0x87, 0x42, 0xe0, 0xd9, 0x27, 0x78, 0xec, 0xcb, 0x07, 0xaa, 0x95, 0xc1, 0x3f,\n            0xb2, 0xdc, 0x26, 0xa7, 0x1f, 0xdf, 0xf3, 0x54, 0xd2, 0xe7, 0x24, 0x3e, 0x32, 0xd1, 0x56, 0xc6,\n            0x35, 0x73, 0xf7, 0x7b, 0x62, 0x29, 0x52, 0x80, 0xa9, 0xba, 0xab, 0xe9, 0x02, 0x53, 0x6a, 0xe4,\n            0x67, 0xa0, 0x8e, 0xfb, 0x9a, 0x79, 0x4e, 0x8d, 0xe5, 0x4a, 0x41, 0xaf, 0x5a, 0x5c, 0xa6, 0x6b,\n            0x16, 0x5e, 0xe8, 0x3c, 0x9c, 0x5b, 0x88, 0x76, 0x15, 0xf4, 0x60, 0xbd, 0x83, 0x98, 0x8f, 0xc8,\n            0x09, 0x68, 0x0d, 0x18, 0x65, 0x45, 0x04, 0xce, 0x7a, 0xf2, 0x39, 0xc5, 0x9e, 0xf1, 0x17, 0xef,\n            0x38, 0x21, 0x94, 0x86, 0x69, 0x37, 0xf5, 0xed, 0x36, 0x66, 0xcf, 0x3b, 0x63, 0x4b, 0x33, 0xb6,\n            0xff, 0xbc, 0x11, 0x5d, 0xb3, 0x2b, 0xd3, 0xd0, 0x3a, 0x96, 0x77, 0x7c, 0x1c, 0xc2, 0xfe, 0x0a,\n            0xc3, 0x25, 0x4d, 0xfc, 0x89, 0xde, 0x30, 0x23, 0x64, 0x81, 0xd5, 0xae, 0x70, 0xdb, 0xe6, 0x7e,\n            0xb0, 0x6f, 0x0f, 0xd7, 0xbf, 0x9b, 0xc4, 0x74, 0xb7, 0x57, 0x4f, 0x58, 0x10, 0x2d, 0xa4, 0xb9,\n            0xa2, 0xad, 0x61, 0xeb, 0xac, 0x1a, 0xa3, 0xd8, 0x2c, 0x5f, 0x91, 0x2f, 0x72, 0x31, 0xb1, 0x82,\n            0x49, 0xda, 0x0c, 0xca, 0x00, 0xa1, 0xb5, 0x75, 0x6e, 0x47, 0x6d, 0x13, 0x19, 0x93, 0x20, 0x05,\n            0x01, 0x9f, 0x1d, 0x44, 0x8a, 0x1e, 0x50, 0x34, 0xfa, 0x9d, 0xa8, 0x8b, 0x0b, 0x4c, 0xa5, 0x2e,\n            0x71, 0xf8, 0x40, 0xcd, 0x99, 0xfd, 0x51, 0x59, 0x0e, 0x2a, 0x3d, 0x92, 0x14, 0x48, 0x6c, 0xea,\n            0x46, 0x22, 0xcc, 0x06, 0xd4, 0x97, 0xe2, 0x1b, 0xdd, 0x7f, 0xbb, 0xc9, 0xb8, 0x03, 0xee, 0x08,\n        )\n\n        def __init__(self, data=b\"\", salt=b\"\"):\n            self.ra = 0\n            self.rb = []\n            self.rc = []\n            self.rd = []\n            self.ctr1 = 0\n            self.ctr2 = 0\n            self.ctr3 = 0\n            self.ctr4 = 0\n            self.out = 0\n            self.msg_len = 0\n            self.salt = b\"\"\n            self.is_finalized = False\n            self.digest_buf = b\"\"\n\n            if not isinstance(salt, (bytes, bytearray, memoryview)):\n                raise TypeError(\"salt must be bytes-like\")\n            self.salt = bytes(salt)\n\n            self.init_state()\n            self.absorb_pretrain()\n\n            if data:\n                self.update(data)\n            return\n\n        def init_state(self):\n            self.ra = self.sbox[0]\n            self.rb = list(self.sbox[1:6])\n            self.rc = list(self.sbox[6:43])\n            self.rd = list(self.sbox[43:132])\n\n            self.ctr1 = 0\n            self.ctr2 = 0\n            self.ctr3 = 0\n            self.ctr4 = 0\n            self.out = 0\n\n            self.msg_len = 0\n            self.is_finalized = False\n            self.digest_buf = b\"\"\n            return\n\n        def copy(self):\n            other = self.__class__(salt=self.salt)\n\n            other.ra = self.ra\n            other.rb = list(self.rb)\n            other.rc = list(self.rc)\n            other.rd = list(self.rd)\n\n            other.ctr1 = self.ctr1\n            other.ctr2 = self.ctr2\n            other.ctr3 = self.ctr3\n            other.ctr4 = self.ctr4\n\n            other.out = self.out\n            other.msg_len = self.msg_len\n            other.is_finalized = self.is_finalized\n            other.digest_buf = bytes(self.digest_buf)\n            return other\n\n        def update(self, data):\n            if self.is_finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            data = bytes(data)\n            self.msg_len += len(data)\n\n            for b in data:\n                self.absorb_round(b)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return bytes(c.digest_buf)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.is_finalized:\n                return self\n\n            for b in self.posttrain():\n                self.absorb_round(b)\n\n            for _ in range(self.num_blank_rounds):\n                self.absorb_round(0x00)\n\n            out = bytearray()\n            for _ in range(self.digest_size):\n                out.append(self.squeeze_round())\n\n            self.digest_buf = bytes(out)\n            self.is_finalized = True\n            return self\n\n        def hash_len_field(self):\n            n = self.digest_size * 8\n            return n.to_bytes(4, \"big\")\n\n        def msg_len_field(self):\n            n = self.msg_len * 8\n            return n.to_bytes(16, \"big\")\n\n        def pretrain(self):\n            # Beta Padding: SALT || HASH_LEN_BITS || NULL_128\n            return self.salt + self.hash_len_field() + (0).to_bytes(16, \"big\")\n\n        def posttrain(self):\n            # Beta Padding: SALT || HASH_LEN_BITS || MSG_LEN_BITS\n            return self.salt + self.hash_len_field() + self.msg_len_field()\n\n        def absorb_pretrain(self):\n            for b in self.pretrain():\n                self.absorb_round(b)\n            return\n\n        def absorb_round(self, msg_byte):\n            for _ in range(self.num_absorb_clocks):\n                self.clock_core(msg_byte, False)\n            return\n\n        def squeeze_round(self):\n            out_byte = 0\n            for _ in range(self.num_squeeze_clocks):\n                out_byte = self.clock_core(self.out, True)\n            return out_byte\n\n        def clock_core(self, in_byte, do_squeeze):\n            s = self.sbox\n\n            ra = s[self.ra ^ self.rd[58]] ^ self.ctr1\n            rb0 = s[self.rb[0] ^ self.rc[24]] ^ self.ctr2\n            rc0 = s[self.rc[0] ^ self.rb[3]] ^ self.ctr3\n            rd0 = s[self.rd[0] ^ in_byte] ^ self.ctr4\n\n            ra, rb0, rc0, rd0 = self.mds4(ra, rb0, rc0, rd0)\n\n            ra = s[ra]\n            rb0 = s[rb0]\n            rc0 = s[rc0]\n            rd0 = s[rd0]\n\n            self.ra = ra\n            self.rb[0] = rb0\n            self.rc[0] = rc0\n            self.rd[0] = rd0\n\n            out_byte = 0\n            if do_squeeze:\n                self.out = s[self.ra ^ self.rb[0]] ^ s[self.rc[0] ^ self.rd[0]]\n                out_byte = self.out\n\n            self.rotate_arrays()\n            self.inc_counters()\n            return out_byte\n\n        def xtime(self, x):\n            y = (x << 1) & 0xff\n            if x & 0x80:\n                y ^= 0x1b\n            return y\n\n        def mds4(self, x0, x1, x2, x3):\n            a0 = x0\n            a1 = x1\n            a2 = x2\n            a3 = x3\n\n            b0 = self.xtime(a0)\n            b1 = self.xtime(a1)\n            b2 = self.xtime(a2)\n            b3 = self.xtime(a3)\n\n            c0 = b0 ^ a0\n            c1 = b1 ^ a1\n            c2 = b2 ^ a2\n            c3 = b3 ^ a3\n\n            r0 = a0 ^ b3 ^ c2 ^ a1\n            r1 = a1 ^ b0 ^ c3 ^ a2\n            r2 = a2 ^ b1 ^ c0 ^ a3\n            r3 = a3 ^ b2 ^ c1 ^ a0\n            return r0, r1, r2, r3\n\n        def rotate_arrays(self):\n            self.rb = self.rb[1:] + self.rb[:1]\n            self.rc = self.rc[1:] + self.rc[:1]\n            self.rd = self.rd[1:] + self.rd[:1]\n            return\n\n        def inc_counters(self):\n            self.ctr1 = (self.ctr1 + 1) % self.ctr1_mod\n            self.ctr2 = (self.ctr2 + 1) % self.ctr2_mod\n            self.ctr3 = (self.ctr3 + 1) % self.ctr3_mod\n            self.ctr4 = (self.ctr4 + 1) % self.ctr4_mod\n            return\n\n    class Abacus224(AbacusBase):\n        digest_size = 28\n\n    class Abacus256(AbacusBase):\n        digest_size = 32\n\n    class Abacus384(AbacusBase):\n        digest_size = 48\n\n    class Abacus512(AbacusBase):\n        digest_size = 64\n\n    class ARIRANG256Base:\n        block_size = 64\n        digest_words = 8\n        digest_size = 32\n\n        iv_words = [\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a,\n            0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        ]\n\n        k_words = [\n            0x517c_c1b7, 0x7651_7cc1, 0xbd76_517c, 0x2dbd_7651,\n            0x272d_bd76, 0xcb27_2dbd, 0x90cb_272d, 0x0a90_cb27,\n            0xec0a_90cb, 0x5bec_0a90, 0x9a5b_ec0a, 0xe69a_5bec,\n            0xb7e6_9a5b, 0xc1b7_e69a, 0x7cc1_b7e6, 0x517c_c1b7,\n        ]\n\n        round_pairs_1 = [(16, 17), (0, 1), (2, 3), (4, 5), (6, 7), (18, 19), (8, 9), (10, 11), (12, 13), (14, 15)]\n        round_pairs_2 = [(20, 21), (3, 6), (9, 12), (15, 2), (5, 8), (22, 23), (11, 14), (1, 4), (7, 10), (13, 0)]\n        round_pairs_3 = [(24, 25), (12, 5), (14, 7), (0, 9), (2, 11), (26, 27), (4, 13), (6, 15), (8, 1), (10, 3)]\n        round_pairs_4 = [(28, 29), (7, 2), (13, 8), (3, 14), (9, 4), (30, 31), (15, 10), (5, 0), (11, 6), (1, 12)]\n\n        sbx = None\n        f2 = None\n        f3 = None\n        f4 = None\n        f8 = None\n        f9 = None\n        fa = None\n\n        def __init__(self, data=b\"\"):\n            self.ensure_tables()\n            self.h = list(self.iv_words)\n            self.buf = bytearray()\n            self.count0 = 0\n            self.count1 = 0\n            self.counter0 = 0\n            self.counter1 = 0\n            self.finalized = False\n            if data:\n                self.update(data)\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n            if cls.sbx is not None:\n                return\n\n            pow_tab = [0] * 256\n            log_tab = [0] * 256\n\n            p = 1\n            for i in range(256):\n                pow_tab[i] = p & 0xff\n                log_tab[p & 0xff] = i\n                p = p ^ (p << 1) ^ (0x01b if (p & 0x80) else 0)\n                p &= 0xff\n\n            sbx = [0] * 256\n            for i in range(256):\n                if i != 0:\n                    p = pow_tab[255 - log_tab[i]]\n                else:\n                    p = 0\n\n                q = p\n                q = ((q >> 7) | (q << 1)) & 0xff\n                p ^= q\n                q = ((q >> 7) | (q << 1)) & 0xff\n                p ^= q\n                q = ((q >> 7) | (q << 1)) & 0xff\n                p ^= q\n                q = ((q >> 7) | (q << 1)) & 0xff\n                p ^= q ^ 0x63\n\n                sbx[i] = p & 0xff\n\n            def ff_mult(a, b):\n                if a == 0 or b == 0:\n                    return 0\n                return pow_tab[(log_tab[a] + log_tab[b]) % 255]\n\n            f2 = [0] * 256\n            f3 = [0] * 256\n            f4 = [0] * 256\n            f8 = [0] * 256\n            f9 = [0] * 256\n            fa = [0] * 256\n\n            for i in range(256):\n                f2[i] = ff_mult(i, 2)\n                f3[i] = ff_mult(i, 3)\n                f4[i] = ff_mult(i, 4)\n                f8[i] = ff_mult(i, 8)\n                f9[i] = ff_mult(i, 9)\n                fa[i] = ff_mult(i, 10)\n\n            cls.sbx = sbx\n            cls.f2 = f2\n            cls.f3 = f3\n            cls.f4 = f4\n            cls.f8 = f8\n            cls.f9 = f9\n            cls.fa = fa\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.count0 = self.count0\n            other.count1 = self.count1\n            other.counter0 = self.counter0\n            other.counter1 = self.counter1\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.finalized:\n                raise ValueError(\"hash already finalized\")\n\n            data = bytes(data)\n\n            add_bits = len(data) << 3\n            new_count0 = (self.count0 + add_bits) & 0xffff_ffff_ffff_ffff\n            if new_count0 < self.count0:\n                self.count1 = (self.count1 + 1) & 0xffff_ffff_ffff_ffff\n            self.count0 = new_count0\n\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def byte(self, x, n):\n            return (x >> (8 * n)) & 0xff\n\n        def rol32(self, x, n):\n            x &= 0xffff_ffff\n            return ((x << n) | (x >> (32 - n))) & 0xffff_ffff\n\n        def g256(self, x):\n            sbx = self.sbx\n            f2 = self.f2\n            f3 = self.f3\n\n            t = (\n                sbx[self.byte(x, 0)]\n                | (sbx[self.byte(x, 1)] << 8)\n                | (sbx[self.byte(x, 2)] << 16)\n                | (sbx[self.byte(x, 3)] << 24)\n            )\n\n            b0 = self.byte(t, 0)\n            b1 = self.byte(t, 1)\n            b2 = self.byte(t, 2)\n            b3 = self.byte(t, 3)\n\n            out = (\n                (f2[b0] ^ f3[b1] ^ b2 ^ b3)\n                | ((b0 ^ f2[b1] ^ f3[b2] ^ b3) << 8)\n                | ((b0 ^ b1 ^ f2[b2] ^ f3[b3]) << 16)\n                | ((f3[b0] ^ b1 ^ b2 ^ f2[b3]) << 24)\n            )\n\n            return out & 0xffff_ffff\n\n        def step(self, r, m1, m2):\n            r[0] ^= m1\n            r[4] ^= m2\n\n            t1 = self.g256(r[0])\n            t2 = self.g256(r[4])\n\n            r[1] ^= t1\n            r[2] ^= self.rol32(t1, 13)\n            r[3] ^= self.rol32(t1, 23)\n            r[5] ^= t2\n            r[6] ^= self.rol32(t2, 29)\n            r[7] ^= self.rol32(t2, 7)\n\n            t = r[7]\n            r[7] = r[6]\n            r[6] = r[5]\n            r[5] = r[4]\n            r[4] = r[3]\n            r[3] = r[2]\n            r[2] = r[1]\n            r[1] = r[0]\n            r[0] = t\n            return\n\n        def message_schedule(self, w):\n            k = self.k_words\n            w = list(w)\n\n            w.append(self.rol32(w[9] ^ w[11] ^ w[13] ^ w[15] ^ k[0], 5))\n            w.append(self.rol32(w[8] ^ w[10] ^ w[12] ^ w[14] ^ k[1], 11))\n            w.append(self.rol32(w[1] ^ w[3] ^ w[5] ^ w[7] ^ k[2], 19))\n            w.append(self.rol32(w[0] ^ w[2] ^ w[4] ^ w[6] ^ k[3], 31))\n\n            w.append(self.rol32(w[14] ^ w[4] ^ w[10] ^ w[0] ^ k[4], 5))\n            w.append(self.rol32(w[11] ^ w[1] ^ w[7] ^ w[13] ^ k[5], 11))\n            w.append(self.rol32(w[6] ^ w[12] ^ w[2] ^ w[8] ^ k[6], 19))\n            w.append(self.rol32(w[3] ^ w[9] ^ w[15] ^ w[5] ^ k[7], 31))\n\n            w.append(self.rol32(w[13] ^ w[15] ^ w[1] ^ w[3] ^ k[8], 5))\n            w.append(self.rol32(w[4] ^ w[6] ^ w[8] ^ w[10] ^ k[9], 11))\n            w.append(self.rol32(w[5] ^ w[7] ^ w[9] ^ w[11] ^ k[10], 19))\n            w.append(self.rol32(w[12] ^ w[14] ^ w[0] ^ w[2] ^ k[11], 31))\n\n            w.append(self.rol32(w[10] ^ w[0] ^ w[6] ^ w[12] ^ k[12], 5))\n            w.append(self.rol32(w[15] ^ w[5] ^ w[11] ^ w[1] ^ k[13], 11))\n            w.append(self.rol32(w[2] ^ w[8] ^ w[14] ^ w[4] ^ k[14], 19))\n            w.append(self.rol32(w[7] ^ w[13] ^ w[3] ^ w[9] ^ k[15], 31))\n\n            return w\n\n        def compress(self, block):\n            self.h[0] ^= (self.counter0 >> 32) & 0xffff_ffff\n            self.h[4] ^= self.counter0 & 0xffff_ffff\n\n            w0 = struct.unpack(\">16I\", block)\n            w = self.message_schedule(w0)\n\n            r = [v & 0xffff_ffff for v in self.h]\n\n            for i, j in self.round_pairs_1:\n                self.step(r, w[i], w[j])\n            for i, j in self.round_pairs_2:\n                self.step(r, w[i], w[j])\n\n            for i in range(8):\n                r[i] ^= self.h[i]\n\n            for i, j in self.round_pairs_3:\n                self.step(r, w[i], w[j])\n            for i, j in self.round_pairs_4:\n                self.step(r, w[i], w[j])\n\n            for i in range(8):\n                self.h[i] ^= r[i]\n\n            self.counter0 = (self.counter0 + 1) & 0xffff_ffff_ffff_ffff\n            if self.counter0 == 0:\n                self.counter1 = (self.counter1 + 1) & 0xffff_ffff_ffff_ffff\n\n            return\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            buf = bytearray(self.buf)\n            buf.append(0x80)\n\n            if len(buf) > (self.block_size - 8):\n                while len(buf) < self.block_size:\n                    buf.append(0x00)\n                self.compress(bytes(buf))\n                buf = bytearray()\n\n            while len(buf) < (self.block_size - 8):\n                buf.append(0x00)\n\n            buf.extend(struct.pack(\">Q\", self.count0))\n\n            self.counter0 = 0xb7e1_5162_8aed_2a6a\n            self.compress(bytes(buf))\n\n            self.buf = bytearray()\n            self.finalized = True\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            words = c.h[:self.digest_words]\n            return struct.pack(\">\" + (\"I\" * len(words)), *words)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class ARIRANG224(ARIRANG256Base):\n        digest_words = 7\n        digest_size = 28\n\n        iv_words = [\n            0xcbbb_9d5d, 0x629a_292a, 0x9159_015a, 0x152f_ecd8,\n            0x6733_2667, 0x8eb4_4a87, 0xdb0c_2e0d, 0x47b5_481d,\n        ]\n\n    class ARIRANG256(ARIRANG256Base):\n        pass\n\n    class ARIRANG512Base(ARIRANG256Base):\n        block_size = 128\n        digest_words = 8\n        digest_size = 64\n\n        iv_words = [\n            0x6a09_e667_f3bc_c908, 0xbb67_ae85_84ca_a73b, 0x3c6e_f372_fe94_f82b, 0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1, 0x9b05_688c_2b3e_6c1f, 0x1f83_d9ab_fb41_bd6b, 0x5be0_cd19_137e_2179,\n        ]\n\n        k_words = [\n            0x517c_c1b7_2722_0a94, 0x2db6_517c_c1b7_2722, 0xe695_2db6_517c_c1b7, 0x90cb_e695_2db6_517c,\n            0x7cca_90cb_e695_2db6, 0xcb23_7cca_90cb_e695, 0x765e_cb23_7cca_90cb, 0xec01_765e_cb23_7cca,\n            0xb7e9_ec01_765e_cb23, 0xbd7d_b7e9_ec01_765e, 0x9a5f_bd7d_b7e9_ec01, 0x5be8_9a5f_bd7d_b7e9,\n            0x0a94_5be8_9a5f_bd7d, 0x2722_0a94_5be8_9a5f, 0xc1b7_2722_0a94_5be8, 0x517c_c1b7_2722_0a94,\n        ]\n\n        def __init__(self, data=b\"\"):\n            self.ensure_tables()\n\n            self.h = list(self.iv_words)\n            self.buf = bytearray()\n            self.count0 = 0\n            self.count1 = 0\n            self.counter0 = 0\n            self.counter1 = 0\n            self.finalized = False\n\n            if data:\n                self.update(data)\n\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.count0 = self.count0\n            other.count1 = self.count1\n            other.counter0 = self.counter0\n            other.counter1 = self.counter1\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.finalized:\n                raise ValueError(\"hash already finalized\")\n\n            data = bytes(data)\n\n            add_bits = len(data) << 3\n            new_count0 = (self.count0 + add_bits) & 0xffff_ffff_ffff_ffff\n            if new_count0 < self.count0:\n                self.count1 = (self.count1 + 1) & 0xffff_ffff_ffff_ffff\n            self.count0 = new_count0\n\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def byte(self, x, n):\n            return (x >> (8 * n)) & 0xff\n\n        def rol64(self, x, n):\n            x &= 0xffff_ffff_ffff_ffff\n            return ((x << n) | (x >> (64 - n))) & 0xffff_ffff_ffff_ffff\n\n        def g512(self, x):\n            sbx = self.sbx\n            f2 = self.f2\n            f4 = self.f4\n            f8 = self.f8\n            f9 = self.f9\n            fa = self.fa\n\n            t = 0\n            t |= sbx[self.byte(x, 0)]\n            t |= sbx[self.byte(x, 1)] << 8\n            t |= sbx[self.byte(x, 2)] << 16\n            t |= sbx[self.byte(x, 3)] << 24\n            t |= sbx[self.byte(x, 4)] << 32\n            t |= sbx[self.byte(x, 5)] << 40\n            t |= sbx[self.byte(x, 6)] << 48\n            t |= sbx[self.byte(x, 7)] << 56\n\n            b0 = self.byte(t, 0)\n            b1 = self.byte(t, 1)\n            b2 = self.byte(t, 2)\n            b3 = self.byte(t, 3)\n            b4 = self.byte(t, 4)\n            b5 = self.byte(t, 5)\n            b6 = self.byte(t, 6)\n            b7 = self.byte(t, 7)\n\n            out = 0\n            out |= (b0 ^ f2[b1] ^ fa[b2] ^ f9[b3] ^ f8[b4] ^ b5 ^ f4[b6] ^ b7)\n            out |= (b0 ^ b1 ^ f2[b2] ^ fa[b3] ^ f9[b4] ^ f8[b5] ^ b6 ^ f4[b7]) << 8\n            out |= (f4[b0] ^ b1 ^ b2 ^ f2[b3] ^ fa[b4] ^ f9[b5] ^ f8[b6] ^ b7) << 16\n            out |= (b0 ^ f4[b1] ^ b2 ^ b3 ^ f2[b4] ^ fa[b5] ^ f9[b6] ^ f8[b7]) << 24\n            out |= (f8[b0] ^ b1 ^ f4[b2] ^ b3 ^ b4 ^ f2[b5] ^ fa[b6] ^ f9[b7]) << 32\n            out |= (f9[b0] ^ f8[b1] ^ b2 ^ f4[b3] ^ b4 ^ b5 ^ f2[b6] ^ fa[b7]) << 40\n            out |= (fa[b0] ^ f9[b1] ^ f8[b2] ^ b3 ^ f4[b4] ^ b5 ^ b6 ^ f2[b7]) << 48\n            out |= (f2[b0] ^ fa[b1] ^ f9[b2] ^ f8[b3] ^ b4 ^ f4[b5] ^ b6 ^ b7) << 56\n\n            return out & 0xffff_ffff_ffff_ffff\n\n        def step(self, r, m1, m2):\n            r[0] ^= m1\n            r[4] ^= m2\n\n            t1 = self.g512(r[0])\n            t2 = self.g512(r[4])\n\n            r[1] ^= t1\n            r[2] ^= self.rol64(t1, 29)\n            r[3] ^= self.rol64(t1, 41)\n            r[5] ^= t2\n            r[6] ^= self.rol64(t2, 53)\n            r[7] ^= self.rol64(t2, 13)\n\n            t = r[7]\n            r[7] = r[6]\n            r[6] = r[5]\n            r[5] = r[4]\n            r[4] = r[3]\n            r[3] = r[2]\n            r[2] = r[1]\n            r[1] = r[0]\n            r[0] = t\n            return\n\n        def message_schedule(self, w):\n            k = self.k_words\n            w = list(w)\n\n            w.append(self.rol64(w[9] ^ w[11] ^ w[13] ^ w[15] ^ k[0], 11))\n            w.append(self.rol64(w[8] ^ w[10] ^ w[12] ^ w[14] ^ k[1], 23))\n            w.append(self.rol64(w[1] ^ w[3] ^ w[5] ^ w[7] ^ k[2], 37))\n            w.append(self.rol64(w[0] ^ w[2] ^ w[4] ^ w[6] ^ k[3], 59))\n\n            w.append(self.rol64(w[14] ^ w[4] ^ w[10] ^ w[0] ^ k[4], 11))\n            w.append(self.rol64(w[11] ^ w[1] ^ w[7] ^ w[13] ^ k[5], 23))\n            w.append(self.rol64(w[6] ^ w[12] ^ w[2] ^ w[8] ^ k[6], 37))\n            w.append(self.rol64(w[3] ^ w[9] ^ w[15] ^ w[5] ^ k[7], 59))\n\n            w.append(self.rol64(w[13] ^ w[15] ^ w[1] ^ w[3] ^ k[8], 11))\n            w.append(self.rol64(w[4] ^ w[6] ^ w[8] ^ w[10] ^ k[9], 23))\n            w.append(self.rol64(w[5] ^ w[7] ^ w[9] ^ w[11] ^ k[10], 37))\n            w.append(self.rol64(w[12] ^ w[14] ^ w[0] ^ w[2] ^ k[11], 59))\n\n            w.append(self.rol64(w[10] ^ w[0] ^ w[6] ^ w[12] ^ k[12], 11))\n            w.append(self.rol64(w[15] ^ w[5] ^ w[11] ^ w[1] ^ k[13], 23))\n            w.append(self.rol64(w[2] ^ w[8] ^ w[14] ^ w[4] ^ k[14], 37))\n            w.append(self.rol64(w[7] ^ w[13] ^ w[3] ^ w[9] ^ k[15], 59))\n\n            return w\n\n        def compress(self, block):\n            self.h[0] ^= self.counter1\n            self.h[4] ^= self.counter0\n\n            w = struct.unpack(\">16Q\", block)\n            w = self.message_schedule(w)\n\n            r = [v & 0xffff_ffff_ffff_ffff for v in self.h]\n\n            for i, j in self.round_pairs_1:\n                self.step(r, w[i], w[j])\n            for i, j in self.round_pairs_2:\n                self.step(r, w[i], w[j])\n\n            for i in range(8):\n                r[i] ^= self.h[i]\n\n            for i, j in self.round_pairs_3:\n                self.step(r, w[i], w[j])\n            for i, j in self.round_pairs_4:\n                self.step(r, w[i], w[j])\n\n            for i in range(8):\n                self.h[i] ^= r[i]\n\n            self.counter0 = (self.counter0 + 1) & 0xffff_ffff_ffff_ffff\n            if self.counter0 == 0:\n                self.counter1 = (self.counter1 + 1) & 0xffff_ffff_ffff_ffff\n\n            return\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            buf = bytearray(self.buf)\n            buf.append(0x80)\n\n            if len(buf) > (self.block_size - 16):\n                while len(buf) < self.block_size:\n                    buf.append(0x00)\n                self.compress(bytes(buf))\n                buf = bytearray()\n\n            while len(buf) < (self.block_size - 16):\n                buf.append(0x00)\n\n            buf.extend(struct.pack(\">Q\", self.count1))\n            buf.extend(struct.pack(\">Q\", self.count0))\n\n            self.counter1 = 0xb7e1_5162_8aed_2a6a\n            self.counter0 = 0xbf71_5880_9cf4_f3c7\n            self.compress(bytes(buf))\n\n            self.buf = bytearray()\n            self.finalized = True\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            words = c.h[:self.digest_words]\n            return struct.pack(\">\" + (\"Q\" * len(words)), *words)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class ARIRANG384(ARIRANG512Base):\n        digest_words = 6\n        digest_size = 48\n\n        iv_words = [\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x8eb4_4a87_6858_1511, 0xdb0c_2e0d_64f9_8fa7, 0x47b5_481d_befa_4fa4,\n        ]\n\n    class ARIRANG512(ARIRANG512Base):\n        pass\n\n    class AURORABase:\n        block_size = 64\n        digest_size = 0\n        init_fill = 0x00\n        con_iv = ()\n        con_mask = ()\n        mode = \"\"  # \"256\", \"512\", \"256m\"\n        sbox = [\n            0xd9, 0xdc, 0xd3, 0x69, 0xbd, 0x00, 0x4d, 0xeb, 0x02, 0x24, 0x57, 0xc2, 0xb8, 0x5d, 0xb7, 0x6d,\n            0xf5, 0x40, 0x37, 0x4e, 0x19, 0xd8, 0x64, 0x62, 0x9d, 0x34, 0x0f, 0x7c, 0xec, 0xce, 0x94, 0x04,\n            0xd1, 0x8a, 0x74, 0xfb, 0xe7, 0x87, 0x12, 0x23, 0xb5, 0x5c, 0x1a, 0xbb, 0x42, 0x49, 0x18, 0x85,\n            0x11, 0x46, 0x0d, 0x71, 0x67, 0x8f, 0xc6, 0x50, 0x58, 0xfd, 0x4b, 0xa4, 0xcd, 0x8e, 0x99, 0x1f,\n            0xad, 0x63, 0xc9, 0x6b, 0xf7, 0x28, 0x9f, 0x65, 0x2f, 0x5f, 0x61, 0x73, 0x3d, 0x8b, 0x0e, 0x1b,\n            0x33, 0xe0, 0xac, 0x26, 0xa1, 0xe3, 0xf3, 0x82, 0x83, 0x75, 0x44, 0x90, 0x13, 0xaf, 0xf0, 0x07,\n            0x96, 0x21, 0xf8, 0x3f, 0xa2, 0x98, 0x9a, 0xa3, 0x91, 0x4c, 0x7f, 0x92, 0x97, 0xea, 0x01, 0x1c,\n            0x1e, 0x2d, 0x89, 0x39, 0xe6, 0x9c, 0x0a, 0x54, 0x0c, 0x51, 0x6c, 0x43, 0xae, 0xdb, 0x53, 0x59,\n            0xa6, 0xf4, 0x06, 0xda, 0xe2, 0x78, 0x1d, 0x29, 0x30, 0xe1, 0x35, 0xfc, 0xed, 0xbc, 0x47, 0xd5,\n            0xc0, 0xab, 0xcc, 0xa8, 0x80, 0x2b, 0x09, 0xb0, 0x93, 0xd4, 0xc5, 0xb3, 0xd0, 0xdf, 0xa9, 0xaa,\n            0x7a, 0x36, 0x2a, 0xd6, 0xb2, 0xfa, 0xe8, 0xb1, 0xa0, 0x68, 0x5a, 0x81, 0x48, 0x08, 0x17, 0xc7,\n            0xfe, 0x76, 0xbf, 0xc4, 0xf2, 0x3e, 0x4a, 0x0b, 0x10, 0x14, 0xf1, 0xef, 0xa7, 0x27, 0xe5, 0xc8,\n            0xde, 0x9b, 0x8d, 0x3c, 0x56, 0xd7, 0x8c, 0x60, 0x6a, 0x79, 0xee, 0xa5, 0x31, 0x2e, 0x77, 0x41,\n            0xff, 0x95, 0xdd, 0x25, 0x3b, 0x55, 0xca, 0x52, 0x9e, 0x2c, 0x15, 0x4f, 0xe4, 0x16, 0x70, 0x7d,\n            0x72, 0x3a, 0x7b, 0x84, 0xf6, 0x32, 0x86, 0x03, 0xb4, 0x38, 0x6f, 0xb9, 0xc1, 0x45, 0x88, 0xe9,\n            0xba, 0xb6, 0x6e, 0x5e, 0xbe, 0x7e, 0x20, 0xf9, 0x22, 0x66, 0x05, 0xd2, 0xcb, 0xc3, 0xcf, 0x5b,\n        ]\n        mat0 = [0x01, 0x02, 0x02, 0x03]\n        mat1 = [0x01, 0x06, 0x08, 0x02]\n        mat2 = [0x03, 0x01, 0x02, 0x02]\n        mat3 = [0x06, 0x08, 0x02, 0x01]\n        pi = [\n            4, 29, 22, 15, 8, 9, 10, 11, 12, 5, 30, 23, 16, 17, 18, 19,\n            20, 13, 6, 31, 24, 25, 26, 27, 28, 21, 14, 7, 0, 1, 2, 3\n        ]\n        mul_table_0x01 = (\n            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,\n            0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n            0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n            0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n            0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\n            0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n            0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,\n            0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n            0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,\n            0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,\n            0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,\n            0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,\n            0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,\n            0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,\n            0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,\n        )\n        mul_table_0x02 = ()\n        mul_table_0x03 = ()\n        mul_table_0x06 = ()\n        mul_table_0x08 = ()\n\n        @classmethod\n        def build_mul_table(cls, y):\n            tbl = [0x00] * 256\n            x = 0\n            while x < 256:\n                xy = 0x00\n                xx = x\n                yy = y\n                i = 0\n                while i < 4:\n                    if yy & 0x01:\n                        xy ^= xx\n                    yy >>= 1\n                    if xx & 0x80:\n                        xx ^= 0x0d\n                    xx = ((xx << 1) | (xx >> 7)) & 0xff\n                    i += 1\n                tbl[x] = xy\n                x += 1\n            return tuple(tbl)\n\n        @classmethod\n        def init_mul_tables(cls):\n            if cls.mul_table_0x02:\n                return\n            cls.mul_table_0x02 = cls.build_mul_table(0x02)\n            cls.mul_table_0x03 = cls.build_mul_table(0x03)\n            cls.mul_table_0x06 = cls.build_mul_table(0x06)\n            cls.mul_table_0x08 = cls.build_mul_table(0x08)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.__class__.init_mul_tables()\n            self.h = [self.init_fill] * 64\n            self.blk_num = [0x00] * 8\n            self.cnt = 0\n            self.blk_idx = 0\n            self.buf = [0x00] * 64\n            if data:\n                self.update(data)\n            return\n\n        def get_mul_table(self, v):\n            if v == 0x01:\n                return self.mul_table_0x01\n            if v == 0x02:\n                return self.mul_table_0x02\n            if v == 0x03:\n                return self.mul_table_0x03\n            if v == 0x06:\n                return self.mul_table_0x06\n            if v == 0x08:\n                return self.mul_table_0x08\n            raise ValueError(\"invalid mul table\")\n\n        def byte_cpy(self, dst, dst_ofs, src, src_ofs, bytelen):\n            dst[dst_ofs:dst_ofs + bytelen] = src[src_ofs:src_ofs + bytelen]\n            return\n\n        def byte_xor(self, dst, dst_ofs, src, src_ofs, bytelen):\n            i = 0\n            while i < bytelen:\n                dst[dst_ofs + i] ^= src[src_ofs + i]\n                i += 1\n            return\n\n        def aurora_f_xor(self, y, y_ofs, x, x_ofs, cirmat):\n            sbox = self.sbox\n            z0 = sbox[x[x_ofs + 0]]\n            z1 = sbox[x[x_ofs + 1]]\n            z2 = sbox[x[x_ofs + 2]]\n            z3 = sbox[x[x_ofs + 3]]\n\n            t0 = self.get_mul_table(cirmat[0])\n            t1 = self.get_mul_table(cirmat[1])\n            t2 = self.get_mul_table(cirmat[2])\n            t3 = self.get_mul_table(cirmat[3])\n\n            y0 = t0[z0] ^ t1[z1] ^ t2[z2] ^ t3[z3]\n            y1 = t3[z0] ^ t0[z1] ^ t1[z2] ^ t2[z3]\n            y2 = t2[z0] ^ t3[z1] ^ t0[z2] ^ t1[z3]\n            y3 = t1[z0] ^ t2[z1] ^ t3[z2] ^ t0[z3]\n\n            y[y_ofs + 0] = y0\n            y[y_ofs + 1] = y1\n            y[y_ofs + 2] = y2\n            y[y_ofs + 3] = y3\n            y[y_ofs + 4] = x[x_ofs + 4] ^ y0\n            y[y_ofs + 5] = x[x_ofs + 5] ^ y1\n            y[y_ofs + 6] = x[x_ofs + 6] ^ y2\n            y[y_ofs + 7] = x[x_ofs + 7] ^ y3\n            return\n\n        def aurora_bd(self, y, x):\n            pi = self.pi\n            y[0] = x[pi[0]]\n            y[1] = x[pi[1]]\n            y[2] = x[pi[2]]\n            y[3] = x[pi[3]]\n            y[4] = x[pi[4]]\n            y[5] = x[pi[5]]\n            y[6] = x[pi[6]]\n            y[7] = x[pi[7]]\n            y[8] = x[pi[8]]\n            y[9] = x[pi[9]]\n            y[10] = x[pi[10]]\n            y[11] = x[pi[11]]\n            y[12] = x[pi[12]]\n            y[13] = x[pi[13]]\n            y[14] = x[pi[14]]\n            y[15] = x[pi[15]]\n            y[16] = x[pi[16]]\n            y[17] = x[pi[17]]\n            y[18] = x[pi[18]]\n            y[19] = x[pi[19]]\n            y[20] = x[pi[20]]\n            y[21] = x[pi[21]]\n            y[22] = x[pi[22]]\n            y[23] = x[pi[23]]\n            y[24] = x[pi[24]]\n            y[25] = x[pi[25]]\n            y[26] = x[pi[26]]\n            y[27] = x[pi[27]]\n            y[28] = x[pi[28]]\n            y[29] = x[pi[29]]\n            y[30] = x[pi[30]]\n            y[31] = x[pi[31]]\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.blk_num = list(self.blk_num)\n            other.cnt = self.cnt\n            other.blk_idx = self.blk_idx\n            other.buf = list(self.buf)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if self.mode == \"256\":\n                self.aurora256_update(data)\n            elif self.mode in (\"512\", \"256m\"):\n                self.aurora512_update(data)\n            else:\n                raise ValueError(\"invalid mode\")\n            return self\n\n        def digest(self):\n            c = self.copy()\n            out = c.final_bytes()\n            return out\n\n        def hexdigest(self):\n            out = self.digest().hex()\n            return out\n\n        def final_bytes(self):\n            if self.mode == \"256\":\n                out = self.aurora256_final()\n            elif self.mode == \"512\":\n                out = self.aurora512_final()\n            elif self.mode == \"256m\":\n                out = self.aurora256m_final()\n            else:\n                raise ValueError(\"invalid mode\")\n            out = self.truncate_digest(out)\n            return out\n\n        def truncate_digest(self, out):\n            return out[:self.digest_size]\n\n        def aurora_one_round(self, inout, cirmat0, cirmat1):  # codespell:ignore\n            x = [0x00] * 32\n            self.aurora_bd(x, inout)  # codespell:ignore\n            self.aurora_f_xor(inout, 0, x, 0, cirmat0)  # codespell:ignore\n            self.aurora_f_xor(inout, 8, x, 8, cirmat1)  # codespell:ignore\n            self.aurora_f_xor(inout, 16, x, 16, cirmat0)  # codespell:ignore\n            self.aurora_f_xor(inout, 24, x, 24, cirmat1)  # codespell:ignore\n            return\n\n        def aurora_con_update(self, con, iv, mask):\n            con[0] = (iv[0] ^ mask[0]) & 0xff\n            con[1] = (iv[1] ^ mask[1]) & 0xff\n            con[2] = (~iv[1]) & 0xff\n            con[3] = (~iv[0]) & 0xff\n            con[4] = (iv[2] ^ mask[2]) & 0xff\n            con[5] = (iv[3] ^ mask[3]) & 0xff\n            con[6] = (~iv[3]) & 0xff\n            con[7] = (~iv[2]) & 0xff\n            con[8] = iv[1] & 0xff\n            con[9] = iv[0] & 0xff\n            con[10] = (iv[0] ^ mask[4]) & 0xff\n            con[11] = (iv[1] ^ mask[5]) & 0xff\n            con[12] = ((iv[2] >> 7) | (iv[3] << 1)) & 0xff\n            con[13] = ((iv[3] >> 7) | (iv[2] << 1)) & 0xff\n            con[14] = (iv[2] ^ mask[6]) & 0xff\n            con[15] = (iv[3] ^ mask[7]) & 0xff\n\n            if iv[0] & 0x80:\n                iv[0] = (iv[0] ^ 0x54) & 0xff\n                iv[1] = (iv[1] ^ 0x18) & 0xff\n            tmp = (iv[0] >> 7) & 0xff\n            iv0 = iv[0]\n            iv1 = iv[1]\n            iv[0] = ((iv0 << 1) | (iv1 >> 7)) & 0xff\n            iv[1] = ((iv1 << 1) | tmp) & 0xff\n\n            if iv[3] & 0x01:\n                iv[2] = (iv[2] ^ 0xa8) & 0xff\n                iv[3] = (iv[3] ^ 0x30) & 0xff\n            tmp = ((iv[2] << 7) & 0xff)\n            iv2 = iv[2]\n            iv3 = iv[3]\n            iv[2] = ((iv2 >> 1) | (iv3 << 7)) & 0xff\n            iv[3] = ((iv3 >> 1) | tmp) & 0xff\n            return\n\n        def aurora_rotl_con_xor(self, inout, con, mask, rotval):  # codespell:ignore\n            inout[4] = (inout[4] ^ ((con[0] << rotval) ^ (con[1] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[5] = (inout[5] ^ ((con[1] << rotval) ^ (con[2] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[6] = (inout[6] ^ ((con[2] << rotval) ^ (con[3] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[7] = (inout[7] ^ ((con[3] << rotval) ^ (con[0] >> (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[12] = (inout[12] ^ ((con[4] << rotval) ^ (con[5] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[13] = (inout[13] ^ ((con[5] << rotval) ^ (con[6] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[14] = (inout[14] ^ ((con[6] << rotval) ^ (con[7] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[15] = (inout[15] ^ ((con[7] << rotval) ^ (con[4] >> (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[20] = (inout[20] ^ ((con[8] << rotval) ^ (con[9] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[21] = (inout[21] ^ ((con[9] << rotval) ^ (con[10] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[22] = (inout[22] ^ ((con[10] << rotval) ^ (con[11] >> (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[23] = (inout[23] ^ ((con[11] << rotval) ^ (con[8] >> (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[28] = (inout[28] ^ ((con[12] << rotval) ^ (con[13] >> (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[29] = (inout[29] ^ ((con[13] << rotval) ^ (con[14] >> (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[30] = (inout[30] ^ ((con[14] << rotval) ^ (con[15] >> (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[31] = (inout[31] ^ ((con[15] << rotval) ^ (con[12] >> (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            return\n\n        def aurora_rotr_con_xor(self, inout, con, mask, rotval):  # codespell:ignore\n            inout[4] = (inout[4] ^ ((con[0] >> rotval) ^ (con[3] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[5] = (inout[5] ^ ((con[1] >> rotval) ^ (con[0] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[6] = (inout[6] ^ ((con[2] >> rotval) ^ (con[1] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[7] = (inout[7] ^ ((con[3] >> rotval) ^ (con[2] << (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[12] = (inout[12] ^ ((con[4] >> rotval) ^ (con[7] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[13] = (inout[13] ^ ((con[5] >> rotval) ^ (con[4] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[14] = (inout[14] ^ ((con[6] >> rotval) ^ (con[5] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[15] = (inout[15] ^ ((con[7] >> rotval) ^ (con[6] << (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[20] = (inout[20] ^ ((con[8] >> rotval) ^ (con[11] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[21] = (inout[21] ^ ((con[9] >> rotval) ^ (con[8] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[22] = (inout[22] ^ ((con[10] >> rotval) ^ (con[9] << (8 - rotval)))) & 0xff  # codespell:ignore\n            inout[23] = (inout[23] ^ ((con[11] >> rotval) ^ (con[10] << (8 - rotval)))) & 0xff  # codespell:ignore\n\n            inout[28] = (inout[28] ^ ((con[12] >> rotval) ^ (con[15] << (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[29] = (inout[29] ^ ((con[13] >> rotval) ^ (con[12] << (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[30] = (inout[30] ^ ((con[14] >> rotval) ^ (con[13] << (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            inout[31] = (inout[31] ^ ((con[15] >> rotval) ^ (con[14] << (8 - rotval)) ^ mask)) & 0xff  # codespell:ignore\n            return\n\n        def aurora_protl_xor(self, dst, x):\n            z = [0x00] * 32\n            self.byte_cpy(z, 0, x, 0, 4)\n            self.byte_cpy(z, 8, x, 8, 4)\n            self.byte_cpy(z, 16, x, 16, 16)\n            z[4] = ((x[4] << 1) | (x[5] >> 7)) & 0xff\n            z[5] = ((x[5] << 1) | (x[6] >> 7)) & 0xff\n            z[6] = ((x[6] << 1) | (x[7] >> 7)) & 0xff\n            z[7] = ((x[7] << 1) | (x[12] >> 7)) & 0xff\n            z[12] = ((x[12] << 1) | (x[13] >> 7)) & 0xff\n            z[13] = ((x[13] << 1) | (x[14] >> 7)) & 0xff\n            z[14] = ((x[14] << 1) | (x[15] >> 7)) & 0xff\n            z[15] = ((x[15] << 1) | (x[4] >> 7)) & 0xff\n            self.byte_xor(dst, 0, z, 0, 32)\n            return\n\n        def aurora_protr_xor(self, dst, y):\n            z = [0x00] * 32\n            self.byte_cpy(z, 0, y, 0, 4)\n            self.byte_cpy(z, 8, y, 8, 4)\n            self.byte_cpy(z, 16, y, 16, 16)\n            z[4] = ((y[4] >> 1) | (y[15] << 7)) & 0xff\n            z[5] = ((y[5] >> 1) | (y[4] << 7)) & 0xff\n            z[6] = ((y[6] >> 1) | (y[5] << 7)) & 0xff\n            z[7] = ((y[7] >> 1) | (y[6] << 7)) & 0xff\n            z[12] = ((y[12] >> 1) | (y[7] << 7)) & 0xff\n            z[13] = ((y[13] >> 1) | (y[12] << 7)) & 0xff\n            z[14] = ((y[14] >> 1) | (y[13] << 7)) & 0xff\n            z[15] = ((y[15] >> 1) | (y[14] << 7)) & 0xff\n            self.byte_xor(dst, 0, z, 0, 32)\n            return\n\n        def aurora256_cf(self, cv, m, mask, con_iv, con_mask):\n            ml = [0x00] * 32\n            mr = [0x00] * 32\n            x = [0x00] * 32\n            t = [0x00] * 4\n            con = [0x00] * 16\n\n            self.byte_cpy(ml, 0, m, 0, 32)\n            self.byte_cpy(mr, 0, m, 32, 32)\n            self.byte_cpy(x, 0, cv, 0, 32)\n            self.byte_cpy(t, 0, con_iv, 0, 4)\n\n            r = 0\n            while r < 17:\n                self.aurora_con_update(con, t, con_mask)\n                if (r % 2) == 0:\n                    if r < 16:\n                        self.aurora_rotl_con_xor(ml, con, 0x00, 1)\n                    self.aurora_protl_xor(x, ml)\n                    self.aurora_one_round(ml, self.mat0, self.mat1)\n                else:\n                    self.aurora_rotr_con_xor(mr, con, 0x00, 1)\n                    self.aurora_protr_xor(x, mr)\n                    self.aurora_one_round(mr, self.mat2, self.mat3)\n\n                self.aurora_rotl_con_xor(x, con, mask, 0)\n                self.aurora_one_round(x, self.mat1, self.mat0)\n                r += 1\n\n            self.aurora_protr_xor(x, mr)\n            self.byte_xor(cv, 0, x, 0, 32)\n            return\n\n        def aurora512_cf(self, cv, m, mask, con_iv, con_mask):\n            ml = [0x00] * 32\n            mr = [0x00] * 32\n            xl = [0x00] * 32\n            xr = [0x00] * 32\n            t = [0x00] * 4\n            con = [0x00] * 16\n\n            self.byte_cpy(ml, 0, m, 0, 32)\n            self.byte_cpy(mr, 0, m, 32, 32)\n            self.byte_cpy(xl, 0, cv, 0, 32)\n            self.byte_cpy(xr, 0, cv, 32, 32)\n            self.byte_cpy(t, 0, con_iv, 0, 4)\n\n            r = 0\n            while r < 17:\n                self.aurora_con_update(con, t, con_mask)\n                if (r % 2) == 0:\n                    if r < 16:\n                        self.aurora_rotl_con_xor(ml, con, 0x00, 1)\n                    self.aurora_protl_xor(xl, ml)\n                    self.aurora_protl_xor(xr, ml)\n                    self.aurora_one_round(ml, self.mat0, self.mat1)\n                else:\n                    self.aurora_rotr_con_xor(mr, con, 0x00, 1)\n                    self.aurora_protr_xor(xl, mr)\n                    self.aurora_protr_xor(xr, mr)\n                    self.aurora_one_round(mr, self.mat2, self.mat3)\n\n                self.aurora_rotl_con_xor(xl, con, mask, 0)\n                self.aurora_one_round(xl, self.mat1, self.mat0)\n                self.aurora_rotl_con_xor(xr, con, mask, 3)\n                self.aurora_one_round(xr, self.mat3, self.mat2)\n                r += 1\n\n            self.aurora_protr_xor(xl, mr)\n            self.aurora_protr_xor(xr, mr)\n            self.byte_xor(cv, 0, xl, 0, 32)\n            self.byte_xor(cv, 32, xr, 0, 32)\n            return\n\n        def aurora512_cfmf(self):\n            if self.blk_idx >= 0x08:\n                self.aurora512_cf(self.h, self.h, self.blk_idx, self.con_iv, self.con_mask)\n                self.blk_idx = 0\n            self.aurora512_cf(self.h, self.buf, self.blk_idx, self.con_iv, self.con_mask)\n            self.blk_idx = (self.blk_idx + 1) & 0xff\n            return\n\n        def aurora256_mff(self, cv):\n            mr = [0x00] * 32\n            x = [0x00] * 32\n            t = [0x3c, 0x6e, 0xa5, 0x4f]\n            con_mask = [0xb5, 0xc0, 0xe9, 0xb5, 0x61, 0x35, 0x79, 0xcc]\n            con = [0x00] * 16\n\n            self.byte_cpy(mr, 0, cv, 32, 32)\n            self.byte_cpy(x, 0, cv, 0, 32)\n\n            r = 0\n            while r < 17:\n                self.aurora_con_update(con, t, con_mask)\n                if (r % 2) == 1:\n                    self.aurora_rotr_con_xor(mr, con, 0x00, 1)\n                    self.aurora_protr_xor(x, mr)\n                    self.aurora_one_round(mr, self.mat2, self.mat3)\n                self.aurora_rotl_con_xor(x, con, 0x09, 0)\n                self.aurora_one_round(x, self.mat1, self.mat0)\n                r += 1\n\n            self.aurora_protr_xor(x, mr)\n            self.byte_xor(cv, 0, x, 0, 32)\n            return\n\n        def add_blk(self):\n            i = 7\n            while i >= 0:\n                self.blk_num[i] = (self.blk_num[i] + 1) & 0xff\n                if self.blk_num[i] != 0:\n                    break\n                i -= 1\n            return\n\n        def aurora256_update(self, msg):\n            if self.cnt & 0x07:\n                raise ValueError(\"bit-aligned state is not supported\")\n            if (self.cnt < 0) or (self.cnt >= 512):\n                raise ValueError(\"invalid internal state\")\n\n            byte_cnt = self.cnt // 8\n            msg_pos = 0\n            msg_len = len(msg)\n\n            while msg_pos < msg_len:\n                self.buf[byte_cnt] = msg[msg_pos] & 0xff\n                byte_cnt += 1\n                msg_pos += 1\n                self.cnt += 8\n\n                if byte_cnt >= 64:\n                    self.aurora256_cf(self.h, self.buf, 0x00, self.con_iv, self.con_mask)\n                    self.add_blk()\n                    byte_cnt = 0\n                    self.cnt = 0\n            return\n\n        def aurora512_update(self, msg):\n            if self.cnt & 0x07:\n                raise ValueError(\"bit-aligned state is not supported\")\n            if (self.cnt < 0) or (self.cnt >= 512):\n                raise ValueError(\"invalid internal state\")\n\n            byte_cnt = self.cnt // 8\n            msg_pos = 0\n            msg_len = len(msg)\n\n            while msg_pos < msg_len:\n                self.buf[byte_cnt] = msg[msg_pos] & 0xff\n                byte_cnt += 1\n                msg_pos += 1\n                self.cnt += 8\n\n                if byte_cnt >= 64:\n                    self.aurora512_cfmf()\n                    self.add_blk()\n                    byte_cnt = 0\n                    self.cnt = 0\n            return\n\n        def aurora256_final(self):\n            byte_cnt = self.cnt // 8\n            if (self.cnt < 0) or (self.cnt >= 512):\n                return bytes([0x00] * 32)\n\n            if self.cnt != 0:\n                self.add_blk()\n\n            if self.cnt & 0x07:\n                raise ValueError(\"bit-aligned state is not supported\")\n            self.buf[byte_cnt] = 0x80\n            byte_cnt += 1\n\n            if self.cnt > 447:\n                while byte_cnt < 64:\n                    self.buf[byte_cnt] = 0x00\n                    byte_cnt += 1\n                byte_cnt = 0\n                self.aurora256_cf(self.h, self.buf, 0x00, self.con_iv, self.con_mask)\n\n            while byte_cnt < 56:\n                self.buf[byte_cnt] = 0x00\n                byte_cnt += 1\n\n            self.byte_cpy(self.buf, 56, self.blk_num, 0, 8)\n            self.aurora256_cf(self.h, self.buf, 0x01, self.con_iv, self.con_mask)\n            return bytes(self.h[:32])\n\n        def aurora512_final(self):\n            byte_cnt = self.cnt // 8\n            if (self.cnt < 0) or (self.cnt >= 512):\n                return bytes([0x00] * 64)\n\n            if self.cnt != 0:\n                self.add_blk()\n\n            if self.cnt & 0x07:\n                raise ValueError(\"bit-aligned state is not supported\")\n            self.buf[byte_cnt] = 0x80\n            byte_cnt += 1\n\n            if self.cnt > 447:\n                while byte_cnt < 64:\n                    self.buf[byte_cnt] = 0x00\n                    byte_cnt += 1\n                byte_cnt = 0\n                self.aurora512_cfmf()\n\n            while byte_cnt < 56:\n                self.buf[byte_cnt] = 0x00\n                byte_cnt += 1\n\n            self.byte_cpy(self.buf, 56, self.blk_num, 0, 8)\n            self.aurora512_cfmf()\n            self.aurora512_cf(self.h, self.h, 0x09, self.con_iv, self.con_mask)\n            return bytes(self.h[:64])\n\n        def aurora256m_final(self):\n            byte_cnt = self.cnt // 8\n            if (self.cnt < 0) or (self.cnt >= 512):\n                return bytes([0x00] * 32)\n\n            if self.cnt != 0:\n                self.add_blk()\n\n            if self.cnt & 0x07:\n                raise ValueError(\"bit-aligned state is not supported\")\n            self.buf[byte_cnt] = 0x80\n            byte_cnt += 1\n\n            if self.cnt > 447:\n                while byte_cnt < 64:\n                    self.buf[byte_cnt] = 0x00\n                    byte_cnt += 1\n                byte_cnt = 0\n                self.aurora512_cfmf()\n\n            while byte_cnt < 56:\n                self.buf[byte_cnt] = 0x00\n                byte_cnt += 1\n\n            self.byte_cpy(self.buf, 56, self.blk_num, 0, 8)\n            self.aurora512_cfmf()\n            self.aurora256_mff(self.h)\n            return bytes(self.h[:32])\n\n    class AURORA256(AURORABase):\n        digest_size = 32\n        init_fill = 0x00\n        con_iv = [0x6a, 0x09, 0xbb, 0x67]\n        con_mask = [0x42, 0x8a, 0x71, 0x37, 0x26, 0x11, 0x3e, 0xe8]\n        mode = \"256\"\n\n    class AURORA224(AURORA256):\n        digest_size = 28\n        init_fill = 0xff\n\n        def truncate_digest(self, out):\n            dst = bytearray()\n            i = 0\n            while i < 4:\n                base = i * 8\n                j = 0\n                while j < 7:\n                    dst.append(out[base + j])\n                    j += 1\n                i += 1\n            return bytes(dst)\n\n    class AURORA512(AURORABase):\n        digest_size = 64\n        init_fill = 0x00\n        con_iv = [0x51, 0x0e, 0x9b, 0x05]\n        con_mask = [0x39, 0x56, 0x59, 0xf1, 0x9d, 0x8a, 0xab, 0x97]\n        mode = \"512\"\n\n    class AURORA384(AURORA512):\n        digest_size = 48\n        init_fill = 0xff\n\n        def truncate_digest(self, out):\n            dst = bytearray()\n            i = 0\n            while i < 8:\n                base = i * 8\n                j = 0\n                while j < 6:\n                    dst.append(out[base + j])\n                    j += 1\n                i += 1\n            return bytes(dst)\n\n    class AURORA256M(AURORABase):\n        digest_size = 32\n        init_fill = 0x00\n        con_iv = [0x3c, 0x6e, 0xa5, 0x4f]\n        con_mask = [0xb5, 0xc0, 0xe9, 0xb5, 0x61, 0x35, 0x79, 0xcc]\n        mode = \"256m\"\n\n    class AURORA224M(AURORA256M):\n        digest_size = 28\n        init_fill = 0xff\n\n        def truncate_digest(self, out):\n            dst = bytearray()\n            i = 0\n            while i < 4:\n                base = i * 8\n                j = 0\n                while j < 7:\n                    dst.append(out[base + j])\n                    j += 1\n                i += 1\n            return bytes(dst)\n\n    class BlenderBase:\n        block_size = 0\n        digest_size = 0\n        word_bits = 0\n        word_count = 0\n        iv_words = ()\n        first_block_size = 13\n\n        def __init__(self, data=b\"\"):\n            self.word_bytes = self.word_bits // 8\n            self.mask = (1 << self.word_bits) - 1\n\n            self.word = list(self.iv_words)\n            self.sum_words = [0] * self.word_count\n\n            self.checksum1 = 0\n            self.checksum2 = 0\n            self.carry1 = 0\n            self.carry2 = 0\n\n            self.rounds_to_go = 32\n            self.block_size_frags = 16\n\n            self.buf = bytearray()\n            self.first_block = bytearray()\n            self.msg_bits = 0\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.word = list(self.word)\n            other.sum_words = list(self.sum_words)\n            other.checksum1 = self.checksum1\n            other.checksum2 = self.checksum2\n            other.carry1 = self.carry1\n            other.carry2 = self.carry2\n            other.rounds_to_go = self.rounds_to_go\n            other.block_size_frags = self.block_size_frags\n            other.buf = bytearray(self.buf)\n            other.first_block = bytearray(self.first_block)\n            other.msg_bits = self.msg_bits\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            if not data:\n                return self\n\n            self.msg_bits += len(data) * 8\n\n            if len(self.first_block) < self.first_block_size:\n                need = self.first_block_size - len(self.first_block)\n                self.first_block.extend(data[:need])\n\n            self.buf.extend(data)\n\n            frag_bytes = self.word_bytes\n            whole = (len(self.buf) // frag_bytes) * frag_bytes\n            if whole > 0:\n                block = bytes(self.buf[:whole])\n                del self.buf[:whole]\n                self.compress_fragments(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n\n            out = bytearray()\n            for value in c.sum_words:\n                out.extend(c.word_to_big_endian_bytes(value))\n            return bytes(out)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            len_bytes = self.encode_length_le(self.msg_bits)\n            residue = bytearray(self.buf)\n\n            space_left = (self.rounds_to_go - 2) * self.word_bytes\n            space_needed = len(len_bytes) + 2 + len(residue)\n            while space_left < space_needed:\n                space_left += self.block_size_frags * self.word_bytes\n            fill_size = space_left + 1 - space_needed\n\n            fill_source = bytearray(self.first_block)\n            if len(fill_source) < self.first_block_size and residue:\n                need = self.first_block_size - len(fill_source)\n                fill_source.extend(residue[:need])\n            if not fill_source:\n                fill_source = bytearray(b\"\\x00\" * self.first_block_size)\n\n            work = bytearray(residue)\n            if fill_size > 0:\n                reps = (fill_size + len(fill_source) - 1) // len(fill_source)\n                work.extend((fill_source * reps)[:fill_size])\n\n            work.extend(len_bytes)\n            work.append(len(len_bytes))\n\n            if len(work) % self.word_bytes != 0:\n                raise ValueError(\"internal error: pre-checksum tail is not fragment-aligned\")\n\n            if work:\n                self.compress_fragments(bytes(work))\n\n            chk = bytearray()\n            chk.extend(self.word_to_little_endian_bytes((~self.checksum1) & self.mask))\n            chk.extend(self.word_to_little_endian_bytes(self.checksum2))\n            self.compress_fragments(bytes(chk))\n            return\n\n        def compress_fragments(self, data):\n            if not data:\n                return\n            if len(data) % self.word_bytes != 0:\n                raise ValueError(\"fragment data must be aligned\")\n\n            pos = 0\n            while pos < len(data):\n                fragment = self.bytes_to_little_endian_word(data[pos:pos + self.word_bytes])\n                pos += self.word_bytes\n\n                self.checksum1 = (self.checksum1 + fragment) & self.mask\n                self.checksum2 = (self.checksum2 + ((~fragment) & self.mask)) & self.mask\n\n                even_left = self.ror(fragment, 8) ^ self.word[0]\n                even_right = self.ror(self.word[2], 8) ^ self.word[4]\n                self.carry2, t2 = self.add_with_carry(even_left, even_right, self.carry2)\n\n                odd_left = fragment ^ self.word[5]\n                odd_right = self.rol(self.word[3], 8) ^ self.word[1]\n                self.carry1, t1 = self.add_with_carry(odd_left, odd_right, self.carry1)\n\n                rotate_bits = 8 - (self.carry1 + self.carry2)\n                t1 = self.rol(t1, rotate_bits)\n                t2 = self.ror(t2, rotate_bits)\n\n                temp = self.ror(self.word[0], 7)\n                old = list(self.word)\n\n                self.word[0] = old[1] ^ t2\n                self.word[1] = old[2] ^ t1\n                self.word[2] = old[3] ^ t2\n                self.word[3] = old[4] ^ t1\n                self.word[4] = old[5] ^ t2\n\n                if self.word_count == 6:\n                    self.word[5] = temp ^ t1\n                elif self.word_count == 7:\n                    self.word[5] = old[6] ^ t1\n                    self.word[6] = temp ^ t2\n                elif self.word_count == 8:\n                    self.word[5] = old[6] ^ t1\n                    self.word[6] = old[7] ^ t2\n                    self.word[7] = temp ^ t1\n                else:\n                    raise ValueError(\"unsupported word_count\")\n\n                for i in range(self.word_count):\n                    self.sum_words[i] = (self.sum_words[i] + self.word[i]) & self.mask\n\n                self.rounds_to_go -= 1\n                if self.rounds_to_go == 0:\n                    self.rounds_to_go = self.block_size_frags\n            return\n\n        def add_with_carry(self, x, y, carry_in):\n            total = x + y + carry_in\n            carry_out = 0\n            if total > self.mask:\n                carry_out = 1\n            result = total & self.mask\n            return carry_out, result\n\n        def rol(self, value, count):\n            value &= self.mask\n            count %= self.word_bits\n            if count == 0:\n                return value\n            return ((value << count) | (value >> (self.word_bits - count))) & self.mask\n\n        def ror(self, value, count):\n            value &= self.mask\n            count %= self.word_bits\n            if count == 0:\n                return value\n            return ((value >> count) | (value << (self.word_bits - count))) & self.mask\n\n        def encode_length_le(self, value):\n            if value == 0:\n                return b\"\\x00\"\n\n            out = bytearray()\n            while value > 0:\n                out.append(value & 0xff)\n                value >>= 8\n            return bytes(out)\n\n        def bytes_to_little_endian_word(self, chunk):\n            value = 0\n            shift = 0\n            for b in chunk:\n                value |= b << shift\n                shift += 8\n            return value\n\n        def word_to_little_endian_bytes(self, value):\n            out = bytearray()\n            for i in range(self.word_bytes):\n                out.append((value >> (8 * i)) & 0xff)\n            return bytes(out)\n\n        def word_to_big_endian_bytes(self, value):\n            out = bytearray()\n            for i in range(self.word_bytes - 1, -1, -1):\n                out.append((value >> (8 * i)) & 0xff)\n            return bytes(out)\n\n    class Blender224(BlenderBase):\n        block_size = 64\n        digest_size = 28\n        word_bits = 32\n        word_count = 7\n        iv_words = [\n            0xc105_9ed8, 0x367c_d507, 0x3070_dd17, 0xf70e_5939,\n            0xffc0_0b31, 0x6858_1511, 0x64f9_8fa7,\n        ]\n\n    class Blender256(BlenderBase):\n        block_size = 64\n        digest_size = 32\n        word_bits = 32\n        word_count = 8\n        iv_words = [\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a,\n            0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        ]\n\n    class Blender384(BlenderBase):\n        # KAT-compatible version of Reference Implementation / BlenderUpdate.zip\n        # The sixth word is set to 0 to accommodate V384 initialization.\n        block_size = 128\n        digest_size = 48\n        word_bits = 64\n        word_count = 6\n        iv_words = [\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x0000_0000_0000_0000,\n        ]\n\n    class Blender384Spec(BlenderBase):\n        # Version using SHA-384-derived initial values ​​as per the specification\n        block_size = 128\n        digest_size = 48\n        word_bits = 64\n        word_count = 6\n        iv_words = [\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x8eb4_4a87_6858_1511,\n        ]\n\n    class Blender512(BlenderBase):\n        block_size = 128\n        digest_size = 64\n        word_bits = 64\n        word_count = 8\n        iv_words = [\n            0x6a09_e667_f3bc_c908, 0xbb67_ae85_84ca_a73b, 0x3c6e_f372_fe94_f82b, 0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1, 0x9b05_688c_2b3e_6c1f, 0x1f83_d9ab_fb41_bd6b, 0x5be0_cd19_137e_2179,\n        ]\n\n    class BOOLEBase:\n        word_size = 64\n        block_size = 8\n        state_words = 16\n        initsum = 0x6996_c53a\n        mask = 0xffff_ffff_ffff_ffff\n\n        def __init__(self, data=b\"\", digest_bits=None):\n            if digest_bits is None:\n                if not hasattr(self, \"default_digest_bits\"):\n                    raise ValueError(\"digest_bits is required\")\n                digest_bits = self.default_digest_bits\n\n            if digest_bits <= 0 or digest_bits > (8 * self.word_size):\n                raise ValueError(\"invalid digest_bits\")\n            if (digest_bits % 8) != 0:\n                raise ValueError(\"digest_bits must be byte-aligned\")\n\n            self.digest_bits = int(digest_bits)\n            self.digest_size = self.digest_bits // 8\n            self.hashbitlen = self.digest_bits\n\n            self.r = [0] * self.state_words\n            self.nbits_total = 0\n            self.xsum = 0\n            self.lsum = 0\n            self.rsum = 0\n            self.buf = bytearray()\n            self.msg_len = 0\n\n            self.init_state()\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__(digest_bits=self.digest_bits)\n            other.r = list(self.r)\n            other.nbits_total = self.nbits_total\n            other.xsum = self.xsum\n            other.lsum = self.lsum\n            other.rsum = self.rsum\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.nbits_total = (self.nbits_total + (len(data) * 8)) & self.mask\n            self.buf.extend(data)\n\n            while len(self.buf) >= self.block_size:\n                word = int.from_bytes(self.buf[:self.block_size], \"little\")\n                del self.buf[:self.block_size]\n                self.data_cycle(word)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.generate()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            self.finish()\n            self.finish()\n            return\n\n        def rol(self, value, count):\n            value &= self.mask\n            return ((value << count) | (value >> (self.word_size - count))) & self.mask\n\n        def ror(self, value, count):\n            value &= self.mask\n            return ((value >> count) | (value << (self.word_size - count))) & self.mask\n\n        def sbox1(self, value):\n            value &= self.mask\n            value ^= self.initsum\n            value ^= self.rol(value, 34) | self.rol(value, 42)\n            value ^= self.rol(value, 20) | self.rol(value, 55)\n            value ^= (value << 3) | self.rol(value, 60)\n            return value & self.mask\n\n        def sbox2(self, value):\n            value &= self.mask\n            value ^= self.initsum\n            value ^= self.ror(value, 35) | self.ror(value, 46)\n            value ^= self.ror(value, 27) | self.ror(value, 52)\n            value ^= (value >> 5) | self.ror(value, 55)\n            return value & self.mask\n\n        def soft_reset(self):\n            self.nbits_total = 0\n            self.xsum = 0\n            self.lsum = self.initsum\n            self.rsum = self.rol(self.initsum, 8)\n            return\n\n        def init_state(self):\n            self.r[0] = self.sbox1(1)\n\n            i = 1\n            while i < self.state_words:\n                self.r[i] = self.sbox1(self.r[i - 1])\n                i += 1\n\n            self.soft_reset()\n            return\n\n        def cycle(self):\n            t = self.r[12] ^ self.r[13]\n            t = self.sbox1(t) ^ self.rol(self.r[0], 1)\n\n            i = 1\n            while i < self.state_words:\n                self.r[i - 1] = self.r[i]\n                i += 1\n            self.r[self.state_words - 1] = t\n\n            t = self.sbox2(self.r[2] ^ self.r[15])\n            self.r[0] ^= t\n            return\n\n        def data_cycle(self, word):\n            self.xsum ^= word\n            self.lsum = self.sbox1(self.lsum) ^ word\n            self.rsum ^= self.lsum\n            self.lsum = self.rol(self.lsum, 1)\n            self.rsum = self.ror(self.rsum, 1)\n\n            self.r[3] ^= self.lsum\n            self.r[13] ^= self.rsum\n\n            self.cycle()\n            return\n\n        def stream_cycle(self):\n            self.cycle()\n            return self.r[0] ^ self.r[8] ^ self.r[12]\n\n        def diffuse(self):\n            i = 0\n            while i < self.state_words:\n                self.cycle()\n                i += 1\n            return\n\n        def finish(self):\n            if len(self.buf) != 0:\n                # Absorb remaining bytes as a zero-padded little-endian word.\n                tail = bytes(self.buf)\n                word = int.from_bytes(tail.ljust(self.block_size, b\"\\x00\"), \"little\")\n                self.data_cycle(word)\n                self.buf.clear()\n\n            # For 64-bit DataLength, only R[0] is xored with the message bit length.\n            self.r[0] ^= self.nbits_total\n            self.r[4] ^= self.hashbitlen\n\n            i = 4\n            while i < self.state_words:\n                self.r[i] ^= self.lsum\n                self.r[i + 1] ^= self.xsum\n                self.r[i + 2] ^= self.rsum\n                i += 3\n\n            self.diffuse()\n            return\n\n        def generate(self):\n            out = bytearray()\n            while len(out) < self.digest_size:\n                word = self.stream_cycle()\n                out.extend(word.to_bytes(self.block_size, \"little\"))\n            return bytes(out[:self.digest_size])\n\n    class BOOLE224(BOOLEBase):\n        default_digest_bits = 224\n        digest_size = 28\n\n    class BOOLE256(BOOLEBase):\n        default_digest_bits = 256\n        digest_size = 32\n\n    class BOOLE384(BOOLEBase):\n        default_digest_bits = 384\n        digest_size = 48\n\n    class BOOLE512(BOOLEBase):\n        default_digest_bits = 512\n        digest_size = 64\n\n    class CheetahBase:\n        block_size = 128\n        reference_stride_bytes = 1\n\n        shift_rows4c = [0, 1, 3, 4]\n        shift_rows8c = [0, 1, 2, 3, 4, 5, 6, 7]\n        shift_rows8c_message = [0, 1, 2, 3, 5, 6, 7, 8]\n\n        mc8 = [\n            [0x02, 0x0c, 0x06, 0x08, 0x01, 0x04, 0x01, 0x01],\n            [0x01, 0x02, 0x0c, 0x06, 0x08, 0x01, 0x04, 0x01],\n            [0x01, 0x01, 0x02, 0x0c, 0x06, 0x08, 0x01, 0x04],\n            [0x04, 0x01, 0x01, 0x02, 0x0c, 0x06, 0x08, 0x01],\n            [0x01, 0x04, 0x01, 0x01, 0x02, 0x0c, 0x06, 0x08],\n            [0x08, 0x01, 0x04, 0x01, 0x01, 0x02, 0x0c, 0x06],\n            [0x06, 0x08, 0x01, 0x04, 0x01, 0x01, 0x02, 0x0c],\n            [0x0c, 0x06, 0x08, 0x01, 0x04, 0x01, 0x01, 0x02],\n        ]\n\n        mc64 = [\n            [0x01, 0x04, 0x01, 0x01, 0x02, 0x0c, 0x06, 0x08],\n            [0x08, 0x01, 0x04, 0x01, 0x01, 0x02, 0x0c, 0x06],\n            [0x06, 0x08, 0x01, 0x04, 0x01, 0x01, 0x02, 0x0c],\n            [0x0c, 0x06, 0x08, 0x01, 0x04, 0x01, 0x01, 0x02],\n            [0x02, 0x0c, 0x06, 0x08, 0x01, 0x04, 0x01, 0x01],\n            [0x01, 0x02, 0x0c, 0x06, 0x08, 0x01, 0x04, 0x01],\n            [0x01, 0x01, 0x02, 0x0c, 0x06, 0x08, 0x01, 0x04],\n            [0x04, 0x01, 0x01, 0x02, 0x0c, 0x06, 0x08, 0x01],\n        ]\n\n        sbox = [\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        ]\n\n        mul_identity = list(range(256))\n        mul_tables = None\n\n        def __init__(self, data=b\"\"):\n            self.data = bytearray()\n            self.ensure_mul_tables()\n            if data:\n                self.update(data)\n            return\n\n        @classmethod\n        def ensure_mul_tables(cls):\n            if cls.mul_tables is not None:\n                return\n\n            mul2 = [0] * 256\n            mul3 = [0] * 256\n            mul4 = [0] * 256\n            mul6 = [0] * 256\n            mul8 = [0] * 256\n            mul12 = [0] * 256\n\n            for x in range(256):\n                x2 = ((x << 1) & 0xff) ^ (0x1b if (x & 0x80) else 0x00)\n                x4 = ((x2 << 1) & 0xff) ^ (0x1b if (x2 & 0x80) else 0x00)\n                x8 = ((x4 << 1) & 0xff) ^ (0x1b if (x4 & 0x80) else 0x00)\n\n                mul2[x] = x2\n                mul3[x] = x2 ^ x\n                mul4[x] = x4\n                mul6[x] = x4 ^ x2\n                mul8[x] = x8\n                mul12[x] = x8 ^ x4\n\n            cls.mul2 = mul2\n            cls.mul3 = mul3\n            cls.mul4 = mul4\n            cls.mul6 = mul6\n            cls.mul8 = mul8\n            cls.mul12 = mul12\n            cls.mul_tables = {\n                0x01: cls.mul_identity,\n                0x02: cls.mul2,\n                0x03: cls.mul3,\n                0x04: cls.mul4,\n                0x06: cls.mul6,\n                0x08: cls.mul8,\n                0x0c: cls.mul12,\n            }\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.data = bytearray(self.data)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.data.extend(data)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            return c.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def xtime(self, a):\n            a = ((a << 1) & 0xff) ^ (0x1b if (a & 0x80) else 0x00)\n            return a\n\n        def sub_bytes(self, a):\n            sbox = self.sbox\n            for row in a:\n                for j in range(8):\n                    row[j] = sbox[row[j]]\n            return\n\n        def sub_bytes_m(self, message_block):\n            sbox = self.sbox\n            for row in message_block:\n                for j in range(16):\n                    row[j] = sbox[row[j]]\n            return\n\n        def shift_rows4(self, a):\n            shifts = self.shift_rows4c\n            for i in range(4):\n                row = a[i]\n                shift = shifts[i]\n                a[i] = row[shift:] + row[:shift]\n            return\n\n        def shift_rows64(self, a):\n            shifts = self.shift_rows8c\n            for i in range(8):\n                row = a[i]\n                shift = shifts[i]\n                a[i] = row[shift:] + row[:shift]\n            return\n\n        def shift_rows8_message(self, message_block):\n            shifts = self.shift_rows8c_message\n            for i in range(8):\n                row = message_block[i]\n                shift = shifts[i]\n                a = row[shift:]\n                b = row[:shift]\n                message_block[i] = a + b\n            return\n\n        def mix_column4(self, a):\n            mul2 = self.mul2\n            mul3 = self.mul3\n\n            r0 = a[0]\n            r1 = a[1]\n            r2 = a[2]\n            r3 = a[3]\n\n            t0 = [0] * 8\n            t1 = [0] * 8\n            t2 = [0] * 8\n            t3 = [0] * 8\n\n            for j in range(8):\n                x0 = r0[j]\n                x1 = r1[j]\n                x2 = r2[j]\n                x3 = r3[j]\n\n                t0[j] = mul2[x0] ^ mul3[x1] ^ x2 ^ x3\n                t1[j] = x0 ^ mul2[x1] ^ mul3[x2] ^ x3\n                t2[j] = x0 ^ x1 ^ mul2[x2] ^ mul3[x3]\n                t3[j] = mul3[x0] ^ x1 ^ x2 ^ mul2[x3]\n\n            a[0] = t0\n            a[1] = t1\n            a[2] = t2\n            a[3] = t3\n            return\n\n        def mix_column64(self, a):\n            mc = self.mc64\n            mul_tables = self.mul_tables\n            temp = [[0] * 8 for _ in range(8)]\n\n            for i in range(8):\n                c0, c1, c2, c3, c4, c5, c6, c7 = mc[i]\n                t0 = mul_tables[c0]\n                t1 = mul_tables[c1]\n                t2 = mul_tables[c2]\n                t3 = mul_tables[c3]\n                t4 = mul_tables[c4]\n                t5 = mul_tables[c5]\n                t6 = mul_tables[c6]\n                t7 = mul_tables[c7]\n                out = temp[i]\n\n                for j in range(8):\n                    out[j] = (\n                        t0[a[0][j]] ^\n                        t1[a[1][j]] ^\n                        t2[a[2][j]] ^\n                        t3[a[3][j]] ^\n                        t4[a[4][j]] ^\n                        t5[a[5][j]] ^\n                        t6[a[6][j]] ^\n                        t7[a[7][j]]\n                    )\n\n            for i in range(8):\n                a[i] = temp[i]\n            return\n\n        def mix_column8_message(self, message_block):\n            mc = self.mc8\n            mul_tables = self.mul_tables\n            temp = [[0] * 16 for _ in range(8)]\n\n            for i in range(8):\n                c0, c1, c2, c3, c4, c5, c6, c7 = mc[i]\n                t0 = mul_tables[c0]\n                t1 = mul_tables[c1]\n                t2 = mul_tables[c2]\n                t3 = mul_tables[c3]\n                t4 = mul_tables[c4]\n                t5 = mul_tables[c5]\n                t6 = mul_tables[c6]\n                t7 = mul_tables[c7]\n                out = temp[i]\n\n                for j in range(16):\n                    out[j] = (\n                        t0[message_block[0][j]] ^\n                        t1[message_block[1][j]] ^\n                        t2[message_block[2][j]] ^\n                        t3[message_block[3][j]] ^\n                        t4[message_block[4][j]] ^\n                        t5[message_block[5][j]] ^\n                        t6[message_block[6][j]] ^\n                        t7[message_block[7][j]]\n                    )\n\n            for i in range(8):\n                message_block[i] = temp[i]\n            return\n\n        def add_round_constant(self, message_block, r):\n            sbox = self.sbox\n            base = 4 * r\n            message_block[0][0] ^= sbox[base + 0]\n            message_block[1][0] ^= sbox[base + 1]\n            message_block[2][0] ^= sbox[base + 2]\n            message_block[3][0] ^= sbox[base + 3]\n            return\n\n        def internal_round4(self, a):\n            self.sub_bytes(a)\n            self.shift_rows4(a)\n            self.mix_column4(a)\n            return\n\n        def internal_round64(self, a):\n            self.sub_bytes(a)\n            self.shift_rows64(a)\n            self.mix_column64(a)\n            return\n\n        def message_expansion(self, block, rounds):\n            message_block = [[0] * 16 for _ in range(8)]\n            expanded_block = [[0] * 16 for _ in range((rounds + 1) * 8)]\n\n            for j in range(16):\n                base = 8 * j\n                for i in range(8):\n                    b = block[base + 7 - i]\n                    message_block[i][j] = b\n                    expanded_block[i][j] = b\n\n            for k in range(1, rounds + 1):\n                self.sub_bytes_m(message_block)\n                self.shift_rows8_message(message_block)\n                self.mix_column8_message(message_block)\n                self.add_round_constant(message_block, k)\n\n                dst = k * 8\n                for i in range(8):\n                    expanded_block[dst + i] = message_block[i][:]\n\n            return expanded_block\n\n        def compress32(self, a, block, block_counter):\n            temp = [row[:] for row in a]\n\n            for i in range(4):\n                a[i][0] ^= (block_counter >> (56 - i * 8)) & 0xff\n                a[i][1] ^= (block_counter >> (24 - i * 8)) & 0xff\n\n            expanded_block = self.message_expansion(block, 3)\n\n            for k in range(16):\n                src_row = (k // 2) * 4\n                src_col = (k % 2) * 8\n\n                for i in range(4):\n                    row = a[i]\n                    exp = expanded_block[src_row + i]\n                    for j in range(8):\n                        row[j] ^= exp[src_col + j]\n\n                self.internal_round4(a)\n\n            for i in range(4):\n                a[i][0] ^= (block_counter >> (56 - i * 8)) & 0xff\n                a[i][1] ^= (block_counter >> (24 - i * 8)) & 0xff\n\n            for i in range(4):\n                row = a[i]\n                old = temp[i]\n                for j in range(8):\n                    row[j] ^= old[j]\n\n            return\n\n        def compress64(self, a, block, block_counter):\n            temp = [row[:] for row in a]\n\n            for i in range(8):\n                a[i][0] ^= (block_counter >> (56 - i * 8)) & 0xff\n\n            expanded_block = self.message_expansion(block, 5)\n\n            for k in range(12):\n                src_row = (k // 2) * 8\n                src_col = (k % 2) * 8\n\n                for i in range(8):\n                    row = a[i]\n                    exp = expanded_block[src_row + i]\n                    for j in range(8):\n                        row[j] ^= exp[src_col + j]\n\n                self.internal_round64(a)\n\n            for i in range(8):\n                a[i][0] ^= (block_counter >> (56 - i * 8)) & 0xff\n\n            for i in range(8):\n                row = a[i]\n                old = temp[i]\n                for j in range(8):\n                    row[j] ^= old[j]\n\n            return\n\n        def last_block_permutation(self, a):\n            for i in range(self.n_rows):\n                row = a[i]\n                row[0], row[4] = row[4], row[0]\n                row[1], row[5] = row[5], row[1]\n                row[2], row[6] = row[6], row[2]\n                row[3], row[7] = row[7], row[3]\n            return\n\n        def set_length_and_digest(self, block, databitlen):\n            for i in range(1, 9):\n                block[self.block_size - 11 + i] = (databitlen >> (64 - 8 * i)) & 0xff\n\n            block[self.block_size - 2] = (self.hashbitlen >> 8) & 0xff\n            block[self.block_size - 1] = self.hashbitlen & 0xff\n            return\n\n        def hash_reference_bytes(self, data):\n            if len(data) > ((1 << 64) - 1) // 8:\n                raise ValueError(\"message too long\")\n\n            databitlen = len(data) * 8\n            a = [[0] * 8 for _ in range(self.n_rows)]\n\n            done_length = 0\n            block_count = databitlen // 1024\n\n            while (done_length + 1) <= block_count:\n                start = done_length * self.reference_stride_bytes\n                block = bytes(data[start:start + self.block_size])\n                if len(block) != self.block_size:\n                    raise ValueError(\"internal block underflow\")\n\n                if self.hashbitlen <= 256:\n                    self.compress32(a, block, done_length)\n                else:\n                    self.compress64(a, block, done_length)\n\n                done_length += 1\n\n            lrs = databitlen - 1024 * done_length\n            if (lrs % 8) != 0:\n                raise ValueError(\"only byte-aligned messages are supported\")\n\n            rem_len = lrs // 8\n            rs = bytearray(self.block_size)\n\n            for i in range(rem_len):\n                rs[i] = data[done_length + i]\n\n            if lrs > 0:\n                rs[rem_len] ^= 0x80\n\n                if rem_len < self.block_size - 10:\n                    self.set_length_and_digest(rs, databitlen)\n                    self.last_block_permutation(a)\n\n                    if self.hashbitlen <= 256:\n                        self.compress32(a, bytes(rs), done_length)\n                    else:\n                        self.compress64(a, bytes(rs), done_length)\n                else:\n                    if self.hashbitlen <= 256:\n                        self.compress32(a, bytes(rs), done_length)\n                    else:\n                        self.compress64(a, bytes(rs), done_length)\n\n                    rs = bytearray(self.block_size)\n                    self.last_block_permutation(a)\n                    self.set_length_and_digest(rs, databitlen)\n\n                    if self.hashbitlen <= 256:\n                        self.compress32(a, bytes(rs), done_length + 1)\n                    else:\n                        self.compress64(a, bytes(rs), done_length + 1)\n            else:\n                rs[0] = 0x80\n                self.set_length_and_digest(rs, databitlen)\n                self.last_block_permutation(a)\n\n                if self.hashbitlen <= 256:\n                    self.compress32(a, bytes(rs), done_length)\n                else:\n                    self.compress64(a, bytes(rs), done_length)\n\n            out = bytearray(self.digest_size)\n\n            if self.hashbitlen <= 256:\n                for j in range(self.hashbitlen // 32):\n                    for i in range(4):\n                        out[4 * j + 3 - i] = a[i][j]\n            else:\n                for j in range(self.hashbitlen // 64):\n                    for i in range(8):\n                        out[8 * j + 7 - i] = a[i][j]\n\n            return bytes(out)\n\n        def finalize(self):\n            out = self.hash_reference_bytes(bytes(self.data))\n            return out\n\n    class Cheetah224(CheetahBase):\n        digest_size = 28\n        hashbitlen = 224\n        n_rows = 4\n\n    class Cheetah256(CheetahBase):\n        digest_size = 32\n        hashbitlen = 256\n        n_rows = 4\n\n    class Cheetah384(CheetahBase):\n        digest_size = 48\n        hashbitlen = 384\n        n_rows = 8\n\n    class Cheetah512(CheetahBase):\n        digest_size = 64\n        hashbitlen = 512\n        n_rows = 8\n\n    class CHIBase:\n        K_TABLE = [\n            0x9b05_688c_2b3e_6c1f, 0xdbd9_9e6f_f3c9_0bdc, 0x4dbc_6471_2a5b_b168, 0x767e_27c3_cf76_c8e7,\n            0x21ee_9ac5_ef4c_823a, 0xb36c_cfc1_204a_9bd8, 0x754c_8a7f_b36b_d941, 0xcf20_868f_04a8_25e9,\n            0xabb3_79e0_a883_8bb0, 0x12d8_b70a_5959_e391, 0xb591_68fa_9f69_e181, 0x15c7_d491_8739_f18f,\n            0x4b54_7673_ea8d_68e0, 0x3ced_7326_fcd0_ef81, 0x09f1_d773_0999_8460, 0x1af3_9374_15e9_1f32,\n            0x1f83_d9ab_fb41_bd6b, 0x23c4_654c_2a21_7583, 0x2842_0121_3157_3f2a, 0xa599_16ac_a399_1fca,\n            0xec1b_7c06_fd19_d256, 0x1ec7_85bc_dc8b_af26, 0x69ca_4e0f_f2e6_bdd8, 0xca25_75ee_6c95_0d0e,\n            0x5bcf_66d2_fb3d_99f6, 0x9d6d_08c7_bbca_18f3, 0xeef6_4039_f217_5e83, 0x00ed_5aeb_aa2a_b6e0,\n            0x5040_712f_c29a_d308, 0x6daf_e433_438d_2c43, 0xbd7f_aa3f_06c7_1f15, 0x03b5_aa8c_e9b6_a4dd,\n            0x5be0_cd19_137e_2179, 0x867f_5e3b_7222_1265, 0x43b6_cbe0_d67f_4a20, 0xdb99_d767_cb0e_4933,\n            0xdc45_0dbc_4692_48bd, 0xfe1e_5e48_7610_0d6f, 0xb799_d29e_a173_3137, 0x16ea_7abc_f920_53c4,\n            0xbe3e_ce96_8dba_92ac, 0x1853_8f84_d82c_318b, 0x38d7_9f4e_9c8a_18c0, 0xa8bb_c28f_1271_f1f7,\n            0x2796_e710_67d2_c8cc, 0xde1b_f233_4edb_3ff6, 0xb094_d782_a857_f9c1, 0x639b_484b_0c1d_aed1,\n            0xcbbb_9d5d_c105_9ed8, 0xe773_0eaf_f25e_24a3, 0xf367_f2fc_266a_0373, 0xfe7a_4d34_486d_08ae,\n            0xd416_70a1_3685_1f32, 0x6639_14b6_6b4b_3c23, 0x1b9e_3d77_40a6_0887, 0x63c1_1d86_d446_cb1c,\n            0xd167_d246_9049_d628, 0xdddb_b606_b9a4_9e38, 0x557f_1c8b_ee68_a7f7, 0xf99d_c58b_50f9_24bd,\n            0x205a_cc9f_6535_12a5, 0x67c6_6344_e4ba_b193, 0x1802_6e46_7960_d0c8, 0xa2f5_d84d_aeca_8980,\n            0x629a_292a_367c_d507, 0x98e6_7012_d90c_bb6d, 0xeed7_58d1_d18c_7e35, 0x031c_02e4_437d_c71e,\n            0x79b6_3d64_8219_8eb7, 0x936a_9d7e_8c9e_4b33, 0xb30c_a682_c3e6_c65d, 0xcc44_2382_ba42_62fa,\n            0x5117_9ba5_a1d3_7ff6, 0x7202_bde7_a98e_ea51, 0x2b9f_65d1_df9c_610f, 0xf56b_742b_0af1_ce83,\n            0xf998_9d19_9b75_848b, 0xd142_f19d_8b46_d578, 0x7a75_8051_4d75_ea33, 0xb74f_9690_808e_704d,\n        ]\n\n        INIT224 = [\n            0xbb67_ae85_84ca_a73b, 0x2574_2d70_78b8_3b89, 0x25d8_34cc_53da_4798, 0xc720_a648_6e45_a6e2,\n            0x490b_cfd9_5ef1_5dbd, 0xa993_0aae_1222_8f87,\n        ]\n        INIT256 = [\n            0x3c6e_f372_fe94_f82b, 0xe739_80c0_b9db_9068, 0x2104_4ed7_e744_e4a3, 0xf0d8_d423_a183_1d2a,\n            0x4ecf_e162_a7a4_f6fe, 0x068e_08b6_b7e3_04fe,\n        ]\n        INIT384 = [\n            0xa54f_f53a_5f1d_36f1, 0xcea7_e61f_c37a_20d5, 0x4a77_fe7b_7841_5dfc, 0x8e34_a6fe_8e2d_f92a,\n            0x4e5b_408c_9c97_d4d8, 0x24a0_5eee_2992_2401, 0x5a81_76cf_fc7c_2224, 0xc3ed_ebda_29be_c4c8,\n            0x8a07_4c0f_4d99_9610,\n        ]\n        INIT512 = [\n            0x510e_527f_ade6_82d1, 0xde49_e330_e42b_4cbb, 0x29ba_5a45_5316_e0c6, 0x5507_cd18_e9e5_1e69,\n            0x4f9b_11c8_1009_a030, 0xe3d3_775f_1553_85c6, 0x4892_2163_2788_fb30, 0x4192_1db8_feeb_38c2,\n            0x9af9_4a7c_48bb_d5b6,\n        ]\n\n        mask32 = 0xffff_ffff\n        mask64 = 0xffff_ffff_ffff_ffff\n\n        block_size = None\n        digest_size = None\n        hash_bit_len = None\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.finalized = False\n            self.init_state()\n            if data:\n                self.update(data)\n            return\n\n        def init_state(self):\n            if self.hash_bit_len == 224:\n                self.state = list(self.INIT224)\n            elif self.hash_bit_len == 256:\n                self.state = list(self.INIT256)\n            elif self.hash_bit_len == 384:\n                self.state = list(self.INIT384)\n            elif self.hash_bit_len == 512:\n                self.state = list(self.INIT512)\n            else:\n                raise ValueError(\"invalid hash_bit_len\")\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.finalized = self.finalized\n            other.state = list(self.state)\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block, False)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.output_bytes()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            bit_len = self.msg_len * 8\n            if self.hash_bit_len in (224, 256):\n                length_bytes = 8\n            else:\n                length_bytes = 16\n\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != (self.block_size - length_bytes):\n                self.buf.append(0x00)\n\n            if length_bytes == 16:\n                high = (bit_len >> 64) & self.mask64\n                low = bit_len & self.mask64\n                self.buf.extend(struct.pack(\">Q\", high))\n                self.buf.extend(struct.pack(\">Q\", low))\n            else:\n                self.buf.extend(struct.pack(\">Q\", bit_len & self.mask64))\n\n            while len(self.buf) > self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block, False)\n\n            if len(self.buf) != self.block_size:\n                raise AssertionError(\"invalid final block size\")\n\n            block = bytes(self.buf)\n            self.buf.clear()\n            self.compress(block, True)\n            self.finalized = True\n            return\n\n        def output_bytes(self):\n            out = bytearray()\n\n            if self.hash_bit_len == 224:\n                out.extend(struct.pack(\">Q\", self.state[0]))\n                out.extend(struct.pack(\">Q\", self.state[1]))\n                out.extend(struct.pack(\">Q\", self.state[3]))\n                out.extend(struct.pack(\">I\", (self.state[4] >> 32) & self.mask32))\n                return bytes(out)\n\n            if self.hash_bit_len == 256:\n                out.extend(struct.pack(\">Q\", self.state[0]))\n                out.extend(struct.pack(\">Q\", self.state[1]))\n                out.extend(struct.pack(\">Q\", self.state[3]))\n                out.extend(struct.pack(\">Q\", self.state[4]))\n                return bytes(out)\n\n            if self.hash_bit_len == 384:\n                i = 0\n                while i < 6:\n                    out.extend(struct.pack(\">Q\", self.state[i]))\n                    i += 1\n                return bytes(out)\n\n            if self.hash_bit_len == 512:\n                i = 0\n                while i < 8:\n                    out.extend(struct.pack(\">Q\", self.state[i]))\n                    i += 1\n                return bytes(out)\n\n            raise ValueError(\"invalid hash_bit_len\")\n\n        def rotr32(self, x, r):\n            x &= self.mask32\n            return ((x >> r) | (x << (32 - r))) & self.mask32\n\n        def rotr64(self, x, r):\n            x &= self.mask64\n            return ((x >> r) | (x << (64 - r))) & self.mask64\n\n        def drotr32(self, x, r1, r2):\n            hi = (x >> 32) & self.mask32\n            lo = x & self.mask32\n            return ((self.rotr32(hi, r1) << 32) | self.rotr32(lo, r2)) & self.mask64\n\n        def swap8(self, x):\n            x &= self.mask64\n            x = ((x & 0xffff_ffff_0000_0000) >> 32) | ((x & 0x0000_0000_ffff_ffff) << 32)\n            x = ((x & 0xffff_0000_ffff_0000) >> 16) | ((x & 0x0000_ffff_0000_ffff) << 16)\n            x = ((x & 0xff00_ff00_ff00_ff00) >> 8) | ((x & 0x00ff_00ff_00ff_00ff) << 8)\n            return x\n\n        def swap32(self, x):\n            return self.rotr64(x, 32)\n\n        def map0(self, r, s, t, u):\n            return (\n                (r & (~s) & t & u)\n                | ((~s) & (~t) & (~u))\n                | ((~r) & (~t) & u)\n                | ((~r) & s & t)\n                | (r & (~t) & (~u))\n            ) & self.mask64\n\n        def map1(self, r, s, t, u):\n            return (\n                (r & s & t & (~u))\n                | (r & (~s) & (~t) & (~u))\n                | ((~r) & (~s) & t)\n                | (s & (~t) & u)\n                | ((~r) & u)\n            ) & self.mask64\n\n        def map2(self, r, s, t, u):\n            return (\n                ((~r) & (~s) & t & u)\n                | ((~r) & s & t & (~u))\n                | (s & (~t) & u)\n                | (r & (~t) & (~u))\n                | (r & s & u)\n                | (r & (~s) & (~u))\n            ) & self.mask64\n\n        def map_func(self, r, s, t, u, i):\n            m0 = self.map0(r, s, t, u)\n            m1 = self.map1(r, s, t, u)\n            m2 = self.map2(r, s, t, u)\n            m = [m0, m1, m2]\n            x = m[i % 3]\n            y = m[(i + 1) % 3]\n            z = m[(i + 2) % 3]\n            return x, y, z\n\n        def theta256_0(self, x):\n            return self.drotr32(x, 21, 21) ^ self.drotr32(x, 26, 26) ^ self.drotr32(x, 30, 30)\n\n        def theta256_1(self, x):\n            return self.drotr32(x, 14, 14) ^ self.drotr32(x, 24, 24) ^ self.drotr32(x, 31, 31)\n\n        def mu256_0(self, x):\n            return self.rotr64(x, 36) ^ self.rotr64(x, 18) ^ (x >> 1)\n\n        def mu256_1(self, x):\n            return self.rotr64(x, 59) ^ self.rotr64(x, 37) ^ (x >> 10)\n\n        def message_expansion256(self, w):\n            i = 8\n            while i < 40:\n                w[i] = w[i - 8] ^ self.mu256_0(w[i - 7]) ^ self.mu256_1(w[i - 2])\n                i += 1\n            return\n\n        def premix256(self, a, b, d, e):\n            pre_r = self.drotr32(b, 8, 8) ^ self.drotr32(self.swap32(d), 5, 1)\n            pre_s = a ^ self.drotr32(self.swap32(d), 18, 17)\n            pre_t = self.drotr32(self.swap32(a), 7, 26) ^ self.drotr32(d, 14, 22)\n            pre_u = self.drotr32(a, 17, 12) ^ self.drotr32(self.swap32(e), 2, 23)\n            return pre_r, pre_s, pre_t, pre_u\n\n        def datainput256(self, pre_r, pre_s, pre_t, pre_u, v0, v1):\n            r = pre_r ^ v0\n            s = pre_s ^ v1\n            t = pre_t ^ self.theta256_0(v0)\n            u = pre_u ^ self.theta256_1(v1)\n            return r, s, t, u\n\n        def postmix256(self, x, y, z):\n            xx = x\n            yy = self.swap8(self.drotr32(y, 5, 5))\n            zz = self.swap32(z)\n            aa = self.rotr64((xx + yy) & self.mask64, 16)\n            dd = self.rotr64((yy + zz) & self.mask64, 48)\n            return xx, yy, zz, aa, dd\n\n        def theta512_0(self, x):\n            return self.rotr64(x, 5) ^ self.rotr64(x, 6) ^ self.rotr64(x, 43)\n\n        def theta512_1(self, x):\n            return self.rotr64(x, 20) ^ self.rotr64(x, 30) ^ self.rotr64(x, 49)\n\n        def mu512_0(self, x):\n            return self.rotr64(x, 36) ^ self.rotr64(x, 18) ^ (x >> 1)\n\n        def mu512_1(self, x):\n            return self.rotr64(x, 60) ^ self.rotr64(x, 30) ^ (x >> 3)\n\n        def message_expansion512(self, w):\n            i = 16\n            while i < 80:\n                w[i] = w[i - 16] ^ w[i - 7] ^ self.mu512_0(w[i - 15]) ^ self.mu512_1(w[i - 2])\n                i += 1\n            return\n\n        def premix512(self, a, b, d, e, g, p):\n            pre_r = self.rotr64(b, 11) ^ self.rotr64(d, 8) ^ self.rotr64(g, 13)\n            pre_s = a ^ self.rotr64(d, 21) ^ self.rotr64(g, 29)\n            pre_t = self.rotr64(a, 11) ^ self.rotr64(d, 38) ^ p\n            pre_u = self.rotr64(a, 26) ^ self.rotr64(e, 40) ^ self.rotr64(g, 50)\n            return pre_r, pre_s, pre_t, pre_u\n\n        def datainput512(self, pre_r, pre_s, pre_t, pre_u, v0, v1):\n            r = pre_r ^ v0\n            s = pre_s ^ v1\n            t = pre_t ^ self.theta512_0(v0)\n            u = pre_u ^ self.theta512_1(v1)\n            return r, s, t, u\n\n        def postmix512(self, x, y, z):\n            xx = x\n            yy = self.swap8(self.rotr64(y, 31))\n            zz = self.swap32(z)\n            aa = self.rotr64((xx + yy) & self.mask64, 16)\n            dd = self.rotr64((yy + zz) & self.mask64, 48)\n            gg = (zz + (xx << 1)) & self.mask64\n            return xx, yy, zz, aa, dd, gg\n\n        def compress(self, block, final_flag):\n            if self.hash_bit_len in (224, 256):\n                self.compress256(block, final_flag)\n            else:\n                self.compress512(block, final_flag)\n            return\n\n        def compress256(self, block, final_flag):\n            a, b, c, d, e, f = self.state[:6]\n\n            if final_flag:\n                a = self.rotr64(a, 1)\n                b = self.rotr64(b, 1)\n                c = self.rotr64(c, 1)\n                d = self.rotr64(d, 1)\n                e = self.rotr64(e, 1)\n                f = self.rotr64(f, 1)\n\n            w = [0] * 40\n            i = 0\n            while i < 8:\n                w[i] = struct.unpack(\">Q\", block[i * 8:(i + 1) * 8])[0]\n                i += 1\n\n            self.message_expansion256(w)\n\n            i = 0\n            while i < 20:\n                pre_r, pre_s, pre_t, pre_u = self.premix256(a, b, d, e)\n                v0 = w[2 * i] ^ self.K_TABLE[2 * i]\n                v1 = w[2 * i + 1] ^ self.K_TABLE[2 * i + 1]\n                r, s, t, u = self.datainput256(pre_r, pre_s, pre_t, pre_u, v0, v1)\n                x, y, z = self.map_func(r, s, t, u, i)\n                xx, yy, zz, aa, dd = self.postmix256(x, y, z)\n\n                new_a = aa ^ f\n                new_d = dd ^ c\n\n                f = e\n                e = d\n                d = new_d & self.mask64\n                c = b\n                b = a\n                a = new_a & self.mask64\n                i += 1\n\n            self.state[0] = (self.rotr64(self.state[0], 1) ^ a) & self.mask64\n            self.state[1] = (self.rotr64(self.state[1], 1) ^ b) & self.mask64\n            self.state[2] = (self.rotr64(self.state[2], 1) ^ c) & self.mask64\n            self.state[3] = (self.rotr64(self.state[3], 1) ^ d) & self.mask64\n            self.state[4] = (self.rotr64(self.state[4], 1) ^ e) & self.mask64\n            self.state[5] = (self.rotr64(self.state[5], 1) ^ f) & self.mask64\n            return\n\n        def compress512(self, block, final_flag):\n            a, b, c, d, e, f, g, p, q = self.state[:9]\n\n            if final_flag:\n                a = self.rotr64(a, 1)\n                b = self.rotr64(b, 1)\n                c = self.rotr64(c, 1)\n                d = self.rotr64(d, 1)\n                e = self.rotr64(e, 1)\n                f = self.rotr64(f, 1)\n                g = self.rotr64(g, 1)\n                p = self.rotr64(p, 1)\n                q = self.rotr64(q, 1)\n\n            w = [0] * 80\n            i = 0\n            while i < 16:\n                w[i] = struct.unpack(\">Q\", block[i * 8:(i + 1) * 8])[0]\n                i += 1\n\n            self.message_expansion512(w)\n\n            i = 0\n            while i < 40:\n                pre_r, pre_s, pre_t, pre_u = self.premix512(a, b, d, e, g, p)\n                v0 = w[2 * i] ^ self.K_TABLE[2 * i]\n                v1 = w[2 * i + 1] ^ self.K_TABLE[2 * i + 1]\n                r, s, t, u = self.datainput512(pre_r, pre_s, pre_t, pre_u, v0, v1)\n                x, y, z = self.map_func(r, s, t, u, i)\n                xx, yy, zz, aa, dd, gg = self.postmix512(x, y, z)\n\n                new_a = aa ^ q\n                new_d = dd ^ c\n                new_g = gg ^ f\n\n                q = p\n                p = g\n                g = new_g & self.mask64\n                f = e\n                e = d\n                d = new_d & self.mask64\n                c = b\n                b = a\n                a = new_a & self.mask64\n                i += 1\n\n            self.state[0] = (self.rotr64(self.state[0], 1) ^ a) & self.mask64\n            self.state[1] = (self.rotr64(self.state[1], 1) ^ b) & self.mask64\n            self.state[2] = (self.rotr64(self.state[2], 1) ^ c) & self.mask64\n            self.state[3] = (self.rotr64(self.state[3], 1) ^ d) & self.mask64\n            self.state[4] = (self.rotr64(self.state[4], 1) ^ e) & self.mask64\n            self.state[5] = (self.rotr64(self.state[5], 1) ^ f) & self.mask64\n            self.state[6] = (self.rotr64(self.state[6], 1) ^ g) & self.mask64\n            self.state[7] = (self.rotr64(self.state[7], 1) ^ p) & self.mask64\n            self.state[8] = (self.rotr64(self.state[8], 1) ^ q) & self.mask64\n            return\n\n    class CHI224(CHIBase):\n        block_size = 64\n        digest_size = 28\n        hash_bit_len = 224\n\n    class CHI256(CHIBase):\n        block_size = 64\n        digest_size = 32\n        hash_bit_len = 256\n\n    class CHI384(CHIBase):\n        block_size = 128\n        digest_size = 48\n        hash_bit_len = 384\n\n    class CHI512(CHIBase):\n        block_size = 128\n        digest_size = 64\n        hash_bit_len = 512\n\n    class DCHBase:\n        block_size = 64\n        state_size = 64\n        num_rounds = 4\n        sbox_table = (\n            0x03, 0x02, 0x8d, 0xf7, 0x44, 0xa4, 0x79, 0xb9, 0xae, 0x9e, 0xde, 0x9b, 0x3e, 0xa9, 0x5e, 0x95,\n            0xdb, 0x71, 0xc3, 0x5b, 0xe3, 0x3d, 0x4f, 0x65, 0x93, 0xdd, 0x56, 0x83, 0xa3, 0x80, 0x48, 0x29,\n            0x6f, 0xee, 0x3a, 0x52, 0x63, 0x55, 0x2f, 0x89, 0x73, 0xd3, 0x1c, 0x49, 0x25, 0x88, 0x30, 0x6d,\n            0x4b, 0x8a, 0x6c, 0x2d, 0xa7, 0xc0, 0x43, 0x5d, 0x53, 0x21, 0xcc, 0xaa, 0xa8, 0x0f, 0x16, 0xe2,\n            0x35, 0x5c, 0xfb, 0xd6, 0x91, 0x4d, 0xa5, 0x07, 0x33, 0x8b, 0x28, 0x1d, 0x15, 0x64, 0x46, 0x90,\n            0x3b, 0x20, 0x6b, 0x8f, 0x82, 0x19, 0x26, 0x62, 0x10, 0xc2, 0xc8, 0x60, 0x94, 0x0d, 0x34, 0x42,\n            0x27, 0x54, 0xc9, 0x58, 0xba, 0xc7, 0x14, 0x4e, 0x51, 0x8e, 0xec, 0xb0, 0x23, 0xef, 0x2c, 0x31,\n            0x2b, 0xd2, 0x12, 0xda, 0xea, 0xf8, 0xd9, 0x7a, 0xd8, 0x74, 0x05, 0xb8, 0x87, 0xce, 0xfd, 0xff,\n            0x18, 0x57, 0xa2, 0x1e, 0x7f, 0xcf, 0xe7, 0xb3, 0x4a, 0x32, 0x24, 0x2e, 0x50, 0x6a, 0x01, 0xf6,\n            0x1b, 0xdc, 0x47, 0x4c, 0x98, 0xbf, 0x0c, 0x5f, 0x08, 0xdf, 0xbe, 0x97, 0xaf, 0x0a, 0xc4, 0xa1,\n            0x1f, 0x81, 0x9c, 0xc5, 0x37, 0xc1, 0x45, 0x06, 0xcd, 0x38, 0x0e, 0x3f, 0x9f, 0x0b, 0xbd, 0xb4,\n            0x84, 0xe6, 0xed, 0x68, 0xe8, 0xf1, 0xbc, 0xac, 0xc6, 0x67, 0x04, 0x78, 0x96, 0x99, 0xad, 0xb5,\n            0x11, 0x5a, 0xa6, 0x36, 0x66, 0xbb, 0xa0, 0x9d, 0xd1, 0xf4, 0x61, 0x59, 0x86, 0x7e, 0xab, 0x39,\n            0x2a, 0x72, 0xcb, 0xf5, 0xfa, 0x40, 0xd4, 0xd5, 0x13, 0x70, 0x75, 0x7b, 0x9a, 0x09, 0x1a, 0x92,\n            0x17, 0x3c, 0xe5, 0xf3, 0x85, 0xb2, 0xe1, 0xf2, 0xf9, 0x77, 0xf0, 0xb7, 0x6e, 0x22, 0xb1, 0x69,\n            0xe0, 0xe4, 0xb6, 0xe9, 0x00, 0x8c, 0xd0, 0xca, 0x41, 0xd7, 0xeb, 0x76, 0x7c, 0xfc, 0x7d, 0xfe,\n        )\n\n        gf_table = (\n            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,\n            0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,\n            0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,\n            0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,\n            0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,\n            0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,\n            0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,\n            0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,\n            0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,\n            0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,\n            0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,\n            0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,\n            0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,\n            0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,\n            0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,\n            0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01,\n        )\n\n        gfinv_table = (\n            0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,\n            0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,\n            0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,\n            0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,\n            0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,\n            0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,\n            0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,\n            0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,\n            0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,\n            0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,\n            0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,\n            0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,\n            0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,\n            0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,\n            0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,\n            0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,\n        )\n\n        transform_table = (\n            0x01, 0x02, 0x04, 0x08, 0x99, 0x2f, 0x5e, 0xbc, 0x4f, 0x9e, 0x21, 0x42, 0xdd, 0xa7, 0x53, 0xa6,\n            0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0xd6, 0xb1, 0x7f, 0xfe, 0x92, 0x39, 0x72, 0xe4, 0x45, 0x8a, 0x09,\n            0x12, 0x22, 0x4e, 0x9c, 0x25, 0x4a, 0x44, 0x88, 0x0d, 0x1a, 0xd7, 0xb3, 0x7b, 0xf6, 0x0b, 0x16,\n            0x2c, 0x58, 0x6e, 0x0a, 0x14, 0x28, 0x50, 0x93, 0x3b, 0x76, 0xec, 0xdc, 0xa5, 0x57, 0xae, 0xa1,\n        )\n\n        tables_ready = False\n\n        @classmethod\n        def init_tables(cls):\n            if cls.tables_ready:\n                return\n\n            cls.round_key_ints = tuple(\n                int.from_bytes(bytes(cls.sbox_table[round_index * 64:(round_index + 1) * 64]), \"big\")\n                for round_index in range(cls.num_rounds)\n            )\n\n            gf_table = cls.gf_table\n            gfinv_table = cls.gfinv_table\n            mul_tables = []\n\n            for coeff in cls.transform_table:\n                row = bytearray(256)\n                if coeff != 0:\n                    coeff_log = gfinv_table[coeff]\n                    for value in range(1, 256):\n                        row[value] = gf_table[(gfinv_table[value] + coeff_log) % 255]\n                mul_tables.append(bytes(row))\n\n            round_tables = [[0] * 256 for i in range(64)]\n            sbox_table = cls.sbox_table\n\n            for value in range(256):\n                repeated = int.from_bytes(bytes([sbox_table[value]]) * 64, \"big\")\n                round_tables[0][value] = repeated\n\n                column = bytearray([sbox_table[value]]) * 64\n                for pos in range(1, 64):\n                    for row_index in range(64):\n                        column[row_index] = mul_tables[row_index][column[row_index]]\n                    round_tables[pos][value] = int.from_bytes(column, \"big\")\n\n            cls.round_tables = tuple(tuple(row) for row in round_tables)\n            cls.tables_ready = True\n            return\n\n        def __init__(self, data=b\"\", data_bitlen=None):\n            self.__class__.init_tables()\n\n            self.hashbitlen = self.digest_size * 8\n            self.num_unprocessed = 0\n            self.unprocessed = bytearray(self.block_size)\n            self.curr = bytearray(self.state_size)\n            self.datalen = 0\n            self.p = [bytearray(64), bytearray(64), bytearray(64)]\n            for i in range(63):\n                self.p[0][i] = 64 - i\n            self.p[1][0] = 64\n            self.p[2][0] = 64\n            self.top = [63, 0, 0]\n            self.parity = 1\n            self.small = 0\n            self.count = 0\n            self.move = 0x60\n            if data:\n                if data_bitlen is None:\n                    self.update(data)\n                else:\n                    self.update_bits(data, data_bitlen)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.num_unprocessed = self.num_unprocessed\n            other.unprocessed = bytearray(self.unprocessed)\n            other.curr = bytearray(self.curr)\n            other.datalen = self.datalen\n            other.p = [bytearray(self.p[0]), bytearray(self.p[1]), bytearray(self.p[2])]\n            other.top = list(self.top)\n            other.parity = self.parity\n            other.small = self.small\n            other.count = self.count\n            other.move = self.move\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.update_bits(data, len(data) * 8)\n            return self\n\n        def update_bits(self, data, databitlen):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if databitlen < 0:\n                raise ValueError(\"databitlen must be >= 0\")\n            if databitlen > len(data) * 8:\n                raise ValueError(\"databitlen exceeds input size\")\n            if databitlen == 0:\n                return self\n\n            if isinstance(data, bytes):\n                pass\n            elif isinstance(data, memoryview):\n                data = data.cast(\"B\")\n            else:\n                data = memoryview(data)\n\n            full_bits = self.block_size * 8\n\n            if self.num_unprocessed == 0:\n                self.set_next_sequence_value()\n                self.num_unprocessed = 8\n\n            max_bits = full_bits - self.num_unprocessed\n            if databitlen < max_bits:\n                max_bits = databitlen\n            databitlen -= max_bits\n\n            self.datalen += max_bits\n            dst = self.num_unprocessed >> 3\n            nbytes = (max_bits + 7) >> 3\n            self.unprocessed[dst:dst + nbytes] = data[:nbytes]\n            self.num_unprocessed += max_bits\n            data = data[max_bits >> 3:]\n\n            while self.num_unprocessed == full_bits:\n                self.hash_one_block()\n                if databitlen > 0:\n                    self.set_next_sequence_value()\n                    self.num_unprocessed = 8\n\n                    max_bits = full_bits - 8\n                    if databitlen < max_bits:\n                        max_bits = databitlen\n                    databitlen -= max_bits\n\n                    self.datalen += max_bits\n                    nbytes = (max_bits + 7) >> 3\n                    self.unprocessed[1:1 + nbytes] = data[:nbytes]\n                    self.num_unprocessed = 8 + max_bits\n                    data = data[max_bits >> 3:]\n                else:\n                    self.num_unprocessed = 0\n\n            return self\n\n        def digest(self):\n            copied = self.copy()\n            copied.finalize()\n            return bytes(copied.curr[:self.digest_size])\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.num_unprocessed == 0:\n                self.num_unprocessed = 8\n                self.set_next_sequence_value()\n\n            idx = self.num_unprocessed >> 3\n            rem = self.num_unprocessed & 7\n\n            self.unprocessed[idx] |= 0x80 >> rem\n            self.unprocessed[idx] &= 0xff ^ ((1 << (7 - rem)) - 1)\n            self.unprocessed[idx + 1:self.block_size] = b\"\\x00\" * (self.block_size - (idx + 1))\n\n            self.num_unprocessed += 1\n            if (self.block_size * 8) - self.num_unprocessed < 64:\n                self.hash_one_block()\n                self.unprocessed[:] = b\"\\x00\" * self.block_size\n                self.set_next_sequence_value()\n\n            self.unprocessed[self.block_size - 8:self.block_size] = int(self.datalen).to_bytes(8, \"big\", signed=False)\n            self.unprocessed[0] &= 0x1f\n            self.hash_one_block()\n            return\n\n        def set_next_sequence_value(self):\n            self.unprocessed[0] = self.move ^ self.count\n            self.count += 1\n\n            if self.count == 32:\n                self.count = 0\n\n                if self.parity:\n                    self.move = (self.small + 3 * ((self.small + 1) % 3)) << 5\n                    self.top[self.small] -= 1\n                    self.small += 1\n                    self.small %= 3\n                    self.top[self.small] += 1\n                    self.p[self.small][self.top[self.small]] = 1\n                else:\n                    a = 1\n                    b = 2\n                    if self.small == 1:\n                        a = 0\n                    elif self.small == 2:\n                        b = 0\n\n                    if self.p[b][self.top[b]] > self.p[a][self.top[a]]:\n                        b, a = a, b\n\n                    self.move = (b + 3 * a) << 5\n                    self.top[a] += 1\n                    self.p[a][self.top[a]] = self.p[b][self.top[b]]\n                    self.top[b] -= 1\n\n                self.parity ^= 1\n\n            return\n\n        def hash_one_block(self):\n            unprocessed_int = int.from_bytes(self.unprocessed, \"big\")\n            block = bytes(self.unprocessed)\n            round_tables = self.round_tables\n\n            for round_key_int in self.round_key_ints:\n                acc = 0\n                for pos in range(64):\n                    acc ^= round_tables[pos][block[pos]]\n                acc ^= round_key_int\n                block = acc.to_bytes(64, \"big\")\n\n            final_int = int.from_bytes(self.curr, \"big\") ^ unprocessed_int ^ acc\n            self.curr[:] = final_int.to_bytes(64, \"big\")\n            self.num_unprocessed = 0\n            return\n\n    class DCH224(DCHBase):\n        digest_size = 28\n\n    class DCH256(DCHBase):\n        digest_size = 32\n\n    class DCH384(DCHBase):\n        digest_size = 48\n\n    class DCH512(DCHBase):\n        digest_size = 64\n\n    class DynamicSHABase:\n        round_count = 48\n\n        def __init__(self, data=b\"\"):\n            self.h = list(self.iv)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            out = bytearray()\n            for value in other.h:\n                out.extend(struct.pack(self.pack_fmt, value))\n            return bytes(out[:self.digest_size])\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n\n            if (bit_len % (self.block_size * 8)) > self.length_block_threshold:\n                while len(self.buf) < self.block_size:\n                    self.buf.append(0x00)\n                block = bytes(self.buf[:self.block_size])\n                self.buf.clear()\n                self.compress(block)\n\n            while len(self.buf) < (self.block_size - self.length_size):\n                self.buf.append(0x00)\n\n            self.buf.extend(bit_len.to_bytes(self.length_size, \"big\"))\n\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return\n\n        def rotr(self, value, count):\n            return ((value >> count) | (value << (self.word_size - count))) & self.word_mask\n\n        def calc_d(self, index, w, ch):\n            if (index % 4) == 0:\n                value = w[index % 16] + (ch[0] ^ ch[1] ^ ch[2]) + self.tt[index // 16]\n            elif (index % 4) == 1:\n                value = w[index % 16] + ((ch[0] & ch[1]) ^ ch[2]) + self.tt[index // 16]\n            elif (index % 4) == 2:\n                value = (\n                    w[index % 16]\n                    + ((~(ch[0] | ch[2])) | (ch[0] & (ch[1] ^ ch[2])))\n                    + self.tt[index // 16]\n                )\n            else:\n                value = (\n                    w[index % 16]\n                    + ((~(ch[0] | (ch[1] ^ ch[2]))) | (ch[0] & (~ch[2])))\n                    + self.tt[index // 16]\n                )\n            return value & self.word_mask\n\n        def compress(self, block):\n            w = list(struct.unpack(self.unpack_fmt, block))\n            ch = list(self.h)\n\n            for i in range(self.round_count):\n                temp = (ch[0] + ch[1]) & self.word_mask\n                temp = (temp ^ ch[2]) & self.word_mask\n                temp = (temp + ch[3]) & self.word_mask\n                temp = (temp ^ ch[4]) & self.word_mask\n                temp = (temp + ch[5]) & self.word_mask\n                temp = (temp ^ ch[6]) & self.word_mask\n\n                temp = self.reduce_temp(temp)\n                temp = self.rotr(ch[7], temp)\n\n                d = self.calc_d(i, w, ch)\n\n                ch[7] = ch[6]\n                ch[6] = ch[5]\n                ch[5] = ch[4]\n                ch[4] = ch[3]\n                ch[3] = d\n                ch[2] = ch[1]\n                ch[1] = ch[0]\n                ch[0] = temp\n\n            for i in range(8):\n                self.h[i] = (self.h[i] + ch[i]) & self.word_mask\n            return\n\n    class DynamicSHA32Base(DynamicSHABase):\n        block_size = 64\n        word_size = 32\n        word_mask = 0xffff_ffff\n        length_size = 8\n        length_block_threshold = 512 - 65\n        pack_fmt = \">I\"\n        unpack_fmt = \">16I\"\n        tt = [\n            0x5a82_7999, 0x6ed9_eba1, 0x8f1b_bcdc,\n        ]\n\n        def reduce_temp(self, value):\n            value = ((value >> 17) ^ value) & 0x1f_fff\n            value = ((value >> 10) ^ value) & 0x3ff\n            value = ((value >> 5) ^ value) & 0x1f\n            return value\n\n    class DynamicSHA64Base(DynamicSHABase):\n        block_size = 128\n        word_size = 64\n        word_mask = 0xffff_ffff_ffff_ffff\n        length_size = 16\n        length_block_threshold = 1024 - 129\n        pack_fmt = \">Q\"\n        unpack_fmt = \">16Q\"\n        tt = [\n            0x5a82_7999_50a2_8be6, 0x6ed9_eba1_5c4d_d124, 0x8f1b_bcdc_6d70_3ef3,\n        ]\n\n        def reduce_temp(self, value):\n            value = ((value >> 36) ^ value) & 0xf_ffff_ffff\n            value = ((value >> 18) ^ value) & 0x3f_fff\n            value = ((value >> 12) ^ value) & 0xfff\n            value = ((value >> 6) ^ value) & 0x3f\n            return value\n\n    class DynamicSHA224(DynamicSHA32Base):\n        digest_size = 28\n        iv = [\n            0xc105_9ed8, 0x367c_d507, 0x3070_dd17, 0xf70e_5939,\n            0xffc0_0b31, 0x6858_1511, 0x64f9_8fa7, 0xbefa_4fa4,\n        ]\n\n    class DynamicSHA256(DynamicSHA32Base):\n        digest_size = 32\n        iv = [\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a,\n            0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        ]\n\n    class DynamicSHA384(DynamicSHA64Base):\n        digest_size = 48\n        iv = [\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x8eb4_4a87_6858_1511, 0xdb0c_2e0d_64f9_8fa7, 0x47b5_481d_befa_4fa4,\n        ]\n\n    class DynamicSHA512(DynamicSHA64Base):\n        digest_size = 64\n        iv = [\n            0x6a09_e667_f3bc_c908, 0xbb67_ae85_84ca_a73b, 0x3c6e_f372_fe94_f82b, 0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1, 0x9b05_688c_2b3e_6c1f, 0x1f83_d9ab_fb41_bd6b, 0x5be0_cd19_137e_2179,\n        ]\n\n    class DynamicSHA2Base:\n        def __init__(self, data=b\"\"):\n            self.state = list(self.iv)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.state = list(self.state)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.state_to_bytes()[:self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != (self.block_size - self.length_size):\n                self.buf.append(0x00)\n            self.buf.extend(bit_len.to_bytes(self.length_size, \"big\"))\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return\n\n        def rotr(self, x, n):\n            n %= self.word_bits\n            return ((x >> n) | (x << (self.word_bits - n))) & self.mask\n\n        def state_to_bytes(self):\n            out = bytearray()\n            for value in self.state:\n                out.extend(value.to_bytes(self.word_bytes, \"big\"))\n            return bytes(out)\n\n        def g0(self, x, y, z):\n            return x ^ y ^ z\n\n        def g1(self, x, y, z):\n            return (x & y) ^ z\n\n        def g2(self, x, y, z):\n            return (~(x | z)) | (x & (y ^ z))\n\n        def g3(self, x, y, z):\n            return (~(x | (y ^ z))) | (x & (~z))\n\n        def unpack_block(self, block):\n            return list(struct.unpack(self.unpack_fmt, block))\n\n        def apply_g(self, selector, x, y, z):\n            if selector == 0:\n                return self.g0(x, y, z)\n            if selector == 1:\n                return self.g1(x, y, z)\n            if selector == 2:\n                return self.g2(x, y, z)\n            return self.g3(x, y, z)\n\n        def sum1(self, ch):\n            return ((((((ch[0] ^ ch[1]) + ch[2]) ^ ch[3]) + ch[4]) ^ ch[5]) + ch[6]) ^ ch[7]\n\n        def sum2(self, ch):\n            return (((((ch[0] + ch[1]) ^ ch[2]) + ch[3]) ^ ch[4]) + ch[5]) ^ ch[6]\n\n        def compress(self, block):\n            w = self.unpack_block(block)\n            ch = list(self.state)\n            init = list(self.state)\n\n            for i in range(8):\n                for i1 in range(0, 9, 8):\n                    word = w[i + i1]\n\n                    r0, r1, r2 = self.rotate_amounts_first(word)\n                    temp = self.sum1(ch) & self.mask\n                    temp = self.rotr(temp, r0)\n                    ch[7] = ch[6]\n                    ch[6] = self.update_ch6_first(ch, word)\n                    ch[5] = self.update_ch5_first(ch, w, i, i1, word)\n                    ch[4] = self.rotr(ch[3], r2)\n\n                    selector = self.selector_first(word, i)\n                    ch[3] = (w[((i + 2) % 8) + i1] + self.apply_g(selector, ch[0], ch[1], ch[2])) & self.mask\n                    ch[2] = self.update_ch2_first(ch, word)\n                    ch[1] = ch[0]\n                    ch[0] = (temp + w[((i + 1) % 8) + i1]) & self.mask\n\n                    r3, r4, _r5, r6 = self.rotate_amounts_second(word)\n                    temp = self.sum1(ch) & self.mask\n                    temp = self.rotr(temp, r3)\n                    ch[7] = (ch[6] + w[((i + 7) % 8) + i1]) & self.mask\n                    ch[6] = self.rotr(ch[5], r4)\n                    ch[5] = self.update_ch5_second(ch, w, i, i1, word)\n                    ch[4] = self.rotr(ch[3], r6)\n\n                    selector = self.selector_second(word, i)\n                    ch[3] = (w[((i + 5) % 8) + i1] + self.apply_g(selector, ch[0], ch[1], ch[2])) & self.mask\n                    ch[2] = (ch[1] + word) & self.mask\n                    ch[1] = self.update_ch1_second(ch, word)\n                    ch[0] = (temp + w[((i + 4) % 8) + i1]) & self.mask\n\n                if i == 0:\n                    for _ in range(9):\n                        ch = self.mix_round(ch)\n\n            for i in range(8):\n                self.state[i] = (init[i] + ch[i]) & self.mask\n            return\n\n    class DynamicSHA2_32Base(DynamicSHA2Base):\n        block_size = 64\n        word_bits = 32\n        word_bytes = 4\n        length_size = 8\n        mask = 0xffff_ffff\n        unpack_fmt = \">16I\"\n\n        def selector_first(self, word, i):\n            return word >> 30\n\n        def selector_second(self, word, i):\n            return i % 4\n\n        def rotate_amounts_first(self, word):\n            return (\n                word & 31,\n                (word >> 5) & 31,\n                (word >> 10) & 31,\n            )\n\n        def rotate_amounts_second(self, word):\n            return (\n                (word >> 15) & 31,\n                (word >> 20) & 31,\n                (word >> 25) & 31,\n                (word >> 25) & 31,\n            )\n\n        def update_ch6_first(self, ch, word):\n            return self.rotr(ch[5], (word >> 5) & 31)\n\n        def update_ch5_first(self, ch, w, i, i1, word):\n            return (ch[4] + w[((i + 3) % 8) + i1]) & self.mask\n\n        def update_ch2_first(self, ch, word):\n            return ch[1]\n\n        def update_ch5_second(self, ch, w, i, i1, word):\n            return (ch[4] + w[((i + 6) % 8) + i1]) & self.mask\n\n        def update_ch1_second(self, ch, word):\n            return ch[0]\n\n        def mix_round(self, ch):\n            temp = self.sum2(ch) & self.mask\n            temp = ((temp >> 17) ^ temp) & 0x1_ffff\n            temp = ((temp >> 10) ^ temp) & 0x3ff\n            temp = ((temp >> 5) ^ temp) & 0x1f\n            temp = self.rotr(ch[7], temp)\n            return [temp, ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], ch[6]]\n\n    class DynamicSHA2_64Base(DynamicSHA2Base):\n        block_size = 128\n        word_bits = 64\n        word_bytes = 8\n        length_size = 16\n        mask = 0xffff_ffff_ffff_ffff\n        unpack_fmt = \">16Q\"\n\n        def selector_first(self, word, i):\n            return word >> 62\n\n        def selector_second(self, word, i):\n            return (word >> 60) & 0x3\n\n        def rotate_amounts_first(self, word):\n            return (\n                word & 0x3f,\n                (word >> 6) & 0x3f,\n                (word >> 18) & 0x3f,\n            )\n\n        def rotate_amounts_second(self, word):\n            return (\n                (word >> 30) & 0x3f,\n                (word >> 36) & 0x3f,\n                (word >> 48) & 0x3f,\n                (word >> 48) & 0x3f,\n            )\n\n        def update_ch6_first(self, ch, word):\n            return self.rotr(ch[5], (word >> 6) & 0x3f)\n\n        def update_ch5_first(self, ch, w, i, i1, word):\n            return (self.rotr(ch[4], (word >> 12) & 0x3f) + w[((i + 3) % 8) + i1]) & self.mask\n\n        def update_ch2_first(self, ch, word):\n            return self.rotr(ch[1], (word >> 24) & 0x3f)\n\n        def update_ch5_second(self, ch, w, i, i1, word):\n            return (self.rotr(ch[4], (word >> 42) & 0x3f) + w[((i + 6) % 8) + i1]) & self.mask\n\n        def update_ch1_second(self, ch, word):\n            return self.rotr(ch[0], (word >> 54) & 0x3f)\n\n        def mix_round(self, ch):\n            temp = self.sum2(ch) & self.mask\n            temp = ((temp >> 36) ^ temp) & 0xf_ffff_ffff\n            temp = ((temp >> 18) ^ temp) & 0x3_ffff\n            temp = ((temp >> 12) ^ temp) & 0xfff\n            temp = ((temp >> 6) ^ temp) & 0x3f\n            temp = self.rotr(ch[7], temp)\n            return [temp, ch[0], ch[1], ch[2], ch[3], ch[4], ch[5], ch[6]]\n\n    class DynamicSHA2_224(DynamicSHA2_32Base):\n        digest_size = 28\n        iv = (\n            0xc105_9ed8, 0x367c_d507, 0x3070_dd17, 0xf70e_5939,\n            0xffc0_0b31, 0x6858_1511, 0x64f9_8fa7, 0xbefa_4fa4,\n        )\n\n    class DynamicSHA2_256(DynamicSHA2_32Base):\n        digest_size = 32\n        iv = (\n            0x6a09_e667, 0xbb67_ae85, 0x3c6e_f372, 0xa54f_f53a,\n            0x510e_527f, 0x9b05_688c, 0x1f83_d9ab, 0x5be0_cd19,\n        )\n\n    class DynamicSHA2_384(DynamicSHA2_64Base):\n        digest_size = 48\n        iv = (\n            0xcbbb_9d5d_c105_9ed8, 0x629a_292a_367c_d507, 0x9159_015a_3070_dd17, 0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31, 0x8eb4_4a87_6858_1511, 0xdb0c_2e0d_64f9_8fa7, 0x47b5_481d_befa_4fa4,\n        )\n\n    class DynamicSHA2_512(DynamicSHA2_64Base):\n        digest_size = 64\n        iv = (\n            0x6a09_e667_f3bc_c908, 0xbb67_ae85_84ca_a73b, 0x3c6e_f372_fe94_f82b, 0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1, 0x9b05_688c_2b3e_6c1f, 0x1f83_d9ab_fb41_bd6b, 0x5be0_cd19_137e_2179,\n        )\n\n    class ECOHBase:\n        C_TEMPLATE = r\"\"\"\n        #include <stdint.h>\n        #include <string.h>\n        #include <stdlib.h>\n\n        #define NLIMBS          REPLACE_NLIMBS\n        #define GF_M            REPLACE_M\n        #define GF_K0           REPLACE_K0\n        #define GF_K1           REPLACE_K1\n        #define GF_K2           REPLACE_K2\n        #define GF_NKS          REPLACE_NKS\n        #define HASH_BLOCK_SIZE REPLACE_BLOCK_SIZE\n        #define CLEN_BITS       REPLACE_CLEN_BITS\n        #define YP_BIT          REPLACE_YP_BIT\n        #define COUNTER_LIMBS   REPLACE_COUNTER_LIMBS\n        #define CHECKSUM_LIMBS  REPLACE_CHECKSUM_LIMBS\n\n        typedef uint64_t Limb;\n        typedef Limb GFElem[NLIMBS];\n        typedef Limb GFElem2[NLIMBS * 2];\n\n        static void gfe_zero(GFElem r) {\n            memset(r, 0, sizeof(GFElem));\n        }\n\n        static void gfe_copy(GFElem dst, const GFElem src) {\n            memcpy(dst, src, sizeof(GFElem));\n        }\n\n        static int gfe_is_zero(const GFElem a) {\n            for (int i = 0; i < NLIMBS; i++) if (a[i]) return 0;\n            return 1;\n        }\n\n        static int gfe_eq(const GFElem a, const GFElem b) {\n            for (int i = 0; i < NLIMBS; i++) if (a[i] != b[i]) return 0;\n            return 1;\n        }\n\n        static int gf2_getbit(const Limb *a, int i) {\n            return (int)((a[i >> 6] >> (i & 63)) & 1);\n        }\n\n        static void limbs_from_bytes_be(Limb *dst, int dst_limbs, const uint8_t *src, int len) {\n            memset(dst, 0, sizeof(Limb) * dst_limbs);\n            for (int bi = 0; bi < len; bi++) {\n                int src_idx = len - 1 - bi;\n                dst[bi >> 3] |= (Limb)src[src_idx] << ((bi & 7) * 8);\n            }\n        }\n\n        static void limbs_xor_shifted(Limb *dst, int dst_limbs, const Limb *src, int src_limbs, int bit_offset) {\n            int wshift = bit_offset >> 6;\n            int bshift = bit_offset & 63;\n            for (int i = 0; i < src_limbs; i++) {\n                int dst_idx = i + wshift;\n                if (dst_idx >= dst_limbs) {\n                    break;\n                }\n                dst[dst_idx] ^= src[i] << bshift;\n                if (bshift != 0 && dst_idx + 1 < dst_limbs) {\n                    dst[dst_idx + 1] ^= src[i] >> (64 - bshift);\n                }\n            }\n        }\n\n        static void limbs_add_small(Limb *a, int n, Limb v) {\n            Limb carry = v;\n            for (int i = 0; i < n && carry; i++) {\n                Limb old = a[i];\n                a[i] += carry;\n                carry = (a[i] < old) ? 1 : 0;\n            }\n        }\n\n        static void limbs_rshift1(Limb *dst, const Limb *src, int n) {\n            Limb carry = 0;\n            for (int i = n - 1; i >= 0; i--) {\n                Limb next_carry = src[i] << 63;\n                dst[i] = (src[i] >> 1) | carry;\n                carry = next_carry;\n            }\n        }\n\n        static void gf_reduce_wide(GFElem r, const GFElem2 x) {\n            Limb t[NLIMBS * 2];\n            memcpy(t, x, sizeof(t));\n\n            for (int bit = (NLIMBS * 2 * 64) - 1; bit >= GF_M; bit--) {\n                if (!gf2_getbit(t, bit))\n                    continue;\n                t[bit >> 6] ^= (Limb)1 << (bit & 63);\n                int d = bit - GF_M;\n                t[d >> 6] ^= (Limb)1 << (d & 63);\n                int pos;\n                pos = d + GF_K0;\n                t[pos >> 6] ^= (Limb)1 << (pos & 63);\n        #if GF_NKS >= 2\n                pos = d + GF_K1;\n                t[pos >> 6] ^= (Limb)1 << (pos & 63);\n        #endif\n        #if GF_NKS >= 3\n                pos = d + GF_K2;\n                t[pos >> 6] ^= (Limb)1 << (pos & 63);\n        #endif\n            }\n            memcpy(r, t, sizeof(GFElem));\n        }\n\n        void gf_mul(GFElem r, const GFElem a, const GFElem b)\n        {\n            GFElem2 acc;\n            memset(acc, 0, sizeof(acc));\n\n            for (int wi = 0; wi < NLIMBS; wi++) {\n                Limb bw = b[wi];\n                if (!bw) {\n                    continue;\n                }\n\n                for (int bit = 0; bit < 64; bit++) {\n                    if (((bw >> bit) & 1) == 0) {\n                        continue;\n                    }\n\n                    int shift = wi * 64 + bit;\n                    int wshift = shift >> 6;\n                    int bshift = shift & 63;\n\n                    for (int j = 0; j < NLIMBS; j++) {\n                        int dst = j + wshift;\n                        if (dst >= NLIMBS * 2) {\n                            break;\n                        }\n                        acc[dst] ^= a[j] << bshift;\n                        if (bshift != 0 && dst + 1 < NLIMBS * 2) {\n                            acc[dst + 1] ^= a[j] >> (64 - bshift);\n                        }\n                    }\n                }\n            }\n            gf_reduce_wide(r, acc);\n        }\n\n        void gf_sqr(GFElem r, const GFElem a)\n        {\n            GFElem2 wide;\n            memset(wide, 0, sizeof(wide));\n            for (int i = 0; i < NLIMBS; i++) {\n                Limb w = a[i];\n                Limb lo = 0, hi = 0;\n                for (int b = 0; b < 32; b++) {\n                    if ((w >> b) & 1) lo |= (Limb)1 << (b * 2);\n                }\n                for (int b = 0; b < 32; b++) {\n                    if ((w >> (b + 32)) & 1) hi |= (Limb)1 << (b * 2);\n                }\n                wide[i * 2] ^= lo;\n                wide[i * 2 + 1] ^= hi;\n            }\n            gf_reduce_wide(r, wide);\n        }\n\n        void gf_inv(GFElem r, const GFElem a) {\n            if (gfe_is_zero(a)) {\n                gfe_zero(r);\n                return;\n            }\n\n            Limb mod[NLIMBS + 1];\n            memset(mod, 0, sizeof(mod));\n            mod[GF_M >> 6] |= (Limb)1 << (GF_M & 63);\n            {\n                int pos;\n                pos = GF_K0; mod[pos >> 6] |= (Limb)1 << (pos & 63);\n        #if GF_NKS >= 2\n                pos = GF_K1; mod[pos >> 6] |= (Limb)1 << (pos & 63);\n        #endif\n        #if GF_NKS >= 3\n                pos = GF_K2; mod[pos >> 6] |= (Limb)1 << (pos & 63);\n        #endif\n                mod[0] |= 1;\n            }\n\n            Limb u[NLIMBS + 1], v[NLIMBS + 1];\n            Limb g1[NLIMBS + 1], g2[NLIMBS + 1];\n            memset(u, 0, sizeof(u));  memcpy(u, a, sizeof(GFElem));\n            memcpy(v, mod, sizeof(v));\n            memset(g1, 0, sizeof(g1)); g1[0] = 1;\n            memset(g2, 0, sizeof(g2));\n\n            while (1) {\n                int u_is_one = (u[0] == 1);\n                for (int i = 1; i <= NLIMBS; i++) if (u[i]) { u_is_one = 0; break; }\n                if (u_is_one) break;\n\n                int lu = 0, lv = 0;\n                for (int i = NLIMBS; i >= 0; i--) {\n                    if (u[i] && !lu) {\n                        Limb w = u[i]; int b = 0;\n                        while (w) { b++; w >>= 1; }\n                        lu = i * 64 + b;\n                    }\n                    if (v[i] && !lv) {\n                        Limb w = v[i]; int b = 0;\n                        while (w) { b++; w >>= 1; }\n                        lv = i * 64 + b;\n                    }\n                    if (lu && lv) break;\n                }\n\n                int j = lu - lv;\n                if (j < 0) {\n                    Limb tmpbuf[NLIMBS + 1];\n                    memcpy(tmpbuf, u, sizeof(tmpbuf));\n                    memcpy(u, v, sizeof(tmpbuf));\n                    memcpy(v, tmpbuf, sizeof(tmpbuf));\n                    memcpy(tmpbuf, g1, sizeof(tmpbuf));\n                    memcpy(g1, g2, sizeof(tmpbuf));\n                    memcpy(g2, tmpbuf, sizeof(tmpbuf));\n                    j = -j;\n                }\n\n                int wshift = j >> 6, bshift = j & 63;\n                for (int i = NLIMBS; i >= 0; i--) {\n                    if (i - wshift >= 0)\n                        u[i] ^= v[i - wshift] << bshift;\n                    if (bshift && i - wshift - 1 >= 0)\n                        u[i] ^= v[i - wshift - 1] >> (64 - bshift);\n                }\n                for (int i = NLIMBS; i >= 0; i--) {\n                    if (i - wshift >= 0)\n                        g1[i] ^= g2[i - wshift] << bshift;\n                    if (bshift && i - wshift - 1 >= 0)\n                        g1[i] ^= g2[i - wshift - 1] >> (64 - bshift);\n                }\n            }\n\n            GFElem2 wide;\n            memset(wide, 0, sizeof(wide));\n            memcpy(wide, g1, (NLIMBS + 1) * sizeof(Limb));\n            gf_reduce_wide(r, wide);\n        }\n\n        void half_trace(GFElem r, const GFElem a) {\n            GFElem z, tmp;\n            gfe_copy(z, a);\n            int limit = (GF_M - 1) / 2;\n            for (int i = 0; i < limit; i++) {\n                gf_sqr(tmp, z);\n                gf_sqr(z, tmp);\n                for (int j = 0; j < NLIMBS; j++) z[j] ^= a[j];\n            }\n            gfe_copy(r, z);\n        }\n\n        int point_decompress(\n            GFElem rx, GFElem ry, const GFElem x_in, const GFElem curve_a, const GFElem curve_b, int yp_bit)\n        {\n            GFElem x;\n            gfe_copy(x, x_in);\n            if (gfe_is_zero(x)) return 0;\n\n            GFElem inv_x, sq_inv_x, b_term, rhs;\n            gf_inv(inv_x, x);\n            gf_sqr(sq_inv_x, inv_x);\n            gf_mul(b_term, curve_b, sq_inv_x);\n            for (int i = 0; i < NLIMBS; i++)\n                rhs[i] = x[i] ^ curve_a[i] ^ b_term[i];\n\n            GFElem z;\n            half_trace(z, rhs);\n\n            GFElem z2, lhs;\n            gf_sqr(z2, z);\n            for (int i = 0; i < NLIMBS; i++) lhs[i] = z2[i] ^ z[i];\n            if (!gfe_eq(lhs, rhs)) return 0;\n\n            int yp = gf2_getbit(x, yp_bit) & 1;\n            if ((z[0] & 1) != (Limb)yp) z[0] ^= 1;\n\n            gfe_copy(rx, x);\n            gf_mul(ry, x, z);\n            return 1;\n        }\n\n        int point_add(\n            GFElem rx, GFElem ry, const GFElem p1x, const GFElem p1y, int p1inf,\n            const GFElem p2x, const GFElem p2y, int p2inf, const GFElem curve_a)\n        {\n            if (p1inf) { gfe_copy(rx, p2x); gfe_copy(ry, p2y); return p2inf; }\n            if (p2inf) { gfe_copy(rx, p1x); gfe_copy(ry, p1y); return 0; }\n\n            if (gfe_eq(p1x, p2x)) {\n                if (gfe_eq(p1y, p2y)) {\n                    if (gfe_is_zero(p1x)) { gfe_zero(rx); gfe_zero(ry); return 1; }\n                    GFElem inv_x1, lam, lam_sq, x3, y3, tmp;\n                    gf_inv(inv_x1, p1x);\n                    gf_mul(lam, inv_x1, p1y);\n                    for (int i = 0; i < NLIMBS; i++) lam[i] ^= p1x[i];\n                    gf_sqr(lam_sq, lam);\n                    for (int i = 0; i < NLIMBS; i++)\n                        x3[i] = lam_sq[i] ^ lam[i] ^ curve_a[i];\n                    gf_sqr(tmp, p1x);\n                    GFElem lam1;\n                    gfe_copy(lam1, lam);\n                    lam1[0] ^= 1;\n                    gf_mul(y3, x3, lam1);\n                    for (int i = 0; i < NLIMBS; i++) y3[i] ^= tmp[i];\n                    gfe_copy(rx, x3); gfe_copy(ry, y3);\n                    return 0;\n                }\n                gfe_zero(rx); gfe_zero(ry); return 1;\n            }\n\n            GFElem dx, dy, inv_dx, lam, lam_sq, x3, y3, tmp;\n            for (int i = 0; i < NLIMBS; i++) dx[i] = p1x[i] ^ p2x[i];\n            for (int i = 0; i < NLIMBS; i++) dy[i] = p1y[i] ^ p2y[i];\n            gf_inv(inv_dx, dx);\n            gf_mul(lam, inv_dx, dy);\n            gf_sqr(lam_sq, lam);\n            for (int i = 0; i < NLIMBS; i++)\n                x3[i] = lam_sq[i] ^ lam[i] ^ p1x[i] ^ p2x[i] ^ curve_a[i];\n            GFElem x3_p1x;\n            for (int i = 0; i < NLIMBS; i++) x3_p1x[i] = x3[i] ^ p1x[i];\n            gf_mul(tmp, lam, x3_p1x);\n            for (int i = 0; i < NLIMBS; i++) y3[i] = tmp[i] ^ x3[i] ^ p1y[i];\n            gfe_copy(rx, x3); gfe_copy(ry, y3);\n            return 0;\n        }\n\n        int scalar_mul(\n            GFElem rx, GFElem ry, const uint8_t *kbytes, int klen,\n            const GFElem px, const GFElem py, const GFElem curve_a)\n        {\n            GFElem ax, ay, qx, qy;\n            gfe_copy(ax, px); gfe_copy(ay, py);\n            gfe_zero(qx); gfe_zero(qy);\n            int qinf = 1;\n\n            int total_bits = klen * 8;\n            for (int i = 0; i < total_bits; i++) {\n                int byte_idx = klen - 1 - (i >> 3);\n                int bit = (kbytes[byte_idx] >> (i & 7)) & 1;\n                if (bit) {\n                    GFElem tx, ty;\n                    int tinf = point_add(tx, ty, qx, qy, qinf, ax, ay, 0, curve_a);\n                    gfe_copy(qx, tx); gfe_copy(qy, ty); qinf = tinf;\n                }\n                if (i + 1 < total_bits) {\n                    GFElem tx, ty;\n                    int ainf = point_add(tx, ty, ax, ay, 0, ax, ay, 0, curve_a);\n                    gfe_copy(ax, tx); gfe_copy(ay, ty);\n                    if (ainf) break;\n                }\n            }\n            gfe_copy(rx, qx); gfe_copy(ry, qy);\n            return !qinf;\n        }\n\n        int scalar_mul_limbs(\n            GFElem rx, GFElem ry, const GFElem k,\n            const GFElem px, const GFElem py, const GFElem curve_a)\n        {\n            GFElem ax, ay, qx, qy;\n            gfe_copy(ax, px); gfe_copy(ay, py);\n            gfe_zero(qx); gfe_zero(qy);\n            int qinf = 1;\n\n            for (int i = 0; i < NLIMBS * 64; i++) {\n                if (gf2_getbit(k, i)) {\n                    GFElem tx, ty;\n                    int tinf = point_add(tx, ty, qx, qy, qinf, ax, ay, 0, curve_a);\n                    gfe_copy(qx, tx); gfe_copy(qy, ty); qinf = tinf;\n                }\n                if (i + 1 < NLIMBS * 64) {\n                    GFElem tx, ty;\n                    int ainf = point_add(tx, ty, ax, ay, 0, ax, ay, 0, curve_a);\n                    gfe_copy(ax, tx); gfe_copy(ay, ty);\n                    if (ainf) break;\n                }\n            }\n            gfe_copy(rx, qx); gfe_copy(ry, qy);\n            return !qinf;\n        }\n\n        int decompress_search(\n            GFElem rx, GFElem ry, const GFElem x_in,\n            const GFElem curve_a, const GFElem curve_b, int yp_bit)\n        {\n            GFElem x;\n            gfe_copy(x, x_in);\n            while (1) {\n                if (point_decompress(rx, ry, x, curve_a, curve_b, yp_bit)) {\n                    return 1;\n                }\n                limbs_add_small(x, NLIMBS, 2);\n            }\n        }\n\n        void process_block_state(\n            GFElem qx, GFElem qy, int *qinf,\n            Limb *checksum, Limb *counter,\n            const uint8_t *block,\n            const GFElem curve_a, const GFElem curve_b)\n        {\n            Limb blk[CHECKSUM_LIMBS];\n            GFElem x, px, py;\n\n            limbs_from_bytes_be(blk, CHECKSUM_LIMBS, block, HASH_BLOCK_SIZE);\n            for (int i = 0; i < CHECKSUM_LIMBS; i++) {\n                checksum[i] ^= blk[i];\n            }\n\n            gfe_zero(x);\n            x[0] = 1;\n            limbs_xor_shifted(x, NLIMBS, counter, COUNTER_LIMBS, CLEN_BITS);\n            limbs_xor_shifted(x, NLIMBS, blk, CHECKSUM_LIMBS, CLEN_BITS * 2);\n\n            decompress_search(px, py, x, curve_a, curve_b, YP_BIT);\n            *qinf = point_add(qx, qy, qx, qy, *qinf, px, py, 0, curve_a);\n            limbs_add_small(counter, COUNTER_LIMBS, 1);\n        }\n\n        void process_blocks_state(\n            GFElem qx, GFElem qy, int *qinf, Limb *checksum, Limb *counter,\n            const uint8_t *blocks, int nblocks, const GFElem curve_a, const GFElem curve_b)\n        {\n            for (int i = 0; i < nblocks; i++) {\n                process_block_state(\n                    qx, qy, qinf, checksum, counter,\n                    blocks + (i * HASH_BLOCK_SIZE),\n                    curve_a, curve_b\n                );\n            }\n        }\n\n        int finalize_hash_state(\n            GFElem qx, GFElem qy, int *qinf, Limb *checksum, Limb *counter,\n            const uint8_t *tail, int tail_len, const Limb *msg_len_bits,\n            const GFElem curve_a, const GFElem curve_b, const GFElem gx, const GFElem gy)\n        {\n            uint8_t block[HASH_BLOCK_SIZE];\n            GFElem x, px, py, sx, sy, k;\n\n            memset(block, 0, sizeof(block));\n            if (tail_len > 0) {\n                memcpy(block, tail, tail_len);\n            }\n            block[tail_len] = 0x80;\n\n            process_block_state(qx, qy, qinf, checksum, counter, block, curve_a, curve_b);\n\n            gfe_zero(x);\n            x[0] = 1;\n            limbs_xor_shifted(x, NLIMBS, msg_len_bits, COUNTER_LIMBS, CLEN_BITS);\n            limbs_xor_shifted(x, NLIMBS, checksum, CHECKSUM_LIMBS, CLEN_BITS * 2);\n\n            decompress_search(px, py, x, curve_a, curve_b, YP_BIT);\n            *qinf = point_add(qx, qy, qx, qy, *qinf, px, py, 0, curve_a);\n            if (*qinf) {\n                return 0;\n            }\n\n            limbs_rshift1(k, qx, NLIMBS);\n            if (!scalar_mul_limbs(sx, sy, k, gx, gy, curve_a)) {\n                return 0;\n            }\n            *qinf = point_add(qx, qy, qx, qy, *qinf, sx, sy, 0, curve_a);\n            return !*qinf;\n        }\n        \"\"\"\n        DEF_TEMPLATE = r\"\"\"\n        void gf_mul(uint64_t *r, const uint64_t *a, const uint64_t *b);\n        void gf_sqr(uint64_t *r, const uint64_t *a);\n        void gf_inv(uint64_t *r, const uint64_t *a);\n        void half_trace(uint64_t *r, const uint64_t *a);\n        int  point_decompress(uint64_t *rx, uint64_t *ry, const uint64_t *x_in,\n            const uint64_t *curve_a, const uint64_t *curve_b, int yp_bit);\n        int  point_add(uint64_t *rx, uint64_t *ry, const uint64_t *p1x, const uint64_t *p1y, int p1inf,\n            const uint64_t *p2x, const uint64_t *p2y, int p2inf, const uint64_t *curve_a);\n        int  scalar_mul(uint64_t *rx, uint64_t *ry, const uint8_t *kbytes, int klen,\n            const uint64_t *px, const uint64_t *py, const uint64_t *curve_a);\n        void process_block_state(uint64_t *qx, uint64_t *qy, int *qinf, uint64_t *checksum, uint64_t *counter,\n            const uint8_t *block, const uint64_t *curve_a, const uint64_t *curve_b);\n        void process_blocks_state(uint64_t *qx, uint64_t *qy, int *qinf, uint64_t *checksum, uint64_t *counter,\n            const uint8_t *blocks, int nblocks, const uint64_t *curve_a, const uint64_t *curve_b);\n        int  finalize_hash_state(uint64_t *qx, uint64_t *qy, int *qinf, uint64_t *checksum, uint64_t *counter,\n            const uint8_t *tail, int tail_len, const uint64_t *msg_len_bits,\n            const uint64_t *curve_a, const uint64_t *curve_b, const uint64_t *gx, const uint64_t *gy);\n        \"\"\"\n\n        class ECOHCurve:\n            def __init__(self, m, ks, a, b, gx, gy):\n                self.m = m\n                self.ks = tuple(ks)\n                self.a = a\n                self.b = b\n                self.g = (gx, gy)\n\n                self.modulus = 1 << m\n                for k in self.ks:\n                    self.modulus |= 1 << k\n                self.modulus |= 1\n\n                self.low_mask = (1 << m) - 1\n                self.square_table = self.make_square_table()\n                return\n\n            def make_square_table(self):\n                table = []\n                for value in range(256):\n                    out = 0\n                    for bit in range(8):\n                        if value & (1 << bit):\n                            out |= 1 << (bit * 2)\n                    table.append(out)\n                return table\n\n        def init_cffi_backend(self):\n            try:\n                import cffi\n                import warnings\n            except ImportError:\n                self.USE_CFFI = False\n                return\n\n            key = self.__class__\n            base_class = Hash.ECOHBase\n\n            if not hasattr(base_class, \"cffi_cache\"):\n                base_class.cffi_cache = {}\n\n            # fast return\n            if key in base_class.cffi_cache:\n                self.cffi = base_class.cffi_cache[key]\n                self.USE_CFFI = True\n                return\n\n            # ffi, lib\n            ks_padded = list(self.curve.ks) + [0] * (3 - len(self.curve.ks))\n            nlimbs = (self.curve.m + 63) // 64 + 1  # one extra limb for overflow headroom\n            counter_limbs = (self.clen_bits + 63) // 64\n            checksum_limbs = self.block_size // 8\n            C_TEMPLATE = base_class.C_TEMPLATE\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_NLIMBS\", f\"({nlimbs})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_M\", f\"({self.curve.m})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_K0\", f\"({ks_padded[0]})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_K1\", f\"({ks_padded[1]})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_K2\", f\"({ks_padded[2]})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_NKS\", f\"({len(self.curve.ks)})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_BLOCK_SIZE\", f\"({self.block_size})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_CLEN_BITS\", f\"({self.clen_bits})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_YP_BIT\", f\"({self.yp_bit})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_COUNTER_LIMBS\", f\"({counter_limbs})\")\n            C_TEMPLATE = C_TEMPLATE.replace(\"REPLACE_CHECKSUM_LIMBS\", f\"({checksum_limbs})\")\n            try:\n                with warnings.catch_warnings():\n                    warnings.filterwarnings(\n                        \"ignore\",\n                        message=r\"reimporting '_cffi__.*' might overwrite older definitions\",\n                        category=UserWarning,\n                        module=r\"cffi\\.vengine_cpy\",\n                    )\n                    ffi = cffi.FFI()\n                    ffi.cdef(base_class.DEF_TEMPLATE)\n                    lib = ffi.verify(C_TEMPLATE, extra_compile_args=[\"-O2\"])\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # Different for each class\n            def to_limbs(value, size):\n                arr = ffi.new(\"uint64_t[]\", size)\n                for i in range(size):\n                    arr[i] = (value >> (64 * i)) & 0xffff_ffff_ffff_ffff\n                return arr\n\n            try:\n                curve_a = to_limbs(self.curve.a, nlimbs)\n                curve_b = to_limbs(self.curve.b, nlimbs)\n                gx = to_limbs(self.curve.g[0], nlimbs)\n                gy = to_limbs(self.curve.g[1], nlimbs)\n                qx = ffi.new(\"uint64_t[]\", nlimbs)\n                qy = ffi.new(\"uint64_t[]\", nlimbs)\n            except Exception:\n                self.USE_CFFI = False\n                return\n\n            # add to cache\n            cffi_obj = collections.namedtuple(\"CFFI\",\n                \"ffi lib nlimbs counter_limbs checksum_limbs curve_a curve_b gx gy qx qy\")(\n                ffi, lib, nlimbs, counter_limbs, checksum_limbs,\n                curve_a, curve_b, gx, gy, qx, qy,\n            )\n            self.cffi = base_class.cffi_cache[key] = cffi_obj\n            self.USE_CFFI = True\n            return\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.checksum = 0\n            self.counter = 0\n            self.q = None\n            self.curve = self.ECOHCurve(*self.curve_const)\n            self.init_cffi_backend()\n            if self.USE_CFFI:\n                self.cffi_qinf = self.cffi.ffi.new(\"int *\", 1)\n                self.cffi_qinf[0] = 1\n                self.cffi_checksum = self.cffi.ffi.new(\"uint64_t[]\", self.cffi.checksum_limbs)\n                self.cffi_counter = self.cffi.ffi.new(\"uint64_t[]\", self.cffi.counter_limbs)\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.checksum = self.checksum\n            other.counter = self.counter\n            other.q = None if self.q is None else (self.q[0], self.q[1])\n            other.USE_CFFI = self.USE_CFFI\n            if other.USE_CFFI:\n                other.cffi = self.cffi\n                other.cffi_qinf = other.cffi.ffi.new(\"int *\", self.cffi_qinf[0])\n                other.cffi_checksum = other.cffi.ffi.new(\"uint64_t[]\", list(self.cffi_checksum))\n                other.cffi_counter = other.cffi.ffi.new(\"uint64_t[]\", list(self.cffi_counter))\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n\n            if self.USE_CFFI:\n                full_len = (len(self.buf) // self.block_size) * self.block_size\n                if full_len:\n                    blocks = bytes(self.buf[:full_len])\n                    del self.buf[:full_len]\n                    block_buf = self.cffi.ffi.new(\"uint8_t[]\", blocks)\n                    self.cffi.lib.process_blocks_state(\n                        self.cffi.qx, self.cffi.qy, self.cffi_qinf, self.cffi_checksum, self.cffi_counter,\n                        block_buf, full_len // self.block_size, self.cffi.curve_a, self.cffi.curve_b,\n                    )\n                    self.counter += full_len // self.block_size\n                return self\n\n            # --- pure Python ---\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.process_block(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            value = c.q[0] >> 1\n            mask = (1 << (self.digest_size * 8)) - 1\n            return (value & mask).to_bytes(self.digest_size, \"big\")\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if (self.msg_len * 8) >= (1 << self.clen_bits):\n                raise OverflowError(\"message too long for ECOH length field\")\n\n            def int_to_limbs(value, nlimbs):\n                arr = self.cffi.ffi.new(\"uint64_t[]\", nlimbs)\n                for i in range(nlimbs):\n                    arr[i] = (value >> (64 * i)) & 0xffff_ffff_ffff_ffff\n                return arr\n\n            def limbs_to_int(arr, nlimbs):\n                result = 0\n                for i in range(nlimbs - 1, -1, -1):\n                    result = (result << 64) | int(arr[i])\n                return result\n\n            if self.USE_CFFI:\n                msg_len_bits = int_to_limbs(self.msg_len * 8, self.cffi.counter_limbs)\n                tail_bytes = bytes(self.buf)\n                tail = self.cffi.ffi.new(\"uint8_t[]\", tail_bytes or b\"\\x00\")\n                self.cffi.lib.finalize_hash_state(\n                    self.cffi.qx, self.cffi.qy, self.cffi_qinf, self.cffi_checksum, self.cffi_counter,\n                    tail, len(tail_bytes), msg_len_bits, self.cffi.curve_a, self.cffi.curve_b, self.cffi.gx, self.cffi.gy,\n                )\n                self.buf = bytearray()\n                self.counter += 1\n                if self.cffi_qinf[0]:\n                    self.q = None\n                else:\n                    self.q = (limbs_to_int(self.cffi.qx, self.cffi.nlimbs), limbs_to_int(self.cffi.qy, self.cffi.nlimbs))\n                return\n\n            # --- pure Python ---\n            pad_len = self.block_size - len(self.buf) - 1\n            block = bytes(self.buf) + b\"\\x80\" + (b\"\\x00\" * pad_len)\n            self.process_block(block)\n            x = 1\n            x |= (self.msg_len * 8) << self.clen_bits\n            x |= self.checksum << (2 * self.clen_bits)\n            p = self.decompress_search(x)\n            self.q = self.point_add(self.q, p)\n            k = self.q[0] >> 1\n            self.q = self.point_add(self.q, self.scalar_mul(k, self.curve.g))\n            return\n\n        def process_block(self, block):\n            n = int.from_bytes(block, \"big\")\n            self.checksum ^= n\n            x = 1\n            x |= self.counter << self.clen_bits\n            x |= n << (2 * self.clen_bits)\n            p = self.decompress_search(x)\n            self.q = self.point_add(self.q, p)\n            self.counter += 1\n            return\n\n        def decompress_search(self, x):\n            while True:\n                p = self.point_decompress(x)\n                if p is not None:\n                    return p\n                x += 2\n            return\n\n        def gf_reduce(self, x):\n            m = self.curve.m\n            ks = self.curve.ks\n            low_mask = self.curve.low_mask\n            while x.bit_length() > m:\n                hi = x >> m\n                x = (x & low_mask) ^ hi\n                for k in ks:\n                    x ^= hi << k\n            return x\n\n        def gf_mul(self, a, b):\n            if a == 0 or b == 0:\n                return 0\n            if a < b:\n                a, b = b, a\n            a1 = a\n            a2 = a << 1\n            a4 = a << 2\n            a8 = a << 3\n            table = (\n                0, a1, a2, a1 ^ a2, a4, a1 ^ a4, a2 ^ a4, a1 ^ a2 ^ a4,\n                a8, a1 ^ a8, a2 ^ a8, a1 ^ a2 ^ a8, a4 ^ a8, a1 ^ a4 ^ a8, a2 ^ a4 ^ a8, a1 ^ a2 ^ a4 ^ a8,\n            )\n            r = 0\n            shift = 0\n            while b:\n                r ^= table[b & 0xf] << shift\n                b >>= 4\n                shift += 4\n            return self.gf_reduce(r)\n\n        def gf_sqr(self, a):\n            table = self.curve.square_table\n            r = 0\n            shift = 0\n            while a:\n                r |= table[a & 0xff] << shift\n                a >>= 8\n                shift += 16\n            return self.gf_reduce(r)\n\n        def gf_inv(self, a):\n            if a == 0:\n                return 0\n            u = a\n            v = self.curve.modulus\n            g1 = 1\n            g2 = 0\n            while u != 1:\n                j = u.bit_length() - v.bit_length()\n                if j < 0:\n                    u, v, g1, g2, j = v, u, g2, g1, -j\n                u  ^= v << j\n                g1 ^= g2 << j\n            return self.gf_reduce(g1)\n\n        def half_trace(self, a):\n            z = a\n            limit = (self.curve.m - 1) // 2\n            for _ in range(limit):\n                z = self.gf_sqr(self.gf_sqr(z)) ^ a\n            return z\n\n        def point_decompress(self, x):\n            x = self.gf_reduce(x)\n            if x == 0:\n                return None\n            rhs = x ^ self.curve.a ^ self.gf_mul(self.curve.b, self.gf_sqr(self.gf_inv(x)))\n            z = self.half_trace(rhs)\n            if (self.gf_sqr(z) ^ z) != rhs:\n                return None\n            yp = (x >> self.yp_bit) & 1\n            if (z & 1) != yp:\n                z ^= 1\n            y = self.gf_mul(x, z)\n            return (x, y)\n\n        def point_double(self, p):\n            if p is None:\n                return None\n            x1, y1 = p\n            if x1 == 0:\n                return None\n            lam = self.gf_mul(self.gf_inv(x1), y1) ^ x1\n            x3 = self.gf_sqr(lam) ^ lam ^ self.curve.a\n            y3 = self.gf_sqr(x1) ^ self.gf_mul(x3, lam ^ 1)\n            return (x3, y3)\n\n        def point_add(self, p, q):\n            if p is None:\n                return q\n            if q is None:\n                return p\n            x1, y1 = p\n            x2, y2 = q\n            if x1 == x2:\n                if y1 == y2:\n                    return self.point_double(p)\n                return None\n            lam = self.gf_mul(self.gf_inv(x1 ^ x2), y1 ^ y2)\n            x3 = self.gf_sqr(lam) ^ lam ^ x1 ^ x2 ^ self.curve.a\n            y3 = self.gf_mul(lam, x3 ^ x1) ^ x3 ^ y1\n            return (x3, y3)\n\n        def scalar_mul(self, k, p):\n            r = None\n            a = p\n            while k:\n                if k & 1:\n                    r = self.point_add(r, a)\n                k >>= 1\n                if k:\n                    a = self.point_double(a)\n            return r\n\n    class ECOH224(ECOHBase):\n        block_size = 16\n        digest_size = 28\n        clen_bits = 64\n        yp_bit = 255\n        curve_const = (\n            283,\n            (12, 7, 5),\n            0x1,\n            0x27b_680a_c8b8_596d_a5a4_af8a_19a0_303f_ca97_fd76_4530_9fa2_a581_485a_f626_3e31_3b79_a2f5,\n            0x5f9_3925_8db7_dd90_e193_4f8c_70b0_dfec_2eed_25b8_557e_ac9c_80e2_e198_f8cd_becd_86b1_2053,\n            0x367_6854_fe24_141c_b98f_e6d4_b20d_02b4_516f_f702_350e_ddb0_8267_79c8_13f0_df45_be81_12f4,\n        )\n\n    class ECOH256(ECOH224):\n        digest_size = 32\n\n    class ECOH384(ECOHBase):\n        block_size = 24\n        digest_size = 48\n        clen_bits = 64\n        yp_bit = 319\n        curve_const = (\n            409,\n            (87,),\n            0x1,\n            int(\"0x021_a5c2_c8ee_9feb_5c4b_9a75_3b7b_476b_7fd6_422e_f1f3_dd67_4761_fa99_d6ac_27c8_a9a1_97b2\"\n                \"_7282_2f6c_d57a_55aa_4f50_ae31_7b13_545f\", 16),\n            int(\"0x15d_4860_d088_ddb3_496b_0c60_6475_6260_441c_de4a_f177_1d4d_b01f_fe5b_34e5_9703_dc25_5a86\"\n                \"_8a11_8051_5603_aeab_6079_4e54_bb79_96a7\", 16),\n            int(\"0x061_b1cf_ab6b_e5f3_2bbf_a783_24ed_106a_7636_b9c5_a7bd_198d_0158_aa4f_5488_d08f_3851_4f1f\"\n                \"_df4b_4f40_d218_1b36_81c3_64ba_0273_c706\", 16),\n        )\n\n    class ECOH512(ECOH384):\n        block_size = 32\n        digest_size = 64\n        clen_bits = 128\n        yp_bit = 511\n        curve_const = (\n            571,\n            (10, 5, 2),\n            0x1,\n            int(\"0x2f4_0e7e_2221_f295_de29_7117_b7f3_d62f_5c6a_97ff_cb8c_eff1_cd6b_a8ce_4a9a_18ad_84ff_abbd\"\n                \"_8efa_5933_2be7_ad67_56a6_6e29_4afd_185a_78ff_12aa_520e_4de7_39ba_ca0c_7ffe_ff7f_2955_727a\", 16),\n            int(\"0x303_001d_34b8_5629_6c16_c0d4_0d3c_d775_0a93_d1d2_955f_a80a_a5f4_0fc8_db7b_2abd_bde5_3950\"\n                \"_f4c0_d293_cdd7_11a3_5b67_fb14_99ae_6003_8614_f139_4abf_a3b4_c850_d927_e1e7_769c_8eec_2d19\", 16),\n            int(\"0x37b_f273_42da_639b_6dcc_fffe_b73d_69d7_8c6c_27a6_009c_bbca_1980_f853_3921_e8a6_8442_3e43\"\n                \"_bab0_8a57_6291_af8f_461b_b2a8_b353_1d2f_0485_c19b_16e2_f151_6e23_dd3c_1a48_27af_1b8a_c15b\", 16),\n        )\n\n    class EDONRBase:\n        def __init__(self, data=b\"\"):\n            self.double_pipe = list(self.init_pipe)\n            self.buf = bytearray()\n            self.msg_bits = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.double_pipe = list(self.double_pipe)\n            other.buf = bytearray(self.buf)\n            other.msg_bits = self.msg_bits\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_bits += len(data) * 8\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            word_count = self.digest_size // (self.word_bits // 8)\n            words = other.double_pipe[self.out_offset_words:self.out_offset_words + word_count]\n            return struct.pack(\"<\" + (self.word_format * word_count), *words)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_bits\n            self.buf.append(0x80)\n            while (len(self.buf) % self.block_size) != (self.block_size - 8):\n                self.buf.append(0x00)\n            self.buf.extend(struct.pack(\"<Q\", bit_len))\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return\n\n        def rol(self, x, n):\n            return ((x << n) | (x >> (self.word_bits - n))) & self.word_mask\n\n        def q(self, x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7):\n            t0 = (self.q_const_a + x0 + x1 + x2 + x4 + x7) & self.word_mask\n            t1 = (x0 + x1 + x3 + x4 + x7) & self.word_mask\n            t2 = (x0 + x1 + x4 + x6 + x7) & self.word_mask\n            t3 = (x2 + x3 + x5 + x6 + x7) & self.word_mask\n            t4 = (x1 + x2 + x3 + x5 + x6) & self.word_mask\n            t5 = (x0 + x2 + x3 + x4 + x5) & self.word_mask\n            t6 = (x0 + x1 + x5 + x6 + x7) & self.word_mask\n            t7 = (x2 + x3 + x4 + x5 + x6) & self.word_mask\n\n            t1 = self.rol(t1, self.rot1[0])\n            t2 = self.rol(t2, self.rot1[1])\n            t3 = self.rol(t3, self.rot1[2])\n            t4 = self.rol(t4, self.rot1[3])\n            t5 = self.rol(t5, self.rot1[4])\n            t6 = self.rol(t6, self.rot1[5])\n            t7 = self.rol(t7, self.rot1[6])\n\n            u8 = t3 ^ t5 ^ t6\n            u9 = t2 ^ t5 ^ t6\n            u10 = t2 ^ t3 ^ t5\n            u11 = t0 ^ t1 ^ t4\n            u12 = t0 ^ t4 ^ t7\n            u13 = t1 ^ t6 ^ t7\n            u14 = t2 ^ t3 ^ t4\n            u15 = t0 ^ t1 ^ t7\n\n            s0 = (self.q_const_b + y0 + y1 + y2 + y5 + y7) & self.word_mask\n            s1 = (y0 + y1 + y3 + y4 + y6) & self.word_mask\n            s2 = (y0 + y1 + y2 + y3 + y5) & self.word_mask\n            s3 = (y2 + y3 + y4 + y6 + y7) & self.word_mask\n            s4 = (y0 + y1 + y3 + y4 + y5) & self.word_mask\n            s5 = (y2 + y4 + y5 + y6 + y7) & self.word_mask\n            s6 = (y1 + y2 + y5 + y6 + y7) & self.word_mask\n            s7 = (y0 + y3 + y4 + y6 + y7) & self.word_mask\n\n            s1 = self.rol(s1, self.rot2[0])\n            s2 = self.rol(s2, self.rot2[1])\n            s3 = self.rol(s3, self.rot2[2])\n            s4 = self.rol(s4, self.rot2[3])\n            s5 = self.rol(s5, self.rot2[4])\n            s6 = self.rol(s6, self.rot2[5])\n            s7 = self.rol(s7, self.rot2[6])\n\n            z5 = (u8 + (s3 ^ s4 ^ s6)) & self.word_mask\n            z6 = (u9 + (s2 ^ s5 ^ s7)) & self.word_mask\n            z7 = (u10 + (s4 ^ s6 ^ s7)) & self.word_mask\n            z0 = (u11 + (s0 ^ s1 ^ s5)) & self.word_mask\n            z1 = (u12 + (s2 ^ s6 ^ s7)) & self.word_mask\n            z2 = (u13 + (s0 ^ s1 ^ s3)) & self.word_mask\n            z3 = (u14 + (s0 ^ s3 ^ s4)) & self.word_mask\n            z4 = (u15 + (s1 ^ s2 ^ s5)) & self.word_mask\n            return [z0, z1, z2, z3, z4, z5, z6, z7]\n\n        def compress(self, block):\n            words = list(struct.unpack(\"<\" + (self.word_format * (self.block_size // (self.word_bits // 8))), block))\n            p = self.double_pipe\n\n            z = self.q(\n                words[15], words[14], words[13], words[12], words[11], words[10], words[9], words[8],\n                words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7],\n            )\n            for i in range(8):\n                p[16 + i] = z[i]\n\n            z = self.q(\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n                words[8], words[9], words[10], words[11], words[12], words[13], words[14], words[15],\n            )\n            for i in range(8):\n                p[24 + i] = z[i]\n\n            z = self.q(\n                p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15],\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n            )\n            for i in range(8):\n                p[16 + i] = z[i]\n\n            z = self.q(\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n                p[24], p[25], p[26], p[27], p[28], p[29], p[30], p[31],\n            )\n            for i in range(8):\n                p[24 + i] = z[i]\n\n            z = self.q(\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n                p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],\n            )\n            for i in range(8):\n                p[16 + i] = z[i]\n\n            z = self.q(\n                p[24], p[25], p[26], p[27], p[28], p[29], p[30], p[31],\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n            )\n            for i in range(8):\n                p[24 + i] = z[i]\n\n            z = self.q(\n                words[7], words[6], words[5], words[4], words[3], words[2], words[1], words[0],\n                p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],\n            )\n            for i in range(8):\n                p[i] = z[i]\n\n            z = self.q(\n                p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],\n                p[24], p[25], p[26], p[27], p[28], p[29], p[30], p[31],\n            )\n            for i in range(8):\n                p[8 + i] = z[i]\n            return\n\n    class EDONR224(EDONRBase):\n        block_size = 64\n        digest_size = 28\n        word_bits = 32\n        word_mask = 0xffff_ffff\n        q_const_a = 0xaaaa_aaaa\n        q_const_b = 0x5555_5555\n        rot1 = [4, 8, 13, 17, 22, 24, 29]\n        rot2 = [5, 9, 11, 15, 20, 25, 27]\n        word_format = \"I\"\n        init_pipe = [\n            0x0001_0203, 0x0405_0607, 0x0809_0a0b, 0x0c0d_0e0f,\n            0x1011_1213, 0x1415_1617, 0x1819_1a1b, 0x1c1d_1e1f,\n            0x2021_2223, 0x2425_2627, 0x2829_2a2b, 0x2c2d_2e2f,\n            0x3031_3233, 0x2435_3637, 0x3839_3a3b, 0x3c3d_3e3f,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n        ]\n        out_offset_words = 9\n\n    class EDONR256(EDONR224):\n        digest_size = 32\n        init_pipe = [\n            0x4041_4243, 0x4445_4647, 0x4849_4a4b, 0x4c4d_4e4f,\n            0x5051_5253, 0x5455_5657, 0x5859_5a5b, 0x5c5d_5e5f,\n            0x6061_6263, 0x6465_6667, 0x6869_6a6b, 0x6c6d_6e6f,\n            0x7071_7273, 0x7475_7677, 0x7879_7a7b, 0x7c7d_7e7f,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n            0x0000_0000, 0x0000_0000, 0x0000_0000, 0x0000_0000,\n        ]\n        out_offset_words = 8\n\n    class EDONR384(EDONRBase):\n        block_size = 128\n        digest_size = 48\n        word_bits = 64\n        word_mask = 0xffff_ffff_ffff_ffff\n        q_const_a = 0xaaaa_aaaa_aaaa_aaaa\n        q_const_b = 0x5555_5555_5555_5555\n        rot1 = [5, 15, 22, 31, 40, 50, 59]\n        rot2 = [10, 19, 29, 36, 44, 48, 55]\n        word_format = \"Q\"\n        init_pipe = [\n            0x0001_0203_0405_0607, 0x0809_0a0b_0c0d_0e0f, 0x1011_1213_1415_1617, 0x1819_1a1b_1c1d_1e1f,\n            0x2021_2223_2425_2627, 0x2829_2a2b_2c2d_2e2f, 0x3031_3233_2435_3637, 0x3839_3a3b_3c3d_3e3f,\n            0x4041_4243_4445_4647, 0x4849_4a4b_4c4d_4e4f, 0x5051_5253_5455_5657, 0x5859_5a5b_5c5d_5e5f,\n            0x6061_6263_6465_6667, 0x6869_6a6b_6c6d_6e6f, 0x7071_7273_7475_7677, 0x7879_7a7b_7c7d_7e7f,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n        ]\n        out_offset_words = 10\n\n    class EDONR512(EDONR384):\n        digest_size = 64\n        init_pipe = [\n            0x8081_8283_8485_8687, 0x8889_8a8b_8c8d_8e8f, 0x9091_9293_9495_9697, 0x9899_9a9b_9c9d_9e9f,\n            0xa0a1_a2a3_a4a5_a6a7, 0xa8a9_aaab_acad_aeaf, 0xb0b1_b2b3_b4b5_b6b7, 0xb8b9_babb_bcbd_bebf,\n            0xc0c1_c2c3_c4c5_c6c7, 0xc8c9_cacb_cccd_cecf, 0xd0d1_d2d3_d4d5_d6d7, 0xd8d9_dadb_dcdd_dedf,\n            0xe0e1_e2e3_e4e5_e6e7, 0xe8e9_eaeb_eced_eeef, 0xf0f1_f2f3_f4f5_f6f7, 0xf8f9_fafb_fcfd_feff,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n            0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000, 0x0000_0000_0000_0000,\n        ]\n        out_offset_words = 8\n\n    class EnRUPTBase:\n        word_bits = 64\n        parallelism = 2\n        security_parameter = 4\n\n        def __init__(self, data=b\"\"):\n            self.word_bytes = self.word_bits // 8\n            self.word_mask = (1 << self.word_bits) - 1\n            self.state_words = (\n                (\n                    self.hashbitlen * 2\n                    + self.word_bits * self.parallelism\n                    - 1\n                )\n                // (self.word_bits * self.parallelism)\n            ) * self.parallelism\n            self.x = [0] * self.state_words\n            self.d = [0] * self.parallelism\n            self.r = 0\n            self.buf = bytearray()\n            self.finalized = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.x = self.x[:]\n            other.d = self.d[:]\n            other.r = self.r\n            other.buf = bytearray(self.buf)\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.buf.extend(bytes(data))\n            while len(self.buf) >= self.word_bytes:\n                word = int.from_bytes(self.buf[:self.word_bytes], \"big\")\n                del self.buf[:self.word_bytes]\n                self.absorb_word(word)\n            return self\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.squeeze()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def rotr(self, x, n):\n            return ((x >> n) | (x << (self.word_bits - n))) & self.word_mask\n\n        def ir1(self):\n            r = self.r\n            h = self.state_words\n            p = self.parallelism\n            a = (r // p * p + (r + 1) % p) % h\n            b = (r + 2 * p) % h\n            f = self.rotr(\n                ((self.x[a] * 2) ^ self.x[b] ^ self.d[r % p] ^ r) & self.word_mask,\n                self.word_bits // 4,\n            )\n            f = (f * 9) & self.word_mask\n            self.x[(r + p) % h] ^= f\n            self.d[r % p] ^= f ^ self.x[(h * p // 2 + p % 2 + r) % h]\n            self.r = (r + 1) & self.word_mask\n            return\n\n        def enr2s(self, word):\n            for _ in range(2 * self.security_parameter):\n                self.ir1()\n            self.d[self.parallelism - 1] ^= word\n            return\n\n        def absorb_word(self, word):\n            self.enr2s(word)\n            return\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            padded = bytearray(self.buf)\n            padded.append(0x80)\n            while len(padded) % self.word_bytes != 0:\n                padded.append(0x00)\n\n            for i in range(0, len(padded), self.word_bytes):\n                word = int.from_bytes(padded[i:i + self.word_bytes], \"big\")\n                self.absorb_word(word)\n\n            self.absorb_word(self.hashbitlen)\n\n            for _ in range(self.state_words):\n                self.absorb_word(0)\n\n            self.buf.clear()\n            self.finalized = True\n            return\n\n        def squeeze(self):\n            out = bytearray()\n            full_words = self.hashbitlen // self.word_bits\n            remain_bits = self.hashbitlen % self.word_bits\n\n            for _ in range(full_words):\n                self.absorb_word(0)\n                out.extend(self.d[self.parallelism - 1].to_bytes(self.word_bytes, \"big\"))\n\n            if remain_bits:\n                self.absorb_word(0)\n                out.extend(\n                    self.d[self.parallelism - 1].to_bytes(self.word_bytes, \"big\")[\n                        : (remain_bits + 7) // 8\n                    ]\n                )\n\n            return bytes(out)\n\n    class EnRUPT224(EnRUPTBase):\n        digest_size = 28\n        hashbitlen = 224\n\n    class EnRUPT256(EnRUPTBase):\n        digest_size = 32\n        hashbitlen = 256\n\n    class EnRUPT384(EnRUPTBase):\n        digest_size = 48\n        hashbitlen = 384\n\n    class EnRUPT512(EnRUPTBase):\n        digest_size = 64\n        hashbitlen = 512\n\n    class ESSENCEBase:\n        md_block_size = 1_048_576\n        compress_steps = 32\n        hash_tree_level = 0\n        organizational_small_constant = 0xb7e1_5162\n        organizational_big_constant = 0x8aed_2a6a_bf71_5880\n\n        expansion_of_pi_32 = [\n            0x85a3_08d3, 0x243f_6a88, 0x0370_7344, 0x1319_8a2e,\n            0x299f_31d0, 0xa409_3822, 0xec4e_6c89, 0x082e_fa98,\n        ]\n\n        expansion_of_pi_64 = [\n            0x243f_6a88_85a3_08d3, 0x1319_8a2e_0370_7344, 0xa409_3822_299f_31d0, 0x082e_fa98_ec4e_6c89,\n            0x4528_21e6_38d0_1377, 0xbe54_66cf_34e9_0c6c, 0xc0ac_29b7_c97c_50dd, 0x3f84_d5b5_b547_0917,\n        ]\n\n        l32_table = None\n        l64_table = None\n\n        def __init__(self, data=b\"\"):\n            self.word_bits = 32 if self.block_size == 32 else 64\n            self.word_mask = (1 << self.word_bits) - 1\n            self.chunk_size = self.block_size\n            self.running_hash = self.init_running_hash()\n            self.mdbiv_init = self.init_mdbiv()\n            self.chain_vars = [0] * 8\n            self.buf = bytearray()\n            self.buf_bitlen = 0\n            self.last_md_block_number = 0xffff_ffff_ffff_ffff\n            self.within_md_block = False\n            self.current_md_block_datalen = 0\n            self.ensure_tables()\n            if data:\n                self.update(data)\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n            if cls.l32_table is None:\n                cls.l32_table = cls.generate_l_table(32, 0x814a_3b35)\n            if cls.l64_table is None:\n                cls.l64_table = cls.generate_l_table(64, 0xb0a6_5313_e696_6997)\n            return\n\n        @classmethod\n        def generate_l_table(cls, bits, poly):\n            mask = (1 << bits) - 1\n            top = 1 << (bits - 1)\n            shift = bits - 8\n            table = []\n            value = 0\n            while value < 256:\n                x = value << shift\n                i = 0\n                while i < 8:\n                    if x & top:\n                        x = ((x << 1) & mask) ^ poly\n                    else:\n                        x = (x << 1) & mask\n                    i += 1\n                table.append(x)\n                value += 1\n            return table\n\n        def init_running_hash(self):\n            if self.word_bits == 64:\n                return list(self.expansion_of_pi_64)\n            return list(self.expansion_of_pi_32)\n\n        def init_mdbiv(self):\n            if self.word_bits == 64:\n                return [\n                    0,\n                    self.md_block_size,\n                    (self.hashbitlen & 0xffff)\n                    | (self.compress_steps << 16)\n                    | (self.hash_tree_level << 24)\n                    | (self.organizational_small_constant << 32),\n                    self.organizational_big_constant,\n                    self.expansion_of_pi_64[4],\n                    self.expansion_of_pi_64[5],\n                    self.expansion_of_pi_64[6],\n                    self.expansion_of_pi_64[7],\n                ]\n            return [\n                0,\n                0,\n                self.md_block_size & 0xffff_ffff,\n                (self.md_block_size >> 32) & 0xffff_ffff,\n                (self.hashbitlen & 0xffff)\n                | (self.compress_steps << 16)\n                | (self.hash_tree_level << 24),\n                self.organizational_small_constant,\n                self.organizational_big_constant & 0xffff_ffff,\n                (self.organizational_big_constant >> 32) & 0xffff_ffff,\n            ]\n\n        def copy(self):\n            other = self.__class__()\n            other.running_hash = list(self.running_hash)\n            other.mdbiv_init = list(self.mdbiv_init)\n            other.chain_vars = list(self.chain_vars)\n            other.buf = bytearray(self.buf)\n            other.buf_bitlen = self.buf_bitlen\n            other.last_md_block_number = self.last_md_block_number\n            other.within_md_block = self.within_md_block\n            other.current_md_block_datalen = self.current_md_block_datalen\n            return other\n\n        def normalize_data(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            return bytes(data)\n\n        def update(self, data):\n            data = self.normalize_data(data)\n            return self.update_bits(data, len(data) * 8)\n\n        def update_bits(self, data, databitlen):\n            data = self.normalize_data(data)\n            if databitlen < 0:\n                raise ValueError(\"databitlen must be >= 0\")\n\n            data_bytelen = (databitlen + 7) >> 3\n            if data_bytelen > len(data):\n                raise ValueError(\"databitlen exceeds data length\")\n\n            if databitlen == 0:\n                return self\n\n            if (self.buf_bitlen % 8) != 0:\n                raise ValueError(\"cannot append after non-byte-aligned update\")\n\n            chunk_bits = self.chunk_size * 8\n            offset = 0\n\n            if (self.buf_bitlen + databitlen) < chunk_bits:\n                self.append_partial(data[:data_bytelen], databitlen)\n                return self\n\n            if self.buf_bitlen > 0:\n                needed = self.chunk_size - len(self.buf)\n                self.buf.extend(data[:needed])\n                offset += needed\n                databitlen -= needed * 8\n                self.process_chunk(bytes(self.buf))\n                self.buf.clear()\n                self.buf_bitlen = 0\n\n            full_bytes = databitlen >> 3\n            tail_bits = databitlen & 7\n            direct_bytes = full_bytes - (full_bytes % self.chunk_size)\n            end = offset + direct_bytes\n\n            while offset < end:\n                self.process_chunk(data[offset:offset + self.chunk_size])\n                offset += self.chunk_size\n\n            remain_bytes = full_bytes - direct_bytes\n            if remain_bytes > 0:\n                self.buf.extend(data[offset:offset + remain_bytes])\n                self.buf_bitlen = remain_bytes * 8\n                offset += remain_bytes\n\n            if tail_bits != 0:\n                self.buf.append(data[offset] & (0xff << (8 - tail_bits)))\n                self.buf_bitlen += tail_bits\n\n            return self\n\n        def append_partial(self, data, databitlen):\n            full_bytes = databitlen >> 3\n            tail_bits = databitlen & 7\n            if full_bytes > 0:\n                self.buf.extend(data[:full_bytes])\n            if tail_bits != 0:\n                self.buf.append(data[full_bytes] & (0xff << (8 - tail_bits)))\n            self.buf_bitlen += databitlen\n            return\n\n        def init_chain_vars(self):\n            block_number = (self.last_md_block_number + 1) & 0xffff_ffff_ffff_ffff\n            if self.word_bits == 64:\n                self.chain_vars[0] = block_number\n                index = 1\n                while index < 8:\n                    self.chain_vars[index] = self.mdbiv_init[index]\n                    index += 1\n            else:\n                self.chain_vars[0] = block_number & 0xffff_ffff\n                self.chain_vars[1] = (block_number >> 32) & 0xffff_ffff\n                index = 2\n                while index < 8:\n                    self.chain_vars[index] = self.mdbiv_init[index]\n                    index += 1\n            self.within_md_block = True\n            self.current_md_block_datalen = 0\n            return\n\n        def process_chunk(self, chunk):\n            if not self.within_md_block:\n                self.init_chain_vars()\n            self.compress_words(self.chain_vars, chunk)\n            self.current_md_block_datalen += self.chunk_size * 8\n            if (self.current_md_block_datalen >> 3) == self.md_block_size:\n                self.merge_tree()\n            return\n\n        def merge_tree(self):\n            self.last_md_block_number = (self.last_md_block_number + 1) & 0xffff_ffff_ffff_ffff\n            self.within_md_block = False\n            self.current_md_block_datalen = 0\n            self.compress_words(self.running_hash, self.words_to_bytes(self.chain_vars))\n            return\n\n        def words_to_bytes(self, words):\n            out = bytearray()\n            if self.word_bits == 64:\n                for value in words:\n                    out.extend(value.to_bytes(8, \"little\"))\n            else:\n                for value in words:\n                    out.extend(value.to_bytes(4, \"little\"))\n            return bytes(out)\n\n        def l_func(self, value):\n            if self.word_bits == 64:\n                table = self.l64_table\n                shift = 56\n                count = 8\n            else:\n                table = self.l32_table\n                shift = 24\n                count = 4\n\n            i = 0\n            while i < count:\n                value = table[value >> shift] ^ ((value << 8) & self.word_mask)\n                i += 1\n            return value\n\n        def f_func(self, a, b, c, d, e, f, g):\n            m = self.word_mask\n            na = a ^ m\n            nb = b ^ m\n            nc = c ^ m\n            nd = d ^ m  # codespell:ignore\n            ne = e ^ m\n            nf = f ^ m\n            ng = g ^ m\n\n            result = (\n                (a & nb & c & d & e & f & ng)\n                ^ (a & b & c & e & nf & g)\n                ^ (a & b & d & ne & g)\n                ^ (a & b & e & f & g)\n                ^ (a & nb & d & e & f)\n                ^ (a & c & e & f & g)\n                ^ (a & nc & d & f & ng)\n                ^ (a & d & e & nf & g)\n                ^ (b & c & d & f & g)\n                ^ (b & d & e & nf & g)\n                ^ (c & d & e & f & ng)\n                ^ (a & b & nc & g)\n                ^ (na & b & c & nf)\n                ^ (b & c & ne & g)\n                ^ (b & nc & d & e)\n                ^ (a & b & f)\n                ^ (a & nb & e)\n                ^ (a & c & g)\n                ^ (a & d & ng)\n                ^ (a & e & g)\n                ^ (na & e & f)\n                ^ (b & d & nf)\n                ^ (b & e & g)\n                ^ (nb & f & g)\n                ^ (c & nd & ne)  # codespell:ignore\n                ^ (nc & d & f)\n                ^ (d & e & f)\n                ^ (d & ne & g)\n                ^ (d & f & g)\n                ^ na\n                ^ b\n                ^ f\n            )\n            return result & m\n\n        def compress_words(self, chain_vars, block):\n            if self.word_bits == 64:\n                k0, k1, k2, k3, k4, k5, k6, k7 = struct.unpack(\"<8Q\", block)\n            else:\n                k0, k1, k2, k3, k4, k5, k6, k7 = struct.unpack(\"<8I\", block)\n\n            r0, r1, r2, r3, r4, r5, r6, r7 = chain_vars\n            r0_orig = r0\n            r1_orig = r1\n            r2_orig = r2\n            r3_orig = r3\n            r4_orig = r4\n            r5_orig = r5\n            r6_orig = r6\n            r7_orig = r7\n\n            i = 0\n            while i < self.compress_steps:\n                tmp_r = self.l_func(r0)\n                tmp_k = self.l_func(k0)\n                f_r = self.f_func(r6, r5, r4, r3, r2, r1, r0)\n                f_k = self.f_func(k6, k5, k4, k3, k2, k1, k0)\n\n                tmp_r ^= f_r ^ r7 ^ k7\n                tmp_k ^= f_k ^ k7\n\n                r7 = r6\n                k7 = k6\n                r6 = r5\n                k6 = k5\n                r5 = r4\n                k5 = k4\n                r4 = r3\n                k4 = k3\n                r3 = r2\n                k3 = k2\n                r2 = r1\n                k2 = k1\n                r1 = r0\n                k1 = k0\n                r0 = tmp_r\n                k0 = tmp_k\n                i += 1\n\n            chain_vars[0] = (r0 ^ r0_orig) & self.word_mask\n            chain_vars[1] = (r1 ^ r1_orig) & self.word_mask\n            chain_vars[2] = (r2 ^ r2_orig) & self.word_mask\n            chain_vars[3] = (r3 ^ r3_orig) & self.word_mask\n            chain_vars[4] = (r4 ^ r4_orig) & self.word_mask\n            chain_vars[5] = (r5 ^ r5_orig) & self.word_mask\n            chain_vars[6] = (r6 ^ r6_orig) & self.word_mask\n            chain_vars[7] = (r7 ^ r7_orig) & self.word_mask\n            return\n\n        def finalize(self):\n            if self.buf_bitlen > 0:\n                if not self.within_md_block:\n                    self.init_chain_vars()\n\n                block = bytearray(self.chunk_size)\n                block[:len(self.buf)] = self.buf\n                self.compress_words(self.chain_vars, bytes(block))\n                self.current_md_block_datalen += self.buf_bitlen\n                self.buf.clear()\n                self.buf_bitlen = 0\n\n            last_block_data_bitlen = self.current_md_block_datalen\n\n            if self.within_md_block:\n                self.merge_tree()\n\n            final_block = list(self.mdbiv_init)\n            if self.word_bits == 64:\n                final_block[0] = self.last_md_block_number & 0xffff_ffff_ffff_ffff\n                final_block[3] = last_block_data_bitlen & 0xffff_ffff_ffff_ffff\n            else:\n                final_block[0] = self.last_md_block_number & 0xffff_ffff\n                final_block[1] = (self.last_md_block_number >> 32) & 0xffff_ffff\n                final_block[6] = last_block_data_bitlen & 0xffff_ffff\n                final_block[7] = (last_block_data_bitlen >> 32) & 0xffff_ffff\n\n            self.compress_words(self.running_hash, self.words_to_bytes(final_block))\n            return\n\n        def output_bytes(self):\n            num_bytes = (self.hashbitlen + 7) >> 3\n            out = bytearray()\n\n            if self.word_bits == 64:\n                for value in self.running_hash:\n                    out.extend(value.to_bytes(8, \"little\"))\n            else:\n                for value in self.running_hash:\n                    out.extend(value.to_bytes(4, \"little\"))\n\n            out = out[:num_bytes]\n            if (self.hashbitlen & 7) != 0:\n                out[-1] &= 0xff << (8 - (self.hashbitlen & 7))\n            return bytes(out)\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.output_bytes()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class ESSENCE224(ESSENCEBase):\n        block_size = 32\n        digest_size = 28\n        hashbitlen = 224\n\n    class ESSENCE256(ESSENCEBase):\n        block_size = 32\n        digest_size = 32\n        hashbitlen = 256\n\n    class ESSENCE384(ESSENCEBase):\n        block_size = 64\n        digest_size = 48\n        hashbitlen = 384\n\n    class ESSENCE512(ESSENCEBase):\n        block_size = 64\n        digest_size = 64\n        hashbitlen = 512\n\n    class Khichidi1Base:\n        def __init__(self, data=b\"\", data_bit_length=None):\n            self.total_bits = 0\n            self.num_words = self.digest_size // 4\n            self.h = [0] * (self.num_words + 1)\n            self.z = [0] * self.num_words\n            self.residue = bytearray(self.block_size)\n            self.residue_bit_length = 0\n            if data:\n                self.update(data, data_bit_length)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.total_bits = self.total_bits\n            other.h = list(self.h)\n            other.z = list(self.z)\n            other.residue = bytearray(self.residue)\n            other.residue_bit_length = self.residue_bit_length\n            return other\n\n        def ensure_bytes_like(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            return bytes(data)\n\n        def shuffling(self, x):\n            x = ((x & 0x0000_ff00) << 8) | ((x >> 8) & 0x0000_ff00) | (x & 0xff00_00ff)\n            x = ((x & 0x00f0_00f0) << 4) | ((x >> 4) & 0x00f0_00f0) | (x & 0xf00f_f00f)\n            x = ((x & 0x0c0c_0c0c) << 2) | ((x >> 2) & 0x0c0c_0c0c) | (x & 0xc3c3_c3c3)\n            x = ((x & 0x2222_2222) << 1) | ((x >> 1) & 0x2222_2222) | (x & 0x9999_9999)\n            return x\n\n        def t_function(self, n):\n            return (2 * ((n * n) & 0xffff_ffff) + n) & 0xffff_ffff\n\n        def lfsr(self, x):\n            flag = x & 0x8000_0000\n            x = (x << 1) & 0xffff_ffff\n            if flag:\n                x ^= 0x04c1_1db7\n            return x\n\n        def message_pre_process(self, x):\n            x = self.shuffling(x)\n            x = self.t_function(x)\n            x = self.lfsr(x)\n            return x\n\n        def words_to_bytes(self, words):\n            out = bytearray()\n            for word in words:\n                out.extend(word.to_bytes(4, \"big\"))\n            return bytes(out)\n\n        def copy_bits(self, dest, dest_bit_offset, source, num_bits):\n            if num_bits < 0:\n                raise ValueError(\"num_bits must be non-negative\")\n            if num_bits == 0:\n                return\n\n            if dest_bit_offset % 8 == 0 and num_bits % 8 == 0:\n                start = dest_bit_offset // 8\n                end = start + (num_bits // 8)\n                dest[start:end] = source[: num_bits // 8]\n                return\n\n            for i in range(num_bits):\n                src_byte = source[i // 8]\n                src_mask = 0x80 >> (i % 8)\n                bit = 1 if (src_byte & src_mask) else 0\n\n                dest_index = dest_bit_offset + i\n                dest_byte_index = dest_index // 8\n                dest_mask = 0x80 >> (dest_index % 8)\n\n                if bit:\n                    dest[dest_byte_index] |= dest_mask\n                else:\n                    dest[dest_byte_index] &= (~dest_mask) & 0xff\n            return\n\n        def dopad(self, data, data_bit_length):\n            padded = bytearray(self.block_size)\n            self.copy_bits(padded, 0, data, data_bit_length)\n\n            if data_bit_length < self.block_size * 8:\n                byte_index = data_bit_length // 8\n                bit_index = data_bit_length % 8\n                padded[byte_index] |= 0x80 >> bit_index\n\n            return bytes(padded)\n\n        def digest_block(self, block):\n            k = 0\n            for j in range(self.num_words):\n                mj = int.from_bytes(block[k:k + 4], \"big\")\n                self.z[j] = self.message_pre_process(mj ^ self.h[j])\n                self.h[j + 1] = self.z[j]\n                k += 4\n\n            self.h[0] = self.h[self.num_words]\n            return\n\n        def update(self, data, data_bit_length=None):\n            data = self.ensure_bytes_like(data)\n\n            if data_bit_length is None:\n                data_bit_length = len(data) * 8\n\n            if data_bit_length < 0 or data_bit_length > len(data) * 8:\n                raise ValueError(\"invalid data_bit_length\")\n\n            self.total_bits = (self.total_bits + data_bit_length) & 0xffff_ffff_ffff_ffff\n\n            block_bits = self.block_size * 8\n            remaining_bits = data_bit_length\n            source_bit_offset = 0\n\n            if self.residue_bit_length > 0:\n                take = min(block_bits - self.residue_bit_length, remaining_bits)\n                self.copy_bits(\n                    self.residue,\n                    self.residue_bit_length,\n                    data[source_bit_offset // 8:],\n                    take,\n                )\n                self.residue_bit_length += take\n                remaining_bits -= take\n                source_bit_offset += take\n\n                if self.residue_bit_length == block_bits:\n                    self.digest_block(bytes(self.residue))\n                    self.residue = bytearray(self.block_size)\n                    self.residue_bit_length = 0\n\n            while remaining_bits >= block_bits and source_bit_offset % 8 == 0:\n                start = source_bit_offset // 8\n                block = data[start:start + self.block_size]\n                self.digest_block(block)\n                remaining_bits -= block_bits\n                source_bit_offset += block_bits\n\n            if remaining_bits > 0:\n                self.copy_bits(\n                    self.residue,\n                    self.residue_bit_length,\n                    data[source_bit_offset // 8:],\n                    remaining_bits,\n                )\n                self.residue_bit_length += remaining_bits\n\n            return self\n\n        def finalize(self):\n            if self.residue_bit_length > 0 or self.z[0] == 0:\n                block = self.dopad(self.residue, self.residue_bit_length)\n                self.digest_block(block)\n                self.residue = bytearray(self.block_size)\n                self.residue_bit_length = 0\n\n            block = bytearray(self.block_size)\n            block[-8:] = self.total_bits.to_bytes(8, \"big\")\n            self.digest_block(bytes(block))\n\n            for _i in range(5):\n                mdash = self.words_to_bytes(self.z)\n                self.digest_block(mdash)\n                self.digest_block(mdash)\n\n            return\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.words_to_bytes(c.z)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class Khichidi1_224(Khichidi1Base):\n        block_size = 28\n        digest_size = 28\n\n    class Khichidi1_256(Khichidi1Base):\n        block_size = 32\n        digest_size = 32\n\n    class Khichidi1_384(Khichidi1Base):\n        block_size = 48\n        digest_size = 48\n\n    class Khichidi1_512(Khichidi1Base):\n        block_size = 64\n        digest_size = 64\n\n    class LesamntaBase:\n        rounds = 32\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n        c_table = (\n            (0x01, 0x00), (0x03, 0x02), (0x05, 0x04), (0x07, 0x06), (0x09, 0x08), (0x0b, 0x0a), (0x0d, 0x0c), (0x0f, 0x0e),\n            (0x11, 0x10), (0x13, 0x12), (0x15, 0x14), (0x17, 0x16), (0x19, 0x18), (0x1b, 0x1a), (0x1d, 0x1c), (0x1f, 0x1e),\n            (0x21, 0x20), (0x23, 0x22), (0x25, 0x24), (0x27, 0x26), (0x29, 0x28), (0x2b, 0x2a), (0x2d, 0x2c), (0x2f, 0x2e),\n            (0x31, 0x30), (0x33, 0x32), (0x35, 0x34), (0x37, 0x36), (0x39, 0x38), (0x3b, 0x3a), (0x3d, 0x3c), (0x3f, 0x3e),\n        )\n        mul2_table = (\n            0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,\n            0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,\n            0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,\n            0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,\n            0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,\n            0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,\n            0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,\n            0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,\n            0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,\n            0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,\n            0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,\n            0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,\n            0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,\n            0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,\n            0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,\n            0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,\n        )\n        mul4_table = (\n            0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c,\n            0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c, 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c,\n            0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c, 0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc,\n            0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc, 0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc,\n            0x1b, 0x1f, 0x13, 0x17, 0x0b, 0x0f, 0x03, 0x07, 0x3b, 0x3f, 0x33, 0x37, 0x2b, 0x2f, 0x23, 0x27,\n            0x5b, 0x5f, 0x53, 0x57, 0x4b, 0x4f, 0x43, 0x47, 0x7b, 0x7f, 0x73, 0x77, 0x6b, 0x6f, 0x63, 0x67,\n            0x9b, 0x9f, 0x93, 0x97, 0x8b, 0x8f, 0x83, 0x87, 0xbb, 0xbf, 0xb3, 0xb7, 0xab, 0xaf, 0xa3, 0xa7,\n            0xdb, 0xdf, 0xd3, 0xd7, 0xcb, 0xcf, 0xc3, 0xc7, 0xfb, 0xff, 0xf3, 0xf7, 0xeb, 0xef, 0xe3, 0xe7,\n            0x36, 0x32, 0x3e, 0x3a, 0x26, 0x22, 0x2e, 0x2a, 0x16, 0x12, 0x1e, 0x1a, 0x06, 0x02, 0x0e, 0x0a,\n            0x76, 0x72, 0x7e, 0x7a, 0x66, 0x62, 0x6e, 0x6a, 0x56, 0x52, 0x5e, 0x5a, 0x46, 0x42, 0x4e, 0x4a,\n            0xb6, 0xb2, 0xbe, 0xba, 0xa6, 0xa2, 0xae, 0xaa, 0x96, 0x92, 0x9e, 0x9a, 0x86, 0x82, 0x8e, 0x8a,\n            0xf6, 0xf2, 0xfe, 0xfa, 0xe6, 0xe2, 0xee, 0xea, 0xd6, 0xd2, 0xde, 0xda, 0xc6, 0xc2, 0xce, 0xca,\n            0x2d, 0x29, 0x25, 0x21, 0x3d, 0x39, 0x35, 0x31, 0x0d, 0x09, 0x05, 0x01, 0x1d, 0x19, 0x15, 0x11,\n            0x6d, 0x69, 0x65, 0x61, 0x7d, 0x79, 0x75, 0x71, 0x4d, 0x49, 0x45, 0x41, 0x5d, 0x59, 0x55, 0x51,\n            0xad, 0xa9, 0xa5, 0xa1, 0xbd, 0xb9, 0xb5, 0xb1, 0x8d, 0x89, 0x85, 0x81, 0x9d, 0x99, 0x95, 0x91,\n            0xed, 0xe9, 0xe5, 0xe1, 0xfd, 0xf9, 0xf5, 0xf1, 0xcd, 0xc9, 0xc5, 0xc1, 0xdd, 0xd9, 0xd5, 0xd1,\n        )\n        mul8_table = (\n            0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,\n            0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8,\n            0x1b, 0x13, 0x0b, 0x03, 0x3b, 0x33, 0x2b, 0x23, 0x5b, 0x53, 0x4b, 0x43, 0x7b, 0x73, 0x6b, 0x63,\n            0x9b, 0x93, 0x8b, 0x83, 0xbb, 0xb3, 0xab, 0xa3, 0xdb, 0xd3, 0xcb, 0xc3, 0xfb, 0xf3, 0xeb, 0xe3,\n            0x36, 0x3e, 0x26, 0x2e, 0x16, 0x1e, 0x06, 0x0e, 0x76, 0x7e, 0x66, 0x6e, 0x56, 0x5e, 0x46, 0x4e,\n            0xb6, 0xbe, 0xa6, 0xae, 0x96, 0x9e, 0x86, 0x8e, 0xf6, 0xfe, 0xe6, 0xee, 0xd6, 0xde, 0xc6, 0xce,\n            0x2d, 0x25, 0x3d, 0x35, 0x0d, 0x05, 0x1d, 0x15, 0x6d, 0x65, 0x7d, 0x75, 0x4d, 0x45, 0x5d, 0x55,\n            0xad, 0xa5, 0xbd, 0xb5, 0x8d, 0x85, 0x9d, 0x95, 0xed, 0xe5, 0xfd, 0xf5, 0xcd, 0xc5, 0xdd, 0xd5,\n            0x6c, 0x64, 0x7c, 0x74, 0x4c, 0x44, 0x5c, 0x54, 0x2c, 0x24, 0x3c, 0x34, 0x0c, 0x04, 0x1c, 0x14,\n            0xec, 0xe4, 0xfc, 0xf4, 0xcc, 0xc4, 0xdc, 0xd4, 0xac, 0xa4, 0xbc, 0xb4, 0x8c, 0x84, 0x9c, 0x94,\n            0x77, 0x7f, 0x67, 0x6f, 0x57, 0x5f, 0x47, 0x4f, 0x37, 0x3f, 0x27, 0x2f, 0x17, 0x1f, 0x07, 0x0f,\n            0xf7, 0xff, 0xe7, 0xef, 0xd7, 0xdf, 0xc7, 0xcf, 0xb7, 0xbf, 0xa7, 0xaf, 0x97, 0x9f, 0x87, 0x8f,\n            0x5a, 0x52, 0x4a, 0x42, 0x7a, 0x72, 0x6a, 0x62, 0x1a, 0x12, 0x0a, 0x02, 0x3a, 0x32, 0x2a, 0x22,\n            0xda, 0xd2, 0xca, 0xc2, 0xfa, 0xf2, 0xea, 0xe2, 0x9a, 0x92, 0x8a, 0x82, 0xba, 0xb2, 0xaa, 0xa2,\n            0x41, 0x49, 0x51, 0x59, 0x61, 0x69, 0x71, 0x79, 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39,\n            0xc1, 0xc9, 0xd1, 0xd9, 0xe1, 0xe9, 0xf1, 0xf9, 0x81, 0x89, 0x91, 0x99, 0xa1, 0xa9, 0xb1, 0xb9,\n        )\n        mul9_table = (\n            0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,\n            0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,\n            0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,\n            0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,\n            0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,\n            0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,\n            0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,\n            0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,\n            0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,\n            0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,\n            0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,\n            0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,\n            0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,\n            0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,\n            0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,\n            0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,\n        )\n        mul10_table = (\n            0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66,\n            0xa0, 0xaa, 0xb4, 0xbe, 0x88, 0x82, 0x9c, 0x96, 0xf0, 0xfa, 0xe4, 0xee, 0xd8, 0xd2, 0xcc, 0xc6,\n            0x5b, 0x51, 0x4f, 0x45, 0x73, 0x79, 0x67, 0x6d, 0x0b, 0x01, 0x1f, 0x15, 0x23, 0x29, 0x37, 0x3d,\n            0xfb, 0xf1, 0xef, 0xe5, 0xd3, 0xd9, 0xc7, 0xcd, 0xab, 0xa1, 0xbf, 0xb5, 0x83, 0x89, 0x97, 0x9d,\n            0xb6, 0xbc, 0xa2, 0xa8, 0x9e, 0x94, 0x8a, 0x80, 0xe6, 0xec, 0xf2, 0xf8, 0xce, 0xc4, 0xda, 0xd0,\n            0x16, 0x1c, 0x02, 0x08, 0x3e, 0x34, 0x2a, 0x20, 0x46, 0x4c, 0x52, 0x58, 0x6e, 0x64, 0x7a, 0x70,\n            0xed, 0xe7, 0xf9, 0xf3, 0xc5, 0xcf, 0xd1, 0xdb, 0xbd, 0xb7, 0xa9, 0xa3, 0x95, 0x9f, 0x81, 0x8b,\n            0x4d, 0x47, 0x59, 0x53, 0x65, 0x6f, 0x71, 0x7b, 0x1d, 0x17, 0x09, 0x03, 0x35, 0x3f, 0x21, 0x2b,\n            0x77, 0x7d, 0x63, 0x69, 0x5f, 0x55, 0x4b, 0x41, 0x27, 0x2d, 0x33, 0x39, 0x0f, 0x05, 0x1b, 0x11,\n            0xd7, 0xdd, 0xc3, 0xc9, 0xff, 0xf5, 0xeb, 0xe1, 0x87, 0x8d, 0x93, 0x99, 0xaf, 0xa5, 0xbb, 0xb1,\n            0x2c, 0x26, 0x38, 0x32, 0x04, 0x0e, 0x10, 0x1a, 0x7c, 0x76, 0x68, 0x62, 0x54, 0x5e, 0x40, 0x4a,\n            0x8c, 0x86, 0x98, 0x92, 0xa4, 0xae, 0xb0, 0xba, 0xdc, 0xd6, 0xc8, 0xc2, 0xf4, 0xfe, 0xe0, 0xea,\n            0xc1, 0xcb, 0xd5, 0xdf, 0xe9, 0xe3, 0xfd, 0xf7, 0x91, 0x9b, 0x85, 0x8f, 0xb9, 0xb3, 0xad, 0xa7,\n            0x61, 0x6b, 0x75, 0x7f, 0x49, 0x43, 0x5d, 0x57, 0x31, 0x3b, 0x25, 0x2f, 0x19, 0x13, 0x0d, 0x07,\n            0x9a, 0x90, 0x8e, 0x84, 0xb2, 0xb8, 0xa6, 0xac, 0xca, 0xc0, 0xde, 0xd4, 0xe2, 0xe8, 0xf6, 0xfc,\n            0x3a, 0x30, 0x2e, 0x24, 0x12, 0x18, 0x06, 0x0c, 0x6a, 0x60, 0x7e, 0x74, 0x42, 0x48, 0x56, 0x5c,\n        )\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.hash_words = self.initial_hash_words()\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.hash_words = list(self.hash_words)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = memoryview(data)\n            self.msg_len += len(data)\n\n            if self.buf:\n                need = self.block_size - len(self.buf)\n                if len(data) < need:\n                    self.buf.extend(data)\n                    return self\n                self.buf.extend(data[:need])\n                words = self.load_block_words(self.buf)\n                self.compress(self.hash_words, words)\n                self.buf.clear()\n                data = data[need:]\n\n            block_size = self.block_size\n            limit = len(data) - (len(data) % block_size)\n            offset = 0\n            while offset < limit:\n                words = self.load_block_words(data[offset:offset + block_size])\n                self.compress(self.hash_words, words)\n                offset += block_size\n\n            if offset != len(data):\n                self.buf.extend(data[offset:])\n\n            return self\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.store_hash_words(other.hash_words)[:self.digest_size]\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            final_block = bytearray(self.block_size)\n            buf_len = len(self.buf)\n            final_block[:buf_len] = self.buf\n            final_block[buf_len] = 0x80\n\n            if buf_len != 0:\n                words = self.load_block_words(final_block)\n                self.compress(self.hash_words, words)\n                final_block = bytearray(self.block_size)\n\n            words = self.load_block_words(final_block)\n            self.set_length_words(words, self.msg_len * 8)\n            self.output(self.hash_words, words)\n            return\n\n    class Lesamnta256Base(LesamntaBase):\n        block_size = 32\n        block_bits = 256\n\n        def initial_hash_words(self):\n            return [self.digest_bits] * 8\n\n        def load_block_words(self, block):\n            return [\n                int.from_bytes(block[0:4], \"big\"),\n                int.from_bytes(block[4:8], \"big\"),\n                int.from_bytes(block[8:12], \"big\"),\n                int.from_bytes(block[12:16], \"big\"),\n                int.from_bytes(block[16:20], \"big\"),\n                int.from_bytes(block[20:24], \"big\"),\n                int.from_bytes(block[24:28], \"big\"),\n                int.from_bytes(block[28:32], \"big\"),\n            ]\n\n        def store_hash_words(self, words):\n            return (\n                words[0].to_bytes(4, \"big\") +\n                words[1].to_bytes(4, \"big\") +\n                words[2].to_bytes(4, \"big\") +\n                words[3].to_bytes(4, \"big\") +\n                words[4].to_bytes(4, \"big\") +\n                words[5].to_bytes(4, \"big\") +\n                words[6].to_bytes(4, \"big\") +\n                words[7].to_bytes(4, \"big\")\n            )\n\n        def set_length_words(self, words, bit_len):\n            words[6] = (bit_len >> 32) & 0xffff_ffff\n            words[7] = bit_len & 0xffff_ffff\n            return\n\n        def f_func(self, words):\n            s = self.sbox\n            m2 = self.mul2_table\n\n            b0 = (words[0] >> 24) & 0xff\n            b1 = (words[0] >> 16) & 0xff\n            b2 = (words[0] >> 8) & 0xff\n            b3 = words[0] & 0xff\n            b4 = (words[1] >> 24) & 0xff\n            b5 = (words[1] >> 16) & 0xff\n            b6 = (words[1] >> 8) & 0xff\n            b7 = words[1] & 0xff\n\n            for _round_index in range(4):\n                b0 = s[b0]\n                b1 = s[b1]\n                b2 = s[b2]\n                b3 = s[b3]\n                b4 = s[b4]\n                b5 = s[b5]\n                b6 = s[b6]\n                b7 = s[b7]\n\n                b0, b1, b2, b3, b4, b5, b6, b7 = b0, b3, b2, b5, b4, b7, b6, b1\n\n                a0 = b0\n                a1 = b1\n                b0 = m2[a0] ^ a1\n                b1 = a0 ^ m2[a1]\n\n                a0 = b2\n                a1 = b3\n                b2 = m2[a0] ^ a1\n                b3 = a0 ^ m2[a1]\n\n                a0 = b4\n                a1 = b5\n                b4 = m2[a0] ^ a1\n                b5 = a0 ^ m2[a1]\n\n                a0 = b6\n                a1 = b7\n                b6 = m2[a0] ^ a1\n                b7 = a0 ^ m2[a1]\n\n            return [\n                (b0 << 24) | (b1 << 16) | (b2 << 8) | b3,\n                (b4 << 24) | (b5 << 16) | (b6 << 8) | b7,\n            ]\n\n        def sub_words(self, w0, w1):\n            s = self.sbox\n            return (\n                (s[(w0 >> 24) & 0xff] << 24) |\n                (s[(w0 >> 16) & 0xff] << 16) |\n                (s[(w0 >> 8) & 0xff] << 8) |\n                s[w0 & 0xff],\n                (s[(w1 >> 24) & 0xff] << 24) |\n                (s[(w1 >> 16) & 0xff] << 16) |\n                (s[(w1 >> 8) & 0xff] << 8) |\n                s[w1 & 0xff],\n            )\n\n        def key_linear_words(self, w0, w1):\n            m2 = self.mul2_table\n\n            a0 = (w0 >> 24) & 0xff\n            a1 = (w0 >> 16) & 0xff\n            a2 = (w0 >> 8) & 0xff\n            a3 = w0 & 0xff\n            x0 = m2[a0] ^ m2[a1] ^ a1 ^ a2 ^ a3\n            x1 = a0 ^ m2[a1] ^ m2[a2] ^ a2 ^ a3\n            x2 = a0 ^ a1 ^ m2[a2] ^ m2[a3] ^ a3\n            x3 = m2[a0] ^ a0 ^ a1 ^ a2 ^ m2[a3]\n\n            b0 = (w1 >> 24) & 0xff\n            b1 = (w1 >> 16) & 0xff\n            b2 = (w1 >> 8) & 0xff\n            b3 = w1 & 0xff\n            y0 = m2[b0] ^ m2[b1] ^ b1 ^ b2 ^ b3\n            y1 = b0 ^ m2[b1] ^ m2[b2] ^ b2 ^ b3\n            y2 = b0 ^ b1 ^ m2[b2] ^ m2[b3] ^ b3\n            y3 = m2[b0] ^ b0 ^ b1 ^ b2 ^ m2[b3]\n\n            return (\n                (y0 << 24) | (y1 << 16) | (x2 << 8) | x3,\n                (x0 << 24) | (x1 << 16) | (y2 << 8) | y3,\n            )\n\n        def compress(self, chain, mb):\n            x0, x1, x2, x3, x4, x5, x6, x7 = mb\n            k0, k1, k2, k3, k4, k5, k6, k7 = chain\n            f_func = self.f_func\n            c_table = self.c_table\n\n            for round_index in range(self.rounds):\n                t0, t1 = self.sub_words(k4 ^ c_table[round_index][0], k5 ^ c_table[round_index][1])\n                t0, t1 = self.key_linear_words(t0, t1)\n                k6 ^= t0\n                k7 ^= t1\n                k0, k1, k2, k3, k4, k5, k6, k7 = k6, k7, k0, k1, k2, k3, k4, k5\n                sub0, sub1 = f_func([x4 ^ k2, x5 ^ k3])\n                x6 ^= sub0\n                x7 ^= sub1\n                x0, x1, x2, x3, x4, x5, x6, x7 = x6, x7, x0, x1, x2, x3, x4, x5\n\n            chain[0] = x0 ^ mb[0]\n            chain[1] = x1 ^ mb[1]\n            chain[2] = x2 ^ mb[2]\n            chain[3] = x3 ^ mb[3]\n            chain[4] = x4 ^ mb[4]\n            chain[5] = x5 ^ mb[5]\n            chain[6] = x6 ^ mb[6]\n            chain[7] = x7 ^ mb[7]\n            return\n\n        def output(self, chain, mb):\n            x0, x1, x2, x3, x4, x5, x6, x7 = mb\n            k0, k1, k2, k3, k4, k5, k6, k7 = chain\n            f_func = self.f_func\n            c_table = self.c_table\n\n            for round_index in range(self.rounds):\n                sub0, sub1 = f_func([k4 ^ c_table[round_index][0], k5 ^ c_table[round_index][1]])\n                k6 ^= sub0\n                k7 ^= sub1\n                k0, k1, k2, k3, k4, k5, k6, k7 = k6, k7, k0, k1, k2, k3, k4, k5\n                sub0, sub1 = f_func([x4 ^ k2, x5 ^ k3])\n                x6 ^= sub0\n                x7 ^= sub1\n                x0, x1, x2, x3, x4, x5, x6, x7 = x6, x7, x0, x1, x2, x3, x4, x5\n\n            chain[0] = x0 ^ mb[0]\n            chain[1] = x1 ^ mb[1]\n            chain[2] = x2 ^ mb[2]\n            chain[3] = x3 ^ mb[3]\n            chain[4] = x4 ^ mb[4]\n            chain[5] = x5 ^ mb[5]\n            chain[6] = x6 ^ mb[6]\n            chain[7] = x7 ^ mb[7]\n            return\n\n    class Lesamnta512Base(LesamntaBase):\n        block_size = 64\n        block_bits = 512\n\n        def initial_hash_words(self):\n            return [self.digest_bits] * 8\n\n        def load_block_words(self, block):\n            return [\n                int.from_bytes(block[0:8], \"big\"),\n                int.from_bytes(block[8:16], \"big\"),\n                int.from_bytes(block[16:24], \"big\"),\n                int.from_bytes(block[24:32], \"big\"),\n                int.from_bytes(block[32:40], \"big\"),\n                int.from_bytes(block[40:48], \"big\"),\n                int.from_bytes(block[48:56], \"big\"),\n                int.from_bytes(block[56:64], \"big\"),\n            ]\n\n        def store_hash_words(self, words):\n            return (\n                words[0].to_bytes(8, \"big\") +\n                words[1].to_bytes(8, \"big\") +\n                words[2].to_bytes(8, \"big\") +\n                words[3].to_bytes(8, \"big\") +\n                words[4].to_bytes(8, \"big\") +\n                words[5].to_bytes(8, \"big\") +\n                words[6].to_bytes(8, \"big\") +\n                words[7].to_bytes(8, \"big\")\n            )\n\n        def set_length_words(self, words, bit_len):\n            words[6] = 0\n            words[7] = bit_len\n            return\n\n        def f_func(self, words):\n            s = self.sbox\n            m2 = self.mul2_table\n\n            b0 = (words[0] >> 56) & 0xff\n            b1 = (words[0] >> 48) & 0xff\n            b2 = (words[0] >> 40) & 0xff\n            b3 = (words[0] >> 32) & 0xff\n            b4 = (words[0] >> 24) & 0xff\n            b5 = (words[0] >> 16) & 0xff\n            b6 = (words[0] >> 8) & 0xff\n            b7 = words[0] & 0xff\n            b8 = (words[1] >> 56) & 0xff\n            b9 = (words[1] >> 48) & 0xff\n            b10 = (words[1] >> 40) & 0xff\n            b11 = (words[1] >> 32) & 0xff\n            b12 = (words[1] >> 24) & 0xff\n            b13 = (words[1] >> 16) & 0xff\n            b14 = (words[1] >> 8) & 0xff\n            b15 = words[1] & 0xff\n\n            for _round_index in range(4):\n                b0 = s[b0]\n                b1 = s[b1]\n                b2 = s[b2]\n                b3 = s[b3]\n                b4 = s[b4]\n                b5 = s[b5]\n                b6 = s[b6]\n                b7 = s[b7]\n                b8 = s[b8]\n                b9 = s[b9]\n                b10 = s[b10]\n                b11 = s[b11]\n                b12 = s[b12]\n                b13 = s[b13]\n                b14 = s[b14]\n                b15 = s[b15]\n\n                b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 = (\n                    b0, b5, b10, b15, b4, b9, b14, b3, b8, b13, b2, b7, b12, b1, b6, b11\n                )\n\n                a0 = b0\n                a1 = b1\n                a2 = b2\n                a3 = b3\n                b0 = m2[a0] ^ m2[a1] ^ a1 ^ a2 ^ a3\n                b1 = a0 ^ m2[a1] ^ m2[a2] ^ a2 ^ a3\n                b2 = a0 ^ a1 ^ m2[a2] ^ m2[a3] ^ a3\n                b3 = m2[a0] ^ a0 ^ a1 ^ a2 ^ m2[a3]\n\n                a0 = b4\n                a1 = b5\n                a2 = b6\n                a3 = b7\n                b4 = m2[a0] ^ m2[a1] ^ a1 ^ a2 ^ a3\n                b5 = a0 ^ m2[a1] ^ m2[a2] ^ a2 ^ a3\n                b6 = a0 ^ a1 ^ m2[a2] ^ m2[a3] ^ a3\n                b7 = m2[a0] ^ a0 ^ a1 ^ a2 ^ m2[a3]\n\n                a0 = b8\n                a1 = b9\n                a2 = b10\n                a3 = b11\n                b8 = m2[a0] ^ m2[a1] ^ a1 ^ a2 ^ a3\n                b9 = a0 ^ m2[a1] ^ m2[a2] ^ a2 ^ a3\n                b10 = a0 ^ a1 ^ m2[a2] ^ m2[a3] ^ a3\n                b11 = m2[a0] ^ a0 ^ a1 ^ a2 ^ m2[a3]\n\n                a0 = b12\n                a1 = b13\n                a2 = b14\n                a3 = b15\n                b12 = m2[a0] ^ m2[a1] ^ a1 ^ a2 ^ a3\n                b13 = a0 ^ m2[a1] ^ m2[a2] ^ a2 ^ a3\n                b14 = a0 ^ a1 ^ m2[a2] ^ m2[a3] ^ a3\n                b15 = m2[a0] ^ a0 ^ a1 ^ a2 ^ m2[a3]\n\n            return [\n                (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7,\n                (b8 << 56) | (b9 << 48) | (b10 << 40) | (b11 << 32) | (b12 << 24) | (b13 << 16) | (b14 << 8) | b15,\n            ]\n\n        def sub_words(self, w0, w1):\n            s = self.sbox\n            return (\n                (s[(w0 >> 56) & 0xff] << 56) |\n                (s[(w0 >> 48) & 0xff] << 48) |\n                (s[(w0 >> 40) & 0xff] << 40) |\n                (s[(w0 >> 32) & 0xff] << 32) |\n                (s[(w0 >> 24) & 0xff] << 24) |\n                (s[(w0 >> 16) & 0xff] << 16) |\n                (s[(w0 >> 8) & 0xff] << 8) |\n                s[w0 & 0xff],\n                (s[(w1 >> 56) & 0xff] << 56) |\n                (s[(w1 >> 48) & 0xff] << 48) |\n                (s[(w1 >> 40) & 0xff] << 40) |\n                (s[(w1 >> 32) & 0xff] << 32) |\n                (s[(w1 >> 24) & 0xff] << 24) |\n                (s[(w1 >> 16) & 0xff] << 16) |\n                (s[(w1 >> 8) & 0xff] << 8) |\n                s[w1 & 0xff],\n            )\n\n        def key_linear_words(self, w0, w1):\n            m2 = self.mul2_table\n            m4 = self.mul4_table\n            m8 = self.mul8_table\n            m9 = self.mul9_table\n            m10 = self.mul10_table\n\n            src = [\n                (w0 >> 56) & 0xff,\n                (w0 >> 48) & 0xff,\n                (w0 >> 40) & 0xff,\n                (w0 >> 32) & 0xff,\n                (w0 >> 24) & 0xff,\n                (w0 >> 16) & 0xff,\n                (w0 >> 8) & 0xff,\n                w0 & 0xff,\n                (w1 >> 56) & 0xff,\n                (w1 >> 48) & 0xff,\n                (w1 >> 40) & 0xff,\n                (w1 >> 32) & 0xff,\n                (w1 >> 24) & 0xff,\n                (w1 >> 16) & 0xff,\n                (w1 >> 8) & 0xff,\n                w1 & 0xff,\n            ]\n\n            out = [0] * 16\n            for base in (0, 8):\n                a0 = src[base + 0]\n                a1 = src[base + 1]\n                a2 = src[base + 2]\n                a3 = src[base + 3]\n                a4 = src[base + 4]\n                a5 = src[base + 5]\n                a6 = src[base + 6]\n                a7 = src[base + 7]\n\n                out[base + 0] = a0 ^ a1 ^ m2[a2] ^ m10[a3] ^ m9[a4] ^ m8[a5] ^ a6 ^ m4[a7]\n                out[base + 1] = m4[a0] ^ a1 ^ a2 ^ m2[a3] ^ m10[a4] ^ m9[a5] ^ m8[a6] ^ a7\n                out[base + 2] = a0 ^ m4[a1] ^ a2 ^ a3 ^ m2[a4] ^ m10[a5] ^ m9[a6] ^ m8[a7]\n                out[base + 3] = m8[a0] ^ a1 ^ m4[a2] ^ a3 ^ a4 ^ m2[a5] ^ m10[a6] ^ m9[a7]\n                out[base + 4] = m9[a0] ^ m8[a1] ^ a2 ^ m4[a3] ^ a4 ^ a5 ^ m2[a6] ^ m10[a7]\n                out[base + 5] = m10[a0] ^ m9[a1] ^ m8[a2] ^ a3 ^ m4[a4] ^ a5 ^ a6 ^ m2[a7]\n                out[base + 6] = m2[a0] ^ m10[a1] ^ m9[a2] ^ m8[a3] ^ a4 ^ m4[a5] ^ a6 ^ a7\n                out[base + 7] = a0 ^ m2[a1] ^ m10[a2] ^ m9[a3] ^ m8[a4] ^ a5 ^ m4[a6] ^ a7\n\n            return (\n                (out[8] << 56) | (out[9] << 48) | (out[10] << 40) | (out[11] << 32) | (out[4] << 24) | (out[5] << 16) | (out[6] << 8) | out[7],\n                (out[0] << 56) | (out[1] << 48) | (out[2] << 40) | (out[3] << 32) | (out[12] << 24) | (out[13] << 16) | (out[14] << 8) | out[15],\n            )\n\n        def compress(self, chain, mb):\n            x0, x1, x2, x3, x4, x5, x6, x7 = mb\n            k0, k1, k2, k3, k4, k5, k6, k7 = chain\n            f_func = self.f_func\n            c_table = self.c_table\n\n            for round_index in range(self.rounds):\n                t0, t1 = self.sub_words(k4 ^ c_table[round_index][0], k5 ^ c_table[round_index][1])\n                t0, t1 = self.key_linear_words(t0, t1)\n                k6 ^= t0\n                k7 ^= t1\n                k0, k1, k2, k3, k4, k5, k6, k7 = k6, k7, k0, k1, k2, k3, k4, k5\n                sub0, sub1 = f_func([x4 ^ k2, x5 ^ k3])\n                x6 ^= sub0\n                x7 ^= sub1\n                x0, x1, x2, x3, x4, x5, x6, x7 = x6, x7, x0, x1, x2, x3, x4, x5\n\n            chain[0] = x0 ^ mb[0]\n            chain[1] = x1 ^ mb[1]\n            chain[2] = x2 ^ mb[2]\n            chain[3] = x3 ^ mb[3]\n            chain[4] = x4 ^ mb[4]\n            chain[5] = x5 ^ mb[5]\n            chain[6] = x6 ^ mb[6]\n            chain[7] = x7 ^ mb[7]\n            return\n\n        def output(self, chain, mb):\n            x0, x1, x2, x3, x4, x5, x6, x7 = mb\n            k0, k1, k2, k3, k4, k5, k6, k7 = chain\n            f_func = self.f_func\n            c_table = self.c_table\n\n            for round_index in range(self.rounds):\n                sub0, sub1 = f_func([k4 ^ c_table[round_index][0], k5 ^ c_table[round_index][1]])\n                k6 ^= sub0\n                k7 ^= sub1\n                k0, k1, k2, k3, k4, k5, k6, k7 = k6, k7, k0, k1, k2, k3, k4, k5\n                sub0, sub1 = f_func([x4 ^ k2, x5 ^ k3])\n                x6 ^= sub0\n                x7 ^= sub1\n                x0, x1, x2, x3, x4, x5, x6, x7 = x6, x7, x0, x1, x2, x3, x4, x5\n\n            chain[0] = x0 ^ mb[0]\n            chain[1] = x1 ^ mb[1]\n            chain[2] = x2 ^ mb[2]\n            chain[3] = x3 ^ mb[3]\n            chain[4] = x4 ^ mb[4]\n            chain[5] = x5 ^ mb[5]\n            chain[6] = x6 ^ mb[6]\n            chain[7] = x7 ^ mb[7]\n            return\n\n    class Lesamnta224(Lesamnta256Base):\n        digest_bits = 0x0000_0224\n        digest_size = 28\n\n    class Lesamnta256(Lesamnta256Base):\n        digest_bits = 0x0000_0256\n        digest_size = 32\n\n    class Lesamnta384(Lesamnta512Base):\n        digest_bits = 0x0000_0000_0000_0384\n        digest_size = 48\n\n    class Lesamnta512(Lesamnta512Base):\n        digest_bits = 0x0000_0000_0000_0512\n        digest_size = 64\n\n    class LUXBase:\n        block_size = None\n        digest_size = None\n        hashbitlen = None\n        mrows = None\n\n        SBOX = bytes([\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        ])\n\n        SHIFT_ROWS_4 = (0, 1, 3, 4)\n        SHIFT_ROWS_8 = (0, 1, 2, 3, 4, 5, 6, 7)\n\n        ADD_CONSTANT = (0x2a, 0xd0, 0x1c, 0x64)\n\n        MUL1 = bytes(range(256))\n        MUL2 = None\n        MUL3 = None\n        MUL4 = None\n        MUL6 = None\n        MUL8 = None\n        MUL12 = None\n\n        @classmethod\n        def initTables(cls):\n            if cls.MUL2 is not None:\n                return\n\n            def xtime(x):\n                y = x << 1\n                if x & 0x80:\n                    y ^= 0x1b\n                return y & 0xff\n\n            mul2 = bytearray(256)\n            mul3 = bytearray(256)\n            mul4 = bytearray(256)\n            mul6 = bytearray(256)\n            mul8 = bytearray(256)\n            mul12 = bytearray(256)\n\n            for x in range(256):\n                x2 = xtime(x)\n                x4 = xtime(x2)\n                x8 = xtime(x4)\n                mul2[x] = x2\n                mul3[x] = x2 ^ x\n                mul4[x] = x4\n                mul6[x] = x4 ^ x2\n                mul8[x] = x8\n                mul12[x] = x8 ^ x4\n\n            cls.MUL2 = bytes(mul2)\n            cls.MUL3 = bytes(mul3)\n            cls.MUL4 = bytes(mul4)\n            cls.MUL6 = bytes(mul6)\n            cls.MUL8 = bytes(mul8)\n            cls.MUL12 = bytes(mul12)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.__class__.initTables()\n            self.cr = [bytearray(8) for _ in range(self.mrows)]\n            self.bf = [bytearray(16) for _ in range(self.mrows)]\n            self.buf = bytearray()\n            self.total_bits = 0\n            self.partial_bits = 0\n            self.partial_byte = 0\n            self.finalized = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.cr = [bytearray(row) for row in self.cr]\n            other.bf = [bytearray(row) for row in self.bf]\n            other.buf = bytearray(self.buf)\n            other.total_bits = self.total_bits\n            other.partial_bits = self.partial_bits\n            other.partial_byte = self.partial_byte\n            other.finalized = self.finalized\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if self.partial_bits:\n                raise ValueError(\"cannot update after partial-bit input\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.total_bits += len(data) * 8\n            self.buf.extend(data)\n            self.processBuffer()\n            return self\n\n        def processBuffer(self):\n            block_size = self.mrows\n            compress = self.compress\n            buf = self.buf\n            while len(buf) >= block_size:\n                block = bytes(buf[:block_size])\n                del buf[:block_size]\n                compress(block)\n            return\n\n        def subBytes(self):\n            sbox = self.SBOX\n            for i in range(self.mrows):\n                row = self.cr[i]\n                for j in range(8):\n                    row[j] = sbox[row[j]]\n            return\n\n        def shiftRows(self):\n            if self.mrows == 4:\n                shifts = self.SHIFT_ROWS_4\n            else:\n                shifts = self.SHIFT_ROWS_8\n\n            for i, shift in enumerate(shifts):\n                if shift:\n                    row = self.cr[i]\n                    self.cr[i] = row[shift:] + row[:shift]\n            return\n\n        def mixColumns4(self):\n            m1 = self.MUL1\n            m2 = self.MUL2\n            m3 = self.MUL3\n\n            cr0 = self.cr[0]\n            cr1 = self.cr[1]\n            cr2 = self.cr[2]\n            cr3 = self.cr[3]\n\n            out0 = bytearray(8)\n            out1 = bytearray(8)\n            out2 = bytearray(8)\n            out3 = bytearray(8)\n\n            for j in range(8):\n                a0 = cr0[j]\n                a1 = cr1[j]\n                a2 = cr2[j]\n                a3 = cr3[j]\n                out0[j] = m2[a0] ^ m3[a1] ^ m1[a2] ^ m1[a3]\n                out1[j] = m1[a0] ^ m2[a1] ^ m3[a2] ^ m1[a3]\n                out2[j] = m1[a0] ^ m1[a1] ^ m2[a2] ^ m3[a3]\n                out3[j] = m3[a0] ^ m1[a1] ^ m1[a2] ^ m2[a3]\n\n            self.cr[0] = out0\n            self.cr[1] = out1\n            self.cr[2] = out2\n            self.cr[3] = out3\n            return\n\n        def mixColumns8(self):\n            m1 = self.MUL1\n            m2 = self.MUL2\n            m4 = self.MUL4\n            m6 = self.MUL6\n            m8 = self.MUL8\n            m12 = self.MUL12\n            cr = self.cr\n            out = [bytearray(8) for _ in range(8)]\n\n            for j in range(8):\n                a0 = cr[0][j]\n                a1 = cr[1][j]\n                a2 = cr[2][j]\n                a3 = cr[3][j]\n                a4 = cr[4][j]\n                a5 = cr[5][j]\n                a6 = cr[6][j]\n                a7 = cr[7][j]\n\n                out[0][j] = m1[a0] ^ m4[a1] ^ m1[a2] ^ m1[a3] ^ m2[a4] ^ m12[a5] ^ m6[a6] ^ m8[a7]\n                out[1][j] = m8[a0] ^ m1[a1] ^ m4[a2] ^ m1[a3] ^ m1[a4] ^ m2[a5] ^ m12[a6] ^ m6[a7]\n                out[2][j] = m6[a0] ^ m8[a1] ^ m1[a2] ^ m4[a3] ^ m1[a4] ^ m1[a5] ^ m2[a6] ^ m12[a7]\n                out[3][j] = m12[a0] ^ m6[a1] ^ m8[a2] ^ m1[a3] ^ m4[a4] ^ m1[a5] ^ m1[a6] ^ m2[a7]\n                out[4][j] = m2[a0] ^ m12[a1] ^ m6[a2] ^ m8[a3] ^ m1[a4] ^ m4[a5] ^ m1[a6] ^ m1[a7]\n                out[5][j] = m1[a0] ^ m2[a1] ^ m12[a2] ^ m6[a3] ^ m8[a4] ^ m1[a5] ^ m4[a6] ^ m1[a7]\n                out[6][j] = m1[a0] ^ m1[a1] ^ m2[a2] ^ m12[a3] ^ m6[a4] ^ m8[a5] ^ m1[a6] ^ m4[a7]\n                out[7][j] = m4[a0] ^ m1[a1] ^ m1[a2] ^ m2[a3] ^ m12[a4] ^ m6[a5] ^ m8[a6] ^ m1[a7]\n\n            self.cr = out\n            return\n\n        def addConstant(self):\n            if self.mrows == 4:\n                for i, val in enumerate(self.ADD_CONSTANT):\n                    self.cr[i][0] ^= val\n            else:\n                for i, val in enumerate(self.ADD_CONSTANT):\n                    self.cr[i + 4][0] ^= val\n            return\n\n        def functionG(self):\n            self.subBytes()\n            self.shiftRows()\n            if self.mrows == 4:\n                self.mixColumns4()\n            else:\n                self.mixColumns8()\n            self.addConstant()\n            return\n\n        def functionF(self):\n            bf = self.bf\n            temp = [bf[i][15] for i in range(self.mrows)]\n\n            for j in range(15, 0, -1):\n                for i in range(self.mrows):\n                    bf[i][j] = bf[i][j - 1]\n\n            for i in range(self.mrows):\n                bf[i][0] = temp[i]\n            return\n\n        def compress(self, block):\n            for i in range(self.mrows):\n                x = block[self.mrows - 1 - i]\n                self.bf[i][0] ^= x\n                self.cr[i][0] ^= x\n\n            self.functionG()\n            self.functionF()\n\n            for j in range(8):\n                for i in range(self.mrows):\n                    self.bf[i][j + 4] ^= self.cr[i][j]\n\n            for i in range(self.mrows):\n                self.cr[i][7] ^= self.bf[i][15]\n            return\n\n        def finalBytes(self):\n            rem = bytearray(self.mrows)\n            used = len(self.buf)\n            rem[:used] = self.buf\n\n            if self.partial_bits:\n                idx = used\n                rem[idx] = self.partial_byte & (0xff << (8 - self.partial_bits))\n                rem[idx] ^= 0x01 << (7 - self.partial_bits)\n            elif used:\n                rem[used] = 0x80\n            else:\n                rem[0] = 0x80\n\n            return rem\n\n        def finalize(self):\n            if self.finalized:\n                return\n\n            rem = self.finalBytes()\n            self.compress(rem)\n\n            length_block = self.total_bits.to_bytes(8, \"big\")\n            if self.hashbitlen <= 256:\n                self.compress(length_block[:4])\n                self.compress(length_block[4:])\n            else:\n                self.compress(length_block)\n\n            zero = bytes(self.mrows)\n\n            for _ in range(16):\n                self.compress(zero)\n\n            out = bytearray()\n            if self.hashbitlen <= 256:\n                for _ in range(self.hashbitlen // 32):\n                    self.compress(zero)\n                    out.extend((self.cr[3][3], self.cr[2][3], self.cr[1][3], self.cr[0][3]))\n            else:\n                for _ in range(self.hashbitlen // 64):\n                    self.compress(zero)\n                    out.extend((\n                        self.cr[7][3], self.cr[6][3], self.cr[5][3], self.cr[4][3],\n                        self.cr[3][3], self.cr[2][3], self.cr[1][3], self.cr[0][3],\n                    ))\n\n            self.result = bytes(out)\n            self.finalized = True\n            return\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.result\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class LUX224(LUXBase):\n        block_size = 4\n        digest_size = 28\n        hashbitlen = 224\n        mrows = 4\n\n    class LUX256(LUXBase):\n        block_size = 4\n        digest_size = 32\n        hashbitlen = 256\n        mrows = 4\n\n    class LUX384(LUXBase):\n        block_size = 8\n        digest_size = 48\n        hashbitlen = 384\n        mrows = 8\n\n    class LUX512(LUXBase):\n        block_size = 8\n        digest_size = 64\n        hashbitlen = 512\n        mrows = 8\n\n    class MCSSHA3Base:\n        block_size = 1\n\n        sbox = (\n            0x30, 0x60, 0x67, 0xb5, 0x43, 0xea, 0x93, 0x25,\n            0x48, 0x0d, 0x18, 0x6f, 0x28, 0x7a, 0xfe, 0xb6,\n            0xd5, 0x9c, 0x23, 0x86, 0x52, 0x42, 0xf7, 0xfd,\n            0xf6, 0x9b, 0xee, 0x99, 0x91, 0xbc, 0x2a, 0x63,\n            0xa1, 0xa0, 0x57, 0x3c, 0x39, 0xd2, 0xec, 0x71,\n            0x45, 0xcb, 0x41, 0xdc, 0x0b, 0x5b, 0xc2, 0x36,\n            0x01, 0x55, 0x7d, 0xfb, 0xed, 0x83, 0x8f, 0x31,\n            0xc0, 0x4c, 0x08, 0xe3, 0x9d, 0xc1, 0xd3, 0xe9,\n            0xb8, 0xbd, 0xae, 0x0f, 0xe7, 0x70, 0x5a, 0xeb,\n            0x4d, 0x29, 0xf9, 0xa9, 0x3d, 0x26, 0x46, 0x06,\n            0xd0, 0x50, 0xa5, 0xbe, 0x66, 0x90, 0xf4, 0x20,\n            0xe4, 0x33, 0x27, 0xe2, 0xab, 0xef, 0x68, 0x54,\n            0x37, 0x6a, 0xdb, 0xbb, 0xd8, 0x7b, 0x69, 0xc4,\n            0xf2, 0xbf, 0x85, 0xc7, 0xa6, 0xb4, 0x9a, 0xdd,\n            0x72, 0x34, 0xe8, 0xfc, 0xd6, 0x21, 0x98, 0x96,\n            0x32, 0xca, 0x49, 0xb3, 0xf3, 0x97, 0x8e, 0x2f,\n            0x00, 0xb0, 0x10, 0x1a, 0x77, 0x38, 0xcf, 0x51,\n            0xba, 0x1f, 0x22, 0xac, 0x62, 0x89, 0x76, 0xc3,\n            0x02, 0x6e, 0x2c, 0x47, 0x3a, 0x5c, 0x1b, 0x56,\n            0x8a, 0x5d, 0x03, 0x16, 0x74, 0x58, 0x79, 0x09,\n            0xd7, 0xf5, 0x0a, 0x92, 0x4f, 0x87, 0xcd, 0xda,\n            0x8c, 0xc9, 0x9e, 0x3b, 0x12, 0x6b, 0x53, 0xff,\n            0x80, 0xb7, 0xf8, 0xd9, 0xf1, 0x5e, 0xaf, 0xe0,\n            0x05, 0xa4, 0x14, 0x2b, 0xa3, 0xcc, 0x6c, 0x7c,\n            0x78, 0xaa, 0x95, 0x84, 0x61, 0xa8, 0xce, 0x13,\n            0x88, 0xfa, 0x59, 0x4e, 0xb9, 0xc8, 0x4b, 0x24,\n            0xd1, 0x07, 0x94, 0x2e, 0xdf, 0xb1, 0x17, 0xa2,\n            0x1d, 0x4a, 0xc6, 0xad, 0x15, 0x19, 0x35, 0x7f,\n            0x81, 0x44, 0x0c, 0x9f, 0x75, 0x7e, 0xd4, 0x82,\n            0xde, 0xe6, 0xe1, 0x2d, 0x3e, 0x73, 0x11, 0x8b,\n            0xc5, 0xa7, 0xf0, 0x6d, 0x1c, 0x64, 0x0e, 0x04,\n            0x40, 0x1e, 0x8d, 0xe5, 0x3f, 0xb2, 0x65, 0x5f,\n        )\n\n        def __init__(self, data=b\"\", bit_length=None):\n            if self.hashbitlen not in (224, 256, 384, 512):\n                raise ValueError(\"invalid hashbitlen\")\n\n            n = (self.hashbitlen >> 3) - 1\n            self.points = [0, 1, n - 3, n]\n            self.partial_bits = 0\n            self.partial_byte = 0\n            self.state = bytearray(range(n + 1))\n\n            if data:\n                if bit_length is None:\n                    self.update(data)\n                else:\n                    self.update_bits(data, bit_length)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.points = self.points[:]\n            other.partial_bits = self.partial_bits\n            other.partial_byte = self.partial_byte\n            other.state = bytearray(self.state)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            self.update_bits(data, len(data) * 8)\n            return self\n\n        def update_bits(self, data, bit_length):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            if isinstance(data, memoryview):\n                data = data.tobytes()\n            else:\n                data = bytes(data)\n\n            if bit_length < 0:\n                raise ValueError(\"bit_length must be non-negative\")\n            if bit_length > len(data) * 8:\n                raise ValueError(\"bit_length exceeds input size\")\n\n            x1 = self.points[0]\n            x2 = self.points[1]\n            x3 = self.points[2]\n            x4 = self.points[3]\n            bits = self.partial_bits\n            last = self.partial_byte\n\n            n = (self.hashbitlen >> 3) - 8\n            state_len = n + 8\n            full_bytes = (bit_length + bits) >> 3\n\n            state = self.state\n            sbox = self.sbox\n\n            index = 0\n            while index < full_bytes:\n                value = data[index]\n\n                if bits != 0:\n                    mixed = last ^ (value >> bits)\n                    last = (value << (8 - bits)) & 0xff\n                    state[x1] = (\n                        sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff] + mixed\n                    ) & 0xff\n                else:\n                    state[x1] = (\n                        sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff] + value\n                    ) & 0xff\n\n                x1 += 1\n                x2 += 1\n                x3 += 1\n                x4 += 1\n\n                if x1 == state_len:\n                    x1 = 0\n                if x2 == state_len:\n                    x2 = 0\n                if x3 == state_len:\n                    x3 = 0\n                if x4 == state_len:\n                    x4 = 0\n\n                state[x1] = sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff]\n                x1 += 1\n                x2 += 1\n                x3 += 1\n                x4 += 1\n                if x1 == state_len:\n                    x1 = 0\n                if x2 == state_len:\n                    x2 = 0\n                if x3 == state_len:\n                    x3 = 0\n                if x4 == state_len:\n                    x4 = 0\n\n                state[x1] = sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff]\n                x1 += 1\n                x2 += 1\n                x3 += 1\n                x4 += 1\n                if x1 == state_len:\n                    x1 = 0\n                if x2 == state_len:\n                    x2 = 0\n                if x3 == state_len:\n                    x3 = 0\n                if x4 == state_len:\n                    x4 = 0\n\n                state[x1] = sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff]\n                x1 += 1\n                x2 += 1\n                x3 += 1\n                x4 += 1\n                if x1 == state_len:\n                    x1 = 0\n                if x2 == state_len:\n                    x2 = 0\n                if x3 == state_len:\n                    x3 = 0\n                if x4 == state_len:\n                    x4 = 0\n\n                index += 1\n\n            if bits != 0:\n                self.partial_bits = bit_length + bits - (index << 3)\n                if self.partial_bits != 0:\n                    if index != 0:\n                        self.partial_byte = ((last >> (8 - self.partial_bits)) << (8 - self.partial_bits)) & 0xff\n                    else:\n                        mixed = last ^ (data[index] >> bits)\n                        self.partial_byte = ((mixed >> (8 - self.partial_bits)) << (8 - self.partial_bits)) & 0xff\n                else:\n                    self.partial_byte = 0\n            else:\n                self.partial_bits = bit_length - ((bit_length >> 3) << 3)\n                if self.partial_bits != 0:\n                    self.partial_byte = ((data[index] >> (8 - self.partial_bits)) << (8 - self.partial_bits)) & 0xff\n                else:\n                    self.partial_byte = 0\n\n            self.points[0] = x1\n            self.points[1] = x2\n            self.points[2] = x3\n            self.points[3] = x4\n            return self\n\n        def finalize(self):\n            x1 = self.points[0]\n            x2 = self.points[1]\n            x3 = self.points[2]\n            x4 = self.points[3]\n            bits = self.partial_bits\n            last = self.partial_byte\n\n            n = (self.hashbitlen >> 3) - 8\n            state_len = n + 8\n            final_len = self.hashbitlen >> 1\n\n            state = self.state\n            sbox = self.sbox\n            repeated = bytes(state[:state_len]) * 4\n\n            index = 0\n            while index < final_len:\n                value = repeated[index]\n\n                if bits != 0:\n                    mixed = last ^ (value >> bits)\n                    last = (value << (8 - bits)) & 0xff\n                    state[x1] = (\n                        sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff] + mixed\n                    ) & 0xff\n                else:\n                    state[x1] = (\n                        sbox[(state[x1] - state[x2] - state[x3] + state[x4]) & 0xff] + value\n                    ) & 0xff\n\n                x1 += 1\n                x2 += 1\n                x3 += 1\n                x4 += 1\n\n                if x1 == state_len:\n                    x1 = 0\n                if x2 == state_len:\n                    x2 = 0\n                if x3 == state_len:\n                    x3 = 0\n                if x4 == state_len:\n                    x4 = 0\n\n                index += 1\n\n            self.points[0] = x1\n            self.points[1] = x2\n            self.points[2] = x3\n            self.points[3] = x4\n            self.partial_bits = bits\n            self.partial_byte = last\n            return bytes(state[:state_len])\n\n        def digest(self):\n            other = self.copy()\n            result = other.finalize()\n            return result\n\n        def hexdigest(self):\n            result = self.digest().hex()\n            return result\n\n    class MCSSHA3_224(MCSSHA3Base):\n        digest_size = 28\n        hashbitlen = 224\n\n    class MCSSHA3_256(MCSSHA3Base):\n        digest_size = 32\n        hashbitlen = 256\n\n    class MCSSHA3_384(MCSSHA3Base):\n        digest_size = 48\n        hashbitlen = 384\n\n    class MCSSHA3_512(MCSSHA3Base):\n        digest_size = 64\n        hashbitlen = 512\n\n    class MeshHashBase:\n        word_size = 8\n        counter_length = 4\n        min_number_of_pipes = 4\n        max_number_of_pipes = 256\n        number_of_extra_pipes = 1\n\n        def __init__(self, data=b\"\"):\n            if self.hashbitlen is None or self.digest_size is None:\n                raise ValueError(\"hashbitlen and digest_size must be defined\")\n            self.number_of_pipes = self.compute_number_of_pipes(self.hashbitlen)\n            self.block_size = self.number_of_pipes * self.word_size\n            self.pipe = [0] * (self.number_of_pipes + 1)\n            self.bit_counter = [0] * self.counter_length\n            self.block_counter = [0] * self.counter_length\n            self.block_round_counter = 0\n            self.data_buffer = bytearray()\n            self.msg_len = 0\n            self.squeezing = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.number_of_pipes = self.number_of_pipes\n            other.block_size = self.block_size\n            other.pipe = self.pipe[:]\n            other.bit_counter = self.bit_counter[:]\n            other.block_counter = self.block_counter[:]\n            other.block_round_counter = self.block_round_counter\n            other.data_buffer = bytearray(self.data_buffer)\n            other.msg_len = self.msg_len\n            other.squeezing = self.squeezing\n            return other\n\n        def compute_number_of_pipes(self, hashbitlen):\n            number_of_pipes = (hashbitlen + 63) // 64\n            number_of_pipes += self.number_of_extra_pipes\n            if number_of_pipes < self.min_number_of_pipes:\n                number_of_pipes = self.min_number_of_pipes\n            if number_of_pipes > self.max_number_of_pipes:\n                number_of_pipes = self.max_number_of_pipes\n            return number_of_pipes\n\n        def rot64(self, word, bits):\n            bits &= 63\n            if bits == 0:\n                return word\n            return ((word >> bits) | ((word << (64 - bits)) & 0xffff_ffff_ffff_ffff)) & 0xffff_ffff_ffff_ffff\n\n        def sbox(self, word):\n            word = (word * 0x9e37_79b9_7f4a_7bb9 + 0x5e2d_58d8_b3bc_def7) & 0xffff_ffff_ffff_ffff\n            word = self.rot64(word, 37)\n            word = (word * 0x9e37_79b9_7f4a_7bb9 + 0x5e2d_58d8_b3bc_def7) & 0xffff_ffff_ffff_ffff\n            word = self.rot64(word, 37)\n            return word\n\n        def add_to_counter(self, counter, to_add):\n            carry = 0\n            for i in range(self.counter_length):\n                temp = ((to_add & 0xffff_ffff_ffff_ffff) + carry) & 0xffff_ffff_ffff_ffff\n                counter[i] = (counter[i] + temp) & 0xffff_ffff_ffff_ffff\n                if carry == 1 and temp == 0:\n                    carry = 1\n                elif counter[i] < temp:\n                    carry = 1\n                else:\n                    carry = 0\n                to_add >>= 64\n            return\n\n        def normal_round(self, data_word):\n            pipe = self.pipe\n            number_of_pipes = self.number_of_pipes\n            rot64 = self.rot64\n            sbox = self.sbox\n            xor_step = 0x0101_0101_0101_0101\n\n            pipe[number_of_pipes] = pipe[0]\n            for i in range(number_of_pipes):\n                value = pipe[i] ^ (i * xor_step) ^ data_word\n                value = rot64(value, (i * 37) & 63)\n                value = sbox(value)\n                pipe[i] = (value + pipe[i + 1]) & 0xffff_ffff_ffff_ffff\n\n            self.block_round_counter += 1\n            return\n\n        def final_block_round(self):\n            pipe = self.pipe\n            number_of_pipes = self.number_of_pipes\n            sbox = self.sbox\n            block_counter = self.block_counter\n\n            self.block_round_counter = 0\n            for i in range(number_of_pipes):\n                pipe[i] = sbox(pipe[i] ^ block_counter[i % self.counter_length])\n            self.add_to_counter(block_counter, 1)\n            return\n\n        def process_word(self, data_word):\n            self.normal_round(data_word)\n            if self.block_round_counter == self.number_of_pipes:\n                self.final_block_round()\n            return\n\n        def update(self, data):\n            if self.squeezing:\n                raise ValueError(\"cannot update after finalize\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            mv = memoryview(data).cast(\"B\")\n            data_len = len(mv)\n            if data_len == 0:\n                return self\n\n            self.msg_len += data_len\n            self.add_to_counter(self.bit_counter, data_len * 8)\n\n            offset = 0\n\n            if self.data_buffer:\n                needed = 8 - len(self.data_buffer)\n                take = needed\n                if take > data_len:\n                    take = data_len\n                self.data_buffer.extend(mv[:take])\n                offset += take\n                if len(self.data_buffer) == 8:\n                    self.process_word(int.from_bytes(self.data_buffer, \"big\"))\n                    self.data_buffer.clear()\n\n            remaining = data_len - offset\n            full_len = remaining & ~7\n            end = offset + full_len\n            while offset < end:\n                self.process_word(int.from_bytes(mv[offset:offset + 8], \"big\"))\n                offset += 8\n\n            if offset < data_len:\n                self.data_buffer.extend(mv[offset:data_len])\n\n            return self\n\n        def finalize(self):\n            if self.squeezing:\n                return\n\n            if self.data_buffer:\n                padded = bytes(self.data_buffer) + (b\"\\x00\" * (8 - len(self.data_buffer)))\n                self.process_word(int.from_bytes(padded, \"big\"))\n                self.data_buffer.clear()\n\n            if self.block_round_counter != 0:\n                while self.block_round_counter < self.number_of_pipes:\n                    self.normal_round(0)\n                self.final_block_round()\n\n            pipe = self.pipe\n            sbox = self.sbox\n            xor_step = 0x0101_0101_0101_0101\n\n            for counter_word in self.bit_counter:\n                for pipe_index in range(self.number_of_pipes):\n                    pipe[pipe_index] = sbox(pipe[pipe_index] ^ counter_word ^ (pipe_index * xor_step))\n\n            for pipe_index in range(self.number_of_pipes):\n                pipe[pipe_index] = sbox(pipe[pipe_index] ^ self.hashbitlen ^ (pipe_index * xor_step))\n\n            self.squeezing = True\n            return\n\n        def squeeze_bytes(self, size):\n            out = bytearray(size)\n            pipe = self.pipe\n            for i in range(size):\n                self.normal_round(0)\n                temp = 0\n                for j in range(0, self.number_of_pipes, 2):\n                    temp ^= pipe[j]\n                out[i] = temp & 0xff\n                if self.block_round_counter == self.number_of_pipes:\n                    self.final_block_round()\n            return bytes(out)\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.squeeze_bytes(other.digest_size)\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n    class MeshHash224(MeshHashBase):\n        digest_size = 28\n        hashbitlen = 224\n\n    class MeshHash256(MeshHashBase):\n        digest_size = 32\n        hashbitlen = 256\n\n    class MeshHash384(MeshHashBase):\n        digest_size = 48\n        hashbitlen = 384\n\n    class MeshHash512(MeshHashBase):\n        digest_size = 64\n        hashbitlen = 512\n\n    class NaSHABase:\n        sbox = (\n            0x8c, 0x90, 0xd9, 0xc1, 0x46, 0x63, 0x53, 0xf1, 0x61, 0x32, 0x15, 0x3e, 0x26, 0x9a, 0x97, 0x2e,\n            0xd8, 0xa0, 0x99, 0x9e, 0xc0, 0x95, 0x67, 0xb7, 0x6d, 0xe0, 0xf3, 0x28, 0x20, 0x86, 0xb6, 0xef,\n            0x4b, 0x31, 0xb5, 0xd2, 0x13, 0x39, 0x6c, 0xa5, 0x03, 0x3f, 0x4d, 0x34, 0xf9, 0xec, 0x8e, 0x17,\n            0xc5, 0x25, 0x3c, 0x89, 0xc9, 0x2b, 0x3a, 0xc2, 0x6e, 0xc6, 0xaa, 0x91, 0x49, 0x18, 0x93, 0xde,\n            0x0d, 0x6f, 0x65, 0xaf, 0x92, 0xa7, 0xf6, 0xa6, 0x40, 0xb9, 0xed, 0xb0, 0xc3, 0xd7, 0x7d, 0x7c,\n            0x54, 0x59, 0xdf, 0x2f, 0xda, 0xa4, 0x05, 0x94, 0x9b, 0x72, 0x01, 0x74, 0xa9, 0xf7, 0x81, 0xe9,\n            0x1f, 0xb3, 0xeb, 0xcf, 0xe8, 0x47, 0x52, 0x36, 0xbc, 0x16, 0x29, 0x76, 0x12, 0xfa, 0x9c, 0x8a,\n            0x5b, 0xa8, 0x43, 0xd1, 0x79, 0x85, 0x42, 0x82, 0xc7, 0xa1, 0x78, 0x4f, 0xe2, 0x35, 0xea, 0xad,\n            0xdc, 0x0e, 0xd3, 0x2d, 0x6a, 0x5a, 0x44, 0xab, 0xc8, 0xe5, 0x37, 0x0a, 0x6b, 0x51, 0xe3, 0x14,\n            0xcd, 0x56, 0x4a, 0xd6, 0x08, 0x83, 0xbb, 0x33, 0xe1, 0x30, 0x4e, 0x24, 0x5e, 0xb4, 0x00, 0x48,\n            0x5f, 0x22, 0x0b, 0x50, 0x3d, 0x80, 0x1a, 0xbf, 0xcc, 0xff, 0x64, 0x87, 0x1b, 0xc4, 0x07, 0xf8,\n            0x0c, 0xd4, 0xac, 0x02, 0x10, 0x84, 0x7e, 0x69, 0x70, 0x60, 0x55, 0x2a, 0x21, 0x57, 0x23, 0x66,\n            0x62, 0x73, 0xcb, 0x41, 0x58, 0x71, 0x77, 0x1c, 0x7b, 0x8f, 0x9f, 0x9d, 0xa3, 0xb1, 0x7f, 0x5d,\n            0xf4, 0x06, 0xae, 0xd5, 0xe6, 0x3b, 0xba, 0xfe, 0x96, 0xe7, 0x0f, 0x45, 0x2c, 0xf0, 0xfc, 0xbd,\n            0xe4, 0x98, 0xfb, 0xca, 0x11, 0xf5, 0xdd, 0x7a, 0x5c, 0xfd, 0xce, 0x88, 0xd0, 0x68, 0x8d, 0x4c,\n            0xbe, 0x04, 0x38, 0x1d, 0x1e, 0xf2, 0x27, 0x19, 0xb2, 0x75, 0xa2, 0xee, 0xdb, 0xb8, 0x09, 0x8b,\n        )\n\n        def __init__(self, data=b\"\"):\n            self.h = list(self.h_init)\n            self.hash_words = list(self.hash_init)\n            self.buf = bytearray()\n            self.msg_len = 0\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.hash_words = list(self.hash_words)\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            out = bytearray()\n            for word in c.hash_words:\n                out.extend(word.to_bytes(8, \"big\"))\n            return bytes(out[:self.digest_size])\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def u64_to_le_list(self, x):\n            return list(x.to_bytes(8, \"little\"))\n\n        def u64_from_le_list(self, values):\n            return int.from_bytes(bytes(values), \"little\")\n\n        def get_f16(self, x, a, b, c):\n            return [x[1] ^ a, x[0] ^ b ^ self.sbox[x[1] ^ c]]\n\n        def get_f32(self, x, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama):\n            y0 = x[2] ^ ((alpha >> 8) & 0xff)\n            y1 = x[3] ^ (alpha & 0xff)\n\n            z = [\n                x[2] ^ ((gama >> 8) & 0xff),\n                x[3] ^ (gama & 0xff),\n            ]\n\n            f = self.get_f16(z, a3, b3, c3)\n            z = self.get_f16(f, a2, b2, c2)\n            f = self.get_f16(z, a1, b1, c1)\n\n            return [\n                y0,\n                y1,\n                x[0] ^ ((beta >> 8) & 0xff) ^ f[0],\n                x[1] ^ (beta & 0xff) ^ f[1],\n            ]\n\n        def get_f64(self, x, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama, a_word, b_word, c_word):\n            y = [\n                x[4] ^ ((a_word >> 24) & 0xff),\n                x[5] ^ ((a_word >> 16) & 0xff),\n                x[6] ^ ((a_word >> 8) & 0xff),\n                x[7] ^ (a_word & 0xff),\n            ]\n\n            z = [\n                x[4] ^ ((c_word >> 24) & 0xff),\n                x[5] ^ ((c_word >> 16) & 0xff),\n                x[6] ^ ((c_word >> 8) & 0xff),\n                x[7] ^ (c_word & 0xff),\n            ]\n\n            f = self.get_f32(z, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama)\n\n            return y + [\n                x[0] ^ ((b_word >> 24) & 0xff) ^ f[0],\n                x[1] ^ ((b_word >> 16) & 0xff) ^ f[1],\n                x[2] ^ ((b_word >> 8) & 0xff) ^ f[2],\n                x[3] ^ (b_word & 0xff) ^ f[3],\n            ]\n\n        def get_q64(self, x, y, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama, a_word, b_word, c_word):\n            z = [xb ^ yb for xb, yb in zip(x, y)]\n            fp = self.get_f64(\n                z[::-1],\n                a1, b1, c1,\n                a2, b2, c2,\n                a3, b3, c3,\n                alpha, beta, gama,\n                a_word, b_word, c_word,\n            )\n            fz = fp[::-1]\n            return [fb ^ yb for fb, yb in zip(fz, y)]\n\n        def ae(self, leader, values, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama, a_word, b_word, c_word):\n            out = [0] * len(values)\n            m1 = leader\n\n            for i, value in enumerate(values):\n                p = (value + m1) & 0xffff_ffff_ffff_ffff\n                m1 = value\n                q = self.get_q64(\n                    self.u64_to_le_list(p),\n                    self.u64_to_le_list(m1),\n                    a1, b1, c1,\n                    a2, b2, c2,\n                    a3, b3, c3,\n                    alpha, beta, gama,\n                    a_word, b_word, c_word,\n                )\n                m1 = self.u64_from_le_list(q)\n                out[i] = m1\n\n            return out\n\n        def rae(self, leader, values, a1, b1, c1, a2, b2, c2, a3, b3, c3, alpha, beta, gama, a_word, b_word, c_word):\n            out = [0] * len(values)\n            p = leader\n\n            for i in range(len(values) - 1, -1, -1):\n                p = (p + values[i]) & 0xffff_ffff_ffff_ffff\n                q = self.get_q64(\n                    self.u64_to_le_list(values[i]),\n                    self.u64_to_le_list(p),\n                    a1, b1, c1,\n                    a2, b2, c2,\n                    a3, b3, c3,\n                    alpha, beta, gama,\n                    a_word, b_word, c_word,\n                )\n                p = self.u64_from_le_list(q)\n                out[i] = p\n\n            return out\n\n        def lintr(self, values):\n            values = list(values)\n            last = len(values) - 1\n            t0, t1, t2, t3 = self.lintr_taps\n\n            for _ in range(self.lintr_rounds):\n                pom = values[t0] ^ values[t1] ^ values[t2] ^ values[t3]\n                for i in range(last, 0, -1):\n                    values[i] = values[i - 1]\n                values[0] = pom\n\n            return values\n\n        def swap_64_halves(self, values):\n            return [((x & 0xffff_ffff) << 32) | (x >> 32) for x in values]\n\n        def compile_words(self, message_words):\n            chain_words = len(self.h)\n            x = [0] * (chain_words * 4)\n\n            for k in range(chain_words):\n                x[k << 2] = message_words[k << 1]\n                x[(k << 2) + 1] = self.h[k]\n                x[(k << 2) + 2] = message_words[(k << 1) + 1]\n                x[(k << 2) + 3] = self.hash_words[k]\n\n            x = self.lintr(x)\n\n            l1 = (x[0] + x[1]) & 0xffff_ffff_ffff_ffff\n            l2 = (x[2] + x[3]) & 0xffff_ffff_ffff_ffff\n\n            tmp = (x[4] + x[5]) & 0xffff_ffff_ffff_ffff\n            a1 = (tmp >> 56) & 0xff\n            b1 = (tmp >> 48) & 0xff\n            c1 = (tmp >> 40) & 0xff\n            a2 = (tmp >> 32) & 0xff\n            b2 = (tmp >> 24) & 0xff\n            c2 = (tmp >> 16) & 0xff\n            a3 = (tmp >> 8) & 0xff\n            b3 = tmp & 0xff\n            c3 = a1\n\n            tmp = (x[6] + x[7]) & 0xffff_ffff_ffff_ffff\n            alpha1 = (tmp >> 48) & 0xffff\n            beta1 = (tmp >> 32) & 0xffff\n            gama1 = (tmp >> 16) & 0xffff\n            alpha2 = tmp & 0xffff\n\n            tmp = (x[8] + x[9]) & 0xffff_ffff_ffff_ffff\n            beta2 = (tmp >> 48) & 0xffff\n            gama2 = (tmp >> 32) & 0xffff\n\n            tmp = (x[10] + x[11]) & 0xffff_ffff_ffff_ffff\n            a_word1 = (tmp >> 32) & 0xffff_ffff\n            b_word1 = tmp & 0xffff_ffff\n\n            tmp = (x[12] + x[13]) & 0xffff_ffff_ffff_ffff\n            c_word1 = (tmp >> 32) & 0xffff_ffff\n            a_word2 = tmp & 0xffff_ffff\n\n            tmp = (x[14] + x[15]) & 0xffff_ffff_ffff_ffff\n            b_word2 = (tmp >> 32) & 0xffff_ffff\n            c_word2 = tmp & 0xffff_ffff\n\n            y = self.ae(\n                l2,\n                x,\n                a1, b1, c1,\n                a2, b2, c2,\n                a3, b3, c3,\n                alpha1, beta1, gama1,\n                a_word1, b_word1, c_word1,\n            )\n\n            y = self.swap_64_halves(y)\n\n            x = self.rae(\n                l1,\n                y,\n                a1, b1, c1,\n                a2, b2, c2,\n                a3, b3, c3,\n                alpha2, beta2, gama2,\n                a_word2, b_word2, c_word2,\n            )\n\n            for i in range(chain_words):\n                self.h[i] = x[(i << 2) + 1]\n                self.hash_words[i] = x[(i << 2) + 3]\n\n            return\n\n        def compress(self, block):\n            message_words = [\n                int.from_bytes(block[i:i + 8], \"little\")\n                for i in range(0, self.block_size, 8)\n            ]\n            self.compile_words(message_words)\n            return\n\n        def finalize(self):\n            total_bits = self.msg_len * 8\n            word_count = self.block_size // 8\n\n            buf = bytearray(self.buf)\n            buf.extend(b\"\\x00\" * (self.block_size - len(buf)))\n\n            words = [\n                int.from_bytes(buf[i:i + 8], \"little\")\n                for i in range(0, self.block_size, 8)\n            ]\n\n            i = len(self.buf)\n            bit_mod_64 = total_bits % 64\n            word_index = i >> 3\n\n            if bit_mod_64 != 0:\n                words[word_index] &= 0xffff_ffff_ffff_fffe >> (64 - bit_mod_64)\n            else:\n                words[word_index] = 0\n\n            words[word_index] |= 1 << bit_mod_64\n\n            if i > self.block_size - 17:\n                if i < self.block_size - 8:\n                    words[word_count - 1] = 0\n                self.compile_words(words)\n                i = 0\n                words = [0] * word_count\n            else:\n                i = (i >> 3) + 1\n\n            while i < word_count - 2:\n                words[i] = 0\n                i += 1\n\n            words[word_count - 2] = 0\n            words[word_count - 1] = total_bits\n\n            self.compile_words(words)\n            return\n\n    class NaSHA224(NaSHABase):\n        name = \"nasha224\"\n        block_size = 64\n        digest_size = 28\n        lintr_rounds = 16\n        lintr_taps = (15, 9, 6, 3)\n\n        h_init = (\n            0x6a09_e667_f3bc_c908,\n            0xbb67_ae85_84ca_a73b,\n            0x3c6e_f372_fe94_f82b,\n            0xa54f_f53a_5f1d_36f1,\n        )\n\n        hash_init = (\n            0xcbbb_9d5d_c105_9ed8,\n            0x629a_292a_367c_d507,\n            0x9159_015a_3070_dd17,\n            0x152f_ecd8_f70e_5939,\n        )\n\n    class NaSHA256(NaSHABase):\n        name = \"nasha256\"\n        block_size = 64\n        digest_size = 32\n        lintr_rounds = 16\n        lintr_taps = (15, 9, 6, 3)\n\n        h_init = (\n            0x510e_527f_ade6_82d1,\n            0x9b05_688c_2b3e_6c1f,\n            0x1f83_d9ab_fb41_bd6b,\n            0x5be0_cd19_137e_2179,\n        )\n\n        hash_init = (\n            0x6733_2667_ffc0_0b31,\n            0x8eb4_4a87_6858_1511,\n            0xdb0c_2e0d_64f9_8fa7,\n            0x47b5_481d_befa_4fa4,\n        )\n\n    class NaSHA384(NaSHABase):\n        name = \"nasha384\"\n        block_size = 128\n        digest_size = 48\n        lintr_rounds = 32\n        lintr_taps = (31, 24, 14, 6)\n\n        h_init = (\n            0x6a09_e667_f3bc_c908,\n            0xbb67_ae85_84ca_a73b,\n            0x3c6e_f372_fe94_f82b,\n            0xa54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1,\n            0x9b05_688c_2b3e_6c1f,\n            0x1f83_d9ab_fb41_bd6b,\n            0x5be0_cd19_137e_2179,\n        )\n\n        hash_init = (\n            0xcbbb_9d5d_c105_9ed8,\n            0x629a_292a_367c_d507,\n            0x9159_015a_3070_dd17,\n            0x152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31,\n            0x8eb4_4a87_6858_1511,\n            0xdb0c_2e0d_64f9_8fa7,\n            0x47b5_481d_befa_4fa4,\n        )\n\n    class NaSHA512(NaSHABase):\n        name = \"nasha512\"\n        block_size = 128\n        digest_size = 64\n        lintr_rounds = 32\n        lintr_taps = (31, 24, 14, 6)\n\n        h_init = (\n            0x2dd8_a09a_3c4e_3efb,\n            0x061a_77a0_6094_8dcd,\n            0x8a47_ea18_8055_9ce6,\n            0x9f22_535b_2646_07a8,\n            0x2547_d84e_9ccd_e59d,\n            0x9486_eb50_c7d8_037f,\n            0xc0f9_05d7_41c9_cb74,\n            0xad0d_1e41_a985_e51e,\n        )\n\n        hash_init = (\n            0xe076_88dc_6f16_6b73,\n            0x0c34_aa2a_315e_01d5,\n            0xc785_f436_4a0b_98f4,\n            0x53a8_c8ca_56e1_288c,\n            0x3c15_63a9_317c_57a1,\n            0x7734_1eda_d21e_9a40,\n            0xd648_813e_4512_1dbb,\n            0x4cf7_68fc_7df1_1b00,\n        )\n\n    class SANDstorm256Base:\n        block_size = 64\n        extra_rounds = 0\n\n        mask64 = 0xffff_ffff_ffff_ffff\n        aconst_256 = 0xa611_186b\n        bconst_256 = 0xbee8_390d\n        cconst_256 = 0x6135_f68d_4c0c_bb6f\n        dconst_256 = 0x79cc_4519_5cf5_b7a4\n        j3 = 0x3333_3333_3333_3333\n        j5 = 0x5555_5555_5555_5555\n        j6 = 0x6666_6666_6666_6666\n        ms_rot_bits = 27\n        bitmix_rot_bits = 19\n        r_rot_bits = 25\n\n        b = [\n            0x428a_2f98_7137_4491, 0xb5c0_fbcf_e9b5_dba5, 0x3956_c25b_59f1_11f1, 0x923f_82a4_ab1c_5ed5,\n            0xd807_aa98_1283_5b01, 0x2431_85be_550c_7dc3, 0x72be_5d74_80de_b1fe, 0x9bdc_06a7_c19b_f174,\n            0xe49b_69c1_efbe_4786, 0x0fc1_9dc6_240c_a1cc, 0x2de9_2c6f_4a74_84aa, 0x5cb0_a9dc_76f9_88da,\n            0x983e_5152_a831_c66d, 0xb003_27c8_bf59_7fc7, 0xc6e0_0bf3_d5a7_9147, 0x06ca_6351_1429_2967,\n            0x27b7_0a85_2e1b_2138, 0x4d2c_6dfc_5338_0d13, 0x650a_7354_766a_0abb, 0x81c2_c92e_9272_2c85,\n            0xa2bf_e8a1_a81a_664b, 0xc24b_8b70_c76c_51a3, 0xd192_e819_d699_0624, 0xf40e_3585_106a_a070,\n            0x19a4_c116_1e37_6c08,\n        ]\n\n        fsbox = [\n            0x63, 0x7d, 0x75, 0x78, 0xf6, 0x6e, 0x69, 0xc2, 0x38, 0x08, 0x6d, 0x20, 0xf2, 0xda, 0xa5, 0x79,\n            0xda, 0x93, 0xdb, 0x6e, 0xee, 0x4c, 0x51, 0xe7, 0xb5, 0xcd, 0xb8, 0xb4, 0x80, 0xb9, 0x6c, 0xdf,\n            0x97, 0xdc, 0xb1, 0x05, 0x12, 0x1a, 0xd1, 0xeb, 0x1c, 0x8c, 0xcf, 0xda, 0x5d, 0xf5, 0x1f, 0x3a,\n            0x34, 0xf6, 0x11, 0xf0, 0x2c, 0xa3, 0x33, 0xad, 0x3f, 0x2b, 0xba, 0xd9, 0xd7, 0x1a, 0x8c, 0x4a,\n            0x49, 0xc2, 0x6e, 0x59, 0x5f, 0x2b, 0x1c, 0xe7, 0x1a, 0x72, 0x9c, 0xf8, 0x65, 0xae, 0x61, 0xcb,\n            0x03, 0x80, 0x52, 0xbe, 0x74, 0xa9, 0xe7, 0x0c, 0x32, 0x92, 0xe4, 0x62, 0x16, 0x11, 0x06, 0x90,\n            0xb0, 0x8e, 0xc8, 0x98, 0x27, 0x28, 0x55, 0xe2, 0x2d, 0x90, 0x68, 0x14, 0x3c, 0x51, 0xf1, 0xc7,\n            0x21, 0xd2, 0x32, 0xfc, 0xe6, 0xe8, 0x4e, 0x82, 0xc4, 0xcf, 0xa0, 0x5a, 0x6c, 0x82, 0x8d, 0xad,\n            0x4d, 0x8d, 0x91, 0x6f, 0xdb, 0x12, 0xc2, 0x90, 0x4c, 0x2e, 0xf4, 0xb6, 0xe8, 0xd0, 0x97, 0xfc,\n            0xf0, 0x10, 0xdd, 0x4f, 0xb6, 0xbf, 0x06, 0x1f, 0xde, 0x77, 0x22, 0x8f, 0x42, 0xc3, 0x95, 0x44,\n            0x40, 0x93, 0x98, 0xa9, 0xed, 0xa3, 0x82, 0xfb, 0x6a, 0x7a, 0x06, 0xc9, 0x3d, 0x38, 0x4a, 0xd6,\n            0x57, 0x79, 0x85, 0xde, 0x39, 0x60, 0xf8, 0x1e, 0xd4, 0xef, 0x4e, 0x51, 0xd9, 0xc7, 0x10, 0xb7,\n            0x7a, 0xb9, 0xe7, 0xed, 0xd8, 0x63, 0x72, 0x01, 0x20, 0x14, 0xbe, 0xd4, 0x87, 0x70, 0x45, 0x45,\n            0xa0, 0xef, 0x67, 0xb5, 0x9c, 0xd6, 0x20, 0xd9, 0xb9, 0xec, 0x8d, 0x62, 0x5a, 0x1c, 0xc3, 0x41,\n            0x01, 0x19, 0x7a, 0xf2, 0x8d, 0x3c, 0x68, 0x73, 0x73, 0xf7, 0x6d, 0x02, 0x22, 0xb8, 0xc6, 0x30,\n            0x7c, 0x50, 0x7b, 0xfe, 0x4b, 0x13, 0xb4, 0x9f, 0xb9, 0x60, 0xd7, 0xf4, 0x4c, 0xa9, 0x45, 0xe9,\n        ]\n\n        constants_224 = [\n            [0xc105_9ed8_367c_d507, 0x3070_dd17_f70e_5939, 0xffc0_0b31_6858_1511, 0x64f9_8fa7_befa_4fa4],\n            [0x367c_d507_3070_dd17, 0xf70e_5939_ffc0_0b31, 0x6858_1511_64f9_8fa7, 0xbefa_4fa4_c105_9ed8],\n            [0x3070_dd17_f70e_5939, 0xffc0_0b31_6858_1511, 0x64f9_8fa7_befa_4fa4, 0xc105_9ed8_367c_d507],\n            [0xf70e_5939_ffc0_0b31, 0x6858_1511_64f9_8fa7, 0xbefa_4fa4_c105_9ed8, 0x367c_d507_3070_dd17],\n            [0xffc0_0b31_6858_1511, 0x64f9_8fa7_befa_4fa4, 0xc105_9ed8_367c_d507, 0x3070_dd17_f70e_5939],\n        ]\n\n        constants_256 = [\n            [0x6a09_e667_bb67_ae85, 0x3c6e_f372_a54f_f53a, 0x510e_527f_9b05_688c, 0x1f83_d9ab_5be0_cd19],\n            [0xbb67_ae85_3c6e_f372, 0xa54f_f53a_510e_527f, 0x9b05_688c_1f83_d9ab, 0x5be0_cd19_6a09_e667],\n            [0x3c6e_f372_a54f_f53a, 0x510e_527f_9b05_688c, 0x1f83_d9ab_5be0_cd19, 0x6a09_e667_bb67_ae85],\n            [0xa54f_f53a_510e_527f, 0x9b05_688c_1f83_d9ab, 0x5be0_cd19_6a09_e667, 0xbb67_ae85_3c6e_f372],\n            [0x510e_527f_9b05_688c, 0x1f83_d9ab_5be0_cd19, 0x6a09_e667_bb67_ae85, 0x3c6e_f372_a54f_f53a],\n        ]\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.piped_bits = 0\n            self.init_compress_flag = 0\n            self.block_iters = [0, 0, 0]\n            self.queued_data = bytearray(64)\n            self.prev_block = [[[0, 0, 0, 0] for _ in range(5)] for _ in range(3)]\n            self.level_one_to_four_const = [[[0, 0, 0, 0] for _ in range(5)] for _ in range(4)]\n            if self.hashbitlen == 224:\n                base = self.constants_224\n            elif self.hashbitlen == 256:\n                base = self.constants_256\n            else:\n                raise ValueError(\"invalid hash bit length\")\n            self.main_constant_input_words = [row[:] for row in base]\n            self.initial_vector_temp_words = [row[:] for row in base]\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.piped_bits = self.piped_bits\n            other.init_compress_flag = self.init_compress_flag\n            other.block_iters = self.block_iters[:]\n            other.queued_data = bytearray(self.queued_data)\n            other.prev_block = [[row[:] for row in level] for level in self.prev_block]\n            other.level_one_to_four_const = [[row[:] for row in level] for level in self.level_one_to_four_const]\n            other.main_constant_input_words = [row[:] for row in self.main_constant_input_words]\n            other.initial_vector_temp_words = [row[:] for row in self.initial_vector_temp_words]\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                self.queued_data[:] = self.buf[:64]\n                del self.buf[:64]\n                self.piped_bits = 512\n                if self.init_compress_flag == 0:\n                    self.init_compress()\n                else:\n                    self.compress()\n            self.piped_bits = len(self.buf) * 8\n            self.queued_data[:len(self.buf)] = self.buf\n            return self\n\n        def digest(self):\n            other = self.copy()\n            return other.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            last = len(self.buf)\n            self.queued_data[:last] = self.buf\n            self.queued_data[last] = 0x80\n            for i in range(last + 1, 64):\n                self.queued_data[i] = 0\n\n            if self.init_compress_flag == 0:\n                self.init_compress()\n                message_words = self.create_message_from_block(self.initial_vector_temp_words)\n                message_length = self.piped_bits\n            else:\n                message_length = (self.block_iters[0] + 1) * 512 + self.piped_bits\n                self.compress()\n                message_words = self.create_message_from_block(self.prev_block[0])\n                if self.block_iters[1] > 0:\n                    self.do_block_mod_mix_ref(message_words, self.prev_block[1])\n                    message_words = self.create_message_from_block(self.prev_block[1])\n                    if self.block_iters[2] > 0:\n                        self.do_block_mod_mix_ref(message_words, self.prev_block[2])\n                        message_words = self.create_message_from_block(self.prev_block[2])\n\n            for i in range(5):\n                for j in range(1, 4, 2):\n                    self.level_one_to_four_const[3][i][j] ^= message_length\n\n            self.do_block_mod_mix_ref(message_words, self.level_one_to_four_const[3])\n\n            out_words = []\n            for i in range(4):\n                out_words.append(\n                    self.level_one_to_four_const[3][1][i]\n                    ^ self.level_one_to_four_const[3][2][i]\n                    ^ self.level_one_to_four_const[3][3][i]\n                    ^ self.level_one_to_four_const[3][4][i]\n                )\n\n            raw = b\"\".join(word.to_bytes(8, \"big\") for word in out_words)\n            return raw[:self.digest_size]\n\n        def init_compress(self):\n            self.init_compress_flag = 1\n            message_words = self.create_message_from_queue()\n            self.do_block_mod_mix_ref(message_words, self.initial_vector_temp_words)\n\n            for i in range(4):\n                self.level_one_to_four_const[0][0][i] = self.main_constant_input_words[0][i] ^ self.initial_vector_temp_words[4][i]\n                self.level_one_to_four_const[0][1][i] = self.main_constant_input_words[1][i] ^ self.initial_vector_temp_words[1][i]\n                self.level_one_to_four_const[0][2][i] = self.main_constant_input_words[2][i] ^ self.initial_vector_temp_words[2][i]\n                self.level_one_to_four_const[0][3][i] = self.main_constant_input_words[3][i] ^ self.initial_vector_temp_words[3][i]\n                self.level_one_to_four_const[0][4][i] = self.main_constant_input_words[4][i] ^ self.initial_vector_temp_words[4][i]\n\n            for i in range(5):\n                for j in range(4):\n                    self.level_one_to_four_const[1][i][j] = self.level_one_to_four_const[0][i][j]\n                    self.level_one_to_four_const[2][i][j] = self.level_one_to_four_const[0][i][j]\n                    self.level_one_to_four_const[3][i][j] = self.main_constant_input_words[i][j]\n\n            for i in range(5):\n                self.level_one_to_four_const[1][i][3] ^= self.cconst_256\n                self.level_one_to_four_const[2][i][3] ^= self.dconst_256\n                self.level_one_to_four_const[3][i][3] ^= self.dconst_256\n                self.level_one_to_four_const[3][i][0] = (~self.level_one_to_four_const[3][i][0]) & self.mask64\n                self.level_one_to_four_const[3][i][1] = (~self.level_one_to_four_const[3][i][1]) & self.mask64\n\n            for i in range(3):\n                for j in range(5):\n                    for k in range(4):\n                        self.prev_block[i][j][k] = self.level_one_to_four_const[i][j][k]\n\n            for i in range(2):\n                for j in range(5):\n                    for k in range(1, 4, 2):\n                        self.prev_block[i][j][k] ^= 1\n            return\n\n        def compress(self):\n            message_l1 = self.create_message_from_queue()\n\n            if (self.block_iters[0] % 10) == 0 and self.block_iters[0] > 1:\n                message_l2 = self.create_message_from_block(self.prev_block[0])\n                self.do_block_mod_mix_ref(message_l2, self.prev_block[1])\n\n                level_one_superblock = self.block_iters[0] // 10 + 1\n                for i in range(5):\n                    for j in range(4):\n                        self.prev_block[0][i][j] = self.level_one_to_four_const[0][i][j] ^ (level_one_superblock if (j & 1) else 0)\n\n                self.block_iters[1] += 1\n\n                if (self.block_iters[1] % 100) == 0 and self.block_iters[1] > 1:\n                    message_l3 = self.create_message_from_block(self.prev_block[1])\n                    self.do_block_mod_mix_ref(message_l3, self.prev_block[2])\n\n                    level_two_superblock = self.block_iters[1] // 100 + 1\n                    for i in range(5):\n                        for j in range(4):\n                            self.prev_block[1][i][j] = self.level_one_to_four_const[1][i][j] ^ (level_two_superblock if (j & 1) else 0)\n\n                    self.block_iters[2] += 1\n\n            self.do_block_mod_mix_ref(message_l1, self.prev_block[0])\n            self.block_iters[0] += 1\n            return\n\n        def create_message_from_queue(self):\n            words = []\n            for i in range(8):\n                words.append(int.from_bytes(self.queued_data[i * 8:(i + 1) * 8], \"big\"))\n            return words\n\n        def create_message_from_block(self, state_words):\n            return [\n                state_words[1][0] ^ state_words[3][0],\n                state_words[1][1] ^ state_words[3][1],\n                state_words[1][2] ^ state_words[3][2],\n                state_words[1][3] ^ state_words[3][3],\n                state_words[2][0] ^ state_words[4][0],\n                state_words[2][1] ^ state_words[4][1],\n                state_words[2][2] ^ state_words[4][2],\n                state_words[2][3] ^ state_words[4][3],\n            ]\n\n        def do_block_mod_mix_ref(self, data_input, prev_block_arr):\n            msd = data_input[:] + [0] * 25\n\n            for i in range(8, 33):\n                value = (\n                    msd[i - 8]\n                    + self.b[i - 8]\n                    + self.g(msd[i - 1])\n                    + self.ch(msd[i - 1], msd[i - 2], msd[i - 3])\n                    + msd[i - 4]\n                ) & self.mask64\n                msd[i] = self.rol64(self.sb(value), self.ms_rot_bits)\n\n            ws = [self.rol64(msd[i], self.bitmix_rot_bits) ^ msd[i + 4] for i in range(4)]\n            ws = self.bit_mix(ws)\n\n            ws = [ws[i] ^ prev_block_arr[0][i] for i in range(4)]\n            ws = self.do_round(ws, 0)\n            ws = self.bit_mix(ws)\n            prev_block_arr[1] = [(prev_block_arr[1][i] ^ ws[i]) & self.mask64 for i in range(4)]\n\n            ws = [prev_block_arr[1][i] ^ msd[14 + i] for i in range(4)]\n            ws = self.do_round(ws, 1)\n            ws = self.bit_mix(ws)\n            prev_block_arr[1] = [(prev_block_arr[2][i] ^ ws[i]) & self.mask64 for i in range(4)]\n\n            ws = [prev_block_arr[1][i] ^ msd[19 + i] for i in range(4)]\n            ws = self.do_round(ws, 2)\n            ws = self.bit_mix(ws)\n            prev_block_arr[2] = [(prev_block_arr[3][i] ^ ws[i]) & self.mask64 for i in range(4)]\n\n            ws = [prev_block_arr[2][i] ^ msd[24 + i] for i in range(4)]\n            ws = self.do_round(ws, 3)\n            ws = self.bit_mix(ws)\n            prev_block_arr[3] = [(prev_block_arr[4][i] ^ ws[i]) & self.mask64 for i in range(4)]\n\n            ws = [prev_block_arr[3][i] ^ msd[29 + i] for i in range(4)]\n            ws = self.do_round(ws, 4)\n            ws = self.bit_mix(ws)\n\n            for _ in range(self.extra_rounds):\n                ws = self.do_round(ws, 4)\n                ws = self.bit_mix(ws)\n\n            prev_block_arr[4] = [value & self.mask64 for value in ws]\n            return\n\n        def bit_mix(self, ws):\n            ws = ws[:]\n            value = (ws[0] ^ ws[2]) & self.j6\n            ws[0] ^= value\n            ws[2] ^= value\n            value = (ws[1] ^ ws[3]) & self.j3\n            ws[1] ^= value\n            ws[3] ^= value\n            value = (ws[0] ^ ws[1]) & self.j5\n            ws[0] ^= value\n            ws[1] ^= value\n            value = (ws[2] ^ ws[3]) & self.j5\n            ws[2] ^= value\n            ws[3] ^= value\n            return ws\n\n        def do_round(self, ws, round_index):\n            ws = ws[:]\n            ws[0] = self.rol64(\n                self.sb((ws[0] + self.f(ws[3]) + self.ch(ws[3], ws[2], ws[1]) + self.b[24 - (4 * round_index)]) & self.mask64),\n                self.r_rot_bits,\n            )\n            ws[1] = self.rol64(\n                self.sb((ws[1] + self.f(ws[0]) + self.ch(ws[0], ws[3], ws[2]) + self.b[23 - (4 * round_index)]) & self.mask64),\n                self.r_rot_bits,\n            )\n            ws[2] = self.rol64(\n                self.sb((ws[2] + self.f(ws[1]) + self.ch(ws[1], ws[0], ws[3]) + self.b[22 - (4 * round_index)]) & self.mask64),\n                self.r_rot_bits,\n            )\n            ws[3] = self.rol64(\n                self.sb((ws[3] + self.f(ws[2]) + self.ch(ws[2], ws[1], ws[0]) + self.b[21 - (4 * round_index)]) & self.mask64),\n                self.r_rot_bits,\n            )\n            return ws\n\n        def rol64(self, value, count):\n            value &= self.mask64\n            return ((value << count) | (value >> (64 - count))) & self.mask64\n\n        def rot32(self, value):\n            value &= self.mask64\n            return ((value << 32) | (value >> 32)) & self.mask64\n\n        def f(self, value):\n            upper = (value >> 32) & 0xffff_ffff\n            lower = value & 0xffff_ffff\n            return (upper * upper + lower * lower) & self.mask64\n\n        def g(self, value):\n            upper = (value >> 32) & 0xffff_ffff\n            lower = value & 0xffff_ffff\n            return (\n                upper * upper\n                + lower * lower\n                + self.rot32((((upper + self.aconst_256) & 0xffff_ffff) * ((lower + self.bconst_256) & 0xffff_ffff)) & self.mask64)\n            ) & self.mask64\n\n        def ch(self, a, b, c):\n            return ((a & b) ^ ((~a) & c)) & self.mask64\n\n        def sb(self, value):\n            value &= self.mask64\n            return value ^ self.fsbox[value & 0xff]\n\n    class SANDstorm224(SANDstorm256Base):\n        digest_size = 28\n        hashbitlen = 224\n\n    class SANDstorm256(SANDstorm256Base):\n        digest_size = 32\n        hashbitlen = 256\n\n    class SANDstorm512Base(SANDstorm256Base):\n        block_size = 128\n        extra_rounds = 0\n\n        mask64 = 0xffff_ffff_ffff_ffff\n        mask128 = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff\n        aconst_512 = 0xa611_186b_ae67_496b\n        bconst_512 = 0xbee8_390d_4395_5aed\n        sandwblkc = 0x6135_f68d_4c0c_bb6f_b43b_47a2_4577_8989\n        sandwblkd = 0x79cc_4519_5cf5_b7a4_aec4_e749_6801_dbb9\n        j3_128 = 0x3333_3333_3333_3333_3333_3333_3333_3333\n        j5_128 = 0x5555_5555_5555_5555_5555_5555_5555_5555\n        j6_128 = 0x6666_6666_6666_6666_6666_6666_6666_6666\n        sandwmspick = [4, 14, 19, 24, 29]\n\n        sandwlvlc384 = [\n            0xcbbb_9d5d_c105_9ed8_629a_292a_367c_d507,\n            0x9159_015a_3070_dd17_152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31_8eb4_4a87_6858_1511,\n            0xdb0c_2e0d_64f9_8fa7_47b5_481d_befa_4fa4,\n            0x629a_292a_367c_d507_9159_015a_3070_dd17,\n            0x152f_ecd8_f70e_5939_6733_2667_ffc0_0b31,\n            0x8eb4_4a87_6858_1511_db0c_2e0d_64f9_8fa7,\n            0x47b5_481d_befa_4fa4_cbbb_9d5d_c105_9ed8,\n            0x9159_015a_3070_dd17_152f_ecd8_f70e_5939,\n            0x6733_2667_ffc0_0b31_8eb4_4a87_6858_1511,\n            0xdb0c_2e0d_64f9_8fa7_47b5_481d_befa_4fa4,\n            0xcbbb_9d5d_c105_9ed8_629a_292a_367c_d507,\n            0x152f_ecd8_f70e_5939_6733_2667_ffc0_0b31,\n            0x8eb4_4a87_6858_1511_db0c_2e0d_64f9_8fa7,\n            0x47b5_481d_befa_4fa4_cbbb_9d5d_c105_9ed8,\n            0x629a_292a_367c_d507_9159_015a_3070_dd17,\n            0x6733_2667_ffc0_0b31_8eb4_4a87_6858_1511,\n            0xdb0c_2e0d_64f9_8fa7_47b5_481d_befa_4fa4,\n            0xcbbb_9d5d_c105_9ed8_629a_292a_367c_d507,\n            0x9159_015a_3070_dd17_152f_ecd8_f70e_5939,\n        ]\n\n        sandwlvlc512 = [\n            0x6a09_e667_f3bc_c908_bb67_ae85_84ca_a73b,\n            0x3c6e_f372_fe94_f82b_a54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1_9b05_688c_2b3e_6c1f,\n            0x1f83_d9ab_fb41_bd6b_5be0_cd19_137e_2179,\n            0xbb67_ae85_84ca_a73b_3c6e_f372_fe94_f82b,\n            0xa54f_f53a_5f1d_36f1_510e_527f_ade6_82d1,\n            0x9b05_688c_2b3e_6c1f_1f83_d9ab_fb41_bd6b,\n            0x5be0_cd19_137e_2179_6a09_e667_f3bc_c908,\n            0x3c6e_f372_fe94_f82b_a54f_f53a_5f1d_36f1,\n            0x510e_527f_ade6_82d1_9b05_688c_2b3e_6c1f,\n            0x1f83_d9ab_fb41_bd6b_5be0_cd19_137e_2179,\n            0x6a09_e667_f3bc_c908_bb67_ae85_84ca_a73b,\n            0xa54f_f53a_5f1d_36f1_510e_527f_ade6_82d1,\n            0x9b05_688c_2b3e_6c1f_1f83_d9ab_fb41_bd6b,\n            0x5be0_cd19_137e_2179_6a09_e667_f3bc_c908,\n            0xbb67_ae85_84ca_a73b_3c6e_f372_fe94_f82b,\n            0x510e_527f_ade6_82d1_9b05_688c_2b3e_6c1f,\n            0x1f83_d9ab_fb41_bd6b_5be0_cd19_137e_2179,\n            0x6a09_e667_f3bc_c908_bb67_ae85_84ca_a73b,\n            0x3c6e_f372_fe94_f82b_a54f_f53a_5f1d_36f1,\n        ]\n\n        sandwmsc = [\n            0x428a_2f98_d728_ae22_7137_4491_23ef_65cd,\n            0xb5c0_fbcf_ec4d_3b2f_e9b5_dba5_8189_dbbc,\n            0x3956_c25b_f348_b538_59f1_11f1_b605_d019,\n            0x923f_82a4_af19_4f9b_ab1c_5ed5_da6d_8118,\n            0xd807_aa98_a303_0242_1283_5b01_4570_6fbe,\n            0x2431_85be_4ee4_b28c_550c_7dc3_d5ff_b4e2,\n            0x72be_5d74_f27b_896f_80de_b1fe_3b16_96b1,\n            0x9bdc_06a7_25c7_1235_c19b_f174_cf69_2694,\n            0xe49b_69c1_9ef1_4ad2_efbe_4786_384f_25e3,\n            0x0fc1_9dc6_8b8c_d5b5_240c_a1cc_77ac_9c65,\n            0x2de9_2c6f_592b_0275_4a74_84aa_6ea6_e483,\n            0x5cb0_a9dc_bd41_fbd4_76f9_88da_8311_53b5,\n            0x983e_5152_ee66_dfab_a831_c66d_2db4_3210,\n            0xb003_27c8_98fb_213f_bf59_7fc7_beef_0ee4,\n            0xc6e0_0bf3_3da8_8fc2_d5a7_9147_930a_a725,\n            0x06ca_6351_e003_826f_1429_2967_0a0e_6e70,\n            0x27b7_0a85_46d2_2ffc_2e1b_2138_5c26_c926,\n            0x4d2c_6dfc_5ac4_2aed_5338_0d13_9d95_b3df,\n            0x650a_7354_8baf_63de_766a_0abb_3c77_b2a8,\n            0x81c2_c92e_47ed_aee6_9272_2c85_1482_353b,\n            0xa2bf_e8a1_4cf1_0364_a81a_664b_bc42_3001,\n            0xc24b_8b70_d0f8_9791_c76c_51a3_0654_be30,\n            0xd192_e819_d6ef_5218_d699_0624_5565_a910,\n            0xf40e_3585_5771_202a_106a_a070_32bb_d1b8,\n            0x19a4_c116_b8d2_d0c8_1e37_6c08_5141_ab53,\n        ]\n\n        def __init__(self, data=b\"\"):\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.msglen_bits = 0\n            self.mbcnt = 0\n            self.msgbytes = bytearray(128)\n            self.msg = [0] * 8\n            self.blkn1 = 1\n            self.blkn2 = 1\n            self.lvl0flag = 0\n            self.lvl1cnt = 0\n            self.lvl2cnt = 0\n            self.lvl3flag = 0\n            self.prev = [0] * 100\n            if self.hashbitlen == 384:\n                self.lvlc = self.sandwlvlc384\n            elif self.hashbitlen == 512:\n                self.lvlc = self.sandwlvlc512\n            else:\n                raise ValueError(\"invalid hash bit length\")\n            for i in range(20):\n                self.prev[i] = self.lvlc[i]\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.msglen_bits = self.msglen_bits\n            other.mbcnt = self.mbcnt\n            other.msgbytes = bytearray(self.msgbytes)\n            other.msg = self.msg[:]\n            other.blkn1 = self.blkn1\n            other.blkn2 = self.blkn2\n            other.lvl0flag = self.lvl0flag\n            other.lvl1cnt = self.lvl1cnt\n            other.lvl2cnt = self.lvl2cnt\n            other.lvl3flag = self.lvl3flag\n            other.prev = self.prev[:]\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.msglen_bits = (self.msglen_bits + (len(data) * 8)) & self.mask128\n            self.buf.extend(data)\n            while len(self.buf) >= 128:\n                self.msgbytes[:] = self.buf[:128]\n                del self.buf[:128]\n                self.mbcnt = 128\n                self.sandwdoit()\n            return self\n\n        def digest(self):\n            other = self.copy()\n            return other.finalize()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            self.msgbytes[:len(self.buf)] = self.buf\n            self.mbcnt = len(self.buf)\n            for i in range(self.mbcnt, 128):\n                self.msgbytes[i] = 0\n            self.mbcnt += 1\n            self.msgbytes[self.mbcnt - 1] |= 0x80\n            self.sandwdoit()\n\n            if not (self.lvl2cnt == 0 and self.blkn2 == 1):\n                if self.lvl1cnt:\n                    if self.lvl2cnt == 100:\n                        for i in range(8):\n                            self.msg[i] = self.x128(self.prev[44 + i], self.prev[52 + i])\n                        if not self.lvl3flag:\n                            for i in range(20):\n                                self.prev[60 + i] = self.x128(self.lvlc[i], self.prev[i + 16 if i < 4 else i])\n                            for i in range(0, 20, 4):\n                                self.prev[63 + i] = self.x128(self.prev[63 + i], self.sandwblkd)\n                        self.sandwcmprs(self.msg, self.prev, 3, self.extra_rounds)\n                        self.lvl2cnt = 0\n                        self.blkn2 = self.a128(self.blkn2, 1)\n                        self.lvl3flag = 1\n\n                    if not self.lvl2cnt:\n                        for i in range(20):\n                            self.prev[40 + i] = self.x128(self.lvlc[i], self.prev[i + 16 if i < 4 else i])\n                        for i in range(0, 20, 4):\n                            self.prev[43 + i] = self.x128(self.prev[43 + i], self.sandwblkc)\n                        for i in range(0, 20, 2):\n                            self.prev[41 + i] = self.x128(self.prev[41 + i], self.blkn2)\n\n                    for i in range(8):\n                        self.msg[i] = self.x128(self.prev[24 + i], self.prev[32 + i])\n                    self.sandwcmprs(self.msg, self.prev, 2, self.extra_rounds)\n                    self.lvl1cnt = 0\n                    self.blkn1 = self.a128(self.blkn1, 1)\n                    self.lvl2cnt += 1\n\n                if self.lvl3flag and self.lvl2cnt:\n                    for i in range(8):\n                        self.msg[i] = self.x128(self.prev[44 + i], self.prev[52 + i])\n                    self.sandwcmprs(self.msg, self.prev, 3, self.extra_rounds)\n                    self.lvl2cnt = 0\n                    self.blkn2 = self.a128(self.blkn2, 1)\n\n            for i in range(20):\n                self.prev[80 + i] = self.lvlc[i]\n            for i in range(0, 20, 4):\n                self.prev[83 + i] = self.x128(self.prev[83 + i], self.sandwblkd)\n            for i in range(0, 20, 2):\n                self.prev[81 + i] = self.x128(self.prev[81 + i], self.msglen_bits)\n            for i in range(20):\n                if not (i & 2):\n                    self.prev[80 + i] = self.c128(self.prev[80 + i])\n\n            if self.lvl1cnt == 0 and self.blkn1 == 1:\n                for i in range(8):\n                    self.msg[i] = self.x128(self.prev[4 + i], self.prev[12 + i])\n            elif self.lvl2cnt == 0 and self.blkn2 == 1:\n                for i in range(8):\n                    self.msg[i] = self.x128(self.prev[24 + i], self.prev[32 + i])\n            elif self.lvl3flag == 0:\n                for i in range(8):\n                    self.msg[i] = self.x128(self.prev[44 + i], self.prev[52 + i])\n            else:\n                for i in range(8):\n                    self.msg[i] = self.x128(self.prev[64 + i], self.prev[72 + i])\n\n            self.sandwcmprs(self.msg, self.prev, 4, self.extra_rounds)\n\n            for i in range(4):\n                self.prev[96 + i] = self.x128(\n                    self.prev[84 + i],\n                    self.x128(\n                        self.prev[88 + i],\n                        self.x128(self.prev[92 + i], self.prev[96 + i]),\n                    ),\n                )\n\n            raw = b\"\".join(word.to_bytes(16, \"big\") for word in self.prev[96:100])\n            return raw[:self.digest_size]\n\n        def sandwdoit(self):\n            if self.lvl1cnt == 10:\n                if self.lvl2cnt == 100:\n                    for i in range(8):\n                        self.msg[i] = self.x128(self.prev[44 + i], self.prev[52 + i])\n                    if not self.lvl3flag:\n                        for i in range(20):\n                            self.prev[60 + i] = self.x128(self.lvlc[i], self.prev[i + 16 if i < 4 else i])\n                        for i in range(0, 20, 4):\n                            self.prev[63 + i] = self.x128(self.prev[63 + i], self.sandwblkd)\n                    self.sandwcmprs(self.msg, self.prev, 3, self.extra_rounds)\n                    self.lvl2cnt = 0\n                    self.blkn2 = self.a128(self.blkn2, 1)\n                    self.lvl3flag = 1\n\n                if not self.lvl2cnt:\n                    for i in range(20):\n                        self.prev[40 + i] = self.x128(self.lvlc[i], self.prev[i + 16 if i < 4 else i])\n                    for i in range(0, 20, 4):\n                        self.prev[43 + i] = self.x128(self.prev[43 + i], self.sandwblkc)\n                    for i in range(0, 20, 2):\n                        self.prev[41 + i] = self.x128(self.prev[41 + i], self.blkn2)\n\n                for i in range(8):\n                    self.msg[i] = self.x128(self.prev[24 + i], self.prev[32 + i])\n                self.sandwcmprs(self.msg, self.prev, 2, self.extra_rounds)\n                self.lvl1cnt = 0\n                self.blkn1 = self.a128(self.blkn1, 1)\n                self.lvl2cnt += 1\n\n            for i in range(8):\n                self.msg[i] = 0\n            for i in range(128):\n                self.msg[i >> 4] ^= self.msgbytes[i] << (120 - ((i & 15) << 3))\n            self.mbcnt = 0\n\n            if self.lvl0flag == 0:\n                self.sandwcmprs(self.msg, self.prev, 0, self.extra_rounds)\n                self.lvl0flag = 1\n            else:\n                if not self.lvl1cnt:\n                    for i in range(20):\n                        self.prev[20 + i] = self.x128(self.lvlc[i], self.prev[i + 16 if i < 4 else i])\n                    for i in range(0, 20, 2):\n                        self.prev[21 + i] = self.x128(self.prev[21 + i], self.blkn1)\n                self.sandwcmprs(self.msg, self.prev, 1, self.extra_rounds)\n                self.lvl1cnt += 1\n            return\n\n        def sandwcmprs(self, msg, prev, level, xrnds):\n            ms = msg[:] + [0] * 25\n\n            for i in range(8, 33):\n                ms[i] = self.r128(\n                    self.sb128(\n                        self.a128(\n                            ms[i - 8],\n                            self.a128(\n                                self.sandwmsc[i - 8],\n                                self.a128(\n                                    self.sandwg(ms[i - 1]),\n                                    self.a128(\n                                        self.x128(\n                                            self.b128(ms[i - 1], ms[i - 2]),\n                                            self.b128(self.c128(ms[i - 1]), ms[i - 3]),\n                                        ),\n                                        ms[i - 4],\n                                    ),\n                                ),\n                            ),\n                        ),\n                    ),\n                    59,\n                )\n\n            for i in range(4):\n                ms[i + 4] = self.x128(self.r128(ms[i], 37), ms[i + 4])\n\n            temp = self.b128(self.x128(ms[4], ms[6]), self.j6_128)\n            ms[4] = self.x128(ms[4], temp)\n            ms[6] = self.x128(ms[6], temp)\n\n            temp = self.b128(self.x128(ms[5], ms[7]), self.j3_128)\n            ms[5] = self.x128(ms[5], temp)\n            ms[7] = self.x128(ms[7], temp)\n\n            temp = self.b128(self.x128(ms[4], ms[5]), self.j5_128)\n            ms[4] = self.x128(ms[4], temp)\n            ms[5] = self.x128(ms[5], temp)\n\n            temp = self.b128(self.x128(ms[6], ms[7]), self.j5_128)\n            ms[6] = self.x128(ms[6], temp)\n            ms[7] = self.x128(ms[7], temp)\n\n            w = [prev[20 * level + i] for i in range(4)]\n\n            for rnd in range(5):\n                for i in range(4):\n                    w[i] = self.x128(w[i], ms[self.sandwmspick[rnd] + i])\n\n                rounds = 1 if rnd < 4 else (xrnds + 1)\n                for _ in range(rounds):\n                    for i in range(4):\n                        w[i] = self.r128(\n                            self.sb128(\n                                self.a128(\n                                    w[i],\n                                    self.a128(\n                                        self.sandwf(w[(i + 3) & 3]),\n                                        self.a128(\n                                            self.x128(\n                                                self.b128(w[(i + 3) & 3], w[i ^ 2]),\n                                                self.b128(self.c128(w[(i + 3) & 3]), w[(i + 1) & 3]),\n                                            ),\n                                            self.sandwmsc[24 - i - (rnd << 2)],\n                                        ),\n                                    ),\n                                ),\n                            ),\n                            57,\n                        )\n\n                    temp = self.b128(self.x128(w[0], w[2]), self.j6_128)\n                    w[0] = self.x128(w[0], temp)\n                    w[2] = self.x128(w[2], temp)\n\n                    temp = self.b128(self.x128(w[1], w[3]), self.j3_128)\n                    w[1] = self.x128(w[1], temp)\n                    w[3] = self.x128(w[3], temp)\n\n                    temp = self.b128(self.x128(w[0], w[1]), self.j5_128)\n                    w[0] = self.x128(w[0], temp)\n                    w[1] = self.x128(w[1], temp)\n\n                    temp = self.b128(self.x128(w[2], w[3]), self.j5_128)\n                    w[2] = self.x128(w[2], temp)\n                    w[3] = self.x128(w[3], temp)\n\n                if rnd < 4:\n                    for i in range(4):\n                        w[i] = self.x128(w[i], prev[20 * level + 4 * rnd + 4 + i])\n\n                if rnd:\n                    for i in range(4):\n                        prev[20 * level + 4 * rnd + i] = w[i]\n            return\n\n        def a128(self, a, b):\n            return (a + b) & self.mask128\n\n        def x128(self, a, b):\n            return (a ^ b) & self.mask128\n\n        def c128(self, value):\n            return (~value) & self.mask128\n\n        def b128(self, a, b):\n            return a & b\n\n        def r128(self, value, count):\n            count &= 127\n            if count == 0:\n                return value & self.mask128\n            return ((value << count) | (value >> (128 - count))) & self.mask128\n\n        def m128(self, a, b):\n            return (a * b) & self.mask128\n\n        def sandwf(self, value):\n            upper = (value >> 64) & self.mask64\n            lower = value & self.mask64\n            return self.a128(self.m128(upper, upper), self.m128(lower, lower))\n\n        def sandwg(self, value):\n            upper = (value >> 64) & self.mask64\n            lower = value & self.mask64\n            return self.a128(\n                self.m128(upper, upper),\n                self.a128(\n                    self.m128(lower, lower),\n                    self.r128(\n                        self.m128((upper + self.aconst_512) & self.mask64, (lower + self.bconst_512) & self.mask64),\n                        64,\n                    ),\n                ),\n            )\n\n        def sb128(self, value):\n            value &= self.mask128\n            return value ^ self.fsbox[value & 0xff]\n\n    class SANDstorm384(SANDstorm512Base):\n        digest_size = 48\n        hashbitlen = 384\n\n    class SANDstorm512(SANDstorm512Base):\n        digest_size = 64\n        hashbitlen = 512\n\n    class SarmalBase:\n        block_size = 128\n        hashbitlen = None\n        digest_size = None\n        MASK64 = 0xffff_ffff_ffff_ffff\n\n        S = (\n            0x3a, 0x5b, 0xf2, 0xf, 0xe4, 0xad, 0x29, 0x91, 0xc5, 0x47, 0xb8, 0x63, 0x8c, 0x10, 0xde, 0x76,\n            0x2c, 0x75, 0x89, 0x40, 0xa3, 0xe1, 0x32, 0x6d, 0xbb, 0xe, 0xc6, 0x94, 0xfa, 0xdf, 0x17, 0x58,\n            0x61, 0xd0, 0xa4, 0xb5, 0x82, 0xfc, 0x93, 0x2a, 0x4f, 0xc8, 0x7, 0x39, 0xed, 0x7b, 0x56, 0x1e,\n            0xe7, 0x44, 0x90, 0x79, 0x3b, 0x26, 0xaf, 0xf8, 0xd3, 0x5a, 0x11, 0x85, 0x6e, 0xb2, 0xcc, 0xd,\n            0x45, 0xec, 0x16, 0x21, 0x5e, 0x70, 0x8, 0xbf, 0x6a, 0x33, 0x99, 0xc7, 0xdb, 0xfd, 0x84, 0xa2,\n            0xf6, 0xb9, 0x35, 0xd4, 0x9f, 0x67, 0x8b, 0xee, 0x72, 0x1d, 0x5c, 0xa0, 0x28, 0x43, 0x1, 0xca,\n            0xd9, 0x66, 0xc, 0xf7, 0xcd, 0xb4, 0x1a, 0x73, 0xe8, 0x8f, 0xa5, 0x51, 0x42, 0x2e, 0x30, 0x9b,\n            0x9d, 0x1f, 0xe3, 0xcb, 0xf9, 0x8a, 0x64, 0x3c, 0x0, 0xb6, 0x4e, 0x22, 0xa1, 0x55, 0x78, 0xd7,\n            0x12, 0x98, 0x4a, 0x8e, 0xb1, 0xc3, 0xdc, 0x54, 0xa6, 0xf0, 0xeb, 0x7d, 0x9, 0x37, 0x2f, 0x65,\n            0x88, 0xc2, 0x2b, 0x13, 0x60, 0x9e, 0xf5, 0xa7, 0x59, 0xd1, 0x7a, 0xef, 0x36, 0x4, 0x4d, 0xbc,\n            0x53, 0x3e, 0xbd, 0xa8, 0x4c, 0x2, 0x71, 0x19, 0x87, 0xe5, 0xff, 0xda, 0xc4, 0x96, 0x6b, 0x20,\n            0x74, 0x27, 0xc1, 0xe6, 0xa, 0x49, 0x5d, 0xd2, 0xfe, 0xab, 0x80, 0x1c, 0xb3, 0x68, 0x95, 0x3f,\n            0xcf, 0x8d, 0x7e, 0x9a, 0xd6, 0x1b, 0xb7, 0x5, 0x31, 0x69, 0x23, 0x48, 0x50, 0xac, 0xe2, 0xf4,\n            0xae, 0x3, 0x6f, 0x52, 0x25, 0x38, 0xe0, 0x86, 0x14, 0x7c, 0xdd, 0xfb, 0x97, 0xc9, 0xba, 0x41,\n            0xb0, 0xf1, 0x57, 0x6c, 0x18, 0xd5, 0xce, 0x4b, 0x2d, 0x92, 0x34, 0x6, 0x7f, 0xea, 0xa9, 0x83,\n            0xb, 0xaa, 0xd8, 0x3d, 0x77, 0x5f, 0x46, 0xc0, 0x9c, 0x24, 0x62, 0xbe, 0x15, 0x81, 0xf3, 0xe9,\n        )\n\n        MDS = (\n            (1, 6, 8, 9, 6, 9, 5, 1),\n            (1, 1, 6, 8, 9, 6, 9, 5),\n            (5, 1, 1, 6, 8, 9, 6, 9),\n            (9, 5, 1, 1, 6, 8, 9, 6),\n            (6, 9, 5, 1, 1, 6, 8, 9),\n            (9, 6, 9, 5, 1, 1, 6, 8),\n            (8, 9, 6, 9, 5, 1, 1, 6),\n            (6, 8, 9, 6, 9, 5, 1, 1),\n        )\n\n        SIGMA0 = (\n            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n        )\n        SIGMA1 = (\n            1, 14, 15, 10, 12, 2, 7, 4, 13, 8, 3, 9, 11, 5, 0, 6,\n        )\n        SIGMA2 = (\n            11, 4, 10, 7, 14, 9, 13, 1, 6, 5, 8, 2, 3, 15, 12, 0,\n        )\n        SIGMA3 = (\n            8, 2, 0, 5, 10, 3, 14, 13, 12, 7, 1, 15, 9, 4, 6, 11,\n        )\n        SIGMA4 = (\n            2, 8, 5, 7, 11, 1, 12, 4, 6, 14, 15, 10, 0, 13, 9, 3,\n        )\n        SIGMA5 = (\n            13, 14, 2, 1, 10, 12, 11, 7, 5, 3, 9, 15, 8, 4, 0, 6,\n        )\n        SIGMA6 = (\n            3, 13, 4, 0, 5, 6, 2, 10, 9, 8, 7, 11, 12, 15, 1, 14,\n        )\n        SIGMA7 = (\n            6, 3, 11, 14, 4, 0, 5, 8, 7, 13, 2, 12, 10, 1, 15, 9,\n        )\n        SIGMA3_5 = (\n            13, 10, 3, 2, 8, 11, 1, 5, 9, 12, 0, 4, 15, 6, 7, 14,\n        )\n        SIGMA7_5 = (\n            15, 7, 9, 12, 3, 13, 10, 0, 4, 6, 1, 14, 2, 5, 8, 11,\n        )\n\n        LEFT_SIGMAS_COMMON = (SIGMA0, SIGMA1, SIGMA2, SIGMA3)\n        RIGHT_SIGMAS_COMMON = (SIGMA4, SIGMA5, SIGMA6, SIGMA7)\n\n        G_TABLES = None\n\n        INIT_H = ()\n        INIT_C = ()\n        INIT_S = (0, 0, 0, 0)\n\n        def __init__(self, data=b\"\"):\n            if self.hashbitlen is None or self.digest_size is None:\n                raise TypeError(\"SarmalBase must be subclassed\")\n            self.ensure_tables()\n            self.h = list(self.INIT_H)\n            self.c = list(self.INIT_C)\n            self.s = list(self.INIT_S)\n            self.t = 0\n            self.msg_len = 0\n            self.buf = bytearray()\n            if data:\n                self.update(data)\n            return\n\n        @classmethod\n        def ensure_tables(cls):\n            if cls.G_TABLES is not None:\n                return\n\n            constants = (1, 5, 6, 8, 9)\n            mul_tables = {}\n            for constant in constants:\n                table = []\n                for value in range(256):\n                    table.append(cls.gf_multiply(value, constant))\n                mul_tables[constant] = tuple(table)\n\n            tables = []\n            for pos in range(8):\n                pos_table = []\n                for byte_value in range(256):\n                    sboxed = cls.S[byte_value]\n                    word = 0\n                    for row in range(8):\n                        out_byte = mul_tables[cls.MDS[row][pos]][sboxed]\n                        word = (word << 8) | out_byte\n                    pos_table.append(word)\n                tables.append(tuple(pos_table))\n\n            cls.G_TABLES = tuple(tables)\n            return\n\n        @classmethod\n        def gf_multiply(cls, a, b):\n            result = 0\n            while b:\n                if b & 1:\n                    result ^= a\n                a <<= 1\n                if a & 0x100:\n                    a ^= 0x11d\n                b >>= 1\n            return result\n\n        def copy(self):\n            other = self.__class__()\n            other.h = list(self.h)\n            other.c = list(self.c)\n            other.s = list(self.s)\n            other.t = self.t\n            other.msg_len = self.msg_len\n            other.buf = bytearray(self.buf)\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            chunk = bytes(data)\n            self.msg_len += len(chunk)\n            self.buf.extend(chunk)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.compress(block)\n            return self\n\n        def digest(self):\n            clone = self.copy()\n            clone.finalize()\n            return clone.output_digest()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def output_digest(self):\n            state_bytes = b\"\".join(word.to_bytes(8, \"big\") for word in self.h)\n            if self.hashbitlen == 224:\n                return state_bytes[-28:]\n            return state_bytes[:self.digest_size]\n\n        def finalize(self):\n            messagebitlen = self.msg_len * 8\n            block = bytearray(self.buf)\n\n            if len(block) <= 118:\n                block.append(0x80)\n                while len(block) < 119:\n                    block.append(0x00)\n            else:\n                block.append(0x80)\n                while len(block) < 128:\n                    block.append(0x00)\n                self.compress(bytes(block))\n                block = bytearray(119)\n\n            if self.hashbitlen == 224:\n                block.append(0xe0)\n            elif self.hashbitlen == 256:\n                block[118] |= 0x01\n                block.append(0x00)\n            elif self.hashbitlen == 384:\n                block[118] |= 0x01\n                block.append(0x80)\n            elif self.hashbitlen == 512:\n                block[118] |= 0x02\n                block.append(0x00)\n            else:\n                raise ValueError(\"unsupported hashbitlen\")\n\n            block.extend(messagebitlen.to_bytes(8, \"big\"))\n            self.compress(bytes(block))\n            self.buf.clear()\n            return\n\n        def g_func(self, value):\n            tables = self.G_TABLES\n            result = (\n                tables[0][(value >> 56) & 0xff] ^\n                tables[1][(value >> 48) & 0xff] ^\n                tables[2][(value >> 40) & 0xff] ^\n                tables[3][(value >> 32) & 0xff] ^\n                tables[4][(value >> 24) & 0xff] ^\n                tables[5][(value >> 16) & 0xff] ^\n                tables[6][(value >> 8) & 0xff] ^\n                tables[7][value & 0xff]\n            )\n            return result\n\n        def mix(self, state, a, b, c, d):\n            out1 = state[0] ^ a\n            temp1 = self.g_func(out1)\n\n            out2 = temp1 ^ state[1]\n\n            temp2 = state[2] ^ b\n            out3 = (temp1 + temp2) & self.MASK64\n\n            out4 = (state[3] - temp1) & self.MASK64\n\n            out5 = state[4] ^ c\n            temp2 = self.g_func(out5)\n\n            out6 = temp2 ^ state[5]\n\n            temp1 = state[6] ^ d\n            out7 = (temp2 + temp1) & self.MASK64\n\n            out0 = (state[7] - temp2) & self.MASK64\n\n            return [out0, out1, out2, out3, out4, out5, out6, out7]\n\n        def apply_sigmas(self, state, message_words, sigmas):\n            current = state\n            for sigma in sigmas:\n                current = self.mix(current, message_words[sigma[0]], message_words[sigma[1]], message_words[sigma[2]], message_words[sigma[3]])\n                current = self.mix(current, message_words[sigma[4]], message_words[sigma[5]], message_words[sigma[6]], message_words[sigma[7]])\n                current = self.mix(current, message_words[sigma[8]], message_words[sigma[9]], message_words[sigma[10]], message_words[sigma[11]])\n                current = self.mix(current, message_words[sigma[12]], message_words[sigma[13]], message_words[sigma[14]], message_words[sigma[15]])\n            return current\n\n        def compress(self, block):\n            message_words = [int.from_bytes(block[i * 8:(i + 1) * 8], \"big\") for i in range(16)]\n\n            left = [self.h[0], self.h[1], self.h[2], self.h[3], self.s[0], self.s[1], self.c[0], self.t]\n            right = [self.h[4], self.h[5], self.h[6], self.h[7], self.s[2], self.s[3], self.c[1], self.t]\n\n            left = self.apply_sigmas(left, message_words, self.LEFT_SIGMAS_COMMON)\n            right = self.apply_sigmas(right, message_words, self.RIGHT_SIGMAS_COMMON)\n\n            if self.hashbitlen == 384 or self.hashbitlen == 512:\n                left = self.apply_sigmas(left, message_words, (self.SIGMA3_5,))\n                right = self.apply_sigmas(right, message_words, (self.SIGMA7_5,))\n\n            for i in range(8):\n                right[i] ^= left[i]\n\n            for i in range(8):\n                self.h[i] ^= right[i]\n\n            self.t += 1024\n            return\n\n    class Sarmal224(SarmalBase):\n        hashbitlen = 224\n        digest_size = 28\n        INIT_H = (\n            0xbb67_ae85_84ca_a73b, 0x2574_2d70_78b8_3b89, 0x25d8_34cc_53da_4798, 0xc720_a648_6e45_a6e2,\n            0x490b_cfd9_5ef1_5dbd, 0xa993_0aae_1222_8f87, 0xcc4c_f24d_a3a1_ec68, 0xd0cd_33a0_1ad9_a383,\n        )\n        INIT_C = (\n            0xb9e1_22e6_138c_3ae6, 0xde5e_de3b_d42d_b730,\n        )\n        INIT_S = (0, 0, 0, 0)\n\n    class Sarmal256(SarmalBase):\n        hashbitlen = 256\n        digest_size = 32\n        INIT_H = (\n            0x9e37_79b9_7f4a_7c15, 0xf39c_c060_5ced_c834, 0x1082_276b_f3a2_7251, 0xf86c_6a11_d0c1_8e95,\n            0x2767_f0b1_53d2_7b7f, 0x0347_045b_5bf1_827f, 0x0188_6f09_2840_3002, 0xc1d6_4ba4_0f33_5e36,\n        )\n        INIT_C = (\n            0xf06a_d7ae_9717_877e, 0x8583_9d6e_ffbd_7dc6,\n        )\n        INIT_S = (0, 0, 0, 0)\n\n    class Sarmal384(SarmalBase):\n        hashbitlen = 384\n        digest_size = 48\n        INIT_H = (\n            0x3c6e_f372_fe94_f82b, 0xe739_80c0_b9db_9068, 0x2104_4ed7_e744_e4a3, 0xf0d8_d423_a183_1d2a,\n            0x4ecf_e162_a7a4_f6fe, 0x068e_08b6_b7e3_04fe, 0x0310_de12_5080_6005, 0x83ac_9748_1e66_bc6d,\n        )\n        INIT_C = (\n            0xe0d5_af5d_2e2f_0efd, 0xb07_3add_ff7a_fb8c,\n        )\n        INIT_S = (0, 0, 0, 0)\n\n    class Sarmal512(SarmalBase):\n        hashbitlen = 512\n        digest_size = 64\n        INIT_H = (\n            0x243f_6a88_85a3_08d3, 0x1319_8a2e_0370_7344, 0xa409_3822_299f_31d0, 0x082e_fa98_ec4e_6c89,\n            0x4528_21e6_38d0_1377, 0xbe54_66cf_34e9_0c6c, 0xc0ac_29b7_c97c_50dd, 0x3f84_d5b5_b547_0917,\n        )\n        INIT_C = (\n            0x9216_d5d9_8979_fb1b, 0xd131_0ba6_98df_b5ac,\n        )\n        INIT_S = (0, 0, 0, 0)\n\n    class SgailBase:\n        block_size = 512\n        digest_size = None\n        word_modulus_64 = 0xffff_ffff_ffff_ffff\n\n        centre_rounds_for_digest_bits = {\n            224: 4,\n            256: 4,\n            384: 4,\n            512: 4,\n            768: 6,\n            1024: 6,\n            1536: 8,\n            2048: 8,\n        }\n\n        sbox_0 = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        rc_u64 = (\n            0x25d479d8f6e8def7, 0xe3fe501ab6794c3b, 0x976ce0bd04c006ba, 0xc1a94fb6409f60c4,\n            0x5e5c9ec2196a2463, 0x68fb6faf3e6c53b5, 0x1339b2eb3b52ec6f, 0x6dfc511f9b30952c,\n            0xcc814544af5ebd09, 0xbee3d004de334afd, 0x660f2807192e4bb3, 0xc0cba85745c8740f,\n            0xd20b5f39b9d3fbdb, 0x5579c0bd1a60320a, 0xd6a100c6402c7279, 0x679f25fefb1fa3cc,\n            0x8ea5e9f8db3222f8, 0x3c7516dffd616b15, 0x2f501ec8ad0552ab, 0x323db5fafd238760,\n            0x53317b483e00df82, 0x9e5c57bbca6f8ca0, 0x1a87562edf1769db, 0xd542a8f6287effc3,\n            0xac6732c68c4f5573, 0x695b27b0bbca58c8, 0xe1ffa35db8f011a0, 0x10fa3d98fd2183b8,\n            0x4afcb56c2dd1d35b, 0x9a53e479b6f84565, 0xd28e49bc4bfb9790, 0xe1ddf2daa4cb7e33,\n            0x62fb1341cee4c6e8, 0xef20cada36774c01, 0xd07e9efe2bf11fb4, 0x95dbda4dae909198,\n            0xeaad8e716b93d5a0, 0xd08ed1d0afc725e0, 0x8e3c5b2f8e7594b7, 0x8ff6e2fbf2122b64,\n            0x8888b812900df01c, 0x4fad5ea0688fc31c, 0xd1cff191b3a8c1ad, 0x2f2f2218be0e1777,\n            0xea752dfe8b021fa1, 0xe5a0cc0fb56f74e8, 0x18acf3d6ce89e299, 0xb4a84fe0fd13e0b7,\n            0x7cc43b81d2ada8d9, 0x165fa26680957705, 0x93cc7314211a1477, 0xe6ad206577b5fa86,\n            0xc75442f5fb9d35cf, 0xebcdaf0c7b3e89a0, 0xd6411bd3ae1e7e49, 0x00250e2d2071b35e,\n            0x226800bb57b8e0af, 0x2464369bf009b91e, 0x5563911d59dfa6aa, 0x78c14389d95a537f,\n            0x207d5ba202e5b9c5, 0x832603766295cfa9, 0x11c819684e734a41, 0xb3472dca7b14a94a,\n        )\n\n        mds_8x8s_0 = (\n            (0x21f3791f6e74254d, 0x65083159466497f2, 0xebbac2d6e7de8c60, 0x513280cab631cae9,\n             0xb402d78f03fd68cf, 0x61c19b2e9c642ecc, 0x3184c30c965fb1e0, 0xceebe6d38d5e4e14,\n             0xee6ce63f1e17c43f, 0xa9202656ca5611cf, 0x2c7df780d2d4d7e9, 0x07147e9900dbeae4,\n             0x605cb5bec88f29ed, 0xe63d0a871295c268, 0x715dfc34c09c006f, 0x0a274035b99b0985,\n             0x7b5036e2bbb36ab5, 0x60b426e1c677f9a4, 0x77b26e8f83a27fe6, 0x5e3da4d8860c2da6,\n             0x476450ec12fc23b6, 0xcf2e58f0a3ff7afc, 0x6bf7cb63af3090f7, 0x53503ecc28971c5d,\n             0x50efa48c68894c0f, 0x21276ffb7e03ec7e, 0x372f7d214c3fe162, 0x6c634f672f56f0c8,\n             0x67f188214acdcced, 0xef99dbec81bb786c, 0x616a57ff8ac27eed, 0xfe802d2d3817ef96,\n             0x74a28f1f190082b8, 0x7e7be032ac97f1aa, 0x44f5245f45efc65f, 0xe1c3cd519ba07dab,\n             0x5bfe706df793e511, 0xb910dae79f48f386, 0x7239c69f4a218fe8, 0x4ecd8a4e2b95aade,\n             0xb1558e8ac2f7d83e, 0x8c17f6c38f2edfd6, 0xfe37b22b2d9c06ac, 0x380a01d6f908ef75,\n             0x5d15e0e4659474a5, 0x36a1856da14e741d, 0xae922a766eb0a93a, 0x35aa2d82f26b4ee7,\n             0xac36134d4ba9d4b6, 0xf25e058bdc65429d, 0xe251099f3d981cb1, 0xbc0df1764c130a4b,\n             0x075db9351525409f, 0x5bc4fc17f9f00e9d, 0xb940b5dcf96857a6, 0x8ab14b29d7fa3c69,\n             0xea42c5cb26f1e037, 0x3480c96e087cf784, 0x16bdd12c8f643c6f, 0x30e78286dac34073,\n             0x6d57e9d4df1927c4, 0x8adb91d4860855e4, 0x5b59dce1c9664403, 0xcc8d057ff042edf4,\n             0xb01cbaffe8588c6e, 0xa4d714124e015e31, 0xc5ddfba4eb9e2762, 0xe3fbd520af654293,\n             0x0328af0adf11b7a2, 0x78f6b1b345a65894, 0xa515ee0cde825010, 0xdca20fe794a68bef,\n             0x75b0d2bf8c8ef5f0, 0x7864d323d0ad7c53, 0x4b539a49b480e144, 0x5d3dca5622aafb83,\n             0xa317c4a77bda7917, 0x18868a55f0eb4386, 0x6c64bbc24b4f8458, 0xc48c0dcb99b1f90c,\n             0x9b0f7d66e0916b0c, 0xd324c75c0041f761, 0x5c7670aa6a3d173b, 0x7c4c450c4275ce6b,\n             0x9f51c0cad5b5c5bf, 0xa010226e0422300e, 0x32a4ce7654f2682c, 0xcda0e222be738184,\n             0xcef92650daec813f, 0xff778dcd494aaa89, 0x5bf7b44c7ee4841f, 0x5a899183ea22a7b0,\n             0x11a5b5fd8406ad15, 0xf6b1725894d4dbf6, 0x6830726bfe407f32, 0x1100379ea17ec920,\n             0x5d47318e9482db5d, 0xcfe2b57e2600af8e, 0x72c4c4256e76f2e7, 0xee4cd440ac9cb1e2,\n             0x6a120c87e333e3e4, 0x844a1a4ca7186864, 0xad2f614908fa97cf, 0x66fece73d2cb6d54,\n             0xb4ce520e8581f6af, 0xd3601ca7ab92fa2c, 0xae6c2011029658e4, 0x0611ec2543e18ad1,\n             0x37b54b8c6e4533ea, 0x760123eb043cd51f, 0x32531a0db5d37eda, 0x7c64d6a4af08a48b,\n             0x52239f2b32ef79a8, 0x56aeb5bbc1e96cbb, 0xfc457eb98ee2cf93, 0x0bd31ca600b763d6,\n             0x325e4f50eba43149, 0xe1951aa52284973a, 0xc41668d43e36dce3, 0xc9cfb9fa6f7982aa,\n             0x0e5a0c0c602fac12, 0x883b542dec0fca15, 0x7a70cf819b87bc4e, 0x00df4ee43c516fc9,\n             0xb1070711f15d2d8b, 0xda41212584b5175b, 0xb8b273f21bf1d1a2, 0xb1520d55bd80458d,\n             0x7920b85bf8b5be6d, 0xd35ad650af0b5049, 0xeee8a083e0fe19e8, 0x065a5c18896fc495,\n             0x5b5ca657f4d88e7c, 0x582120469e9037d0, 0x7df58b1e8c146893, 0x04dbb1f88857c3b0,\n             0x18f21d0093d63eef, 0xa177c815cbe3c0d6, 0x7cc6fe256b1b7b28, 0x40692155492087b6,\n             0xc87834216f2e16b6, 0x7925980df31868f7, 0x8e12ec81843758fb, 0xfca01a9f48ffa29c,\n             0x7241902e5da5aa7f, 0x4852f7f2c20cd822, 0x961e2ba62f6dfa4b, 0xe8d0d26e769d6dad,\n             0xc41501027b7fa884, 0x60b289a4cc1529c5, 0xaab85bc1dbf380fe, 0xed33b1d8ad5bf89b,\n             0xb3e5019ee75a174d, 0x56c61c074f26da3e, 0x3e26af01150e3e24, 0xc49efd72b5735f9d,\n             0x1c66cf44a8a4f796, 0xe552af9256b1ce72, 0x4f1bdcacfc07eec4, 0x976132ec70a11038,\n             0x4a83987ebc2dba57, 0x5d7ae5115e5b1518, 0x21c4d5df5bc52e7e, 0xc945fd885b3a9302,\n             0x1aa4ca3b9e1ee122, 0x977615f72712d37f, 0x8713a03542001bd9, 0x5cf5e6e8cf8a18bd,\n             0xc7c272ec46289eec, 0xeee34382c5e49963, 0x1997bc57ed7577ae, 0x1e07e060cd4a52ec,\n             0x7659464225af0fe6, 0xc0ce187ec139bb47, 0xa217d13e6ab9e4cb, 0x8efcd447b91db0b1,\n             0xc2822e9a84fa42ef, 0xf703b30e47b1da74, 0x6bb14918144ce4fe, 0x96e12a35810ecccf,\n             0xb7474ef25ea347c9, 0x4754b76b75307779, 0xf899d2965c0399c2, 0xed41912eda8628e3,\n             0x56d409090d5ed502, 0x07e639c1f924a888, 0xef0b1d738d8bc09b, 0x94d6c0d2a20ee4a5,\n             0xde90cb8a3dcad71a, 0x772ce398d92f7a55, 0xe63b8856ef0387dc, 0x19ad7d4c4e966874,\n             0x1621352df9eb959b, 0xb4f8d49283e4c5a2, 0x6bc1dbc70868fefa, 0xa75e67369c9d249c,\n             0x3bc0a04d73522039, 0x3cec35af85c0d546, 0x74c98bdf7d114b64, 0x25a26761dd9d52ed,\n             0x49723301bee41188, 0xd3495ca282518cfe, 0x4a3fe0ba68a796f2, 0xc5b599ec5f9b07ca,\n             0xae1c258959732fd8, 0xeb009224ecec0c9d, 0xb686b9e4a258f586, 0x4c907cd0804a6488,\n             0x69c1cf18ffd3b0ef, 0x8adabe44cf07d077, 0xc6176ec7eae507c8, 0xdb6b1334bc167a53,\n             0xbb3562eea27aaa7a, 0xbeaa84312a2f21b5, 0x057742b444f3aac5, 0xb6bf7386ba4bf63b,\n             0x318a61e1c34d715b, 0xcd067629b45b0f00, 0xe6b443e4b29d00b5, 0x72b9cd07571e057d,\n             0x8ce8c0e3626bcf39, 0x81afa416a6d96439, 0xf301c73f60ba0b44, 0x5d4d11a5d642a95f,\n             0x36e15c7cbff6eeaf, 0x76f0da52833f4f6b, 0xff30598e9cbbdd24, 0x14fd71a418f90e83,\n             0x815bb77a998bb6ad, 0xf4861ceb44304b6d, 0xe1ed2ad43ebf71a2, 0xde6f95c75fc6c08f,\n             0xce3f746cb3034c1c, 0x5e48e14255eb8044, 0x50a13cc9e7e1cc32, 0x83f740ecc9e12301,\n             0xcde57a05fdefc3ec, 0x015c974d6f1c729d, 0xdaa4aceaa16f587c, 0x93549daf41217d03,\n             0xded35d6c27c06574, 0x0094d41d56e9a9bb, 0xfee3fb2188338bec, 0xa3772fa8c48a8ed8,\n             0x21752c765a77f540, 0xc583af8841c17651, 0x98116c6de1bad52e, 0x4e3f759981c52d6e,\n             0x6824805d690ca418, 0xbc294852cad3bf1a, 0xf2e2bd8bd57c54c5, 0xbf53852b20f500f2,\n             0x5b0a8d1ed91673a5, 0x71c01e9b9fae4637, 0xa164f6d009afccad, 0x3f7fc13f651eee41),\n            (0xdc091e1e1d023bfe, 0x4ba4a72d0799ccb5, 0x24e704a59cbe0b4b, 0x2c10e33aab958ee1,\n             0x4378e752d54f2d21, 0xe4eb240c05e00236, 0x09986d3c0bce468a, 0xc26f668145402464,\n             0x3036a3780701631b, 0xb27d42c9e6b49a98, 0x1a55fa108e7e0a78, 0x340f263d1f225e97,\n             0xb0b9c98aead9a623, 0xe2434d3f9643cb1f, 0x0c7dbda3509c8594, 0x4cbaceb8b929dc65,\n             0x011483b83edffe58, 0x18e845b0ec2fdc68, 0xcc41533175993aa6, 0xe40c4e8be4643f3e,\n             0x9a6fe95bef10770f, 0x6cea1ef7464cdb95, 0x5244f741db60e1d1, 0xdbc5dad3b2a32b30,\n             0x1f1b8e7a0da47118, 0x038edf7e2fd3e535, 0xbe7b6c4d078bce3c, 0xcbea7df622b651e2,\n             0xdd5b383a43c9cb63, 0xff4a8a6cdebe88c3, 0xc28c706a50feb325, 0x7bf6277e82810665,\n             0x19d0a306eb8d5090, 0xafdddb90427220b6, 0x8dab6924b88ee2df, 0xb22157159e2fb7be,\n             0x5ffc62c30f24c8a9, 0x6089d1415777373d, 0x6143dc9fb6a44780, 0x889ca6a4c720c6df,\n             0x40d9941ab8add8cb, 0x008e12cf81165f75, 0x086dc34c228bc30d, 0x8da5c0ace780969e,\n             0xb97f8ae86f60aad0, 0xcf4220c9ce2f6499, 0x67abc058a10ede51, 0x2eaac0bd9416c506,\n             0xf516100d80e7a4e6, 0x758efcc910e9616f, 0xe6f8d60d9c4d4064, 0xffe9f4e2d319edf3,\n             0xbc1c318414913110, 0xb2add38f9d882931, 0x570589b178ac64f8, 0xe8f0a26224fd1518,\n             0x6d232cde74efa9de, 0x5e989657e9b28144, 0x06eb0f262a5d0052, 0xa58f0e9859245615,\n             0xf6048851218296a3, 0x347a584c533f7a67, 0x3de874a5c2a25c3e, 0x9c6617a5b2597931,\n             0x589b9b6406bd53c3, 0x57aca310cdc06602, 0x10a385ac53fc7182, 0x6c8ce921d1ec0038,\n             0xa907a82ff590eed5, 0x1bb22106445fddb2, 0x1f2acb543ce5efa0, 0x124cb0552ca677fd,\n             0x9ff9208c0c1c89c3, 0x7a8c58cb55c5f03f, 0x1fc9b6b01dc3673c, 0xdad68ffc443493b8,\n             0x8620b92cdf84922b, 0xaff805c359ddfb9c, 0x5a41a1d0389c9913, 0xfab8cae7154ef6d0,\n             0x5a6a1d79233abcef, 0xe1a117aaaf7438dd, 0xcb9a49b05b32b8bf, 0x1f30edc90442f0d8,\n             0x32b7ef28af1abe32, 0x5f55bdd408d8b201, 0xec068397051b73bd, 0x410b6bac13692c63,\n             0x2a2edd4e719cd7cb, 0x192825af198240dd, 0x1657ce87cb77542f, 0x500abe5bd7cf0634,\n             0x404619f4af0ed79d, 0x89176b015eb5f086, 0x07ea227976265253, 0x34f9fad354e8edb5,\n             0xe11ef1d4b823b43f, 0xb65ed0fb00f475be, 0x8c6b0a5b49dfd571, 0x6bf410af1db4635d,\n             0x1450532ec0cd88e0, 0xcac1306301394aef, 0x0844a66443d7cabf, 0x4c90012669f711eb,\n             0xe81d1fed80397c92, 0x1e71c65ca2f696ba, 0xfcb93caa371299a9, 0xc85e4fb5bdc32358,\n             0x150db782c7176d39, 0x1270e6236884cfee, 0x2a1c5f901328484a, 0x2dab1a3a35febb2a,\n             0x5e88b568ba756f1f, 0x16bbe70cf5799498, 0xd6f8ef4a314e87df, 0xbc1725c5522e242c,\n             0xfc906d65465cc6cc, 0x3406eeed6808c920, 0x35a629fc7417429d, 0x4f542cea74b450ee,\n             0xd4059725677962e0, 0x18c69f86117122cd, 0xb8c83cb49bd38987, 0x6e47475eb76d579c,\n             0xb9b163211e1e93e3, 0x77998487c06cad25, 0x486982e7b1d0adaa, 0x5dd12cd66abd279e,\n             0xa87b32fbc195021a, 0xdc5f80293482cc2d, 0x71ac9099084d0e56, 0xb51b37eb74dd82eb,\n             0x90a8aa773e10a96b, 0x70f053ff4b345bd9, 0xfbef716a1d8356ef, 0x97ceea53d407d793,\n             0x1e91ca10ed42bb74, 0x2300897cb7132dc3, 0xd4955b43c58b9987, 0x39a8e1b597e932ce,\n             0xf79788817ec28db0, 0xf11e11fec040ec1e, 0xbcf15a69450ee4f0, 0x5a4404f9a4f667d0,\n             0x584c917416edb1d4, 0x5f9150ecf2281a6a, 0x577dbfac9717108d, 0xf6a62765c79d9b3b,\n             0x3c5aa30a0530e1dd, 0x84bee8eeb0a8ceb5, 0xfb92258e5f71514d, 0xd0be1fbed8d9b11a,\n             0x62e0f653af400e3f, 0xaa49ce8ca1b387f2, 0xa15de9dc0850e528, 0x6fd10cc750795971,\n             0xf28d86dd3fee6a9a, 0xf7461c419790be7b, 0xbe8d426ef4adf74d, 0xf2cecbf2fcca7166,\n             0x467a1a77f45da2f5, 0xa7a6f8a4e97c7e6d, 0x1cbec5a3a7321764, 0x57940d75fe419b3f,\n             0x92513e3783cb714d, 0x11bdfbeaa04c83eb, 0xf8437e7997e477fc, 0x0b1f1432115802ad,\n             0xada1d17336d6a30c, 0xd64f714ccf6aa1db, 0x0c85519533ac9b04, 0x89bae859a94b485a,\n             0xe732ba981d1568e6, 0x29bc7cc6c985b2e2, 0xe20ea4ef8f05de22, 0x6455abba1354b87c,\n             0x5b81b7ca7531939d, 0x4e3a18520218f6f6, 0x6461a304949ee14c, 0x2ce9bfb2c76f9c60,\n             0xa57016c08f27951c, 0x1a6d369e8f9b3e06, 0x926de9443a25fc3f, 0x14ce9e8b918329a2,\n             0xf4ca6ca3fa6014d9, 0xe43bd7c9a700e89a, 0xc27676f2120260ea, 0xda76cf9fa2b6bffe,\n             0xb623b6fca48addc2, 0xc03e599e619f230c, 0xae7f0d21059d9807, 0x3fb7fa8ca0d95039,\n             0xca1865b67160264d, 0xacbfc8b57dc56cda, 0x8a33149bdfd844c7, 0x00500f8618a23e46,\n             0xd243786cab62df28, 0x186e4f7728c7da03, 0xe265d7e031823801, 0xbe24f3699ce37b2c,\n             0x48c09cfc8c6000c2, 0xdd6571045568b463, 0xd8796bd32c020b33, 0xb680ace772940105,\n             0xa4fa2a00a2a027fd, 0x222a84d177d802b7, 0x09fa5cde5e181c65, 0xb728a521a327f2d3,\n             0x0c418db1618a011a, 0xbb071237f78565d1, 0x0050601b181d372c, 0xd4e494cceac1af80,\n             0xdb98ad49ac4a87d7, 0xcc8f4ac5e2207577, 0x65ecbed93522c314, 0x1086bbfc6e4a01b0,\n             0x9e5c2de01137e8a4, 0xc850bb4af5b264c8, 0x19b9de7a83f944af, 0x2759e635aaa85dc4,\n             0x7b65179fe2b4021f, 0x107b4b77da9ef8b8, 0xa02c787f53820a9c, 0xd4bbf90e4a9d9a16,\n             0x2b0eef38ccda3f2b, 0x6cab81c64ae294e9, 0xfa98db5b314d3608, 0x1fb42b7a7e57f4f9,\n             0xcf9bbef39b904124, 0x132d79e0d9a94354, 0xa40905540d015215, 0x10ed7f391c8fa48f,\n             0xea468a92dcaaaaa7, 0x91cb638a0fe8a332, 0x5be87a98659f0aa4, 0x1ddecac735d60f1e,\n             0xe98803429c3c0525, 0x4161f33aa3dff348, 0x6336a552801eded4, 0x977166fab047d040,\n             0xba4fb2b5c5f5195f, 0xba7bce67fc1d9c67, 0x7d632ecb7b166d73, 0xe402efd7d0ddb9ed,\n             0x9854459563cb850e, 0x87efdcda596efa78, 0xe99327a5e82ab714, 0x0fe1bcb6bb3ab9c4,\n             0x1eaeb88b76e12beb, 0xc8dd40d8dbfb7053, 0x83634df0130a84bb, 0xffa148456b8e1042,\n             0x52b02acdb4d97590, 0x114ce02d320c305e, 0xc1ca2426e305f42b, 0xce37f7ba18e9fef9),\n            (0x6fc2921faa1ec7e1, 0xcf0a9e62c89b454a, 0xc73737b9139da0de, 0x35195652d47556fe,\n             0x9b3d3573731f86fa, 0x4e513e1bf71ba05b, 0x3bd53496128c7ef3, 0x710d8995f84c14c9,\n             0xb1056a6a826689d0, 0x15566e2e56245f1b, 0x2d6dbcc52f92e839, 0x7f775aafa8562d1b,\n             0x1cac474ea5f8f500, 0x962fa97cd3b15f8c, 0x0201ba9d812d2e5c, 0x7168ea0ad0f624e3,\n             0x610630b7e3375abc, 0x8500f408c9426dbe, 0x288c018df3d115ab, 0x10d1742abbddfc2d,\n             0xd2423f92b6989520, 0x94f5b47c22a5f4fb, 0x8811d2737a82a761, 0xb14a4c5be803f6dc,\n             0x05055d40eb223512, 0xb61c400fd3709159, 0x1b3fd7ab9defc967, 0x07742a2e1f3457c2,\n             0x14391707f58e33a8, 0xc1a85c9e1a13c718, 0xbef1cf581aa3b8a1, 0x3dfc1980a8483590,\n             0xa2b44d765687d989, 0xbd965be8a4c41d2f, 0x54a658c71a5c7763, 0x15bae8b276522421,\n             0xcdc6389d7ce3491d, 0x7328d9681e8e489b, 0x6a8b3be699d35676, 0xf0db501cad9e0269,\n             0x6e375102e3fcd321, 0x7a934b182542584a, 0x9b96f3c665ab4e09, 0xccb483f284efa029,\n             0x84121cf66c59dd4c, 0xb4716184d26973a3, 0x6cd4bae9fedee8b5, 0x24e8712a312fc48e,\n             0x88fe2f56fe48b126, 0x648eae87f1591a8e, 0xda390e5c152fc2b3, 0x4f83712782e86113,\n             0x61cb133276af80eb, 0xf9347396ab8def81, 0xae86ee61c95288f5, 0x5a8bbcaf7a95bbfa,\n             0xd3ed9f0f96c09105, 0x04ac5f967200aa0e, 0xd1d8e4af6519d655, 0x850da707d5bf14b7,\n             0x1437883293021475, 0x57e4b5ffca53a9c6, 0xc647c4f719e27786, 0xe37c2d1114732b25,\n             0x9322fb562bc5cac4, 0x04f86c13f09d9751, 0x99328883584556be, 0x14837f107f91f39e,\n             0x93b2306f3aa31130, 0x030f8a770f21d1cb, 0xc6755916e70e0fc7, 0x51569e3a1786705a,\n             0xcd69d10a4059cff6, 0x9658d1b6da68c8fe, 0x52e4491249da1c86, 0x8049528948964763,\n             0xc2a3f2c4298bd646, 0xb3a142a446ba1ea4, 0x73726fd229d6e67b, 0xdecc158d7a432861,\n             0x3ee9cb6b425a2121, 0x881124c4108153af, 0x26fc1238520f6dc5, 0x16d9428fd259a41b,\n             0x491aa8a225d338ba, 0xb09259c43fb59aca, 0x5e9953f496e03d24, 0xea16eba7ff46618c,\n             0x3f7f2c4f3a92bae6, 0xf795c5efa084bcd0, 0x8b34e0b742940e22, 0xea053edc5b9401d7,\n             0x4da30e78f6aba21f, 0xc45b12f93254f7ec, 0xc82d9af7e5af31f9, 0x803f44cfefcf6762,\n             0xfc5f43b7ff9ceb31, 0x245e11c8bfa9ae96, 0x87138003b5a70762, 0x8eae1c6d9eb9646c,\n             0x30bfe90a8523d4eb, 0x2b21ca0cccdc2bcb, 0xccc6fc2ac14b7b90, 0xb27a14b9a7dd59ad,\n             0x560348e135944074, 0x0fd0bab3cf9e5f9c, 0x04a726cebdf6618f, 0x7e7d01bf93c27681,\n             0x56de16d1609f93c2, 0xe6804b157ea2330f, 0x7e5e77472a9220d4, 0xb1b50564d8ed2724,\n             0x40ffc0c34f1f1fdd, 0x7a05271122771783, 0x09314566f84c5028, 0x9b8e16c5136e4025,\n             0xefe5a7f790482842, 0xa84c2fbc12839178, 0xfc3ae0a8770e89d2, 0x3ab916bba4436059,\n             0xbe7ee94c80409bba, 0x35a23e5bd9c2d7b5, 0xcda360f286c14deb, 0x73884457b0943e2c,\n             0xc7a38a644e9c92c0, 0x95068f09744dac34, 0xf226fc06b5260ec4, 0xe2cb738fd6ffa3b7,\n             0xb3a96750be44ad25, 0x49bf9aec78f65184, 0x7a6516d7b4dcf139, 0x2211a40eb076d9a7,\n             0x7c6149dba8e4954e, 0x2927e1787c670b87, 0xf230d3876e76f154, 0x3acdd218b066b3d5,\n             0xc069fb118f94edc7, 0xa2e24d0c5c52e3da, 0x5208baa0893da38a, 0x7710da3bc36e9191,\n             0xc0faa7e41744c1b1, 0xd70aeeafae86ce75, 0xf0adc601049b479c, 0x28e8d822b182cc00,\n             0xcd0000de4bc9f9c4, 0x80766278a7e4c83d, 0xb82d37f661c09b6b, 0x35b1dc3e8173475e,\n             0xed93c2260643e355, 0xcc708e966c2c12c0, 0x9c1db2b40a709ed1, 0x2eaa70477c4fd12c,\n             0x76ba2c1b325ab188, 0x7e0a02e76bbeaf5c, 0xdde2006c1460d65b, 0x5f14c8c0971189bc,\n             0x513fb32a4107f164, 0xd8f92245ed49a64e, 0xf068866975378586, 0x5d73310153a8dd31,\n             0x7756f2ed68d78b18, 0x0546640ad87ba696, 0x61c858c82af10ee3, 0x06ecbc2c1c3234d1,\n             0xfcae9d38643f4d7b, 0xca955a6d5ae3a20d, 0x09785f07208a685f, 0xe2ea26ee65633158,\n             0x0f012cb2d0b450c8, 0x05f545f09cc4e05b, 0xa19a5b4233a20d90, 0xbe4f3e431ba657ca,\n             0xeebeca5ed4f804ce, 0x1fc8f99713eabd4a, 0x7f17d9462830826d, 0xc237d64e0625bded,\n             0xe1e3cfc40a257690, 0x73ef0c5f8e5cd3bc, 0x839f399fc0b245dd, 0x80ffe759bef2934b,\n             0xb96e031ba369d5fd, 0x987c7c9e86ef3bb5, 0x5898cefac2bd2444, 0x1f54e50a7bd1dfca,\n             0x62c8dd9335e3707e, 0x999f75cf455bd4df, 0xd92f511fc8d8b264, 0x8b5f097285d4fe8b,\n             0x74b7751291e59e14, 0x9a71c7c34e271355, 0x2a24e67a4b03c156, 0x0993ce03fdb92065,\n             0x6de9f7c6e3eba322, 0xe7356d25f9f50f99, 0xa9f81071465c6f83, 0x8c051d9450b289f2,\n             0xc9c4a69d2fad67b6, 0x3e1053f48999de06, 0x9a9d9c24723e7f31, 0x8424e4a64e569c3c,\n             0x1b21a5aae192973c, 0xc6400ecd16f2a49f, 0xbc7b1ab12e912977, 0xfa499a609600f634,\n             0x6fd0ff5396ca4f81, 0xfa9b21a8c7640229, 0x1494699d108c2271, 0x3d3e75404a63c076,\n             0x9aafc2f222f7c421, 0x22aedd01fbaa9139, 0x6798896f3caa504f, 0xdedd11c68572a6e6,\n             0x8180ac4303b5f3d9, 0xfaed46bab8b52d62, 0x52629eed8527d67f, 0xed6266764922a5a8,\n             0xf2d60d27fff18d2d, 0xe8eadc8f0208e7b0, 0x3d4c2bd20e0d9c1d, 0x13aa5d311910ccc2,\n             0x1b3def068a9028bf, 0xba3b44ff43f788f0, 0x73e763653b6800f1, 0x7ab61a083ddf22c3,\n             0xdb13b8d1f3e68058, 0x24589016be4c96f7, 0xe0c6fddefa1f17b9, 0x359f0d0ea86c7d5b,\n             0xf0f3d3ab9931f575, 0xf4464e679edda4a8, 0xd3a6b45c24638b04, 0x4e18095682a0176c,\n             0xfbbe8ff951705af0, 0x9892087a2577de2a, 0x34d2e62ca52c5789, 0x8988436cfadda4a4,\n             0x6029b6e8dbb404ab, 0x196493da7159ce0c, 0x42a3193795f63b07, 0x4e4326e213d2caba,\n             0x469f53640ef1ad92, 0x2ae7f9d6daf4e66b, 0xca15a21745e12dbc, 0x5a5383f0e7a2d6c7,\n             0x07bf7c8b3be63925, 0xd0ede6034e8091f6, 0x00ef4b8df501f843, 0x886f0a4f9de457e9,\n             0x7b8f83d781958bb7, 0x12f028dd476b34d7, 0xb84f9785716d4670, 0xca2ac68d47146f6b,\n             0x3ab3679a1444c6a0, 0xc487e9812f64f9dd, 0xf0a2734fa4a6e1c0, 0xaa754d7fb92ec887),\n            (0xa3ca19ec1e3ca6eb, 0x2e25f30dfe4b0e7b, 0x815b95cf08923bc3, 0x5d28901f342a9599,\n             0x961da80c30b2f165, 0x1f57fa4b35cc45da, 0x8f14fc7485a5e929, 0x79c57797c7b94aad,\n             0xe93d05152d016624, 0x74aeffe9d10adfdc, 0x854f4da2e30827ef, 0xde423da15adc16e4,\n             0x266438856b264893, 0xeb2b53f775faee28, 0x0ab4b46b3a30650e, 0xfaa29d29bc040ee4,\n             0x595fc4d774b3df57, 0xa795b06360fdf052, 0xc587f3b4c0ae0406, 0xd6598de1ede5eea0,\n             0x3339146dd11e1726, 0xd48afe5c5da12d8e, 0x71969f8173addd66, 0xdf337ffc2048dbe5,\n             0x7f24932642c982f5, 0x2031bd7764e95978, 0x5c2612876c58eccd, 0x112a96bf57d7706f,\n             0x335a15b8048dfa3a, 0xc5272cd47b68a522, 0xad41d3b51501e4d6, 0xa30cf0af8ed8ec8a,\n             0xc23822d52e495a72, 0xfe7d98845c78d88b, 0xb836d976335de314, 0x8bc79bdbb0c1cd04,\n             0xc946a130e133e9ae, 0xae3f49b9f4d35916, 0xc78b8802d62c590c, 0x1084edf5e01a7e54,\n             0x5d8ce54d5f790050, 0x83c88f86a452983e, 0xec4c43119b477ecf, 0x2f57ea47d1fd8075,\n             0x789ccabff179d6ff, 0xbe9fb89821c12aa2, 0xe77ed152761fdfc6, 0x97cc276528b34979,\n             0x65a248b1f17cedbc, 0x8dbf35ef43260d31, 0xe02533ac974c85dc, 0xd401983bd8ec9e38,\n             0x7718aa14381c592d, 0xfe77b5d1b7958d22, 0x7797a6cd7ec443e1, 0x8193c434a22acbb3,\n             0x7bdb85c6c297913c, 0x079db7a761d4f9e2, 0x135f8174a60b35e2, 0x6b2bcc4acb9eed59,\n             0x9e95091b2c38dff6, 0x39d1add602be929f, 0xed13bc4880ee0c7c, 0x08e2d82df32218b3,\n             0xc564d3b8308ce5c6, 0xc116ca73ad21ddc5, 0xcd3bc3ad80409ce5, 0x36d2f9fa97cf5f64,\n             0xdb2dc405185bb023, 0x8815c4a9c7becd81, 0x9be0a7777cc099cf, 0xb86b50bebd78ce14,\n             0xa2485a77d6f50a36, 0x895862e5da79f7f1, 0x43c9842774740222, 0xae46271ed74c5673,\n             0x4dfcb4c033b5f5c4, 0x7dca7e6e1867a40d, 0x280d4bde5f1900d7, 0x24d6f7728e3e93c7,\n             0xd2d4c6facee851bb, 0x5ccc0a29313aaa2b, 0xf30b52ce9b388a47, 0xd1f230f8425fa119,\n             0x9cfe2d0ee96945dd, 0x2e3ef8073bdea4a4, 0x27db8488d65d6140, 0x74bfb16131f635ab,\n             0xbd13e420fe06d82a, 0x2f20409c75929657, 0xd751cd00bb238621, 0x20379ff2ede8b3cf,\n             0x6e86922ccfcc621a, 0x5bd6ecf6eb062cc9, 0xe83b2415c506d796, 0x05f2d71c5e54d9a1,\n             0xc1b3ee7e955d7a96, 0xe82b94a20697dacf, 0x229213c92a5110e3, 0x27daa40e6f5dcb68,\n             0x542b2f04876f14e9, 0x2f2f7d3d3b9914a0, 0xaf0551997558e665, 0xee87e9860bccbc77,\n             0xac93c788a03ebbe2, 0xa5ed2a87a9d52551, 0xecf74835238f33f6, 0x780166a1a4983305,\n             0xe60f1cc5fd0d7821, 0xce0053e457cba5cb, 0xf81cd730084787fb, 0x7b912f19c88cc763,\n             0x1ad1fcd7c7dd58dc, 0x62fb274fc49638c4, 0x1d04bb94918c6113, 0xf48569b4a682b961,\n             0x72e23fba4b779e9a, 0x8f5a0021a4f4b419, 0x6c2e4d175927a596, 0x4d1a5c14ffbc8b00,\n             0xde6cb81c9470ba72, 0x27f48bf3a412c183, 0x493bedc2603e4338, 0xc02b5d2a4b101b49,\n             0x6c34a8ccabd89c7c, 0xe0cb6e111762dc5e, 0x555a980a74964861, 0x006f580772c42609,\n             0xaa9985f4987d44e0, 0xb7b01602ab7d8c85, 0x123a743accf0fb1a, 0x485b37773133e5ee,\n             0x4d999afe8e0b5245, 0x8812b124c77707f6, 0x152aaf972e193431, 0xa96b2f29ead1d806,\n             0xec06e460aed8468f, 0x44d40bc26b65a863, 0x54fb1dcffc940b8e, 0x9c388700a2852fdb,\n             0xfd3cb77d1b932bf7, 0xad60cb1ab7dc9d91, 0x1ad523744716b853, 0xab4dc63320513247,\n             0x6103df6a7a2bf98a, 0x2e631531271eefe5, 0x716768e6ec3192c9, 0xeee65b6a66203ee8,\n             0x370534dc2516ad03, 0x165f189803b99554, 0xdc1fcb2587d48ee1, 0x32a73ca97d1e50a6,\n             0xbc0b6f5ed42fc7cb, 0xe50dca6be90b44fe, 0x259f6c3ca08ed641, 0x1c5d97abd62d56ec,\n             0x6fe91c3fb5660148, 0xe5a57f06d5d8f5a8, 0xdf73245628549b47, 0xd0b670b94d5f1706,\n             0xec9c2361e043c623, 0xcce4fb07ab7b0598, 0x34f38b4cb52a35c5, 0xfd713cfd148a2322,\n             0x88ea3eb59e3bd966, 0x4aa869c428e79a86, 0xade3f5039b57b638, 0x7a5265c502faf057,\n             0xea0b006876a3a69f, 0x52b3a10e40b1227a, 0xc6128c55de2cbf6d, 0xc5b07128955a1bb3,\n             0xc938e9436f040e15, 0x1b2e118c59cdc572, 0xdb22bc695a0f8ccf, 0x3d37e3f05d7377fe,\n             0xea5b65f3ac49be38, 0x8cfaf5d7853a7afb, 0x082d27b3131ab7d2, 0x97cb4fbe33949c18,\n             0x49968fd355bfd4e4, 0x2db9a0882df435f9, 0x4d47dc4ad738199c, 0xba24998c920691b7,\n             0x0a33c25618efa701, 0x4e5d05db4d54f348, 0xfca73fc54424ffba, 0x67aff86329dd2770,\n             0x5d71f93eccebb6a7, 0x3fad49398279e50a, 0x06e04ba86b0d355c, 0x9ef68c04a1197a36,\n             0xfe00040dad7afd39, 0x24bf6e64f06b971a, 0x9ab14f3f9892cb8d, 0x5d4750883be0221f,\n             0x56ac5f3aa998cce5, 0x03460fd360a35bad, 0x24ff9e17cf1f4061, 0x5fe446cf9e90e24d,\n             0x77007c9debd43f24, 0x45d6d05b6e208e1e, 0xc61df9aea48e3429, 0xb3d64fef69d8fe6b,\n             0x993fbb95a9e7ff96, 0x05a49c472f5d9c97, 0x61d96d955deaf40a, 0x7e2bae19322dd6ed,\n             0x80ad697bf18e24d9, 0x342181f209a19bbb, 0x2e3087c230736ccc, 0x095c0f102c38f6d0,\n             0xdf15cb750b93c3e0, 0x5e3f597b1e63680c, 0xbc8837790d3944cf, 0x3d9b7c48ad083eb4,\n             0xb28ca478d7ffcc0a, 0x63a3c2b1289fea71, 0xc179c66c0a6cd6f7, 0xcaf2519d755bc083,\n             0x373c7cd588b8f3ec, 0x63ccb2ab654d239f, 0x58a8732f397e3240, 0xd1cd00a6c7bbfec1,\n             0x4c93e032a920f6e1, 0xdbee63f01f1f0e1f, 0xb53a78e0184837c4, 0x1d9453204e5cc1fe,\n             0x2c540ec359fbf161, 0x6e362ac2e2e62dc3, 0xc4e63e50fd7f341d, 0xf11c336f5272f81e,\n             0x34238e63e76e284a, 0x51eded1099809558, 0x774cb1dfd9b8be9b, 0xf51814f1062a280a,\n             0x393080e9aa8d8a16, 0x1f364188899d3178, 0xf886f4969f051fc9, 0x44c3c5c1881526c7,\n             0x2794613a617338c8, 0x4f9e59684b59c991, 0xb9ca306caee057dd, 0xa52d955a448b49ec,\n             0x7930a284317397d3, 0xf0d8fcc2370475e7, 0x6ea39e430b10c570, 0x78777fe74748ffb0,\n             0xaa1b523d998c7add, 0x8d4ade5f2ff3ef9e, 0xb1b26bdb813ba4b9, 0x7cdb5d99dfbfb35b,\n             0xdf0e6fce209acf9c, 0x4952ceb5c82de0e1, 0x329444a3db47384f, 0xa1c1c32077699a43),\n            (0xa5daec4ce582914a, 0x1ae3f05b47766548, 0xfd1bc8244a03db45, 0x2f54549832392e52,\n             0xae74d0679accbc12, 0x063498af58705d9b, 0xf5b6a2a7e1755581, 0x9d82bbe31327eb8a,\n             0x673c1556cdf45fa3, 0x5580500eb04546f7, 0x5f2e4f7733539709, 0x61b3f016effbfe0a,\n             0x484a81e10d60f00f, 0xf2032db84d0903da, 0xcc48da35fc5c822c, 0x9dd6694429b8cda3,\n             0x0f9f658d944135ea, 0xb540d8274ecd2f4e, 0x4e0609e158d69823, 0x0661f2b74ed746dc,\n             0x8721d7e2e3cc4b64, 0x897ac591c0eeff0b, 0x4189bc954d7bfefe, 0xba39a7270033a81a,\n             0xc73de2f4184cfe46, 0x50f4a244e28ca10c, 0x344692a57f2db8b7, 0x5f2ff61663c8c916,\n             0x37c8c746a6fc4222, 0x80c80eae7f9ac3f4, 0xfe07d8e40da76b79, 0xe97a9c248b66f90c,\n             0x5ce57815285f2c62, 0x250a5a18ed616226, 0x9c6c74726d5fd611, 0x622bc9a192079ec7,\n             0x4bb7db981fbbc0a9, 0xafeedcc11a515fed, 0x33e3c32905fa57ea, 0x311b3472718ab6e4,\n             0x45283d91f0d22677, 0xc79d3ea67969a731, 0x5702a377d314cba0, 0xb806d57ea8bba6aa,\n             0xc410d73d6db21c2a, 0x20c2fc5290917709, 0x32bbb4e681c951b5, 0xb9bcedbacc1a965f,\n             0x17265684ba1ababd, 0x600765f047755b01, 0x0ff2a521d94afd7d, 0xf9fbea73f2d66288,\n             0x3120002da0cd80b1, 0xe0f0fb44e63bcb23, 0x4dd311e73b06b9e6, 0x4d11f5a04c8aed66,\n             0x3a1dd43fdd79a938, 0x198e14e2f1ec334a, 0x5e9b9f713b948b77, 0x49bcf3aa56f4efe2,\n             0x797da070ec4790a1, 0xa45ca04556c04515, 0xef33f0ad319f5a4a, 0xc1107ae7a3a14d6a,\n             0xcceafabc98fe319b, 0x1eca2ae214c4c0e4, 0xa905c0a1029a4450, 0xcb58c4b78853a814,\n             0x23f6f2b348928709, 0x3397e5abc266e60b, 0xd32ea59fc4f2c040, 0x6c043424b77ba9f5,\n             0xc08f3a34e3ec4e53, 0xc06caa6f3619b3c6, 0xb7ae8ccd0ac989a6, 0x54b42cb72e84b477,\n             0xf13bc82f118188d7, 0x063b17c07faadca7, 0x7b87abde3340839e, 0xdf621bab0b8d77d2,\n             0x399776027ad914c1, 0x7f8817bf7a7c537d, 0x72a3d492d5c0b250, 0x70fcdf20e8bac20e,\n             0x5bc87c0b0041479c, 0x05f23cf2d300fcc2, 0x2f7b94ef197388c4, 0x2079f9c9661376eb,\n             0x418df4e48879057e, 0xbaf446d92d3cdda0, 0x0eacad7c53b1ba95, 0x0d792b6858d3cf83,\n             0xfee291fd1c4c831d, 0x6f9f41e6999617e3, 0x987101655bb124b6, 0x54126e930282baf5,\n             0x6e417532581d6fed, 0x7e6ab0ce3bcbe4cc, 0x269cebfa68d5c2f5, 0x2435aeaf9c7d6b4d,\n             0x7ca0ef313d53153d, 0xe7c978f8e0fdddb6, 0x9063131cdf5a8e61, 0x11e5c333376ccacc,\n             0x4f36772c844b22eb, 0x19a969df2c0331c6, 0x500fedf381935c11, 0x9991ada5c6618792,\n             0x550ccb311555bfd7, 0x46548fe65a4b6851, 0x5b48c281e95a6f1a, 0x65e8f82010ea2d2e,\n             0xf12a55cdc62152bd, 0xf5dfb060dd95743a, 0x8baad19e277f8205, 0xf6973b40c50f93c7,\n             0x74b7917854316e88, 0x7c595148b4b49ee9, 0xbae2701ae2aa8e08, 0x9b55f382fe8aa224,\n             0x1614bb005cd2e535, 0x4c9d8afad853e45d, 0x21511c6493a67fb2, 0xc267a19e50851e83,\n             0xc877ecc70e6f3982, 0x41d6ed94789c963c, 0x9bc64c5a3d7e98aa, 0x871ff7c0e603a089,\n             0x5b91eed23c932721, 0xdb35036ba977ec8e, 0x87d8eab2117cce97, 0x57082a1b706722bf,\n             0xdbe562311d1eb28a, 0xbd295115a2ecaab9, 0xc8feef1ca4310d80, 0xcf2693bb05f3d4a2,\n             0x8fc7c27dd80a4995, 0x88ec7398f7fbde3e, 0x230d9bb8e1ed9c25, 0xa9274dddf97a2cbd,\n             0x3f862ebc92949816, 0xb049c0d47607bf45, 0xcab5f4ef79c5b391, 0xd31bd5d2bb466a2c,\n             0x21b3c4e0917f7f1e, 0x7c15db64fe22bb66, 0x10da4d86de7123f5, 0x0eafd342aad59ba6,\n             0x5e32e0f61d5c248c, 0x8806946a6714bbd2, 0x318ea2cb7c12abe6, 0xca4d5215b479967f,\n             0x5dd9a9196a16cd45, 0xaebec5e6f2ac150f, 0x25931ecdaf19fd9f, 0x382d0c78eb7979a4,\n             0xdbfd6ffe347bd3af, 0xb4a15fc472f1ebb0, 0xe5356b6b3299ab86, 0x8347890b40d394c0,\n             0x2b41c163ae114a92, 0x24810db0f09ca44f, 0xbaa1a2eb17cccc8f, 0xe523179d2e258380,\n             0xf460de015c91c40c, 0xe60b34fe32d7453a, 0x18614b84dfcf1f73, 0x2661937a4ead4888,\n             0xe5bbd5f56b33a284, 0x4b0d4aa517846dd3, 0x40b66c437413fff9, 0xdd2b98d3221a5c85,\n             0x933dcedf5f038372, 0x4cd7ca53c5735e34, 0xf731711ba40fc8c0, 0x2be521ff7b9da3d2,\n             0xaebdf2fb45f69ead, 0xe6e7f7dfd8f4b9f2, 0x29ca222b3e6bc338, 0xfe180e15d8f082cb,\n             0x1d6e2ceb98d82d62, 0xcc3696f12f970320, 0x9c941bfc6924052c, 0xddba42a781f4e64d,\n             0xa4c6d6014211e565, 0x1bd66cf7e3491250, 0x9a1643f38265e94a, 0x5f2393f46f49f7bd,\n             0x6a7cb1e085d76c43, 0xe37904967177a763, 0xc0a9103c3008b8a3, 0x61e760d9555f5335,\n             0xec9706bee23bfba0, 0x58b11226b8690bb5, 0xd59f3738acd66082, 0x9ae530cd12c92fd6,\n             0x19c8b9e6ff8dc17a, 0xaa1494c28fb68e47, 0x32311345e68921a6, 0x81392725d49faf19,\n             0x444d33efa0f93ff8, 0x6fe9cec5d131a7c6, 0x0074b5ac1ff048a3, 0x24ed1f10b9b21d75,\n             0x8fad8c390fa7130e, 0xe3be3019cc752162, 0xd469ed0540fca872, 0xd55717c5222cf580,\n             0x1d7d09899f1d4318, 0xe0b11bb3dab19128, 0xd37faca902421bd9, 0xb9dd739e04b95103,\n             0xc3947adc47fd3bb9, 0xfb32bba8f91e1009, 0xb23dbd9ec74d4d98, 0x5583f5356a6fba27,\n             0xcf4c75e4f54ae2c8, 0x312060b7e3984e24, 0x69e66624dff478bc, 0x7990bd7818927c4a,\n             0x97dfce046da1bb81, 0xe76aca33e2b99fdc, 0x51902b4fa46c7d79, 0x241fd2d55a511276,\n             0xa415f14709fae7f2, 0xdf474c6d89afc348, 0x5f902e9e091d5e6a, 0xfc693f1460891819,\n             0x676c5bbedf905477, 0x510543d996ba526e, 0x6c52fd07e5acde39, 0x591cf6f44d159f62,\n             0x95d2b917e50ab11b, 0x532b5cc642b72c73, 0x50d302cb317e8301, 0x28d5ad2937ada84d,\n             0xa83f103c100e180c, 0x623a54c893076220, 0x2cb6694bf352762e, 0xc68f2291976b88fc,\n             0xc7133026c6e71286, 0x30ef07c1d2538084, 0x3c0ecf4283899ca7, 0x2012eaab9a82d628,\n             0x8c9bf190d310cf64, 0x932e28936eeb7c4d, 0x8755f869af2a72f5, 0xd05500b95e49e133,\n             0xd2b84540a4717c39, 0x1be854429117928c, 0x29c5a06464b5f11a, 0x1310cead18a1261e,\n             0x996a62adb9380e4c, 0x45203ed71265146e, 0x125823dc566005d6, 0x6f85749dc2386470),\n            (0xea1820faababa06a, 0x37bf94578615faaf, 0x7104b0e9398310df, 0x17c94d198ec6760a,\n             0x5619e12da9480b0f, 0x4be16249d4513f46, 0x396ae0569965ea09, 0xea4c3eb900e39435,\n             0x7d311f2ea4be5a58, 0x38b3be5c2a742030, 0x439cb1646f85137e, 0x0d8eaad1936ea70e,\n             0xb0cf831ef3ffc0f3, 0x1c18372980a53fff, 0x287c4d0cc9d451d1, 0x26d5d675e7eee994,\n             0xfb7a34e486141a94, 0x5aaa60b4caa091ea, 0xda38847aa9145809, 0x962eae22d9bdbe50,\n             0x93b389a3042d11f2, 0x047f9a3727886c6b, 0x78f92dfe11aeb59d, 0x98211732e77a88fd,\n             0xde89b0f0baf471bb, 0x1955a7a1afa3dc22, 0xc1c3cb44fa37cf0d, 0xfdedd8b9150cd134,\n             0xdaec7e0134bff79f, 0xe2c4788f4d359268, 0x8c98962ff42193ca, 0x6cb8718740072552,\n             0xe38b56b943e48bef, 0x07660c435199ee62, 0x7ea585982525a864, 0x0281d59c065ef478,\n             0x30f01820e375e4d5, 0xab27955c402fbc88, 0x0762623922847fe8, 0x14d6d77e56e81c82,\n             0x759b5301ab612ca3, 0x1f2257d7e80e6128, 0x07f86242de00ca89, 0xd6bd4f3310b70b09,\n             0xc1e5db3588612553, 0x18b64b49262f893d, 0x803898f352a41ef8, 0xab3e35bb62373b3d,\n             0xc8ce1f60497b630a, 0x4d64ff887802a894, 0xb8d5f05a48bf3267, 0x7bf0f94d3d648902,\n             0x63d92b04a206d965, 0x8a7744d8e6633f0a, 0xd7e71d808c3a5243, 0xc398d4d94cd6a745,\n             0x69f4134b3d4b0075, 0xe24cb50c57a10486, 0x6ff65bedd0ab6784, 0xf53e8056ed8252c4,\n             0x8a3ae4286ae27476, 0x82213f97170cca58, 0xe0ea23125af3b2c4, 0x1f53c9a4dd9a7ddb,\n             0x64e5f7b00299f3b5, 0xa77a6fcba39339e5, 0x5a049181ab91c0eb, 0xb31790f8e0b5d75a,\n             0xb8a89114b5b65f21, 0xde412ae12888e8ce, 0xf86a27952e4bbbb3, 0x1a618f4ee01ee329,\n             0x231e1fe614f8d3c7, 0x2f91770294b77cce, 0x2a5b0aced5f187f8, 0x0182c58068e165f8,\n             0xbac72501fa5578db, 0x0fcdf5c2069587a3, 0x91561111e81b91a0, 0x742f35f8edb78689,\n             0xb203985224d0130f, 0x2cb6f04e77283268, 0xfdd9309a1a4250ba, 0xadb4bbdddda26cb7,\n             0xbcbf15b3b0717cc9, 0x1f72e0bfec2404ea, 0xbc7b7f8f2253896c, 0x0953955d8f9f62ce,\n             0xf6084345282cdcd9, 0x687c7b2372651219, 0x381e2bf7146e5dfa, 0xd986ea990822dadf,\n             0x8ac4b4dd465d71c3, 0x5eea61025cd6a83a, 0x52fd32423c10bdf9, 0xf6436ab633194adb,\n             0xb6881d554b0dae9e, 0x95b5400162992436, 0xea6dae4dece5f22b, 0xfc29e90d21027c10,\n             0x4e0a27478a6d8b42, 0x28d51365483cd03d, 0x491eaa7cbe627461, 0x265bb947b13427dd,\n             0x0e22e6115dbc0a63, 0x0cd245bfbcbcdab5, 0xf7ce62829dac7b74, 0x8f2feb8859be75ae,\n             0x9907c2a0d2ce3013, 0xba992a98985b37ac, 0x8988ac4a085157bf, 0x772e605dc326f157,\n             0x7924b50712e85d2b, 0x607c14c4ac3ca7f7, 0xf2f85e22785bdd24, 0xfc895eff247afd30,\n             0xd3a300154639d5c5, 0xd222106bedb08157, 0x7b14f640d1657740, 0x369b9073a7975b1a,\n             0xe2e9179f0875a71b, 0x5b6c3d9ef2904598, 0xa9d7d7168f08c241, 0x4c85e8ad846e499b,\n             0x41dac7e1a37662e1, 0x0e0d9466d2c20584, 0x428ac02de66a1811, 0x8593111323323280,\n             0x9796fbd510ed0fc9, 0x4b6f052d054e0944, 0xdfae1400042b908f, 0x0d581ba48bf675a9,\n             0x7b015f1d69b01564, 0x4b4f8b2bda9e226b, 0xbd3cb9ccae2ca007, 0x3d7d98807088a197,\n             0x6726e6935cfee9b5, 0x59124f2b902d792e, 0xd0fbacc7231370a6, 0xe622408dd421b0fe,\n             0x23f45d0bce31c3b2, 0xb4eb15f8dee27654, 0xfe100c7edbc6b17d, 0xb96590acb9f5fbf1,\n             0x92869a6e784c9303, 0x9e5e2f392ef3f4bb, 0xe69189b660077e91, 0x1b87e65cbe259875,\n             0x8585a5978cc26228, 0xa986ce26b4f3df44, 0xe1978f4a620529ce, 0xde2842b7b0394b4f,\n             0x4562dcc1b81a4db9, 0x04004ff3a90b0c46, 0x0e09c8eb43366b9a, 0xae59a0e996ef0025,\n             0x1b39116133c551e2, 0x17f8924c2e52559f, 0x6876416ac33a304b, 0x4721be8300dc7405,\n             0x5d34c86e15c6f811, 0xd4fec6d4af59abe2, 0xcbbac114afb48500, 0xf3d7160ebc9d1747,\n             0x6d73de07f3128d76, 0xc310f2aa96db7c1c, 0xb0ed9d284bca961e, 0x4f8b9dbfd506f006,\n             0xef2b5609a4462524, 0x880d6d31077afc15, 0x6d097e373d7a8097, 0xcc83208328ed155f,\n             0xc5c261dfe2246979, 0x5e921d0ddad3fd1e, 0x7d545406d2c995a5, 0x9a32e809010e6bf3,\n             0x775e9a9427f3a68b, 0xf88f5924ec9bdd77, 0x437c005541aaad6d, 0x631a0ed5bd345003,\n             0x25783f92a044a6dd, 0x8047d063a85a8356, 0xb3a76b129161ce96, 0xda77eefb5cf1d599,\n             0x745236451cc5dbd9, 0x14480fd8644f5289, 0x52136fcb3af7e5da, 0x7c0ac7cbffbdaf58,\n             0xfae05363fe0f8bd4, 0xd52e7958e48f18c0, 0x32946ce8698f62e4, 0x2728ad2a0c144122,\n             0x419a7580009e2797, 0x8ab4d484632b5ac7, 0x58ce650ed0f109a7, 0x6b32c93dfc56a0b9,\n             0x300f52f912212aca, 0x0d46bda30fcef7f9, 0xe63383705da4ff19, 0x7fec0863896689d6,\n             0xb28b77af043a4b32, 0x5bef9cbedde0525c, 0x5b3d772273c772cc, 0xd98d7b9b9037b94d,\n             0x446e9dc575aebd84, 0x21b1b813f231652a, 0x2d38d2e4723193aa, 0x83cbc98a72f45ca3,\n             0x8d22bdc091155dcb, 0xfbee83d2d50704c2, 0x64f4d9b093018e9d, 0xbbcd16344fc66c17,\n             0x193363c9d64fb14f, 0x7028ccc5ab0d037f, 0x92e1a0e5121e67ef, 0xeb71208dfa06ba59,\n             0x05a20670c4e64c64, 0xb37bef73ebf5a2ca, 0xddf11a686dcc061e, 0x657598376a5f7936,\n             0xcd97ddd2ca69b32c, 0x28b547f60347dc78, 0x35909922b46c96f5, 0xe8e98df56a1da7d7,\n             0x4fb0d7d29c395740, 0x99f1a255b520d66d, 0x6cc9eab7702b33d4, 0xe897bdfdcddab2ed,\n             0x9f58fd73cb4627a4, 0xeb424dc2e3eec1e0, 0xaec2481d4d6d4a17, 0x2eb50a735a55b3d0,\n             0x4438e790e967883d, 0xe90aac02303c32a4, 0x5aa971da2a801f35, 0x32c0f896f7795a8d,\n             0xa76bfe45898b07ac, 0xb2e49a4c129c41dc, 0x935d176c7b1d9d7b, 0x81f161c651f05552,\n             0xf508522f646067e3, 0x70696aa97a1d031d, 0xaf6fb94208bf4d94, 0x2e11d1fb785a84b6,\n             0x3969aa886f535d57, 0xe6f2fda831186ba3, 0x7ec67bc20bf2d666, 0xc75f25fba87df5af,\n             0x0791a7c07e0a0f5b, 0x872aedae9af315dc, 0x0041853bc93e5e42, 0x398eaa185bcf04a5,\n             0xbca3aff3ea5c213a, 0xcb74ecbcbd6c5eaa, 0xde57e3064abf0a18, 0x1564c089bd75aa22),\n            (0x4fe9223573cef9e1, 0xdc2db2504d791da0, 0xe0648b31d5bb7c7a, 0xbbf1255bcd12c2b3,\n             0xe0a91917f3de1205, 0xec24e86552e64f24, 0x398aec43cd1e45fb, 0x72ae3697a5c31dd4,\n             0x474870e554883334, 0x3aba1e122f625f6e, 0x51e411ba06bb1686, 0x2bfb998241fa2641,\n             0x63da9ec083d3edf5, 0x5458104ebfe93a70, 0x3fd587643da2c9e2, 0x65091e81cd6722d7,\n             0xb95ab72f17c96d13, 0x0da07d461ada93b1, 0x993be3498581ecb9, 0xf45720620b9fd89d,\n             0x10af7c2c7a22ad94, 0x04e9c83e4a111179, 0x70994988f38422db, 0x6684d7ebc7d8adca,\n             0xe62cf69170f634d3, 0xfeeb986687186a11, 0xccfd746024296cc0, 0xff971961b6e3fc94,\n             0xecf30c35c7630b92, 0xd074faabe5d468ee, 0x5df7b94816e48e50, 0xc9e9a195972bd78f,\n             0x717d7ea0bc8b8408, 0x4bef65694779e7ed, 0x62c567ddaa1e98c7, 0x542dfecc0923f7a0,\n             0x4dc5ca2f482d809c, 0x3cd589e39b51c6f7, 0x92208762d018c78f, 0x2ec938209ec2cf0a,\n             0x9009029773f80a0c, 0x0ceee884138db420, 0x136475ca483e7b50, 0x396eea0744b5212d,\n             0x70e72af9db4f8a1e, 0x21d8f2fabbb57cea, 0xdaf01f5961a65cfe, 0x65e88a07314d4104,\n             0x49aa19f1c7f4c265, 0x969d1ac1e40b1741, 0xfff10827ee93f3f5, 0x828b7217182f6135,\n             0x47b8d04f80653970, 0xe3b17bbef8b2cd34, 0x4f69c889c71049fa, 0xee78f6df3e7c7275,\n             0x6e7873c197aa1fef, 0xc7e2a26726069746, 0x0e99cfc4939229a0, 0xf5b677aed45fd196,\n             0x7114035775e0670a, 0xaabc81a12d63dfea, 0xd53e94d10824a119, 0x8e88f6e782509bfd,\n             0x56710b2c063106d3, 0xd3a042cf642ceb23, 0xc888f8777532eb87, 0x02a5d450049ba9fb,\n             0x04da0ca115592e87, 0x47d30bc0efaeef8f, 0x347c53517c236d12, 0x6abf2e683de4a293,\n             0xc30afa1d0e6d8dfc, 0x2651be7e7134654f, 0xfce45ecd8afaf4db, 0xa7cf0da1decf86d8,\n             0x1008a67a75382b25, 0xad24f101cb2c1aa0, 0x1bc9505588e83395, 0xb197dca2dd0a3e6a,\n             0xc75f250fbb455424, 0x990cf33143679b2e, 0x4e1670c05403d48a, 0xca9f3b6c2343996e,\n             0x8d6e249b740a7946, 0x118fab845ad9976a, 0x52ce5e3d87861297, 0x2e2285498bf7aedb,\n             0xbc80cd7e6fffce8b, 0x768584e4dddeb38f, 0xce2d3f7c650c9410, 0x7af84a290690110c,\n             0xbc758b080883fbd4, 0xfe2220b28e8d08ab, 0x94df21dfaab30740, 0xb01bedf338073103,\n             0x9b901eca0a499843, 0x7f27f4b601b7604b, 0x1afb2cb14f7d1e2d, 0xf3c670facf4b6d9f,\n             0x62fc0aa6efe46407, 0xf27e1970f2051844, 0xe7cd0b117bb5e15d, 0x05ac5342036b14e0,\n             0xfbad37627bc5ba7a, 0x0c027cb3a12e1c3b, 0x4e5b88c78425534c, 0x467e5aa65dd2f5a6,\n             0x57bba572fbde2777, 0x667926acfb6f4f11, 0x41ef7b24ccd74415, 0xd97689863a1a4e7f,\n             0x2db4215af3579bc6, 0xe94634f67b826a73, 0xef09663ffdc2feee, 0x4bad9de7990ab3f2,\n             0xf558e0d80136218c, 0x6b1dc6e4647d9c72, 0xabfd05ba0e4da05a, 0xf5470e7b72266636,\n             0x0c23ac04b10e7666, 0x655760f35f195b04, 0x94742ff7098a185c, 0xf10606620251d4b8,\n             0x103bce40960547b4, 0x04889a8c82e9a346, 0xd3eafd5154dd9cc1, 0x9dc42dddc280f0c0,\n             0x1a68c523e500797a, 0x9aafb414792f7199, 0x82b4d1cfe765089e, 0x6962953773ca6f3e,\n             0xfd089f7e05bc85bd, 0x7af82ee70dec3e23, 0x607d36156564de0c, 0xd34e79832b4baf91,\n             0x4b4d87f1f022979a, 0xd6c489c17fc99d2d, 0x559471a1e69484d4, 0x4a23f806b56a2efa,\n             0x31a0946759ca97ff, 0x949f24f8233b8310, 0xc209331d025b6598, 0xa02db491600040a6,\n             0x94f2424db3c9196c, 0x7939359dd36d0483, 0x46894627e893283b, 0xf49be7836203de5a,\n             0x0822b1803fbd371c, 0x4383e1df82adac3a, 0x10a88ad141344d9f, 0x4cd5a654a892e210,\n             0x2aea8eb8b0049584, 0xa9bb0ff8a75ac388, 0xfe057eabb89f179c, 0xfae806bb3e8cce92,\n             0x048672ecd6e9cf49, 0xb644a1f52980c3cc, 0x9fe9cabc6e27849d, 0x25e4423e7fefd2e2,\n             0x558d3ae63281a4e6, 0xae54be2603a538c9, 0x4991f38a0548bee6, 0x148118c9a82e3ab9,\n             0xa0c6ce214b89b67a, 0x58b522ae9b9e310c, 0x446badcfae4e5aa2, 0xc4d2f4ccf9e289e0,\n             0x639a476c0c7f1dc1, 0x7c52ac5287fca418, 0x7d38f439bd3487ef, 0x1a8811de56eb771a,\n             0x29470828b42f4194, 0x4bcc71612b894f1f, 0x9cea0b9e2aa83da6, 0xa532098bd2b43f49,\n             0xf6d39dda5cf86a4e, 0x23f442043f3a0b18, 0x6a3e113cf2864d57, 0xf0a23e5181ea3aeb,\n             0xd4fa49275b579b1d, 0x9cd8383036ee8305, 0xe8c385fdb92c17eb, 0x6965d47ccefc911f,\n             0xdbebd532d03362a5, 0x2c73a11f13cbaa48, 0x75e559d0a28c58fa, 0x620b7e5a5a734d01,\n             0x6f72c52fbf66c3e2, 0x7c212dd39735685c, 0xb7b541cb38cacd2d, 0xa1d334b51665a499,\n             0xedc0476d0b8fc403, 0xde14968d0af0636a, 0x3dce73b681f2743e, 0xa735af736b210711,\n             0x8bc62e557495cb6d, 0x7a53a7f6deef14c7, 0x473a11f54b02fafd, 0x7576e318c4f91d59,\n             0x2f173241961049d2, 0x552a848c1fe2262e, 0x071b7cf087868f6a, 0xd3ded8e7f3116853,\n             0x0f6960f027e11eac, 0xdfa3acb9c5162f3f, 0xb2523fe79ff256c3, 0x3fa4493b0f3e0e49,\n             0x0c62568a888733cc, 0x1030724ae338a7d0, 0xc646ad78381d6156, 0xf26c976af252900a,\n             0x0e592ef7f0663c82, 0xfaa9782484405705, 0x61dc1236c994ceed, 0x104677a7846ba603,\n             0x6265afabbb386dcf, 0xa7141b1fa4f7dd88, 0x48fedcf223cf90f0, 0x27c179d056a2f0ed,\n             0x1c7d66cacf3cd369, 0x0c797405d536a0be, 0x5ab355326e547020, 0x526e813f9b9828e8,\n             0xa089c999711b40db, 0x306b9c81f0cf972b, 0x0b0232b7d186ba26, 0x087c89513a8d1a98,\n             0x17c1b5b9b5d5fb00, 0x8d3f8b1da4451a38, 0xc0aee3b11764d28f, 0xd224166d6686aa2c,\n             0x36da9bc84707b5e0, 0x3befb3a302431c50, 0x438eb0430edbb686, 0xa88dee8867393071,\n             0x6a42fdd5ac14b59d, 0x485128f6b7fba95c, 0xa60c2aa1c61112dd, 0x630ae474ac90d7f3,\n             0x0ab2c73e78e5050e, 0x5570af1aa2ba9c5a, 0x7a274265aa7e7a87, 0x22b63934f604177f,\n             0x4c181cc2bf375fb6, 0x930a4dde1d7040dd, 0x14136117e8491a7d, 0x520cc3001872eabe,\n             0x3aee2e1f638fdaec, 0xf194325f3c54fd57, 0xac7176a266b7895e, 0x275cf37ca133bec3,\n             0xeb9814e3aa11869d, 0xbeb498a63acf6064, 0xe88bf26c61a23502, 0xeb2856cde85bd136),\n            (0x61698ecc0b410e2f, 0xaa843a4bacdee7a5, 0x589d9c72a5b3e063, 0x328be82c53b308d1,\n             0xb03fce5b8c3f9757, 0x4ab5e0a0e8e4dd89, 0xda541464509c2e25, 0xd6c177c2fb345b93,\n             0xfe8cea71d04b6665, 0xd618d8f745b339ca, 0xd51239494474b8cc, 0x8d626aee9750768a,\n             0x1fa9f838b32fbe3d, 0x044facde9613551f, 0x04523ecf9780249e, 0xd08d8d7db1c15e79,\n             0x76edb6c6b8eb20e3, 0x75f6ec2250e2ff09, 0x1b4311feb33a06cd, 0x0c9d217c2ea74f35,\n             0xb555b02dbe37e987, 0x676334981eb1be4f, 0xfe67cdedeabaa089, 0x40a1bc016acab55e,\n             0x49daf1634142f1fa, 0xed4c8258a94bde78, 0xdb82ef1ad14fbed3, 0x36c2ee25c2ea9981,\n             0x458926464f9bcbfb, 0x2ac83b84383cb3d3, 0xc6f563e46df7f28c, 0x0343a07a3ff91e8d,\n             0x7279c71961b961e8, 0xd666caa46cea72dc, 0x9ac6654f293c6aaa, 0xc383dffeb4bce54c,\n             0xb312e645c613e8de, 0x1e6ca35a26cb7bbd, 0xdf8db2d455f0f543, 0x55e182ead2864772,\n             0x45d48eb8ad897752, 0x9da3bd97c7174794, 0x0ae5c75f86a43120, 0x39b68f84e7846fd8,\n             0x485a445ec3771dbc, 0x0e70f83fa86a5783, 0xd603896425099de5, 0x17f9094055c11799,\n             0x4641374a178b8b85, 0x00044011f22cf1f8, 0x12159aad165be495, 0x09f925790e59cccb,\n             0xa00d2f1261837929, 0x841416a1c23e85cb, 0x9a9328a4f4047167, 0x001774feba43eddf,\n             0x2fa8e108ba980515, 0x8254a29236598a78, 0xe04a77e707de5769, 0xb70b3da72f36fd58,\n             0x533c6be732253d96, 0x1028294c7b55b565, 0xb25041e79c8e9716, 0x8eb725311d8dacf9,\n             0x48f1412ebe8495cd, 0x39fd60e6a8dc9437, 0xa85091a1b2f4d68f, 0x73aece74e438e865,\n             0xd6dcda536611c848, 0x3393c9f4bbda8064, 0x9e40b8513fd2c7eb, 0x46fd5da36da24c9c,\n             0xc1e4a25326f8f115, 0x569049dfef71e131, 0x6f3262783ccd4ac6, 0x8949a6ca8ff285fe,\n             0xc668d77d4dcf334f, 0xbbb987f5ee2177cd, 0x2e1e3e437997cb85, 0x84c2256b84d55b3e,\n             0x9597acee89e05592, 0xaec2f80f0f9cdaaf, 0x91505378a9b697a7, 0xb587bdde07b047fb,\n             0xf485710385b7ddf8, 0xedf0c41ed01c61c3, 0xc409cb15d629ac20, 0xced9e0850b9d00c9,\n             0x26c145efe67c9c5f, 0x6a2cbcf078ddb3e0, 0x4469e57fe5303e09, 0xfd3a7a701bfa4cde,\n             0x5c2631d0a211f2ec, 0x2ec499503ac95926, 0xefaac8fc319f879e, 0x360f519481b5ce90,\n             0xdf5800b0850b6172, 0xc43616ded1b1fe1f, 0xf8864b965452313b, 0x9d0fdf10c8c7b595,\n             0xd75094d921f660d8, 0x7a7e6766c2c746a1, 0x39df51220cf09377, 0xdd1dc4120a66428f,\n             0xc6a2f2774b16349f, 0x75cfb9ef644da261, 0xaf0036839ac3eb83, 0x4a5b3a87fee45354,\n             0xad8aa0bb156d69cc, 0x2f3eaac853f259cf, 0x156ac3a99f3f0730, 0x765d23bea3de6205,\n             0x1740544128020806, 0x49ad80e4f4170acf, 0x5239cd82b25dd862, 0xbdb41a9fe35a0acf,\n             0x641eca75af89c1ac, 0xf015ed710d267ff6, 0xd013c82bc5d33f7b, 0xb9c9bd9ce25734f7,\n             0x5cdef3fff51c1bbf, 0x11eb5b74fddae426, 0xecf2c44e0e2f204e, 0xc3eddacb3bdaa03f,\n             0xc5969e37f684195e, 0x31208d229e9dfe0e, 0x8c842cc2b4e40ed2, 0x1f11cb9485d5dd7c,\n             0x48124ee486d78d79, 0xcb0e85ac56dd14bf, 0xcc44b711424b8961, 0x4d8259b930aaaa6b,\n             0x0f7948318d38b90c, 0x2e79d9ac55272400, 0x878e6b21ffe2d8c7, 0xc2ab611e66a1486f,\n             0xe48c2aed202b0824, 0xc2292bac4d7cb2d5, 0x8e379315adf29867, 0xfb27e067b2d7dcb1,\n             0x73610d676753f88e, 0x77a8d81ce35037c6, 0x2c17d3e22482ea01, 0x000b847d4ea9a755,\n             0xd5fad1dc2c1f8e96, 0x098f00d21f956e31, 0x1ad020e4eb6dea5d, 0xba2460c56ab8e36c,\n             0xbd8f1169572d8615, 0x9744fbb204c45603, 0xa53284bf759b387a, 0x27b7e39728c3d937,\n             0xcaaa28303f12c4b0, 0x946f09477f6d95bf, 0xd1adbb897b4a331a, 0x1b05cf48258409f1,\n             0xeaa659a12d7e6197, 0x1fcbb9144238de96, 0x916cdbd80d6ac900, 0x6261bca36f01eb6f,\n             0x38961d8005074365, 0x9e068c1f157f2653, 0x6b9eb9a5ac7c8e4e, 0x5c764306b4b133e7,\n             0xb289fe139478f359, 0x4bdbfbd80378d7b6, 0xc5691f342db79ae2, 0xe343b745ecec30e3,\n             0xb1b0b9ed41f2a7c5, 0x00978a6ecb90350c, 0x08f907fed341892f, 0xb24a2016c926d332,\n             0xfdc42aaa9c6920de, 0x4be1cedb5e6cb7cf, 0x646534eff2418124, 0x4361f3be0fdc1578,\n             0xfe70eeee37014983, 0x474e94b07438fd72, 0xaa43cd148321a576, 0xbe6c345193a90761,\n             0x5a0fd48621fe9a9a, 0xcde086690236c1cd, 0xa6c7055dc8bc64a7, 0x52a637b8e547ebfe,\n             0xa0a907235741a910, 0xb7bb4184dbcda2c3, 0x5f51f93a2d6f9224, 0x8c5c772ab0169e1c,\n             0x7ab7da3577c21b9d, 0x2109af27e79d2189, 0x34bc3f66388dfebb, 0x0bfa3839e88e1668,\n             0xd0a4f9457346e9cc, 0x33a0a6b64175e03d, 0x793be1ac92f76898, 0x9cc2898c830646cd,\n             0xd987d1099f78a888, 0xcf008b1f0d236304, 0xd6ee552e69fcb13b, 0xe1224168a2a071b4,\n             0xa206a30317140094, 0x0bac8c13e1fcad56, 0x163255138fc963e4, 0xcc1a5894afe42d68,\n             0x50ea9f01d9d42c9f, 0x6b1dfbf54d6342f6, 0x5f25841da2d7cbe6, 0x90ede1b0b2bc04cd,\n             0xa6ae21ffb93ec5ce, 0x5e445c805cdd66a0, 0x8ce5c65e9c30c2be, 0x921ff634e367f2b4,\n             0xa44808637e62b23d, 0x8e6a851ebafeda33, 0xe3a4cad58c62dff3, 0x82b37968c5335c0b,\n             0x717ba94877ae4c7e, 0xcbbe4c3e4db91cfe, 0xc83a3555b890b894, 0x9e814c80706d702d,\n             0x2998f8698b6d9339, 0x30c4a7b6c4cdca5d, 0x6de0179badfca2e3, 0x072c68829e3fca28,\n             0xacbd1d90cd367157, 0x4cf7eab61ff31022, 0x433df610bb2fccc3, 0x39099e1d1ec23bc4,\n             0xd435c0d14e1d9e15, 0x6b235431322eadc6, 0xa82229cf66e6767e, 0x0ed907e46d6bff6e,\n             0x54ed9c2ef1f1d207, 0xde503a213ab653b3, 0xbc29c4ca82cfb84c, 0x26af3ac87ae99921,\n             0x4cb53d9991097554, 0xb267fee3b07f13c9, 0x7e184d295a4aec2c, 0x69a6168f72575d59,\n             0x407e3d6abe966c36, 0x8639d5ed35d08225, 0x48c6243e6d8ff3df, 0x2ff3be0cba88a74a,\n             0x844726a536674bc5, 0x8352542c7d81fa71, 0x82119748a8549586, 0x5ea2e48c0a7c3d70,\n             0xcacce4767c334662, 0x8dfb47b59af4df48, 0x4eb53072abb55d06, 0x756fe829401dcdd2,\n             0xb17038e549e16423, 0x26cb8f101f4882bc, 0xd3c06cdade80e990, 0x42e771622ee651e6),\n        )\n\n        mds_16x8s_lhs_0 = (\n            (0x5b276bb177f7aa23, 0x97fdd3eb617c344b, 0xd87e1412d8315e60, 0x45c97c76da29fc38,\n             0x087d41fdd8df20b2, 0x5ae48d27490b50bb, 0x05276d8424c9d053, 0x5f42d683c4956fe3,\n             0x0216f52eb64e0d48, 0x332d69e967e266a0, 0x52c8587aac5799c2, 0x3621ce9475c4123a,\n             0xbb00ac4a2b7f8e8e, 0x63da4e062202ef0d, 0x1da8d81f261f497f, 0xad5b0b36ccef1f37,\n             0xe22536d1f7f1dd57, 0xd62f76a8a6199b84, 0x47ac1873a688a608, 0x81e0f9aa9b9a5e8f,\n             0x2aecbf39c9675f1d, 0xcb2a32d27b86ece5, 0xbe49656f9dc3fc66, 0xc10c29f228829893,\n             0x1360b6024a5eadcf, 0x820306da3a5bb435, 0xce644ac3a9f019f3, 0x5fb563c6a48c016a,\n             0x51aaeea2ddddba10, 0x3f238a069e1a36d8, 0xb0c369bb8f933ceb, 0x1d17d9f31af24b1a,\n             0xc24d9a85b62ac4a7, 0x163736d82d4233c0, 0xca36b4882546d0c4, 0x9466bb6e9ea86e1c,\n             0xb14c183c9b10497e, 0xc4a33559edc63ef6, 0x13e4a99ba2536c29, 0x3737bf5505aca7f0,\n             0xb83d5975f389b636, 0x89685a529d35c30c, 0x0e8ed7684c4551d6, 0xba59d762a5a42fd8,\n             0x81a0cf8261f1db56, 0x29d28214f3d160ad, 0x18828df91cd89f7a, 0xc8f5cb05e23b1473,\n             0x6e6359406046bc59, 0xb53fed1a78739df0, 0x3a5eed44f79e0f2a, 0x9ece39113efc0f51,\n             0x5b16da83dd21466d, 0xc59b1efb53c2dff3, 0x0ad5cb075b43e207, 0xb88e3bb7aa9acd42,\n             0x1d87bf28b9d501b2, 0xb67e943ecc8736b3, 0x1a73e9c7de6894dd, 0x5420c47ac5e0e5c9,\n             0x94c9060ed3198ff4, 0xebaa9bc9c2311754, 0x7d2c20d6d7eb0f64, 0xf38e9bf618bbad5a,\n             0x5f7d3138bbd981dc, 0xb227a7e251f75f6b, 0x0b752033e9f0f521, 0xdd07e29ec97c34dd,\n             0x48bcf9ca9aef68ab, 0xf4bc60b6c512295f, 0x4e947af2c14d9d92, 0x77c0cf739a78a7ed,\n             0xde0ecde3223b28e2, 0xf86d6ebb7845707c, 0xce61176499be6856, 0xfb8ea4bd187b92ba,\n             0x935cce8688bdfe57, 0xd80c94af663f0519, 0x8b515c795881adaf, 0xe26b2a60e177280a,\n             0x0f266cd554d0b24d, 0x815d023b96f94f41, 0x56fb1fd74c20e418, 0xf706c9172a173dfb,\n             0x42c30c4101ad7f91, 0x6dcd99dd92fc0748, 0xceff0a31439db601, 0xec76baaeb41506a2,\n             0x8831ecf2b12044a6, 0xa1269481322ed32a, 0x38fda335614eecf0, 0x319d1a143714426c,\n             0x1ba32e9342d4d691, 0xe2962de985051f8a, 0xabfbbb1facb05713, 0x02718fb4732033d8,\n             0x2ad714af6aa8f53f, 0x8be8878da9508ebd, 0x38bdbff1ca0a3319, 0xbd90882ba2b8e02e,\n             0x4994a97931e4c32e, 0x530bfe622a306489, 0xf3d2263872d31bc4, 0xdfe69676697a4d53,\n             0xe56c22686975eb1f, 0x5cdf77693880ce35, 0xbc1ccc3b81120ee1, 0xfed5662972bb3d65,\n             0xcdb1924fe85cc36d, 0xc5f1fa3a11f0ab59, 0x1d78275d0626c179, 0x94512929f0f6f5a5,\n             0x225c7738d15722ed, 0x3b0e4569adfebf88, 0x9b722a3ac2de1fcf, 0xc3f3a69bdbb3df2f,\n             0xe12262685382f900, 0x854eb3f3fa0e9db2, 0x6f822b1a6dc42a44, 0x1b7051e9904de2a7,\n             0xd146b6aa9df7e3e5, 0xb5a718d73ec4509c, 0x333dab5fb79c8c43, 0x9a516df37e1638c0,\n             0xdc46ac35f913aee4, 0xa8930daa3d547c92, 0x985bc568adf734cf, 0x57ed4cdd5833a53b,\n             0x7bbd19da397400dd, 0xd224122d2fd35c66, 0x9f4a7e7ee8960f02, 0x03bf0d4fe6164ca3,\n             0x98f633d94ec4fe7b, 0xa5ab360e247b2b66, 0xc80080b2c9abe941, 0x83103a7a51db0571,\n             0xb1856df93fba45c0, 0xb1e7a81b96bc0b7f, 0xec6113b612b367d2, 0xb2272d54455323ad,\n             0xb6f24bfd608b568c, 0x8a923dd69359e97f, 0x18846dc1c72eaa7f, 0x42936c704499dc84,\n             0x12c6b2ec9c90abf3, 0xbcda0d82a88c8530, 0x332321e168eb3462, 0x63f03537e699cb7a,\n             0xcef3cbabce427acb, 0x60b8039806848c3c, 0xcd6613f5455b3443, 0xd8e4338e476900bd,\n             0x390628ecc77e779f, 0x09c419237648622f, 0x78ebc0f40a5be029, 0x17170669a938dc9a,\n             0xae38e864a18a9a6d, 0x567f76e8c6234633, 0xb4290fceeeaad95b, 0x658ed71f5573a8d0,\n             0x56f4fc6e4ee52c0f, 0x4f6b2be72bbeb9c7, 0x9531f0e46fbf0ba2, 0xb9ad0dde6b923e42,\n             0xfc98af76c5f6493d, 0x5f54ffad3ed35c1b, 0xa0410bb38d2d842e, 0xccfd0762a324be86,\n             0xa10fc10ab42d40ad, 0xb55b6e9c5bdec366, 0x7eceaa7150a24529, 0xb860171d6221fcdc,\n             0x80ef858ec3f37bea, 0x676d08e4871036b7, 0x9666055126f738e2, 0x1e51513a131c79f4,\n             0x4bbedd71f206ab0f, 0x5c9fd0099fcd972a, 0x45aa63b76d0ee944, 0xe0d353a4df77a6f9,\n             0x85a7fc055d2da5f1, 0xe2e0ad2dc1c93b1b, 0x3c8561ef6d6f4594, 0x5a40a503c38adc97,\n             0x00c99df9d2148fbe, 0xe3206e2310749bfa, 0x1671f4e6fd88f37b, 0xc7a2d8abb88d1f36,\n             0xa9fa5150a77aae6f, 0xc2dacc4848b183f2, 0xdd898b1fa5584767, 0xa86b5dde6e0d7a27,\n             0x56fed89f4a9fc2c1, 0x9c1a5a4dc203e62f, 0x0ca3416304a44368, 0x9b20d29bccaed2ee,\n             0x51eddbd0b91cb40f, 0x755c4e86217fb461, 0xc3c016ea561ae9a3, 0xdba70a7a4583892f,\n             0xc01906fbe53d770f, 0xa05dec47be434027, 0xb4b65e68b3577c09, 0xa33275757875a18c,\n             0xddf5b8443a8735cc, 0x12c0ecb2ab8484f3, 0xfa86ea50c70a3d41, 0xca6732e94e209834,\n             0xfa5f11506cf5a00f, 0x71e2f42fab3eac1b, 0x9c462507c65b018a, 0x52e41152fc8ca99b,\n             0xb4fdcfdc4abf84db, 0x445f29a14b784e6f, 0x04f93e1287919d56, 0xa3c029fd38705d2a,\n             0xebbbdf123dd596e6, 0xffde71ac44f8baaf, 0x3054b83c0c64fc87, 0x8dfcada11cf45283,\n             0xc2ead825abdc550e, 0x15c4807c4088be54, 0x1ecb77aed0f958d7, 0x039323cf1a5a35d1,\n             0x9b0f1289307f949f, 0x41f8f48eda94a298, 0x48276dc18bba9008, 0x5bca991f8503050d,\n             0xabab452614bcbf7b, 0x7a6f79dd51d350d2, 0x0d01e234c4902a83, 0x4f47adc9d2ce0952,\n             0x3e5fdcfe279406a0, 0x4f29fba6f38bb7f1, 0x316d12891b0f8d04, 0xb21e8fa9b11bb81c,\n             0xa5f971e8c575fc10, 0x8fbc44d8dffafd77, 0x3159e65e97782150, 0x0a59903136773e42,\n             0xa5aa9b6dcd7d3b5f, 0x5be222f0fd738b6b, 0x4f309c9be70c189c, 0x7d669cc5ca96009c,\n             0xc79e34e415d4d80c, 0x00d1b203c4562140, 0x9fa1c6204bf512dd, 0x2f9100ad7527d0c2,\n             0x4085f44b0bae98c5, 0xbdddf2221e9282eb, 0x33add18617550312, 0xee61e1a655910c53,\n             0x4a24fe12b65aece4, 0xae5ef6fca874d715, 0x7a5225afce794b07, 0x8cd1f53aaa1d211c),\n            (0xc7c9e602055516cc, 0x8ae9ed37dd727599, 0x68a84e00686bc858, 0xc825038ffbb43b07,\n             0xaf8775746baa2296, 0x419216e1f1ee1b70, 0xd09817bbcde34127, 0xabd16ea3943409d1,\n             0x0150a5014c6840f4, 0xe2d8b8fee7a5da59, 0x87c66fd5f413d23d, 0xd7dfb544a4159ee6,\n             0x8260ca622535dab5, 0xf567205a0453ae3a, 0x53c9b36765dbdc0e, 0x1efcabb640d5737f,\n             0x3e9dceb66ed8654c, 0x33a1c6085f53e1ee, 0x47931e90d0af4ddc, 0xe561de2931e16ee5,\n             0x87c1577cae032dc5, 0x15f2d3e085818b6d, 0xf99a29a420c67746, 0x05ffa7fae8de0c8f,\n             0xb6f34e4408d699d5, 0xb361276c50702b68, 0xca4c9e30c12ef781, 0x6443a5bf9a6ec039,\n             0xa745eb4155339344, 0xeadd4a77222d35d4, 0x923fe821ffc87182, 0x15da5db5d08f1acd,\n             0x9727e26368eb71d2, 0xe4030b649d63befb, 0x4d0cb6ba5db32b24, 0x75d3505358ad5d45,\n             0x0ce82cea2832b671, 0x3a70bcbc2fc2fbf9, 0x3074f1bc1ec6071c, 0xafc57a122ab0bc44,\n             0xf6e7eb8240d97976, 0x6274cf60d7416f01, 0x23c971b5c86a794d, 0xc4bcfcc083155f17,\n             0x54b79b61a462208d, 0xd29af1121f6efb35, 0xddafb7414ee63adc, 0xe9ecfb926fdce226,\n             0x56902281b502aa81, 0x3b7aa31c80bca094, 0xa71d7d539c92ccee, 0x3f01c564e152f62a,\n             0x9dc68324859a4f72, 0xe311005b6901de16, 0x8fdc961818969ae4, 0xf11fe2046a766b7a,\n             0x3ec1c162529dead9, 0xe6f15b746381541b, 0xe7bc1128d29628cb, 0x42978378ee9d4457,\n             0xb51eb756749540b1, 0xd4f9d1d4a0b3f4d7, 0x20144e30638723f0, 0x8d692623bf824ade,\n             0x3b32c5a0c332f598, 0x29fe43344522677d, 0x3dcf67c0a90cd62a, 0xb6ee805813a51f1c,\n             0x06d573ce00f3eb92, 0x8bf4ddd41f67721c, 0x451a3b3b3ae44233, 0xfeffd7df4f597e19,\n             0x3f2883aa4af3fce8, 0x545dff727a8495ae, 0x9f27a0566e12638a, 0x452a8bd9e867248e,\n             0xb70cc312b0c4576b, 0x8ee46e5878d4acc5, 0xe31f046c9fff9d82, 0x2cbe13eb0fc43727,\n             0x2a3160be528827bf, 0x526c721ab71e0707, 0x5e74823eff6b65ae, 0xd38623c9e41d234d,\n             0xd1c1b2137bc2e15b, 0x35e3d0d9ef34fce5, 0x8ad49de492f1849c, 0x62999422a19f3c08,\n             0xa42d4eb1819cc0ae, 0x274c34ec27caa7b7, 0xe8f21e9274bebf76, 0x7b34c874b320b8a6,\n             0x8425c978006553ec, 0x128dd9e0e67681a3, 0xcfaccd8705a7ccee, 0x553911c4f90d8b2e,\n             0xed8b046cc9805419, 0x726bdbb64814f3a5, 0x3d3382597f6fc0e1, 0x7eb32e49ccd280c7,\n             0x123d7ade0a516d5c, 0xf315d48637610275, 0x2e5578a58eb266f3, 0xf8987ebd88a5584c,\n             0xe302fdb63c147085, 0xfe3490f39d6060e5, 0x3880ae0b22f7cc51, 0x6655f8be98751101,\n             0x9f0af3e376b4a7b5, 0xcbfd501de2ce2a93, 0x7d4ebfba3f792f90, 0x46c1e9759c7176dc,\n             0xb9cf946d99bb80ed, 0x5f33a4299a944e25, 0x20a87d893fcccf52, 0x234af0145ac3a8da,\n             0xc364ddc09e359f28, 0xe1530254c4937b46, 0x28eff146eddd840b, 0x8149318b88797251,\n             0x8536e0bfd3a4dbc7, 0x65dcdf194240db27, 0x1f32e2f3fb5e847d, 0x929fc25661897d11,\n             0x3a91b28c95cf420a, 0x84a84732163268c7, 0xe01ba3d3ec288d9e, 0xc44325c7ca0d8ece,\n             0x3edaf422eaa86c75, 0xbcb089e1446a5487, 0x6ca810e59822bf7c, 0x74392427bd9e8948,\n             0xbb72be6637e723f6, 0xef3944f951b6d33f, 0x4b544cc4a266580e, 0xfa058a4cc999f1ab,\n             0xd488a6235f1c4085, 0x3180ec4620c60abc, 0x99560a1705ebf3dd, 0xc8ed9a572867ba24,\n             0x9645a758c7ba5899, 0x645c6bf0800ca106, 0x3181cf0ab92e1f8c, 0xcd1046ba2dc6c24f,\n             0xe2609817de3771a6, 0x99d7d94d1803d069, 0x9dcb3447f9bd9e55, 0x32b2fc502f513fae,\n             0xbb15107e843698e6, 0x8e89e30c01cc9b33, 0xb8b3f3344b26d1da, 0xa513a07927bbd1aa,\n             0xdd18af3783f99d86, 0xfac806c4f1dbb8c4, 0x1f3c424909275ece, 0x15da430764e6ee30,\n             0x42ed3b55e4632911, 0xe48034b27e797b67, 0xb06a16b9642228fa, 0x2de1738350b1c99a,\n             0x7123c382c4074914, 0x8e69a1ad8e661f79, 0x4039da225c31e1c7, 0xc39d48bd1d6c8c77,\n             0xffdae66bd21a2910, 0x8a43714dbad17875, 0x85f6af0e635a340e, 0xb78b9e7df137a667,\n             0x0525213a1517331b, 0x12995ffaf4052c09, 0x7a06448c6838663c, 0xdf5c0ec6d6be0d0f,\n             0xd14f48cc13c79692, 0x50fa0d5f07379ce6, 0x67f8d589b8303684, 0x29db7460ad6e6b27,\n             0xf33c651d2e297440, 0xa27b353fb82522f3, 0xfc6f3edaf0e55b5c, 0x58efa75d919ed888,\n             0xf45dce0815e39d8a, 0x4d84eafe3a9b7be5, 0x2dff78a4b4a54b5d, 0xb88bcba5540093f5,\n             0xd9d26ead9743b328, 0x86aa59cd4b719c4d, 0xa6d884059d516757, 0x8ef87c455a804895,\n             0xe9e478de0c5c03fd, 0x5b09ab6c081a2f54, 0x3d40a49e6b883dcc, 0x18fc871aa22b1f4c,\n             0x4970de355b969478, 0x79b6ebeba927ae08, 0x2c5975a59ec3fe95, 0x9f321ace264204c4,\n             0xc072850fafa556f8, 0x20eb4bb9d504ea6b, 0x2cb26a8d67b332ee, 0xd17fe579d0fe57c0,\n             0x834d794b4803f786, 0x13368d5e2951fee0, 0xb5a5403e047404c4, 0x7669dd1f6fb4c2b0,\n             0x35bddf4aef2f7f5d, 0xeff034d789473247, 0xe11340bc2596c2cd, 0x9902c93fb8ef63f5,\n             0xd8b17cf313f4e815, 0x8bcee52ce3b185fe, 0xefc190f51d02cd5f, 0xd185f3a812f33276,\n             0xc3979ea407a22542, 0x93e01728c797fdd7, 0xb105f008df36b821, 0xbd60e25925b6c8ef,\n             0x4e09ead00ea81315, 0x9d3770b63117765c, 0xc1391e54d1c7f301, 0x5ac6df4f3c9a5d54,\n             0x999d997fc50216b2, 0x66b98a68a0520990, 0xa3ba1862d8cd6f37, 0x586319ef809055de,\n             0xd9d4c852edce800b, 0xe4163f8a535c50c9, 0x84943b9f0b32c78f, 0x5b4a9467cbaa4d92,\n             0x2c55bc536c7dc3a9, 0xbe4549b4bf422d51, 0xa9101eb156ae5050, 0x66569c427401d64e,\n             0x1ec0edc80b63b2a0, 0xc701edef40ae4aca, 0x4a90bad9224655ff, 0x34972cb95e263fca,\n             0xf1cb90fdf64b68b7, 0x919711400c17f679, 0x06b0f7d9dc59e833, 0x6a51d84f00969d49,\n             0xbbe5ea97a494abb2, 0xa8ff16f51ab94545, 0xa9d3d2397162ae97, 0x08fb9ad3fc8d16b1,\n             0x3e46e53f98a081c5, 0x23bc7e91f40c66f5, 0xfd8a1ecd9e50a32d, 0x239cbed6ebde0d79,\n             0xd67874cfa0fbcd0d, 0x9722408f30ed6c9d, 0x42beacbbc19eeda5, 0xdfa4437b459dc67f,\n             0xcff6869f99d44396, 0xedaeee53acf50d53, 0x72c6be3c3dc0e879, 0xce315862fb2b7335),\n            (0xe50ddbb67e550e7d, 0x6538923077c214a7, 0x2278e2ce29ea8a65, 0x56888384a5637423,\n             0xfdb056bdfd7c4e77, 0x093e09ac6a0952b4, 0x13f1ba76a5bbfb7f, 0x579b5076912f562a,\n             0x35c23e453060801d, 0x89237fcdfd96b2b0, 0xced1ed7cbc0e610b, 0xb81edac5f7144d8b,\n             0x0464c803ab1767ba, 0xfc8fb11843932809, 0x9e2b9fdfb99dbb3c, 0xf7edc0c7e651b95d,\n             0x491abb65feb39179, 0xa505458569adee61, 0x65f012a33274f11d, 0x9602da1c5c35c601,\n             0x656a1620440adea6, 0xb75556ff246f457c, 0x7bf2d7483c6ee0a7, 0xca141160b91a44ee,\n             0x500a00e15ec31574, 0x51b2045ac4331e49, 0x755caa1084fb2a35, 0x67b166c2cb34719a,\n             0xfb25e35ea5e5fa2f, 0x0e2e13fc7b819197, 0xd1d97ad6763f596a, 0x1b9aed15c659548d,\n             0x77b434f79a3a125f, 0x42328e4bf70fefb0, 0x579da2202b4a8b76, 0xf85bd2efe53f3207,\n             0x889963c9676f45b8, 0xd54e375ff001560b, 0xe6d5bb5b5be5ab9f, 0x8efcd682405b448c,\n             0x48ba944dc56c9517, 0x6a724c11d9bb6cde, 0x534dd62a9a8780f8, 0x35dbc136af58aa06,\n             0x77df82abd0e3f939, 0xd5a3b0f0f71956fc, 0x0b5bbabf12e6f7ff, 0x52472b1998c65124,\n             0x9a8858f678ac2c7e, 0x83235a21b4d59196, 0x624ac35f06177460, 0x9a59d904c6cd8eef,\n             0x006be640ce7e8130, 0xdba37cc1c045481a, 0x2a9603d3ec51b33b, 0x5f515df4a766ac21,\n             0x73d04e3e55d1236c, 0x4da5a317fc44f745, 0x434f95fc4c3b4856, 0xdccb9a84711521f1,\n             0x9fec6b85b812c233, 0x18c3905a934dd717, 0x522a5df673bdde66, 0xedb5f440b173501b,\n             0x3f567bc884e40b18, 0xcdd5decb6a20efa4, 0x57a32783adb0be65, 0xefd8d1d6cd921447,\n             0xbb8e74a4b776039a, 0xa80927ba7940fd75, 0x7383155e8c84ef27, 0x6b94593e576a0e9d,\n             0xd31a4fbce2ec322b, 0x33bb3801e3b9f1e0, 0x253b15e1fb3686e9, 0xdadd9c2011d2fbf7,\n             0x526ac430a871fd41, 0x505ff7cfb92164ab, 0x638d2fc60101b7e3, 0xe46611cc7bb9e270,\n             0xc018880311f86e44, 0xc212fbccedd5c6c2, 0xb457011e6f359fe1, 0x9140ed1e113dd5aa,\n             0xe6012908e5c5c529, 0xd7566d87872e2b49, 0xfe6a45d23bde1ef2, 0x7878e9e41da9ecd2,\n             0x11877c095c6913f9, 0xa53304358fb3440d, 0x10605aab83cc32a9, 0x62061f8493ba796a,\n             0xb4d7604c1b7df474, 0xa61fd1060bf6aead, 0xb321d1c69166392e, 0xad0539e63506c69a,\n             0xb5e02c3cbe953b50, 0x5d3d92870e9f253d, 0x5adc0a1afeb4b84c, 0x1d05a70ce6f54615,\n             0xbabc1377ef6082af, 0xc7510d57d21d3360, 0xbe954bf5b4f8d104, 0x78f6bf06b56c5e3d,\n             0x21059663d6ab86bf, 0x291f33818ca52559, 0x34079bc4b5572976, 0x34870b4697b8a590,\n             0xc4e77442bad8331d, 0x31bc4fd0faa45562, 0x694831eb3b1ba03c, 0x38e14c79b5b351af,\n             0x5032dcc005deecb9, 0x52847c0fcb4f40b0, 0xa33ddc4d88b1134f, 0xf91cae4c8212ac6e,\n             0x46018797220a2a11, 0x980b94e0488e0243, 0xba532ad0a633b7c1, 0x5f881da6f65e540f,\n             0x644afdd2a460e634, 0x517ed026b815d8eb, 0xe8c08cb2868e59f5, 0x3de744f5772ec38a,\n             0xd8a589b05a3f30eb, 0x65aa5f3dd2facd96, 0xc2f43381a0ee6044, 0x60150c46c348aeb5,\n             0x95b00248a6834a60, 0x82922cf19da216a5, 0xe4580fb2c8176939, 0xb3c6b5b1ed84e516,\n             0x597154d958679273, 0x73c793df53439f90, 0x01c57d4400a3b15b, 0x78813fe7d80d03ec,\n             0x30d897586affcb1a, 0x05a4fe7c063475b5, 0xe230932465eb0d92, 0x3bc99ebbd541d7ea,\n             0x23c581617035c1a6, 0xfe55f664cd5aec33, 0x4fa02270ab805006, 0x216b7f5ea82c2467,\n             0x71cd7a2c9c28a8f9, 0x312605eeb3f3b2f1, 0x2b3e1d1bc6ae7c0e, 0x164703b9187adc56,\n             0x424ced27ae0f3655, 0x3f43c43bb7e1ce47, 0x1f9a260b0c89fbdf, 0xa9c23970d155ad7a,\n             0xc9a1b2a193b0afce, 0x5d8e6548db0049c5, 0xb318132a7a62c6e3, 0x94e68aede3ad01dd,\n             0x3399ae5c71c06735, 0x93e4c328085e6bd6, 0x3d6a351a36a1884a, 0xbdb1e218765aee7a,\n             0x956019116e633d54, 0xb0a44016d3966f3e, 0xa8f1bbfde65281d0, 0xb798aeb9ab5963bb,\n             0x8d343fd4a2182436, 0x20e7443245deacf1, 0x88b9003e4fcface9, 0xedf063979b3c9838,\n             0x07b15d3997964dc7, 0x9b89ca73fb968821, 0x8e1fc130db624b13, 0x8da6a7526f33051b,\n             0xcf4eaf34cb6fbd8e, 0x8894dca0b2ffdafe, 0x75f420e6cda494b6, 0x3ff06a3dd13a80c6,\n             0x31ef52fa7ee9da1a, 0xdd7bb9ae42c3a21f, 0xc78d90cadb109e70, 0x412f6196b34abea6,\n             0x51d4728993ca3dc7, 0x24705b4b1cfb3897, 0x99e5b825ed32f460, 0x57d20822c3327c00,\n             0xe906992a45e4fc02, 0x3ae5bdd5c19bb975, 0xcf9727eb1d4ad21b, 0x52de427972a54709,\n             0xce4f3b05033e770f, 0xf699dfd35e1e9d42, 0x8c6860dd8719a6ba, 0x61e5f5ba9722b70f,\n             0x25f53315758051a8, 0x2ec3eb3bcbcc1531, 0xe5479a51eb32fa4f, 0x6fd3fa1f9115e436,\n             0x28368821ed272f49, 0xe44ae8f577cef695, 0xb438837184498ba7, 0x74cba444804186e4,\n             0xda4976d631a3dfc0, 0x2a8ee20bb66e48be, 0xfddd892b8db87c9b, 0x2f86d2b9c635739f,\n             0x7c15209816d5edf9, 0xe3838ae73fbd8577, 0x1641727f03f5875f, 0x1f81d296f21ee09b,\n             0xcf83a61e19c892ca, 0x95fe976410836f15, 0x2446161dab029ec8, 0x380519dd7b6be8a1,\n             0x1f164d5a8dfeffd5, 0x1ac4ee24164e7780, 0xdaed5dbafa7e171f, 0x9da75356b71ec5d2,\n             0xfaa3cf90aa8fc567, 0x485081ed8a8e1808, 0xa05eb49e11dfc51a, 0xecda446e5e9f49ad,\n             0xfb72e7cdf9fc1eeb, 0x81fedd7ad04b6523, 0xba35e20bfbaff9a2, 0x6f90b17db7160f26,\n             0x9e17f956c7fac402, 0x7fa23235e2c058b7, 0x876ba8bf25d48135, 0x920b72419abbf268,\n             0xdb39cf422c5ad6a9, 0x29eb8f82788b93eb, 0x7c096f392c75231d, 0xd8a9fbf69db1c918,\n             0x4fe7ef7a5cef24b8, 0xb0349d2e6eb27eff, 0x8cb1928fe8cb1800, 0x61ee944f48f6ff38,\n             0x3529e1dd2c5aec0d, 0xf432215eaf75c7bf, 0xb5c479d8a0934bb3, 0x0268e6861c1241dc,\n             0x963696dcb5732737, 0x880393513eaf59cc, 0x37346a8f0944ebb9, 0x89619a38e2d7c835,\n             0x4fcd75566401122f, 0x4586e0dbdb874612, 0x3d4958561abb2dbb, 0x824f76fb5397a95a,\n             0x37e95a8e05c4cc08, 0x79d01a7d624fc8c3, 0x49add57a52d657c8, 0x6ebec80fe02e4e70,\n             0x99ab4b4822fc68c3, 0x9ad2c1423adb6818, 0xe5d32082b5720c81, 0x5f83070377d68c5f),\n            (0x0864c63a477c4fe7, 0x329dbc21f6a02e8f, 0xdcaec6e2f3f31c80, 0xe8f61cdef50a059d,\n             0xdadb7f00178325f9, 0xc63a0fdd5f84720a, 0x1902fd15ed18e1ac, 0x43759fd3f2186bd3,\n             0xcbdf1dbbc11dc459, 0x1f9bf867a3eb5e0e, 0x2e75bac7c3afbe5b, 0x30dd15b276f2926c,\n             0x2e204d2cf1dcbd44, 0x7e119407e3bd4a47, 0xcd33bad3afa7db9c, 0x2363ab0c6dcc094a,\n             0xe7ab0e22e06822e8, 0x0c9dc9e506bb14db, 0x75a352124bc7ca52, 0xf08dd0f54c2ac8e4,\n             0x4a5de0466d94c0b8, 0x4170b1e958d38d74, 0x64daa0eb42a11988, 0xffaa4d71fc9f1fb6,\n             0xb04951224f26cbdd, 0x50a4f6939333020f, 0xa2dbdf601f91afe7, 0xc02f3eef802f9fea,\n             0xd990c4e67607f722, 0x1f703c3ef675eb8b, 0xc84e10c18d3187c9, 0x114e79680ef08cd7,\n             0xa45a92b912437cad, 0x8f8da5444487be7c, 0xb4ab4a1c3885c9c2, 0x0955f6925e2fc795,\n             0xb2d098f7c5251c57, 0x2f853f915d8e161c, 0x8c46571fcbd68e71, 0x66823618e74555b5,\n             0xdce394e240a98fc1, 0x71a17cdd96801099, 0xc3ffa102820e029c, 0xeb5cddd16540b826,\n             0x77db92ba6513d94d, 0x8373320a21225b18, 0xa33e571c8e22df60, 0xacf9a8a08d4b22e9,\n             0x5340acba497e2c50, 0xfb4b473bd888d638, 0x5a5b1ac9f61755d2, 0x415f6130a248c3f3,\n             0xfd70079d464e8f9f, 0x113a5626ce3ea54f, 0x68affcd89877f74a, 0x233bcace630b67bf,\n             0x61fd237e50fde112, 0xa13b5b6ec1dc1f2c, 0x2c2052b4aedc20f6, 0xfb8051b9042ee107,\n             0xb644f332a90ed9a0, 0x78f9d7e70f05aeb5, 0x4a4f727acc547172, 0xe900093f384c4762,\n             0x84fe2812385099af, 0x380679c83b3b4eb3, 0x7d7bab21314ded5a, 0x819dd47cf4a9c375,\n             0xeca9b6c6a431aa3a, 0x4e31bba80bb3f14c, 0x2a45a8fb7f015c06, 0x1a1302edb18cba85,\n             0xa49b9341441a0a73, 0xead30b0e999cc05c, 0x2b50bb69603be131, 0xde6d6f6e2a4c73da,\n             0x6daf0479a03f00b6, 0xa6eac9326ab14916, 0xe94335ac5e6f5847, 0x7403de1ad163e40b,\n             0x8a4627f93a4e1607, 0x7efeba6d469bc490, 0x7d0f7b4ea8b946ea, 0x994b575867042448,\n             0x4f7ff0ff215cf099, 0x7ee977269c958278, 0xd480b6ddde9dad99, 0x2ba2cd31819599d9,\n             0x8814579e414de045, 0x5ec222338a9a189b, 0x4a28ff08754824a1, 0x781bfb38c1c8a1a2,\n             0xb37fb9977bf2afd3, 0x454174b9103d2ea6, 0x739ca459e0f9af01, 0x9ae9cc48c06f8746,\n             0x80ffcbcffb57440f, 0x73814eddb785e54a, 0xa2af3330a11da149, 0xc0fe0f581ba55b73,\n             0x274621158f331ef7, 0x781468eff65c5e85, 0xa88faaeb95f0a672, 0xc683a2deddafbffb,\n             0x4cde600274480261, 0x526fa9d0f6e073ff, 0x469239794eb1ecaa, 0x1d9d85362c91a5de,\n             0x7cc1c669b0fc3a02, 0xb40ef06869de5168, 0x3cd1d981290f5758, 0x9ba1876b89dbb616,\n             0xa20294b4694afc56, 0x2cbb897b23f4b619, 0x9be1c6d6615264e0, 0x0e0d8081635eea9e,\n             0xe20dbacc0251c240, 0x4e37ff04b93cdd5d, 0xec2b14de869b5c70, 0x5e2dfdb347ad600c,\n             0xbc2600be1fa6679c, 0xd3232d4e4338f1da, 0x3559c365910c61c0, 0xd9d662f7ac53a8d5,\n             0x0c2f2ace1e286e69, 0x8296b6cf710867c8, 0x262032dd65961468, 0x6edf9e0bd10f2aa7,\n             0x93c96083ce425867, 0x7b182b2250513938, 0x54d4813698a51f89, 0xe497c309b1c82cd0,\n             0x143e2ea940029634, 0x98e227ad5d1c46a8, 0xeca8135a316b81c2, 0xa127a15a7db82bcc,\n             0x9742a33611c2f53a, 0x5d529a3fdf1b23af, 0x17c414c2a7053255, 0x84d8f724c6b41f88,\n             0x72a063c64703bcae, 0x5f50bb1240d9dfd0, 0x6500a3a053f93807, 0x84a501df50d0df6f,\n             0x44cc72dbd212ce92, 0x4b9745977957269c, 0x602cf7f843ef7d29, 0xb988467c27f0ef14,\n             0x934ff4ddff15666e, 0x83cf8ebeb5211a4f, 0x607e912ca286695a, 0xecef2898e2fcaabf,\n             0x8bee9b3baf91afe9, 0xff06bd30ee927d0b, 0x9b06f72dddd941ba, 0xcea277b3e8de791e,\n             0xf3f621791b825b3f, 0xeeeab9911874f32f, 0x0cd53f087a17cd03, 0x4ec085b36f05a972,\n             0x1614a1e0bfa139cb, 0x03c07ca5fd299e78, 0xb1378ed006edbc8c, 0x2f10b3e443070a38,\n             0x242b58a5218120de, 0x02ca74c4a7727d5e, 0xdd06bf04d4e36105, 0xb836a1be48827e92,\n             0x815d64c9224377a2, 0xf5461ed3fe683571, 0xdb9a3e38dd163ac4, 0xf42cd57415c3b42b,\n             0xf72479c550704102, 0x1c49612a3c58f20f, 0xaf588165aef1e885, 0xb6532e858b71fd7c,\n             0x4f490583860c2242, 0x582a7b26aefbc94a, 0x337d5972a029c80a, 0x7eb384cd5e574351,\n             0x582412382ce780f9, 0x31379cf034a6b749, 0x0979ca7369c97af4, 0x98a0f540715f1c43,\n             0x6ebf025e3736afe3, 0x3e7171fb069e394f, 0xe89d05dc46e0121d, 0x3d061a1588c382da,\n             0x9db9cea5e1fbd830, 0x3f13771386818cf0, 0x5580fa6c261aab06, 0x0c251cad7716ce13,\n             0x8fe1558f053f9fb4, 0x55806d4140ff3fa4, 0xad641f13ba474ac0, 0xe556f7c6aeb3de71,\n             0x6007665fce1ad636, 0xf4274e0f6ec05099, 0x72a221ab588605fa, 0x249dd0a5494a3c5f,\n             0x3362a5c388e68781, 0xc24b681f6eb6fb0a, 0x6f038e67a70c263d, 0xf3616a85e8268413,\n             0x88f2c515ad4ae79f, 0x0d4e4b5aaa4e1e97, 0x0becf567921efc72, 0x5e036be6c40c4b12,\n             0xa943297a064c48ac, 0xf5dad19be84da2f1, 0x173a466c3b594156, 0x43be2364e3a56322,\n             0xd2f9f1c58a92a7bd, 0x53bb9a0036b591c3, 0xe7627ecb06338e3a, 0xa636baccde7ba9ef,\n             0xb66a54819dcc5a0e, 0x66caae6705479fa5, 0xb80c697a1f031160, 0x34d634cf2e46606c,\n             0xbe5b63a65f170f9e, 0xd97979befee8fa96, 0x21e7c1169acbba24, 0x8be940d32a05001e,\n             0x552e1e4e38f056b9, 0x3f8ddcf4c06ff237, 0xaf8da21f2698fe3d, 0xfcb7213fd99fe780,\n             0x5aab9692633ad9e3, 0x0200e3c8ce036f9c, 0x09c88aebb19e9af4, 0x4f5684a0827552ae,\n             0x7628ee96d38856c0, 0x7a733e762d94c106, 0x61e381c3e63fc7c3, 0xcb71ce510aae6ce8,\n             0x93a12291c424aa51, 0x3942bb48fa1e3d8c, 0x6c81bc449f82b79e, 0xf439c0b07d8a25ac,\n             0x1bc3411886ed840e, 0x7304ca5e74ac0af8, 0xe93897b4bce6714f, 0x21192811b616158e,\n             0xb91f4df015498070, 0x8b065d4cdaca17ce, 0x9b5111137173fbc2, 0x15deccab063f893d,\n             0xc770d05cd7eaa9bd, 0x2634de2fe0bb2c2f, 0x769648116cec0fcc, 0x736e532c7baef4d0,\n             0x82a5cd7cb52a6056, 0xd7963218dc0de396, 0x920ba6092c2834cc, 0xc3c2528b135c32c9),\n            (0x158329b7ddc168f2, 0x9a29db39a1a73b44, 0xa62bac228045d323, 0x4a8183728ce4493c,\n             0x4109f5333c2e08a1, 0x4123dd36585dd530, 0x16ea82cd0400ec4c, 0x867a9d946b8f532d,\n             0x2c394a7475961b4c, 0x77d1bee5c2ae1bb9, 0x58a578148aa872b9, 0x96904e25fa9c4633,\n             0xfdf609d139134141, 0x4bf27836ea24fad1, 0x8091d789410f377d, 0x412004fc1c4c8b7d,\n             0xbca572cee5daef29, 0x10294fff9010d730, 0xd1212b64970ee17a, 0x0e8cb8eec0e219b6,\n             0xd499fad1b4d4af53, 0x4d9e55b1a6034ac3, 0xdf11c0fd3fe0165c, 0xef3a195c6de72065,\n             0xdb547cae86df668f, 0x52aef9d7d4eff1e8, 0xc09e4c9bbb90a07c, 0xc4f59832959f8825,\n             0x6670406a73c6e660, 0xa69a76aa556496d8, 0x93313c2f8fa36abf, 0xa4fe558da314a7ef,\n             0xeb6e47c204bc4809, 0x931bbb65b1c23712, 0xf8f8c72f9adf74a8, 0xdcc2f95b1276e9c2,\n             0x415fecb3cf9cb1be, 0xb35f9ec92445ae33, 0x32294ad822b81614, 0x234413c551f82a1f,\n             0x1c32074ef02e945a, 0xd1475057e8e07e0a, 0x59b01890de402019, 0x6c40430c78263f07,\n             0xc1603d826f2bf734, 0x0482d309f6b612e5, 0x808e6e8d5cb202ea, 0xb4f8d02eb84dbaf2,\n             0x67f1454e945a56db, 0xdcb94cc5e576a379, 0x60fb90008da10254, 0xe96c5c49aafd337c,\n             0xa080b5c7400e9742, 0x56d4afbd2941a4b2, 0x25ba1c5ef3c020f7, 0x534e932e7596fa20,\n             0xcf5513a852d9ea51, 0x609fdc4f1dceffe5, 0x358f653015c22c69, 0xf7c71a7f5962265c,\n             0xfe822beebfdeb865, 0xe8931e5ce698cef7, 0xdc05ac7d1e815385, 0x766020d776796c11,\n             0x928e66e4b821d91b, 0x918affb0ee42a5bc, 0x0fe07c0e90ad6a44, 0x1f618a6121f1c6f7,\n             0x8988b2c4dea2433f, 0xd342557fbf6e9179, 0x3c01f5378afc336d, 0xb14da623545f4f83,\n             0xb42e2a460e030dff, 0x2467aa4154be1607, 0x4e51899925d2573f, 0xf6622fc11111e2d5,\n             0x90be99ff8ccaaaf8, 0xd872b982ddfa1e4f, 0xbe1e243aa0fb37e7, 0xc866044b3d6b4fef,\n             0x04b5c59d097ac786, 0x17bbe6962ba64d79, 0x3145d00e7f3068eb, 0x450a003a16dfad6a,\n             0xa9f7b61ba01fe2df, 0x5b6e82ae590987cb, 0xb520f8c5f10e8c11, 0xbb3007af20fb90ba,\n             0x89e56655c53482a4, 0x4f51853a53c948a8, 0xbc8d5ca5e29835a3, 0x11a74e5cbb64d71b,\n             0xea1edc5d02512107, 0x49b67602b335b035, 0xdaed0ba9cea631ee, 0xc89ae5e6d3c7c31c,\n             0xe2b6ab11f96fe0d6, 0x42af0e2d06c72466, 0x14b0961809b52ca7, 0x20353337a881af6d,\n             0x33a2291e0343015f, 0x188c370ddb2ad070, 0xd446fb74a8052285, 0xffea8966553c7ff4,\n             0x99ff8687e155b344, 0x3ba9c74864e615c2, 0xc88bc9c338752e23, 0x8af03b613a15743a,\n             0x70d87f62c0e08510, 0xa0fdd22bfdf86478, 0x6d61357f1390950c, 0x2844b5ebfff29ba7,\n             0x182fc712ae14bf36, 0x8a6336afccc50eca, 0xc4eb6bacb81206f9, 0xd2ed7b2351d874b2,\n             0x4a8ec0a6ca354ea7, 0x3927723d3756c953, 0xfaf900606a0a4cb0, 0xe6da7cd49c0ffed7,\n             0xbd644ba20d67b844, 0x251bdcffa140ecf7, 0x77bcd76b4b73ed2f, 0xd5e94f0d9322ed2b,\n             0xe75a524381dd3393, 0xfa2c1299c3a727c3, 0xe3cf454d27ac9521, 0x48da42c508df27e5,\n             0xd1fea8b547ae7337, 0xa2496c5930f50d9d, 0x52db267274670a86, 0xa326c9d692d0c0b8,\n             0x88f50efc2f20aeaf, 0x543a22066b9f79c2, 0x1124ec03cb31dab1, 0x553bca154e6f9bce,\n             0x161b0c219cdc22a0, 0xab095b0ce8a54cad, 0xfb321696f8916fc4, 0x11dec6859839be5c,\n             0x8293023c249cdef8, 0x0733f17b90f456a8, 0x3afe5c7179007bee, 0xc62e06234f8f59bf,\n             0xb97314e5a1fd3703, 0xe4f9eefee802fe80, 0x17d466b931c05c6a, 0xa454870c4cfc43be,\n             0xf9675c128c8ac4d1, 0x8dd10ffdd641cc72, 0x46f5347d9206a632, 0x0243881f2805d572,\n             0x520409c5fda169f5, 0xbff79449c2d10661, 0xa2dde8ba98650a0b, 0xcf2127509d9136ed,\n             0xf6b111c646f0d2e9, 0x4c2c43add86998e9, 0xe9d1a6f43df2c08b, 0x5dc7b52066f2c155,\n             0xcf8b0cb9e008eb7c, 0x0dd8222e22c0f212, 0xfadf8615792037b7, 0x972caa8d2b8b49c2,\n             0x038bdd23ebb8dbab, 0x7fdd88f8eb2fdc93, 0x322805754197ab36, 0xd905f39876d99bda,\n             0xa49234e4374533fe, 0x5cd72aac1f65b549, 0x10a7fba50254ec9a, 0xbb9c2ee7afd35e47,\n             0x1c85e5177810e263, 0xe9b517bab717617b, 0xc9926302e8ee239b, 0xe130c636e3910d58,\n             0x0edfb38db790f325, 0xc6740f789866cb41, 0x347ec07d3fc45e94, 0x40c0a3ed943bf8b4,\n             0xe804b9c492a45236, 0x580fcf5f6d475e9b, 0xf573e59c8f1e3c31, 0x5e5e3502d63865ef,\n             0xdf00b10ed0376f17, 0x4e10b0be18a10753, 0x87128c42ffe84d8c, 0xbd6c0d0bd06ed70a,\n             0x718f7e7760eeaf34, 0x1ba3ff5327ecdab7, 0x0cabf22c29411b42, 0x9473cdc4598e4f8f,\n             0x3ddfb8602ace5b26, 0xe670abebb619a4e8, 0x0697536b7786de6d, 0xb544d14debc292ba,\n             0xbe2c8342d78528e6, 0xcf1dbd64adce6259, 0xcbc5c0d0f43ca6a7, 0x5218342b8b9092c7,\n             0x99cb63345f49f111, 0x499b094dc0ce8f77, 0xb3da92592b98e310, 0xe1d053736620f1e2,\n             0x9711030e03f9daa4, 0xe69fa65f716be04c, 0xb29444afc2bdd575, 0x57d5403d32b22f74,\n             0xd447c62dda27c651, 0xe5635cb8756351d9, 0x50c07efb9775a4bd, 0x2e96adf4e64ac761,\n             0xfb9599ac8d0c82ba, 0x54470836022ebb92, 0xb40ca24595af851f, 0x3b180b2623095b25,\n             0xdf477d223355df00, 0x9021c2b0cab7cd02, 0x56a85c0b89cd05d2, 0x6baa3ef6b3400e3e,\n             0xabc407f1ff246151, 0xf64d8d654a999958, 0xaeb79aea2fdef02a, 0x79f6bc2feafe4978,\n             0x1bb0d1b273f48005, 0x867a8da519dde6b4, 0xab07f45f2fe777b8, 0x914299fefeff52c0,\n             0xb97d1f3204431bc4, 0x688210fc33bdfda2, 0xdee44438d22d1bab, 0xe2b622a7183d6856,\n             0x2f4b4b70718ec67e, 0x5d0ad020a8a55648, 0xb2ef08f2444f473a, 0x6a3c0cd732cb529e,\n             0xc12d5fd10b932932, 0x78d420376eeda2a5, 0xfa8ec6b7e1e1db2b, 0x814c3ca59c2fa7a7,\n             0x09ef51dc1e3b79e3, 0xc0d19dc33b99c80e, 0x871211f57e39d2ff, 0x050088c170055ebf,\n             0x572caa212ea105ae, 0xd7d2121883a1d580, 0x9586ea76b944a292, 0xc13392358c498769,\n             0xdcad1a588111d441, 0x9ba1e6661afd8aa3, 0x0294ce211bd52e4e, 0xe8ee419a16a7bd03,\n             0xe733869d0229d45a, 0xffa0e393fef2deb5, 0x6e483f23fb94b4c5, 0x3a7768c6ae46403c),\n            (0xa65850663cbd2d0b, 0x92ac42b2313bb4ec, 0xf04c9441a5feb192, 0xab16b01dfa1416db,\n             0x6201841824208267, 0xb0e7b3359a5e47c7, 0xc5ab90c82cd2f20c, 0xd5c03f031e44a4e4,\n             0x77284d0e657b7665, 0xe49de00423ac4153, 0x4f344778777229e3, 0x15321d353ca604d5,\n             0x2cc5b0bdb42ebb87, 0x47a7a9edd8a972d0, 0x8535d69828a7e772, 0x6b18c86d304d682b,\n             0xaf8089dd5101d5dc, 0xc0e130409752c1ac, 0xc49f5c1297c22574, 0x5a036cf302e32765,\n             0xa2672380c789970b, 0x0e31dcb103a71340, 0xdf087c357ccf4730, 0x3db6868ef6e5d62f,\n             0x3db44a689b742817, 0x6136842d40dd069f, 0x93cff4006f6b60af, 0x9cc58428da61f94d,\n             0x5969c872a07d015c, 0xaa962a93edd682c6, 0xaf3918eeca49daf3, 0xd3b89780c2a39ac9,\n             0x6ab5567fb5bdafcd, 0x6e12380dc1c9d53d, 0xe22f782061fa511b, 0xec430b5c5ed61d79,\n             0x6a1b3e15b3a0acba, 0x3abb2baa5a0f5af0, 0x107a5c9a12837ca6, 0xf3f650e23e7c1e87,\n             0x26b716b7809c7cc0, 0x682a519aebbf45a4, 0x74cddf1c4e6292ae, 0xc429b29e9dfa45d3,\n             0xe9cc57b5d4825d1d, 0x67e9b7a7db675a8b, 0x79d415cb519bc290, 0x100f0d170087b9e5,\n             0xd124fb3572f0a481, 0xcfbd2b55038c5d17, 0xf5d2304b99e65e5c, 0x99db5062f9ae6b5d,\n             0x4898bb88c1f4e1e3, 0xc6de8e9706d41596, 0xd6fc5f8d95695d56, 0xb657021f3d3b2f32,\n             0x7103da4f095cfac5, 0xcbe66dfeefb7438b, 0x6313646095623092, 0xd46a351d79b25d0a,\n             0x89f2d9aa50d675f4, 0x5aadaebf6f2589ad, 0x9e74854c69e8dcc6, 0xa30038bf41f58a1f,\n             0xedf97bd9a1fdebcd, 0x3e643189c2215141, 0xa118dec949e0fd35, 0xf60399f71ec3c651,\n             0x1dd9ff3a8ef9fdc0, 0x2ddc8a9a3d7ea814, 0x5ed6345a343a9249, 0x1ec3592ba55b6247,\n             0x06cb412f61c878b7, 0x3a670934a5955d94, 0xf31156e2729a7e3c, 0x5ba200451899ba6c,\n             0xea3f8d99b5ab8ac6, 0x66521f699b979f95, 0x60b2776b9970b934, 0x445dba57bedb6316,\n             0x1cbe4da4c85b4f4c, 0xed65fdfdc6c5b1d2, 0x4a35df2299669798, 0x341250fbb1653330,\n             0xc197c94473f1d7f6, 0x3d332e477d432064, 0xe1eb258f1364268c, 0x278de37acbd0ccc5,\n             0x02ab2430e7c20f51, 0xcab8e22a49b61767, 0x18a8c15cdea3517a, 0x98bffa2b398689fc,\n             0x112294ae22d8b80f, 0xc6c10aa7d2b654fa, 0x098368cd28920936, 0x707c145dc7c4ab78,\n             0x06482aa618370c72, 0x4196ad65eeedd4fb, 0xe08467f31bf94308, 0x9af09876f3eacb5a,\n             0x43321974434d13c7, 0xcc342c29bc5fc175, 0x4cda0dab066f9ec8, 0x01b50012dc9d3898,\n             0x38a5caafe8f5609e, 0x74419758f30ec920, 0x7869d23ffd77f2b1, 0x041d40b0ebcfe66c,\n             0xeda4ae6dc5c72460, 0xac68d5d3dedaf197, 0x5b5b18ca1b65c988, 0x289a5d3d91f387b0,\n             0x6e26a275fab345c9, 0x85fd30bce408edd4, 0x1d37d21e09dceda5, 0x2c9f04cd95650856,\n             0x351f4af5ac810729, 0xc574b1e639e126f5, 0x193ed68dd638d4d9, 0x921803aac14d8df0,\n             0x9586c03c2cd92d04, 0xe800608b5beb6f5e, 0x8c6111caed704c11, 0x739def0541ed2e61,\n             0x20adecbc4579d4c3, 0xcf40eb63dc0b5156, 0x7b14281fdf5e3f43, 0xdd88822b49c4a734,\n             0xb639a20071fc2222, 0x81e4f611b16f10b3, 0x3cbfd55b9d8be9ab, 0x1d244a4f12434bef,\n             0x4e04c135ecee937f, 0x27031d4f9e9d3800, 0xfa0a2744693da7d2, 0x083da176071ac3e7,\n             0x2ff5e5e23b63553e, 0x8fefc158137fe2ac, 0x5d6989cd7d656822, 0xda50ee9d7c4d5a02,\n             0x9b095f13d27a8b37, 0x33b5464eb98d2ce1, 0x131b8daccec1640f, 0x57c741da838d7b3f,\n             0x18dab6477fbfc635, 0x362fcdd0d3625fc1, 0x59df8c8d84ef1e29, 0xc80d9e81b455fca7,\n             0x44503d1f84fbad24, 0x2a90bdc621a88a58, 0x7fd90d9d9366b383, 0x241414856e7f63b3,\n             0x6ccdce14c1e76850, 0x8bee351614a3797d, 0x35cda9d9fc7036d0, 0x32489e588070d276,\n             0xdbcf94d24cc10f3e, 0x89cac832aecc5f6f, 0xf766f6d6519c1240, 0x10062a406d23170e,\n             0xfffa75bbd0788bd7, 0x9b4b9ffb2933e948, 0x72ad6fa5fd02ce4d, 0xb595ece7b985050f,\n             0x60916663a6c9dd6e, 0xf2825ab3907baf6a, 0xfebfe22e89febc02, 0x7f4bdba450ab2ecb,\n             0x82d2991639c6679a, 0x2bdd540651c6c950, 0x25f432e34d876344, 0x36ad28fe7afa28f7,\n             0x5906e88520a4a20a, 0xf37af17541bff5c9, 0xe340bba410e5c568, 0x3dcb19623d8490bc,\n             0xc51d5ab1ceb083b3, 0x09e5282ca95510a2, 0xca493d9ecf923752, 0x768bb84df7b5c82b,\n             0xfc1a1c4c78e0f81c, 0xfe3b01ea18ecf888, 0x472c346d4ba8d811, 0x32b627b2e71c3fa4,\n             0xe14f434856e1a5b2, 0xcfdf5ebec350bfb0, 0xa7337198ecd82767, 0xe166885b17502336,\n             0x0e1f8cc5073bc9ae, 0x9ad12a3eb3f8e9b0, 0x3aad6eb7330fad2f, 0x31f7e5907bbb5f97,\n             0xf7480644a17f9fe0, 0xb9ca40a188d9b349, 0x46c1a5f4c5252cf7, 0x5df18ca5b4eeabd4,\n             0x72585a1b7dc3ba28, 0x2acaa3125cad7ebe, 0x086dfceb84ec2e75, 0xce9ebd22f0a411d9,\n             0x858ff8e5c3a1cb42, 0xa7c30b8a4638d63a, 0x0f43a6e98205a164, 0x5a196153601da126,\n             0x3cfe5eb94522fda1, 0x773858cc9fe6c554, 0x75faa585b7ef1056, 0x1ded6ef3755ba188,\n             0x328501f39f2f5fe7, 0xafd7914fd3adc4a7, 0x50c0545caf6f3504, 0x0290a30aab47a0cc,\n             0x0b8b774c0ffcb772, 0x4b9068f513406a8a, 0xe7f2bddb2c58f0d0, 0xdfed6aaa0f89e29f,\n             0x03fde8b9ed724784, 0xd834718d545cdde7, 0x445d2b319e34cab2, 0xa8fa84085fcb8bcb,\n             0xb1fe8a738084f3ed, 0xbe64f25ab4253604, 0x527ad2479eada413, 0x050d1e6a091c9012,\n             0xf4937c5bed7c16a4, 0x830b711032508fe3, 0xdf3578fb52d77639, 0x1abc82f642879291,\n             0x2e7a237c855d044e, 0xbb3b71ccf421fbdc, 0xacf7d6200e9c4ec6, 0x8b5abf534882e53c,\n             0xa9cfac9c85f3f2e8, 0x8b62f803c3c22edf, 0x25adb123b1d27bef, 0xe5cc3f5744a2ce0a,\n             0xc5500fe753e3061a, 0x9a8e4832bc785d58, 0xdcaa2d3f03ff49cc, 0xc31e90a4f02c494f,\n             0x478d1bdb4de0f0ce, 0x9d8881f32c878d69, 0x34157e74e7de3fcc, 0x87986971b1faf5dc,\n             0xf9f6a2b87a202751, 0x509748b0da4b2314, 0x00bf78fb242e59e2, 0xf1a0eab991c78bae,\n             0x136e098667381770, 0xa883cefb0d9a722a, 0x510ba99a1c91be41, 0x961232669cb24524,\n             0x7bad2866e952a507, 0xafdb048d2557dd80, 0xe43afc0a775267c9, 0xde97438dabcb38c8),\n            (0x0d9e7046371c5cb2, 0xa0908b504c0a40c6, 0x34e191f0efa205c6, 0x8a73e4e6c52e0e0a,\n             0x01f8773842356e0f, 0xdc7c3e507adff346, 0x5d3e5ca6e5b52709, 0x8395e405d46b098b,\n             0xd85f970fbc54e02d, 0xd4964113aa7cd2b4, 0x06a66165cb5053f5, 0x92ede07f24f149a8,\n             0x1eaa664ab6cee154, 0xcc88f7da36a5cab4, 0x23159179e7b584c4, 0x3edec9387626d7b7,\n             0xb5bb7159c869dd39, 0x0b17038b24deb415, 0x5050ed67d1f51e51, 0x849267aa2135b33d,\n             0xbfec86e553048c0a, 0xc85f3ad3fd438124, 0xeae313f8564bd266, 0x275395334dce49bd,\n             0xafcd51322b5047e6, 0x3c7e811ab2e77a42, 0xb989b7aa908cae8e, 0x718822cf66c45730,\n             0xaa475fdf35398f50, 0xe1cdd1e15e4c14f8, 0x52bc140835fdc83e, 0xb65b61a10ff4b96c,\n             0xf59f2f5db911c4c3, 0x8c16bd346fdfd8a6, 0xf8f495a5f47b308c, 0x6ee545ea5b94f454,\n             0xbc72173222523eac, 0xc8a99ab0e40e9632, 0x7ffb6e837e94f850, 0x4906eaae576d9643,\n             0x4a39d3a6d981d699, 0x47f0d97f1c41cbe1, 0x6c0893fbcff46836, 0x2659e9cfb396d94b,\n             0xea6c4cbd1747f055, 0x1d7d4414f0149cc9, 0x7ac1a75054f90464, 0xf1806ad0e73e761c,\n             0x07957e253cb0d845, 0x01992ccc663e7574, 0xa3b7e26c765e2ae3, 0x35dc01301b8510bb,\n             0x3fd0d84cc3d95cb0, 0x2c18f4b964ed1c5b, 0x250cee825443dd97, 0xa8760d95c9e76ff8,\n             0x64112191e7f15482, 0x98a7856245608feb, 0xb0537fb054a3cbc2, 0x7d672cf7bc554412,\n             0x0a3819988e07aa1d, 0x3d53365bfa2e8e8e, 0x8797e73406bf7a78, 0x7015c06329cbc63c,\n             0xc9169d2c1b7f7cdf, 0xc1fb1239d029109d, 0x37b55142a5af178f, 0xac5d9d8132d6c720,\n             0x376299b1ecd7ae2d, 0xb0994ea307385db1, 0x8d26ea7cc4b5bdfd, 0x86dc68c380044767,\n             0x9ee0c08a56e73e99, 0x32ef8e18bc008c66, 0x922f378383b5de11, 0x7140806b147029ae,\n             0x9d117da80412262b, 0xc5fe632679803cd7, 0xd483535b1df302d3, 0x344b6ec6f9c84f5f,\n             0x4a13b17040000a4b, 0x88009b8b080be6d8, 0xfbf84751f1af5edf, 0xf4b079da38f6cc19,\n             0x78a85e00505ba48e, 0xbf5a790acb8d07a3, 0x09facc77e0a617cb, 0x2208e33df106504b,\n             0x28c6b4941135ec96, 0x0ae53e432557ffd5, 0x27f4e5189563f470, 0x97ffa2c7854cc06b,\n             0x807dcc092239da77, 0x118fab2d88e7b6ad, 0x8a7f118ee3c0377e, 0x6190043d18be7f27,\n             0x035a90c364df04a1, 0xbf172ed4c82825dc, 0x7dc4317d210fd8cf, 0xa3fcbb8924c3d544,\n             0x100ecdf2f7c137bc, 0x91c6abfe23b70d4c, 0x5f2b4c3c72f97ab7, 0x6aec488f5aef6fdf,\n             0xa9dab2606c727990, 0xb42e27dd9b30899a, 0x925f54bc1188567a, 0x6717be210d2f121f,\n             0xd183b8009c66bfd7, 0x8f879334c9c508fe, 0x46c7a6e9d15d0971, 0x47b83c3a445ccc39,\n             0x70ba48e45caa2646, 0x076b26e3d197532c, 0x97a431e1e8182b57, 0x8d0142223ff4fea2,\n             0x2347dbc8005afbec, 0x6f2e8965bdbac6d2, 0xf0134f2468adc15d, 0x2f04ea064e489973,\n             0x5e471ed748c65ea9, 0x24d6d85218fe1ced, 0x55c185130c1baaba, 0xc0ae37927b06c7b2,\n             0xbf94d703a0a15ca7, 0x44a58aa07efdf8e0, 0xf29750435d67391c, 0x8ffa287cbbcfa7a1,\n             0xa2cd97f20b2695b7, 0xf83ecc1e2f0d4bed, 0x053cd71d01e25d22, 0x1f87e05df664514f,\n             0xfc3bcac18ddde865, 0x70da5ba2021d2d9d, 0xda053919fe0606b9, 0x742b736aef4f095d,\n             0xf5cad7fbe8ba862a, 0x0a09064bb875407e, 0xedcbbd423a31059f, 0x880dd37d36ee0bae,\n             0x39ab62111295cc63, 0xd450af148a12bb9b, 0x2b0b90eac45ce87c, 0x965ace6f4e9e5123,\n             0x526669f89efdd07a, 0x507e04a02bc7489c, 0x9d488a3c0ca801d4, 0xfe90223ba34c50fb,\n             0xd4422a8cd506c9d9, 0xb5ebb40d2123734d, 0xd5d55b097060b362, 0x491fd251865bd6be,\n             0xc828f72c2c9217ec, 0x8ba6673b60dc0b06, 0xe9e13ad568652524, 0xdb9765515e87ef2e,\n             0xff285a1fdfd79503, 0x97aef67290ed6fbd, 0x43643a8132488225, 0xcec574e3cf14d171,\n             0x06e958827a1b4efb, 0xda9523e416483d12, 0xd6c63a96ccb06a42, 0x9f5f84cdc7a5a00f,\n             0x06253705a78fc8fe, 0x2666a69b2e473729, 0x1e010e599be77e7f, 0x09d5dc4fed5d3df4,\n             0x31f318800b4c9c5c, 0x04775ba46b01ca07, 0x4d445630aaa236d5, 0x398c81be08bc53e3,\n             0xd6220673878aaa26, 0x17d2ad01fc6b69a4, 0xd378e4ea6ebba24d, 0x6830c5fdc48d4458,\n             0xaa1c1fc69c6fea73, 0x6368f377f248509f, 0x492c55f14d1a6c72, 0x02eb8f697c97cf4b,\n             0xdd164d1e9b91997f, 0x162f96234cb17dc0, 0x270978cb10774e24, 0x6e9e70a8bd3601df,\n             0xa1cb5736f41a8977, 0x37c7f5d659603112, 0xf72885750f419d53, 0x5b371956f853c4ad,\n             0x0cd782a67bc8181a, 0xac621ab73b58e4bd, 0x9fc5221bf92b83f2, 0xaa687041abe8dba7,\n             0x8390425b5426a0be, 0x7b83101a9824fb79, 0xbe5f00e906863cc0, 0x54891371dd1c9ddc,\n             0x69273ca3cd89864f, 0x15fe07a12d04432d, 0x169a4627df882e70, 0x4323eaa8fc936ba2,\n             0x733389bade07006c, 0xc42b861c99dfbb8e, 0x3f7b42372e04d488, 0x51945398d0c26cf2,\n             0x463fe79710bb1fde, 0x731e6cca3cd89174, 0x266cf53cde804136, 0xa2719720400226b8,\n             0x7b728ad16d7dea89, 0x7e82326de6ea4a8c, 0x058e178994224d7e, 0x6261d6e99a39bef9,\n             0x06953d9f318e7e2b, 0xd505fb992f1ea217, 0x964901292d736edf, 0xd4945e4ddca616e4,\n             0x59365bbd4ca9ceae, 0x2730e41e91ee8189, 0xbadabe39130f05e6, 0xd3e0895b59d3e355,\n             0x12452310d406298d, 0x468e58c63bd06d6d, 0xd7c99ecd75b230ce, 0x618304cba3443104,\n             0xd921afba32628b33, 0x99eaab39394ac3b9, 0xb4fad51f4ff0e792, 0x32d3684d62fea5d6,\n             0xb841b59154d1e65a, 0x570ffc8c05d7054d, 0x71ce15736202b959, 0x5b9fd05a1a72187a,\n             0x2566994a48d5b46d, 0x42967c0623d164df, 0x681a461c371e860a, 0xf36282e23e1c6568,\n             0x25d1c4e21dfa607d, 0xf3e605d27a04aecc, 0xc4ec6ee848aa636e, 0x1ef2bb0555759bc4,\n             0x3fda4e63db9782e7, 0x3bfcedb42401e817, 0xdbd5a53e205c7655, 0xfa32288e7fb5404b,\n             0xb4f67558f0102c12, 0x7dea02041aeabe16, 0x2cecbf5a725f9812, 0x3d92793e7cd2ed57,\n             0x2e5739dfcc33246f, 0x050ffef08cc6e405, 0x6d064066f43969c2, 0x9385fcc7ba584ee7,\n             0xebcbb6430a98676e, 0xe3907164d71dd20a, 0xec985e6e39086368, 0x213896661e50792b),\n            (0x725ffe2cc58e8106, 0x6f880b22cbfab97a, 0x993575e4c2531f43, 0x6f5998b9b27eaf8b,\n             0x66e9037121263202, 0x43ce9c552168b3b2, 0x7d5844ac378bf4a1, 0xa110181dc762c7e6,\n             0x9c80db42ae701df8, 0xe8bf6002fa27b1d8, 0x56c8129166e1a98d, 0x869b30861391743d,\n             0xd6effeb87b316207, 0x541400e2a3534a55, 0x51337f56d2df5472, 0xc974cdc0e23747b8,\n             0xa541f6714edef161, 0x343df3ef066b5339, 0x92f913586d91d231, 0x2cc2e866b8560ea8,\n             0xd98183b6fd4d3bd9, 0x527a27c0c99bdf06, 0xb440add62c07b41a, 0xcee7b93ccd37afc0,\n             0xa81e54f79577dd4a, 0xf8e00c3fff3f0137, 0x2a4ee347bd0f4ebd, 0x3e2922e65c7a790d,\n             0xebe7395b88c022f7, 0x3b9ba79d5f233109, 0x706491fd330e7c65, 0x925739223178936e,\n             0xed489ccac4ba3966, 0xd0c70cc3d7430fad, 0x7b2c81983afbcb90, 0x381014917b0125d6,\n             0x07261a645f8f3a80, 0x956c878079a7b4e3, 0x5f6ecebbace86267, 0x2708e4fe4dc1050e,\n             0x4d6aa0b716d73008, 0xc20eca6bdc95ea9d, 0xf75c5a3f67b8ef23, 0xe09041510fa3e0ab,\n             0x2789b829efe74ac9, 0x54dbcded40a5ea3c, 0x5ad8e5b13607f791, 0x5af02564a4a9953e,\n             0x3afc483c42001eed, 0x3d7731b527bce3ae, 0xaaa0955e6239ec92, 0xbc5be05823b59dbc,\n             0x5932e5f6aed68d8d, 0x8f54198fb5590459, 0x20045e57bfc2b49a, 0x8239f25a5b86037a,\n             0x8fbf1f003abfa819, 0x47fb1b24b84498fa, 0x09a7dcec148c56c5, 0x33e3fc7beaf03b8a,\n             0x01627bd917afe9db, 0x9d86a7150115e57a, 0x52b1a8e4179588e1, 0x3f47db1ece86c737,\n             0x2b1f9bd9f964faa9, 0x2eeccd787f6b4103, 0x8ef76c8cb01eda53, 0xe7329b4ad51277bd,\n             0x81c79b07ff3300d0, 0xfbc76908fb2f481c, 0x8196b60141936b3e, 0x0e9e71660e163f63,\n             0x1de7e36b259a18b6, 0x56d4be28214d104f, 0x590ce8786214e050, 0xb58daf0ca94b4134,\n             0x615d3c93c6ab3174, 0x48a75bbd76e6beeb, 0xc3f9e1ff3f0cbeff, 0x877191bd748e9e30,\n             0xfdb05717569710c2, 0x1bc4156433ff908a, 0x12c4aabcfeb142d3, 0x7e09388785e8d72d,\n             0xe4cfdc5751ed2a5f, 0x77c84b32aa8f8b29, 0x23b7bb777bcca77b, 0xffafba8685cf0332,\n             0x356f5db76a358126, 0x4323ecec5a190705, 0x3dabdafed4b51c48, 0x690bf7bea38bef0b,\n             0x7c6c7f00fe954a53, 0xd7252ffd1e3f6c61, 0x7124cf32d60c012a, 0x8fbb751e186a909f,\n             0x561e1cf31349a148, 0x4776b09d36795fac, 0x804703bc2293bc2f, 0xed55ca996d97aca3,\n             0x9f8b75c4d2b3a2cc, 0x0c94228b565bac27, 0x12c5621b5f9ae497, 0x4720e252c52faeac,\n             0x2a1f475cc91c198b, 0x4d036790fbd3287a, 0x16f5e48082852918, 0x6e9e7ac3bf9c88ca,\n             0x6f5e9dca5c77a486, 0xfe16ebcc4e7a7028, 0x238e4578039eaf26, 0x646c6d8350284a7b,\n             0xc5c32f72d3e169d2, 0x0a91aadee749032d, 0x905b33825cc4dc5b, 0x73bd4475950ca52e,\n             0x9cbc38d158bc2e30, 0x2f1e8560fb258ac8, 0x9c2d317134e9dabb, 0x4cec4a0e97b8633d,\n             0x6ea7ccddafa9a8b6, 0x46a4914faf4f172a, 0x433587275fa740e6, 0x08831adb2be55c05,\n             0xd6dc72e7c99edcdb, 0xd81f00b9f7a7e04c, 0xab81f69a20eaf7af, 0x0ba2a1de8e139a8b,\n             0x4c4553382a717a5b, 0xcbfda0715441ae7d, 0x52907020c01b74cd, 0x62a113863db06ecd,\n             0x139745508d7bb9bd, 0x200b50758e0789e3, 0x772cdd614c8f354e, 0x6398929e895a5fd8,\n             0xebe7724ba9343ed8, 0x332fdc1f91d4f9e7, 0xab6c82738adbce9c, 0x5b0066c09c9a60cd,\n             0x470b6ecd2e0a4e04, 0x677f4cb52f08aa72, 0x733be4e49ccf478d, 0x351b24b2f4d84344,\n             0x4bedd0be76d15312, 0xf8ac622d91a86377, 0xea60e19dc478a643, 0xce1b3c82270a0da9,\n             0x225294923c8d1de5, 0x0b69886750fe3d7e, 0xe6a9f3b449b4c8f2, 0x3ddc4c933d66cd57,\n             0x655dd68fe480320e, 0xef43295021e4453a, 0x3852a0a4117e5029, 0xe8261998930180fe,\n             0x7f9a55acc776f07c, 0x1eea948da5f71066, 0xad33a2e936125f86, 0x42bc77c6e7408308,\n             0xccb22238fb7be50b, 0xe60a500635032ccf, 0xc5a904679bdb5b65, 0x46434239436884c6,\n             0xe325768674ed5506, 0x113e74d5580749e0, 0xf87a5d6dd5b06897, 0x7f26de90784e0c8b,\n             0x593127ba13241a1b, 0xb09d483e8d1c7e18, 0x2d3a15781574e77b, 0x68ac6f5eb7658d21,\n             0xd62428206df84bbd, 0xe2ffb5f819b72262, 0x4ef63a52f6f6a585, 0x523dbfaafcebcf7f,\n             0xb4d50af8ac913d1d, 0xa80c5b2bbf588788, 0xf03843efbcbc7ab2, 0xe389589d99fc8f7c,\n             0x54894f427202064b, 0xa3188f13cb7783fc, 0xfa81ca5315b502d9, 0x77b48264bcae0597,\n             0x2b62e5a962f06c1a, 0x6cafebac0ac19afb, 0x1552e5e87923a58c, 0x0aff35cf413ed7b3,\n             0x0f7b6954262f283e, 0x850a6b1ff0597356, 0xdafae61427dab01e, 0x6d99010e2383667c,\n             0x64acdb9bd9a41777, 0xe134513d13de9bab, 0x62e702b80775fedc, 0xacf427cdc7a0bb6e,\n             0x0255b582d91c3087, 0x79851e814befc30d, 0x1b90bee867f95e2e, 0xcec8651ffc750518,\n             0xcda664f9b34b0d39, 0x1554a3eb766973d2, 0xcbb8e342f7574332, 0x9eb116b5a4553522,\n             0x418ed189069985f3, 0x4556e2d098ff5d69, 0x3ffcf4128fd0f62f, 0xc521a024a3d49912,\n             0xcf2c5788c9d36887, 0x65704c58cfa20e80, 0x33aefc936114d352, 0x19478ea2689c47a8,\n             0xa022bf86d1216aa6, 0xb634b85c8dce42f8, 0x5b95973a394a7030, 0x69c5601e852aabe0,\n             0xd0089b31191e4c03, 0xc34b895ed3f68c3c, 0x57c17b2fe89dd759, 0x3f18d2c8348e63c5,\n             0xe21bb9fcab1805a3, 0x7a549f2b5e910e3d, 0x931bea5d5c684d94, 0x8b11d6c5ccae457a,\n             0x3045c6b62660dd7f, 0xb77f50e5fb6d9768, 0xd1b71462f4b7ca24, 0x51292fedd704e58a,\n             0xa733c3b4127709b6, 0x76dea7810d72ff70, 0x09b2e1654233b15c, 0x997b27b6b262a38e,\n             0xa3661097a71e2b4f, 0x2d65cd8b8081d1a9, 0x64e1ab39e699c549, 0xa44e2262e644f818,\n             0x56de50b8a57c77ad, 0xf2073c48a4d84c11, 0x314ba65cb199bb6d, 0xff89d0c92af4ebe8,\n             0x6be1f4821a505e9f, 0xc39ea0aab848b48f, 0xadd48b5ca93e5286, 0xbb9d9dcdf95d580d,\n             0x3339c1bd1554ddd0, 0x2eb0e43e9e4d0a6b, 0xe2e6b6b9c3e3c3c6, 0x01b9742fe9259023,\n             0x83f86dce5e527502, 0x5fe08901ea3511e7, 0x634bd1825d9ac552, 0x6969be2c4e944b48,\n             0x1d085e469d4e659f, 0xcc269be706b70cb2, 0x166d27179f3a95f0, 0xd04ee650820d2d57),\n            (0x1ecb6bd0db2dc6b9, 0x35312b3ef14d8dae, 0xac7bf539455b9511, 0x606335e93a7cb84b,\n             0xeaead6b2639fbdd5, 0x145c070d8a385c56, 0x6f746abad2043bb6, 0x774279469aa61ad9,\n             0x3116969e351297f3, 0xea5fc0363cd13c97, 0xa7ebcb2d6a5efa91, 0x720972171091debb,\n             0x6684c079067ad878, 0x01e033add02f1081, 0x0d20a9f6aeb393ca, 0xfea92a7e573636c1,\n             0x4f90e645555a600e, 0xd4f27c5b181b1f44, 0x4729b1909f7c13e3, 0x149b8d38ba60072b,\n             0x46d40ec6af11bc5d, 0xe04d0698c5fc4e84, 0xfb65a17105ef5d53, 0xbf480e073dafe19f,\n             0xc98a8950ce31e61f, 0x67d64a4a80ccfc45, 0x9a5e88d632f29fa9, 0xf350ebebb79f1178,\n             0xd9c89a2a60d0b66b, 0xc86435beeae31dee, 0xa4fc4fcd15d63bc3, 0xba9d3b196739a9da,\n             0xee34d03beaf0d0c8, 0x08cb6660e58cc402, 0x8541350b42d40e34, 0x802e97a9859431b9,\n             0xc978d5965ee32cb8, 0x0facfdf8a397688b, 0x5a5c11324c351bf3, 0xe932fc8453d4564d,\n             0x74f302463deca67e, 0x1187df661dbf40a4, 0x7f40ae35af2eaec3, 0xef8ce73ca44cbf15,\n             0x893bfcdf980b8569, 0x27ca0499b0663ac5, 0x8ba9279447473ca4, 0x608787a7e005dbbe,\n             0xe43745fe25c890e9, 0x5eef2881e37b5dfa, 0x6447a21d68d61490, 0x86f2db0a3d5bab61,\n             0x7eee64a5525ae136, 0x6255b3d40dba17b4, 0x083aac88161486c8, 0xf77fe0274d28aeff,\n             0xe7913275c4ee724d, 0x017437b28d495b55, 0x99628b134b8a96d9, 0x364dd772f7f1fed5,\n             0x0565a4b0585e5088, 0x9b951ea1fe794bee, 0x882af59d2c5039df, 0x998b89655e97d48f,\n             0x92ef581a4876573a, 0xb8169f43a9c59e97, 0x3d9c9b345cc96b5c, 0xf334aa73b827315e,\n             0xe02e835c2b1b361b, 0xbedb71d2c9000f81, 0x53d70e503308eb78, 0x41e6406f1c0e7b9a,\n             0xf022687309afb711, 0xd0172714529fb085, 0x63518020c4273a87, 0x97c2021567af223d,\n             0x153fbb14257a8a05, 0xe26fb6f0ed1208d8, 0x9fa3a569076c2350, 0x2c7a0a38514bb7e1,\n             0x55b17b21e64376c8, 0xaf3127af530748b4, 0xdb9778b61e9b38f5, 0x4c8a7f4064a4b0f2,\n             0x1a8f5f9182c62d31, 0x131bfa6bc1d36e10, 0x165d04333320df9e, 0x0bcd2b28cc74cd1f,\n             0x34dc620de1054b56, 0xc3c0c5e3512566b3, 0x764340e996dc7df2, 0xba4e5a81d9e81325,\n             0x6f1b55b3513df3b6, 0x184176721300614f, 0x2923fa379bfef061, 0xdd37d7de4bc8e2a3,\n             0xa0697ffe5b76b0df, 0xda931af9954f1dab, 0x807e42f6835e757b, 0xdf1645155f424d50,\n             0x1ba7c2cc1adfe7ee, 0x941705d14db037d3, 0xdc08998a458ed148, 0x61d87476e04ab218,\n             0xb01654377beb82ee, 0x008bcdbb48cef32e, 0xf7903cb4a481d00b, 0x628ce2f5141d538b,\n             0xe021a9d4c2d51f9c, 0x3371b6610d72b82f, 0xe3f5cb27cd34b256, 0x029dc5696b213822,\n             0xef731a3c82318a20, 0x5385d813bff15749, 0xcf7f5b790ca11847, 0xc393368cebc71184,\n             0x6836e47a290b58fb, 0x32a8743b039c27ba, 0xe53cfec86d8c495c, 0xccc43a0e55e118ed,\n             0xfbf6c937f7c95e6f, 0x16367ce822619b59, 0x7c114149b1ca3210, 0x79ca5a079086c320,\n             0xcf68cadbeb5cf9e9, 0x860ffc9e1b0b7d4f, 0x481134a841aa272b, 0x983faddb191e4e29,\n             0xfbc1bdfb8b540b7a, 0x6f36004dad65f724, 0xf1e2fd6dcf3fc753, 0x32af6ae0226257c0,\n             0x044cf7e53bd7d4e0, 0xdd61470e04e7d082, 0x27d982e1e847ce56, 0xf72a8f24e4f721b8,\n             0x9b8bb1d6e6ea501e, 0xeaa7cd0509b25ca2, 0xb842536363b0faba, 0xe4da3f8b3bfcd887,\n             0xbd932d361065ba06, 0x9eca370313fc2da2, 0x4c83e396f1dd0021, 0x736f7994e9c8f6d0,\n             0x3ffb5a3d61c968d4, 0x08d8e5f5b52290a1, 0xfb74685303c44c42, 0xb0d224ca8f822196,\n             0xa1a3b5020fb15f10, 0x997487e4d5d80427, 0x3f70da528d56df59, 0x2d57f6db434b4052,\n             0x4dc42d63d2427595, 0x103e2ed0fb8e50bb, 0x0372caa074ae44ce, 0x1a1e47dbe2b61f80,\n             0x309598d72d73d863, 0xca8907ae8837fbd6, 0x5488d21567c40b4a, 0x706aefb716dee3bd,\n             0x80c2b581d4e65c9f, 0xd3ca44bbb4d91f3b, 0x8812961439a9b487, 0xff7006ad825722d9,\n             0x929ee7f4f08a9cca, 0x34f157c18f24e75e, 0xaebbb550107fda89, 0x87b6f7b6a92527bb,\n             0x357c5bdc994eaa23, 0x0928ee03d41cf874, 0xe0c781e8c4beac5d, 0xb1ae862eaac489ff,\n             0x38dcba54b51bd681, 0xed5da05961518eba, 0x5563a0892e5a1fa3, 0x1a049af5d30e1a4c,\n             0x764bde3be98f32bf, 0xe0d9075aee0ce335, 0x5f535b5659e256fe, 0x873974b222f1ea00,\n             0xd888a081be707cf0, 0xf1215d46c44e17d2, 0x4cf419680bc5bb61, 0x972dde1709a3e021,\n             0xe82c9109c3c19d6a, 0xe3a4416cbebc7b5d, 0x9d6043e3a9ba7f0d, 0x032fda0e9b1d8e2b,\n             0x56346632cc3b81f7, 0x5367d31f1a722d65, 0x6f4ca4df5b3a0879, 0x7006f93e7b028207,\n             0xb79d657cccc05e75, 0x00c190a6761e2d93, 0xf9ebe11920c957ea, 0x7db980a6fe125411,\n             0x8786c1da5493b722, 0x24e42205feeec034, 0x6023b4789c9a4981, 0xad1398e15da32925,\n             0x8d06d8d9d0014014, 0x58d84d1e7ad7376d, 0x63b03da2ca89a3c0, 0xaa469b13d1cc1fe2,\n             0xd5eea376b24c5c7a, 0x153958ed22c5940d, 0x7d967fd8e9d29d20, 0x72c645cd51e94f86,\n             0xe0b8d321c2c51b57, 0x6bdca21dd5527536, 0x6f58402f0183b1ce, 0xe1ada6d5c552150f,\n             0xf292cf9f9243028f, 0x84857ad43ab40e02, 0x9009f165e55dccfe, 0x27feeb528ddc26f0,\n             0xf0f04c29fd3470f8, 0x4fb771b412b5fdce, 0x2de1b134d7439776, 0x0f90985aa7a6e3a2,\n             0x7e08c0030cc6ed9d, 0x8caa419b72d70344, 0x1e941950ee78396c, 0x5012381195c88ba9,\n             0xda07a6827460efe0, 0x19a6c4168ca9c9f3, 0x47913746092d94fa, 0xe2866e58b2b5ceb3,\n             0xd8d14e9088adfb11, 0x556db7f2f3c80a1f, 0xe24d5a7b13003271, 0x85940d0290156b82,\n             0x54ac384c6077a3dc, 0xd036ac3ff0336baa, 0xadb6509447c2d17b, 0x78e3969faa8e45bb,\n             0xa2736209de9b4463, 0x1f30ae95031047e9, 0xb88c54cf800824eb, 0xc1bc857bb646a0e9,\n             0x07e4f0d03cfbe2ec, 0xf9e96a7252327950, 0x907b6c1a2312a62e, 0xef009dac45abf0f5,\n             0xa48b2f2188ffd5d6, 0x7534afe9d945a1cc, 0x358722098f709af9, 0x3d608dda268136b6,\n             0xb597da6fc666f400, 0xb4146ee033cc228b, 0x24decb95390d2db8, 0x2ed9660fafdb2f69,\n             0xfbcb64fb3cd89b68, 0xeec35c7be6ded9c0, 0xf3f66ba4ea609a73, 0x62d552b9ff1887fc),\n            (0xbe348b23d10d7b4f, 0x40c1f54be8f0dda0, 0xddfb9394b5354555, 0xe274b7e6d2ddae12,\n             0x8a12830eb74dab17, 0xa304f2b3f0c97c27, 0x2f9ba9dac55ba53c, 0xcef4e107bdc0bd9e,\n             0x57963f73c17f7615, 0x994550b75e2f4223, 0x270e7916443f64e4, 0xc0a236c03631c7c1,\n             0xa1aca1d2caab06a1, 0x5a048e077cf53ca8, 0x3c30852ca67d821b, 0x1ff921114b0c6c7f,\n             0x7d6a9a75c09de756, 0x6df03d13249a41a2, 0xf5748a9f92e0643f, 0x7858dde11ea61ae8,\n             0xa1d228742080dfe4, 0xa1951f54650f8569, 0x30501d3f01c47472, 0x44d8fe18b266b452,\n             0xc7a8fcbe5a2d67ea, 0xa8dd30e95e100d0e, 0xdbe15d22af3190d7, 0x5d694eda02e0e99b,\n             0x542cf17f8e16c598, 0x6b2d75b537ed55f6, 0xe72cd6969fc26b09, 0x754096f394a221ee,\n             0x4cefbab8f7c84614, 0x09d288766d7a515a, 0x095c37322eea6218, 0x7f962692d4a2a8fd,\n             0x0491de4031349fa7, 0x3f41005402841fbc, 0x539a2bb63c0e28cf, 0x5515f0c3f5fee1f6,\n             0xc0bf31ba72eda351, 0x9c25d0ab1b35ace3, 0x8345181a93be0d99, 0x996cf2533f0300a1,\n             0x3094d2b6eb06adba, 0x938a1ebfbbe6a20f, 0xd23e72bcc433afb6, 0xcc1ad49fbc3f3f5a,\n             0x6ff94ca1ca45ffc8, 0x528b377dd91ae7a6, 0x7e824d41e1cf28e1, 0x46f514cbcd03bce4,\n             0x106b1dceea28afd8, 0x8ab4d2c1c41096c3, 0x5fcad1d1cc5b8dea, 0xa745c59e2c053e8c,\n             0x28f7c7344e072952, 0x9cb99f431dfac6de, 0x7aa61bee783f694c, 0xcb5ecf0f07d1465f,\n             0x76e691b46f8d585c, 0xd781c989af3a4229, 0x38958cdea1325b58, 0x7e37d31061f16e9a,\n             0xd92e76ca380efc12, 0x7e0bae0b4240889f, 0xe20c0e7f01bc470c, 0x1383c94314e86bc3,\n             0xad6e62367f4b5a56, 0xcb20cba9fd783b98, 0xe0e869764c62a94d, 0xaf869e6dc9e7489b,\n             0xb3fa08a9fdf55cf4, 0xa3c9c0c483484703, 0x4d0c587bfc4d0f9d, 0x73b2ff142f64ca34,\n             0xbf495b1bcbdec6d1, 0x901baa3b2229b037, 0xc9b7e18522d3ee4b, 0x19db2e53d3da83c6,\n             0x8c5b5181f27d3ad4, 0xafcf3f86df2b7711, 0x75f89825ca0bfe03, 0xcbbea7075c2c47a0,\n             0xf0cc9de637a6d46e, 0x214443898f898e74, 0xc8da3731c2235a00, 0xbcdac16d2e768497,\n             0x4055e3476a2d6995, 0xffe1b23bbebd82f1, 0x50252b4b74768ddd, 0x0c83df35f75c190c,\n             0x19adf29ce33481a1, 0x019ba5dbbd97e4da, 0x0f23256aed1aa301, 0x0d15ba94b7f3fcb2,\n             0xb8d1f12f8aadab32, 0x0d2e91b01aff55d1, 0xf41f6d2c5c61e1d5, 0xbdb0af8a5e1e38d2,\n             0x6b999d358eb79681, 0xf21b1f2a7b39e73d, 0x6adf57dcc25caa21, 0x73ca7591f96f0cd9,\n             0x4bcba6680c7530d6, 0x35e21cda337d27fc, 0x555ec77fbf690840, 0x402f6d37ea15c8a8,\n             0x002c4e731a232f5d, 0xf7acd23d5f9a1ffd, 0x7918584bd270ec05, 0xe74055bc8223efeb,\n             0xc7c0b9943c61ca48, 0x0b9eb3783de2dd1d, 0x29a443615434ec1f, 0x31a9e6b0774884b5,\n             0xee0c4e12c2789c13, 0xcd8c94aec29354a0, 0x702bff6255fa69f0, 0xe4f8beb45907cf81,\n             0x10ebb97cc969f833, 0x472ddeb46297c3d8, 0x392c9cc92a2c09a8, 0xdfab83d9f5279d52,\n             0xeeb818297b82b5de, 0x328ea8951111a7ae, 0x24688e553f3474d4, 0x013dd22d0f08de3b,\n             0x26792f16903b850f, 0xf76e3096b9caa712, 0xbf0b5e1ee53110f0, 0xf8a044a2739f5156,\n             0x30308dc3716ef64f, 0xcdc8cec0d8174e52, 0xdcfbd1f236d26f16, 0xe405e0a29fa69d58,\n             0xc7a7ee8bad24a10c, 0xd1f5e4cadb6b37f5, 0x848b74adeef2c79b, 0xf844fcb68d9a37ec,\n             0x2091ddaf234ee660, 0xde80721815d2e82e, 0x6d8fd0650e5363e4, 0x008a279f43991046,\n             0x5fe70e76174a86d7, 0x7f0da06477173dd4, 0x4b680adcdf16c341, 0x29f3324add3ebb96,\n             0x048a68aa194d91ce, 0xe10d6708f269a621, 0x89ff975f00160ca8, 0x6284d38d385eb3b9,\n             0xf634a2f3522b240e, 0x31e830e06e80e5f2, 0x332b86ccd103e3b7, 0x7b296fc0b25bdc9d,\n             0x6f804ba2abeac454, 0xe2d873eebf569497, 0xd7636939fc779873, 0x06f26eac00da3fba,\n             0x2dbbccbffd826879, 0x5ea5050346e104a7, 0xa687b2edf3346013, 0x567c307d3bb0f21b,\n             0x00f237dfb81d2f65, 0xe1c22f647fbfa4fc, 0x55ae28cd2af0110d, 0x03a6b77e2cb45d0c,\n             0xcea4d06eb470d06c, 0x0154afb2d9e6c5d8, 0x9b1995f176c824d5, 0x38513dbe65b8d8e0,\n             0x146bce9a2eeb76f4, 0x9219d2dccfef3207, 0x2becfd10c29fac7d, 0xef40591659ea15b3,\n             0xb802dd6737a170b0, 0xf96623db86a8ea1d, 0x428430205744c5f0, 0x6c64081a476fbb13,\n             0xc3b653edb64c3323, 0xc657639465fecfb5, 0x49aae5194d9423a7, 0xe02d743e5d613a82,\n             0xf8c933182fe4045b, 0xd32f317e6d8f0dc3, 0xf231ee1b6c1411cf, 0xf218d5f525b2861d,\n             0x7d34789eda495257, 0xac5e2f30caf932e6, 0x39fe6401d46fabc5, 0x597e28e0e4957a7e,\n             0x1cef5c338f0d3005, 0x5e4d5f3308c48360, 0x502f42afb2ef14bd, 0x43d41bd084da9f29,\n             0xea02588bf05bdfd3, 0x3f8d2a1f8577a8c0, 0x78172abd431de6b6, 0xacbc0d7e42613357,\n             0x2ab3f38c055ce328, 0x8ab28068631c09eb, 0xa9981ee67f93750a, 0xc19fe8d739173703,\n             0xb3ada5e9ed09cefa, 0x57e5cdac9d5a40ad, 0x9296f3d81d59df71, 0xaa17dbca92640939,\n             0x79eeb04ef0f8e90c, 0xbc6d0ab366178d13, 0x263fef70706391f4, 0xa2e21380b0c81c88,\n             0x82ad167ee887ea83, 0x027d99d32a35cfa1, 0x459f02164ef9d886, 0x75796a77f2fe75ea,\n             0x1fa018d8871d0d33, 0xdcd2d8844f0e4775, 0xd5e630ce8c5be924, 0x1359754f0258c6ba,\n             0x78150161edbe74dc, 0x7e07095a379fa46d, 0x613dfd1107da59da, 0xd7d5967753e69708,\n             0xef6a6e405b2e1e90, 0x0919caf7bdc177fb, 0x469851f2e36683d4, 0xd8b7d85bde034612,\n             0x7fb03f04681e1a58, 0xeef1e28d28006902, 0xacb89171a566e2ba, 0x602b51033f45d47d,\n             0x59f04438780f1862, 0x960dff6aa407662c, 0x15cca679ab07839d, 0x571de60ee3b168e3,\n             0xf3c539c3c2529246, 0x029d6a832e1f6fcf, 0x3b07357a40eb0cb2, 0x7277538d7449f8c5,\n             0xc3ade43cc7dfe115, 0x8d282b2936d36b08, 0x5bfc7da1cd73b35d, 0x157698b2f873cddd,\n             0xcd80b79e3557039a, 0x7cd562e6196f8449, 0x3208c7b01905e581, 0xc533ad143a87178a,\n             0x07f729a3590cf562, 0xdddc34badd2bb9d4, 0xcc006019e3cad81b, 0x7de074e5c3792c99,\n             0xb7f0709ae5da71b0, 0x40d62ceae92a0642, 0xe3ca4fac06f01bbb, 0x4013cb0f40d3b35c),\n            (0x2de8709d0c4b8c75, 0x67a2815b159c76d6, 0xa78d70baa98e94c3, 0x2ee1575e5765554c,\n             0x9f06e2cf1d42cad1, 0xabe9ed22448c8751, 0xf25fdaba8ff024ed, 0xa7b9c4cdb7e7e5a7,\n             0x837325bb846b1203, 0xc39d608dbbb30a63, 0xae22198010db94f1, 0xd55e6d7361d8ea44,\n             0x33ed9f53dd3cd03e, 0xfa0e1301f1f2c836, 0x641d400c898dfb9c, 0x370db380e29d73e4,\n             0x872291b925004ed3, 0x8693179ccb120134, 0x03fa20e0a578fe3e, 0x596128c7582e010a,\n             0xf839fcabf56d5062, 0xfa2eec45ff5bd762, 0xd15621babdfe40df, 0xf491f4b4838b07d9,\n             0x896297ba6df32846, 0xe5c47faff3ca165f, 0x1f6ed55abe22aec6, 0x140906c994e0921a,\n             0x7ba8d9b08907e64e, 0x4fd68f6bc3ab1393, 0x305e2d33ae5e4745, 0xa58786e09dcc5946,\n             0x946ac42eea6b0977, 0xbd3dce1d551b917f, 0x32222be5fb62b703, 0x498061848b420cae,\n             0x34e1f5af31ecc1a9, 0x2df0536939974555, 0x6434cd30357e1f11, 0xc70096d5bc67bca2,\n             0x394529ee24e5443d, 0x0ca96439869b64af, 0xce0cfb3b25600996, 0xda050e66a2e716e7,\n             0xf1a95471ea99a597, 0x79343b67fc83b547, 0xfb8e38dde82f5477, 0xa110fb1aa6036bf8,\n             0x742ae1e2640c43d6, 0x1e2d232dbfcc425a, 0xa68367c9c3ee3785, 0x576b5931f57ccd6d,\n             0xe7859af1c271a7a5, 0x6673afd326d83ecf, 0xb7c321a6566b8f53, 0x5660ddeb0ea7c2d6,\n             0x72f7a9b08f73ae4f, 0xb76cf83ba365f1d5, 0xf6ef55f01be84464, 0x6e183523bba44953,\n             0xb51ba6ecf2b1235c, 0x8ebe205354d3ff20, 0x2a50b0ff6f51389c, 0x9d6385b6273a702b,\n             0x4afd85b8293760bc, 0x2dc069afe8bb8acd, 0x93ccae50f52c3cfa, 0x0cbfaac2b9b26255,\n             0x15cedfefcc1e149f, 0x2203d12081461691, 0x224db607c0c5e8c0, 0xaff2ef85ddb7dd6e,\n             0x6f33027b9a2ef4e2, 0x1723066e7ed1f240, 0x64954168b5318148, 0x9708552697cccff6,\n             0x1f46f5a30d49e8a9, 0x64500bb6f8c52be7, 0x82f179823980e7b5, 0xb8741e2789277366,\n             0x931160a3a79c72f4, 0x2fbc2906d8f68b1f, 0xdb5a9c8168b0267f, 0x29f57974d3c91c18,\n             0x5962c1f7811b8d94, 0xbded3fb3d03d9675, 0x63d470f1f240248d, 0x8bc739ad0af66941,\n             0xd36d2fce10c3ac38, 0xa2c4d04690e7595a, 0x9dae51c7ee7a61af, 0xea05bfb85a3f9132,\n             0xae8feb4d07701045, 0xfb32d2ee0df5f6c8, 0xe7c97a5fcc52b5b5, 0x57c763ab1425ced9,\n             0xd6c462534d597273, 0xbc4ce6d0635c711b, 0x01d5c403f08a5566, 0xb6e98c0cc94f44c9,\n             0x23be49f1b92ad6ac, 0x1eaa926f94ca6b49, 0xdaa82559dd8b5e69, 0x3b3c2efd8f59a1f0,\n             0x9b0dc09b105df287, 0x8baeb2c8f24c8323, 0x7b82c906779dd003, 0x719c8ce941cfa5c5,\n             0x6e23e9c4285d4476, 0x1e2624c17d848e4d, 0xcca31de8875b4eb5, 0xc976b511ed9b520f,\n             0x3e23079a3a42eee9, 0x7622596526554deb, 0x376a7a6d3b3c8c52, 0x23af66a632a571d4,\n             0x98040d25e03264b6, 0x170c40866208b799, 0xffd33f1e83844fc2, 0xef2bc945b937f0b8,\n             0xc135a4e74956a0d6, 0xa3b068a2347c00d0, 0xc21f0fa7533b090c, 0x1d995d96e425aff3,\n             0xd79245778c00badb, 0x998cce96ebbd8b53, 0xce4096e29d920183, 0x3b606501109b0e0b,\n             0x9671aaa841cf66fd, 0x33203faabd0ba9bb, 0x7c79e769fd595b7d, 0x212b018943fbeafe,\n             0x858910bfa574331b, 0xee46ead9e6b3d527, 0xe01ec4d45b43e455, 0x42ff698f0e2514da,\n             0x54b8164b5b2806b3, 0xdc1067b4bd182b94, 0xa5e99202f45cb150, 0xb056bd82dc96c359,\n             0xa24a4542ca2d700f, 0xcde15ee05722c5c0, 0xd3759955b32fbdc5, 0x14d90ca7ecc7f2fd,\n             0x387de458d302b9f1, 0x195d1766f4323db5, 0x1498603613f3ae67, 0x14f9db6b884fb7c0,\n             0x91014ea8ce68b503, 0x8ee634945fb5e6c2, 0xfabc822d45022c71, 0x8726993a7da0e5e7,\n             0xcfb9ad11bcb6f32b, 0x843b0d0139e7ed13, 0x28f71e0f558c115f, 0xfd5df9e3297b7d5f,\n             0xe7e824d5c3a45143, 0xfd41017a98d916f9, 0xd695c9f736d2c2c7, 0xb4f67b5e4cb6f459,\n             0xfcbb73cf585b11cd, 0xf1ef34d7cfc3e906, 0x0b126da5fd01c3fc, 0x81ff5a25c8064638,\n             0x8cc47945b5c5eef1, 0x39f25741fa9a1c34, 0x67592bb4df6286f0, 0xf54357a44269cbe8,\n             0xb6d1006818895ce0, 0x06e3b27594551898, 0xdbe5c5367079aaa1, 0xe15f1b4b6b4bd407,\n             0x5117fdba0aa9c8fa, 0xa199bafd125e5053, 0x9a3db014318e6349, 0xb42d281f8956f143,\n             0xceb542ff797e36b0, 0x2cb2b1cbb1e42d77, 0x8ce901c26a95be9c, 0x06dbb13875f165f8,\n             0x8dc2bf2bc6ce04f0, 0x91c6bb67f5f4b99c, 0xd24c2a9392551b92, 0x61fd0cedcb54dd7b,\n             0x47764e4893c5cb3f, 0x82b0553e9fcafce1, 0x353ef87727ffcb08, 0xd4c421a8468ebafa,\n             0xc1486d7d9b670982, 0x0b0aae221e16a5e3, 0x07204d042b1b0d87, 0xf29994032248fc2e,\n             0xdc726bd3b86a60b5, 0x12b8ccf6a9df4f41, 0x886174a9c744fdd0, 0x50d5270a75a24b6d,\n             0x3a06d49a4c65c7d1, 0x4aa1240b6854b5f9, 0x4d6c4a96fd3e3214, 0xb98e740e68d55087,\n             0xac3f53f8430c60c6, 0x232cafe2f229a8ba, 0x3047a49337aefdee, 0x1a11826394386fad,\n             0x0d562995949a85ac, 0x632b8a918391e625, 0x5cd3a4737930dd35, 0xadf5da6c9c33d2e1,\n             0x918925ddb9ff05fc, 0x8c1ef5fe9dd540e9, 0x5834cf83b98ac211, 0x953c033674c73e41,\n             0xc18dc05a7db66a41, 0x1f02081896de1aa5, 0x943e99b71fe333ff, 0x05929070e436e5ec,\n             0x1f3d438a762d34c0, 0xa3056ca7a58c7195, 0xc582ae9e3146ff9c, 0x5d4a2125c27fe328,\n             0x19c55be502092507, 0x6a9dcf3a101cd2d0, 0x4633db2b52d0f3b5, 0xdecf40281385e0d4,\n             0xaf2308941e6ee0e5, 0x40ef3ee6f20ad9e8, 0xe8ca8099bfe762b9, 0x8c47989572c63d37,\n             0xf6c5e1e58c3943e6, 0xc40ad08c502664b9, 0x36a0c64933256c0f, 0x7f4f552215b5bf67,\n             0xcc196cb50410b62f, 0xf7397a765ececa6d, 0xcc137c3a36775e83, 0x8883057cbf0ee828,\n             0xff32849fc05d9c81, 0x4b8972c96fb4f26a, 0x03064c475bbc0d41, 0xea554d16b5882125,\n             0x48bd990f056002a7, 0x9788e121acf125bf, 0x094735033afb526f, 0xd49ca1d73044e933,\n             0xa460fc79bab7c96e, 0x1dd312da1e42329b, 0x4dc7b26303f719ec, 0x97f080c7875be0b5,\n             0x25edf65940efbc27, 0x8314adcd5a09b26b, 0x43d3e1839dcf22af, 0x2a86d88b75792469,\n             0x3cf5bb72707a76e3, 0xe6a0b1c4e6c50329, 0x5ffcbb61b323a730, 0x8245ca1455abe453),\n            (0xa39aebb26364c177, 0xd21431e30117a48b, 0x200ae8e11a9fb12e, 0x84f01ac001ec2149,\n             0x327ee55621a0f4df, 0x57a704366e896f04, 0x913c040757a6e7a0, 0xbf0b9fe91f502985,\n             0x3cda730a20e71b97, 0x3c53647f263d4ffd, 0xe85e190e35896a0c, 0x1076ed3a88803fab,\n             0xeb56440a872cdce8, 0x97a471c7e744a2e7, 0xd1d1a7a51782d3b4, 0x8b7ffd145e31db03,\n             0xf204a9a834037db8, 0x46d2fa20f48bdae4, 0x08477cf66ebbd11c, 0xc8722f42b965dc35,\n             0x8de98b87354010ec, 0x007f84dad4206e41, 0xbf67aefa1d3cd0b4, 0xed651282c910b8f2,\n             0xb7cfe39a95e26dbb, 0xcd30bfa92b0d565b, 0x0192ed23b4769318, 0x234288821f1db144,\n             0xe2d48acb71317b54, 0xdad4a3a0674fec5a, 0x749032b682036959, 0x0abc12d3c080e393,\n             0x1e6b2172fa0ae191, 0xe9698c776bf6b219, 0x9a3a80bd00c31390, 0x29d3da5a5b531bd4,\n             0x9977177cf51d75d2, 0xb5cbcde79404cb56, 0x3f325f5a641e30b8, 0xe4eeb998b16f4a13,\n             0xffdc987747c15957, 0x047ef2e13358aa8a, 0x466463c90bb110dd, 0x713340d1d4824f5c,\n             0xc24a510905419239, 0x490321ad6862974f, 0xc7dc41b130466d7b, 0x6402b8ef43397b11,\n             0x225abc58a9e8ed60, 0x67340115db807af6, 0x43bf53f229945092, 0xb8e8bf1f2df170f0,\n             0x3bcd4f810978f0b0, 0xd84af74b9b01f9ed, 0xecd18323c47a4fd8, 0x93a30da4cd5beaf4,\n             0x07702b422dc5319b, 0x3998a933865aa09a, 0x08f71203845c92dc, 0xed3cb8cd2c08773d,\n             0xeea811cc6b9b4381, 0xa0b6b7d26dd82ab0, 0x03231fbbb7b57527, 0xfa48f7382a9c24fe,\n             0x13dc222ab03ab03d, 0xe55b5087aa23ddfd, 0xaa780415e0713910, 0x7bf004cf60dcaf8e,\n             0xfce7338b4fa11637, 0x059a4dd601a3146a, 0x81985c0adc2cf795, 0xb38e21ddc76007f7,\n             0xaf6e71a317393c73, 0x2c08417298afe2d0, 0x1399f92e1ffa3ba1, 0x3303fd6caad78942,\n             0x8669826536ca7e5e, 0xb9d464985ce4f171, 0x946ffa93fcaa54c6, 0x16387bdcce074149,\n             0x9c1de4c2bc278568, 0x360c30158fce90b9, 0x476972d6cba0a167, 0x9b089a0013d72462,\n             0x28df7ddf79caf10f, 0x1627685f6aae3340, 0x34efcdd66d148b9d, 0xd62ad5527548b30f,\n             0xf6e946be282a0d7b, 0x21661e1c039e7aa7, 0x5e6ed4638c9e311c, 0x93c65243924b6be8,\n             0x96ad58ca88c4a214, 0x802f728438363a9e, 0x3e57d4ef5d3b0e69, 0x410209e211903f3e,\n             0x8d8933ded72fe266, 0xa99548d311a78dc6, 0xb6b1a745bd696ba6, 0x6b1bcaed2387143a,\n             0x6fb9500a7118d183, 0x07380be8931b7bd3, 0x95298d9d3e64b1db, 0x0732918135cc6329,\n             0x345e097d088f25f4, 0x173afc52e212d294, 0xc46146f92cd9c41d, 0x88787984e33c3bb9,\n             0x760e61d0fca8c69e, 0xae4c02ca04604795, 0x2407dd5725403d3b, 0xbd656c1a2fc5f0ee,\n             0x8ab889113387e6f2, 0x7e25683493ce6ea4, 0x8147b6821387e427, 0xe6d9c5e310423fbb,\n             0xa97be07e787e4682, 0x96834ce5c841dd03, 0x0dcbcea94589bbd0, 0xab4bf901ef526c8d,\n             0x1ec6a1d473d4c76d, 0x74ea01c97649aa44, 0x90457f7beac3c86c, 0xa5f0d999e4a41cae,\n             0x41272a55cb08bb0b, 0x0c6e93c7fc785783, 0x477b804e392703dc, 0x88245b0345830c38,\n             0xda7e9980b2070805, 0x12d8b82ffc3f0ca2, 0x10a9124b2c4a7b57, 0x454626fa89395f11,\n             0xf57d30ac46d8325a, 0x6ffcaac42e29897a, 0x0f66ef9826a1155d, 0x1f23ebe7791874dc,\n             0xb03de53538f4456f, 0x662f5b71aa885d34, 0x2e4f6b95f42c2ba5, 0xb1d6d7dac9eed523,\n             0xca1f808374c1b0f2, 0x141100e9f48b4442, 0x1f9755ae68b2e203, 0x426302fd4170beab,\n             0xd4c99a92e8fc9ff4, 0x8cceef176eaff95a, 0xdfa4dbeb60a196f7, 0xc492bf921c4d0b56,\n             0x3d2a0ef9319d889b, 0x6cbcc10e809d64e2, 0x4075a1737a31f11f, 0x14f0bb5e26117338,\n             0x4a8ccd8e06f358ac, 0x2ae0da46b71219a4, 0xb932b5ad6cd6be5b, 0x7d4f58e5964358bc,\n             0xf472fb8bac9eafc7, 0x071ce6f706a4b2a1, 0xcf62be3a925e40b4, 0xe92fc78007c2dd87,\n             0xef788f99d4778c75, 0x14634c7ab372821c, 0xa8c0e16d3e86e871, 0xbd25beb0ee6fce26,\n             0xb40d7c8d41e3bd16, 0xfb5f3bd4c90c2a6b, 0x6119ada677d21ef8, 0x364e5995f95ff324,\n             0x38a2042705a5eac5, 0x1b2d59636382c950, 0x4a41e6c3e0d5f2f7, 0x82dc61c3d870e1f1,\n             0x1478bb62ea666922, 0x1cda3ca10f383751, 0x9ffb08c6fe63b9e1, 0x334b79b5cd42155a,\n             0xa4d1dee5e93626a0, 0xe01a64fb94281d0b, 0x36637777b84ca58a, 0x8e495381d641c5e8,\n             0x6f418314a0208848, 0x05d1f46052f86c92, 0x134f2aad2a8ad534, 0x9a5689b80e95ee3f,\n             0x0c1e855c26438d29, 0x9133a62d03bbda55, 0x69f8e3b9de94e397, 0x17652a75cba6601a,\n             0x95d85410337ae05c, 0xc53c186711af8978, 0xd7f7136d82d9bdd4, 0x9bd2d1d7f41c54f9,\n             0x74053b82e2bb0d39, 0x5d944dd003d50ae2, 0x7d893442cb6260fc, 0xfcd359ec15b4f2cc,\n             0x9f8c353469cfe051, 0xa0a91ca4559167a0, 0x8930acc90cc579eb, 0xa09008ca09eb9f34,\n             0xfa2061c9d34bac9d, 0xa4ace78d98b48d59, 0xfb4f2e12e0642d0f, 0x349dab42c255fc78,\n             0xa2350d1e7b1efbfe, 0x091987183a0f74ad, 0x13d0b75b5a868748, 0x7727d38da66dcc65,\n             0xc9f325c6c91b94cc, 0xe705236b98f825b3, 0xefb41d0276a0e451, 0xd64528df37b25e89,\n             0x2bf0833742081229, 0xd90d0f249765bf55, 0xde868ff2dee90192, 0xd46f31953624b60a,\n             0xe3d8705c86040eae, 0xa2f76fc5f3463469, 0xb3ed829bb7c6e8c6, 0x1468e17c5c273f81,\n             0x474fbc6e70b1dd24, 0xa0c069341b3982a4, 0x4cee8fda61742293, 0x0bbe9549357fd223,\n             0xe2403c8c806fc37c, 0x726954250d9b5ff6, 0xe2ceca8aa85a00e0, 0x45a6396d363a41f5,\n             0x26c53565a7ed97df, 0xbf143b13953fdfc5, 0x49d820a6c053aa36, 0xc00fb43d2fa790bc,\n             0x5c807ada71a8469b, 0xcb37e60f3820c2db, 0x09e3053a2e74c5d6, 0xcf7bc11db6157909,\n             0xc83d07021368f97d, 0x81cb75a62bf1a82d, 0xb458c2a811dd09d5, 0xba63a37c2acf7ecd,\n             0x8ec3fbc2a542b5df, 0x0b364530a6415a90, 0x5c9ac35f3de76cdc, 0x483490ca341c158e,\n             0xfa25b55d70ec5989, 0x7913285e265d759f, 0x4981e139498a459c, 0xa6f44be3326b011f,\n             0xc110247c5924a7bd, 0x57d146b0c58adf5b, 0x44fc171395618896, 0xaf3807509696818d,\n             0xbe6e00d29fccf989, 0xb4ed0b4f1ee28ab5, 0x76c5dd71ea224564, 0x0a779db19af5bdf4),\n            (0x8270c58a7e3ccc55, 0xc233ac342fb4683f, 0xe224bda9638323b4, 0xe6d6678a5de3e25f,\n             0x37bb200b60e23781, 0x849fca9f7d38543a, 0xaecb4e719304d7a7, 0xe490f2ad25483714,\n             0xb2499c3485fc371b, 0x14c1985993203504, 0x6c51cb9659a5600a, 0xbb469328f84f9952,\n             0x7b1a013c71ec803c, 0x60c11789875c9c69, 0xaff39650732f8c3b, 0x90faf13bbd38b9a5,\n             0x0b46128962ba15e4, 0xf68a4a0b000d6cff, 0x4fb2ab2268f65187, 0x32412727f8b48061,\n             0xa05dc13c222c0f9d, 0x4adcfd5a2b8ce496, 0xb6708b3c0b9d8e50, 0x0dae5dfc7f27dcb9,\n             0xc2fefe7e8fcd4d37, 0x1575361be7b86c0c, 0x8457de191a7cc0d7, 0xfe86b35ff0b4b3b8,\n             0x920f38ae0544cd78, 0x124c97d18c96e73e, 0xc97a4e9d87f9c161, 0x9dba60028cf73da6,\n             0xe0b474b32cda577a, 0x2a95fd06fddfd532, 0x7d1465d4712cf98f, 0x301c0e8633f8ccdb,\n             0x05dba07c0fdf77cf, 0x7cc0bf8954b98a65, 0x4680b299c79fb341, 0x0cf5e7b4371dff6d,\n             0x5f1994caafba1e98, 0xe6645b0f1f440fbd, 0x2c8c94ee6470278f, 0x8f02fd7fbb2e40da,\n             0xe1b4d870b7bdf989, 0x717e1abb3b396de0, 0x389a1bdab7fdbb46, 0x76d0ffccf4e8f87e,\n             0xbe865038f9273587, 0xd7b5d492710db876, 0x3d9e45e8cddf25d1, 0xfb53731d6da261dc,\n             0xb1868b7a7de2372f, 0x4d597e60e87d884b, 0x46765a237229e195, 0x52291ce3db0a6b10,\n             0xbe9776b61721621b, 0x2766d780d6e62d98, 0x06e32e301143595f, 0x6544f519e588fa41,\n             0xca0daa6ab502b0ed, 0x7b3cf05dc78325ac, 0xcc3fd362e27263a9, 0x4b081bd3fb72735a,\n             0xc1110390963899bb, 0xf9b22c0aa55615d1, 0xd0def6aedb0545f1, 0x178be8edf572392b,\n             0x21d51fab649ff5bb, 0x0b5f7bb7d6f88aee, 0x693016779980c5ee, 0x6588cff8c739c8fd,\n             0x809339bba03af0c8, 0x9ff93a811b9f7782, 0xda2175316e787284, 0x8fe3a08408ce2329,\n             0x315241be048e6109, 0x5ee4b727ace3dad6, 0x9d0ebd6ce0263eda, 0x5aea1f8f61deee48,\n             0xf84c8757b784d393, 0xd53d112cd51feee3, 0xa992215443da96eb, 0xcceea913e4624064,\n             0xdca87aa21cf73c65, 0xc9d9033925116801, 0x7ee41bd62b871d38, 0xd90195c9fb7f603f,\n             0x297bf0ab2e2d641c, 0x44ea3afe613273e6, 0xd1e6789a6871b142, 0x18b3fa9d58346524,\n             0x7c793f07ee132a6b, 0x5bf6a805f23390b6, 0x8741a6b72f843ac4, 0x14e3e36aa8c8af74,\n             0xca46eead220e18b5, 0xf258fcff744b8239, 0xf9b9b6fcdd4aa1db, 0xffa98614b89f9d81,\n             0x803bd8f64d6576e3, 0x0fc5744d6039e100, 0x0b65224fce77ef5f, 0x851cd3141dbd8bd3,\n             0xc1bf2a205454f641, 0xca96208d50268b84, 0x39fe3e903b0dfca0, 0x7508555fbf6fe257,\n             0xa1e4472a60b5308c, 0x1f9916514a4611c7, 0x3ebe28bc7e7d6599, 0x1eab12c00e8a7d02,\n             0x8e3c97a493b2ef08, 0xcf441f3af50e8795, 0x78211ed51d3aa9a4, 0xf151b03024a78086,\n             0x719048537ddf8857, 0x08806ac4fe924b67, 0xf385b13e925b6401, 0x39d8631eeb975904,\n             0x9f6c76c2bae962d6, 0xa237a746297a56fc, 0xa94b7b9448318d1d, 0x979e9c1a90ea1e42,\n             0x4873af3c9027f3a8, 0xa083d55867da74a1, 0x81eb8297ebb3dbd1, 0x2ba416c7d37b42dd,\n             0xf5acc02c973baa7c, 0xa048c19d62c58d08, 0xd42cad12a3dc7030, 0x6e5667f26d6f05a5,\n             0x8b634592552ba1c1, 0xd4b3240e6e18672d, 0x35ad3954189666f5, 0x8e7738d435890db0,\n             0xf4e616bcf8e4e01b, 0xffd079a62bc3193e, 0x2b8955d4cdd477a6, 0xc7991845b81470ea,\n             0x4db8a889fef2fd23, 0x9aae7477ab6e9c92, 0x68ffdd11ed2f3988, 0x122454d2994c1f20,\n             0x9fd71180a2b7db24, 0xc3e5b812bb1e1c69, 0xd98d1dd83a49f119, 0x24e1a5c376f4442b,\n             0x9c6e7e1c316ed43a, 0xa50f3dff982047e5, 0x1b008dd50f89be39, 0xf7f490e059a1b6ef,\n             0x3fc2d7724c276c96, 0x19b92ad2b351118c, 0x03941a4d980fa379, 0x0dcc1db6393e5ae3,\n             0xef17fd708a0c428e, 0xe7b3603646b6889e, 0x3776ec163795447c, 0xdbe8dfec2fa2b2c3,\n             0xf6a1d2e719d2bac4, 0x05cce8208c359d8c, 0x664f9ab99a6a8281, 0x0e318802fc9d8ca2,\n             0x31b00c7761fd6ff5, 0xac2736c0bbd63ada, 0x3feb3e779c9b394b, 0x33c331f81c194e0a,\n             0xc0e1fad94915b0e8, 0xf1e778b4a953281c, 0x85c15d6b8a33e720, 0x8d1e7d0872e75ada,\n             0x5bdad425f0a52ef1, 0x6ee76541694a695c, 0xdf7328da8f3d5979, 0x60068f9a89907a16,\n             0x70280f5bbdc25287, 0xf3ad4f4e96e5f957, 0x76939a656087de97, 0xc840dd22eb2bc374,\n             0x53a484fcb09c498f, 0x604a4d01983cad39, 0x9a45d55ca6c551b9, 0xb72eefc7c9778b82,\n             0x4b957813ae06cccc, 0xf8e2a4f7e9400487, 0x277cf9aeaa2a51f3, 0x54dc111e6993141d,\n             0x003583b892c6a1dc, 0x3bdeaa04d0108724, 0x010c64c7c6530e36, 0xed7ed3b736208e3a,\n             0x846709ea1d334394, 0x794b3c5d9ca1a28b, 0xb55bf8831b4c1f8d, 0x73a632dbf724450c,\n             0xa783618e5edd45a2, 0x245209389ccdda11, 0x26ff76e28bcd5d77, 0x59c887ec8c6a5e9c,\n             0xb067867685f842be, 0xe0195a498885bbaa, 0xf00dbf801a1269d2, 0xec7f6ce6327cd328,\n             0x2971c4c0d4c61b48, 0x4a784da45ba69e1d, 0x8c4a5a3d2b8769ab, 0x53b9f81e78430f85,\n             0xcd8ef9c95d91a296, 0x81ad8a98131c14cb, 0x51b8aafc0c630a32, 0xf920b5cf3d7b6038,\n             0xd366018f6f9c074b, 0xd7b38fedb9576f7e, 0xaaa59aa8b435a722, 0x80cafdf61b69ddff,\n             0xbe142df6c9259793, 0x0918a3d95392401c, 0x297c19a3daffb8be, 0xd025aa11b15233ad,\n             0xf31db0f5e00a86fb, 0x5d66cb2aebd0952b, 0xf91980c469cf031c, 0x8e70d03da0149c0e,\n             0xb6297a9d0c95e7d8, 0x808242de858c00ab, 0x1b41e22654cf5bc7, 0xc83263b4994f2fd2,\n             0xf8d33416c21bd1fe, 0xba379dcd4d10a6e3, 0x404047126f7cbaa3, 0xd0e59e70f4b84cc5,\n             0x4f3f2291036c054d, 0x1be665cd0e1abdc3, 0xb2f216aaa3614021, 0x01daad23cf8fa18d,\n             0x99b0ae860e2143ab, 0x4b539c106ad94853, 0x251e2bf75a09d46f, 0x8a91b11368a439d9,\n             0xb906fb7d818f49e7, 0xe40b0441591e5d64, 0x3b46601a788e9739, 0x2b8a0d54887dd7df,\n             0x3f1a40fa2b72c27f, 0xff06eaed97ba852b, 0xc363936e8bc3c0c1, 0x20a642e5031f63ab,\n             0xe3d7257463fec615, 0xe0d30793ada218ef, 0x2bd10a033c03ea2c, 0x203d7bda407c6331,\n             0xc55d3294076aa056, 0xbd4783ee0e0550e7, 0xeba30c0be3421cf1, 0xf0e36e94dfed4aae),\n            (0xca709918d4674db7, 0x9980136f76ad2016, 0xf3a8c0fe541f8b7e, 0xeeb110d70a4fac66,\n             0xf0b7a37877b3fa79, 0xf68c56de204a3920, 0x371206442c474bd1, 0xcb4c1c76b6355455,\n             0x59f758f5888db255, 0x0450d8d7f031e83a, 0x636f2b97b26a4f28, 0xee409bdc8e1b216d,\n             0x664740fabbe6cc4e, 0x76112ab97739204b, 0xdd38f6d09441d1dc, 0xd8bbc56b5ac87b72,\n             0x95cc221e671426e2, 0x974d2dedb037d072, 0x0810359b99aa43fa, 0xfb720030465a43d0,\n             0x4779ae4c942bb72e, 0xae22a12d2fad47c9, 0x04bd4be70a14ba4b, 0x1c67336c6e747bf8,\n             0xef0b5129fbf0d91d, 0xcb272425f4532b4a, 0x6a9e7887aa2b28d5, 0x1cbde852fae539cb,\n             0xb6ba3014a48647a5, 0x2687534ce4ee995f, 0x8810993fe0da779e, 0xebc20b97e29da1c1,\n             0x434d16e251a6b511, 0xc897a94a36ade6da, 0x09446b260794d068, 0xa63479adc3e71665,\n             0x36d3a7d7a92fbf1b, 0x48f1fafe31207be2, 0xe9732085c870e7b2, 0xd370294e1c71bae9,\n             0xf68160665e136f11, 0x67e82747df4d3084, 0x5902f43d20e9d1b0, 0x44c625483922fd5a,\n             0x5deada8439a78477, 0x17fcdb43729b4540, 0x4ffca6de1ca9ccf3, 0x944068a19d9aae66,\n             0x61eefdd640d12e06, 0xa8e7a96f92e6d53c, 0x90df02a0a3d70093, 0xfe5fee57dab1fdca,\n             0x698fa9f771dd0cbe, 0xd7d0403468ed71cf, 0x25b3da712d162b09, 0xdae0b97c7c28b614,\n             0xab8a0fc6b0325ddf, 0x0882e099428eaeab, 0x0aa1274dc32fc3a3, 0x2572e9c16486e5cc,\n             0x86c4ff6847db4659, 0x090fad6e12c39cf5, 0xa95de69ca84295cd, 0x5322b70f505d1678,\n             0x81ed84a8c416ad36, 0xcb87099698e8e46c, 0x822921e3333ec626, 0x51d4aa2e9b15ccd6,\n             0x8eea33fd0ffc7029, 0x69b7daaaf931bd18, 0xe400a4f9a8eb6041, 0xad11605ead5ab4ae,\n             0xd1d758873e7922c2, 0x18f4d2f70ed5640d, 0x3f06ca69722caf2c, 0x0aa52dbf9f4b326f,\n             0xda194bd52d15b2ed, 0x7674f798116a740d, 0x114482a29bf79877, 0xb8cc27bd1a2c5443,\n             0xda881e3161f17766, 0x0476035d52ad265c, 0x9e2309517ef3960d, 0xbec051a696e80916,\n             0x2094c117a2cb479d, 0xcb32cc3a27de99b2, 0x7536f87bea199279, 0xe1eebba1e9ed7e5f,\n             0x0cd60c97df496a00, 0x5cefeaac20377484, 0x20c448885596617f, 0xaa2d66e96249b7fb,\n             0x9fe4156fb3eeb3b9, 0x9eb8f2626d98faf2, 0xb6203d5b279d7a5c, 0x571b2acb59983fa6,\n             0x447881c2b4821687, 0x4c8f8fd7a37a163d, 0x2c488770b76a3036, 0x11a557733d626434,\n             0xfd32b63b973808fd, 0xcb795e1a42edbe35, 0xda4956d690564ddc, 0xa92a770fd031f2f6,\n             0x42ac68c41c86e6da, 0xc77eb52d0f755349, 0x7b92a7c2e754c636, 0xe22a33c034f1134e,\n             0x745cc33d9ab88f48, 0xdb9ca59ca276ed50, 0xd54d36604533ed2b, 0x6268fba366575684,\n             0x8c4a29ed9cae0972, 0xbc9574d774ec06cc, 0x52d2c4467ef96472, 0xce1547ef547453bb,\n             0x824c29126ffbfc29, 0x9871802783a606da, 0x3d3fc1e9dab2d847, 0xb5e32fbe1dddfb99,\n             0x430bbf105deba6cd, 0x1d47118c78b5a2f8, 0x3d21b37cb3de784e, 0xba6d7b79311d35cf,\n             0xff7cf77d29d2eae4, 0x3c1022bc81ca4e18, 0x7682704b51b97a04, 0x08346c16b460c9b3,\n             0x4fbf6e046715a9fc, 0x1630ab25ca3a14ce, 0xf16ec670d37298f8, 0x978a30e8fa599bd3,\n             0x9f1dda6a049340fd, 0x8a97c7fb09f3df94, 0x1eeb23cef56f51e3, 0x0cfd66798867001c,\n             0xba95dc91d8ec7ce9, 0x4a209b71ec0175a6, 0xdd1835f85d96ac71, 0x4ffe327fd6c47d36,\n             0xa7d28df2f4da0443, 0x02d92a90899ea6e5, 0x3c14a80d8958bd30, 0x8d35946880cf6958,\n             0x9440dc0d6b24f39e, 0xade0f776ab78c03e, 0x5e81d3fd307139ce, 0x36412afff7bc4a96,\n             0xb7a69cc6fb82ca0d, 0x2e95055f61b6dca8, 0x8e06f4373c4ea917, 0x1f25aa32fe4acb35,\n             0xe1cb358cbfdb8981, 0xc6d073de4ec88b6e, 0xb4c023525078286a, 0x4a9e91e56b096795,\n             0x45fcc4aa02107997, 0xaf07e20f66a17c3e, 0x66318ed34c34de17, 0xf9ef098225a6d28e,\n             0x819649e651114d9b, 0x5337ee1e912524e5, 0x0697beb41f1c23c0, 0x41c57aa9e77b6be2,\n             0x5825b9601bee8458, 0x6e7a4efae63a6d2d, 0x9e56110b55f3854c, 0x44c8e4b83508dd44,\n             0xef3544b71e68ac53, 0xc1fb80eff7c243ce, 0x7eb8208e0d5121a7, 0xee4249354859975a,\n             0x39178e5512230967, 0xc4838a093cad664d, 0xf86d1c00090c9351, 0x87b5debd410430bb,\n             0x7b65756fabe5b840, 0x4f20b39554bef6d4, 0x75d3811e0d0cc031, 0x4d068d625ce7fbb7,\n             0xb16b5316544547c3, 0x38716bd7b3289406, 0x654d6350745b58e2, 0xf6e28b7a70eb055f,\n             0xd1690380fb174b82, 0xfe9ddc9417eb2325, 0x988b4c4848605f30, 0xa5bb93f7e6fe9f01,\n             0x384df62d394ad805, 0x879b038b5b1b64e5, 0xef6faa6b5a1abe20, 0xb9a43eae5da71a25,\n             0xc363b4e94dc22e2d, 0x924f761510841cfa, 0xe4efbbbb942e34a2, 0x49f242cbb35c9cb1,\n             0x1978444a67080892, 0x7dae453cfd96587e, 0x7579c6ffafc8962a, 0xa6f9bf1beae0e677,\n             0x6d48cfad33401238, 0x8a8c3e6dc3f8c98f, 0x5ba1dc6dd7024014, 0x7a5d3ecc08819c56,\n             0x211afc4f71c9acbd, 0x119a330e8277350e, 0x81f2371e54173463, 0x02d4cc9b04c1ee60,\n             0xa4d3ad7adae50672, 0x2f8bc9dec9175da6, 0xdb34e18fafdd2b69, 0x086542d87c42dfef,\n             0xd9d6c5fef0cd9ea2, 0x5cd8c313d763e88a, 0xd719d48ac8a6cf91, 0xe07b3b116137ccc5,\n             0x8f1418b3f4c772a9, 0xded46f5faf6d817c, 0xd19882dedce50a76, 0x354312c092efd6c9,\n             0xc25233908865480c, 0xab9121670176e53a, 0x3b77b1d301a0748f, 0xc3dfbf827f3f0be8,\n             0x1d3729daaa2fa930, 0x97d250db498cf6e0, 0xea07abedf61c84af, 0x67b956aff567c13c,\n             0x35f362e22495673a, 0x61f90020eddbe016, 0xbc18aacfed843c1c, 0x34aaf990489c15eb,\n             0xc3f01f91389fc1c5, 0x86136ea3ffbd3fe5, 0x7ccd2751d0998e59, 0x052c2a6ad31edf95,\n             0x226a9c8d19cb55ff, 0xf70af1b692cc3335, 0x9737f6a8fc6a8715, 0xd32a1f7140233fb3,\n             0x874614619540983a, 0xf7dbcfb8ba5216d7, 0x965d4f63a70b2435, 0xfee9bf29fcb54dec,\n             0x4d30e81cf590128f, 0xffe049b9465da940, 0xe35d7f2c40c6b2f4, 0xda583eefb727d5e9,\n             0x7e12e0ee7e7ac524, 0x5a640a83a0fbc881, 0xe88b1e190a281119, 0x8bf16b7a31711a04,\n             0x3936bfd17c458f2e, 0x60dae6795ffe4002, 0xb3aa4c8dedff59c5, 0x422fa605da7cc141),\n            (0xc804edee57e3de5f, 0x4ff50140ec29112c, 0xe63dda807dfa6b91, 0xaf720da490dc3139,\n             0xb842a003d00c454b, 0x55339a0568c0f9c4, 0x140e1607ec6074fc, 0xcb926943a01f2b4d,\n             0xda4a1128ca62e533, 0xcf464699adba7092, 0x6132af6bbef58921, 0xfd0b9f20f502151a,\n             0x921b9fe41b412cc3, 0xdb1a2c2b18508a4f, 0x12fc6b1236404302, 0x1ab16a5fe8ce0984,\n             0x1ab4b92f414e0a20, 0xdc6f0217d9a8ba62, 0xa3c7f39d4ce3e9d5, 0x3201a021500d3ddd,\n             0x0d9e08a057012c1d, 0x896dd8376459edb7, 0xe65dee0701f0616e, 0xed844879e823d1b2,\n             0x9904183f320cba38, 0x2e3784984fd94848, 0x6054e806984b2147, 0xe25866894e587f3a,\n             0x6cbc38c6c4c996cb, 0xcdc7d97817b7efbe, 0x91b62b80e4e1a20c, 0xf0e30aa575d8d502,\n             0xbb5206febb15d2f8, 0x90e5f7f88f8fd09c, 0xb43d69c9f8286d1f, 0xeb1888abe773878b,\n             0xc54dabada7f18a98, 0x95cff74bcb63f360, 0xbd0a7df239e60df4, 0x03ce04abc7c60e85,\n             0xf3542fea4a20937a, 0xb633bdd33714f428, 0x2d557009aa025a9a, 0x4cb2310795a4874b,\n             0x2a279056883a7dcd, 0x0b7b7c24797330eb, 0x14ee9b6c3ecb24a8, 0x7a0eb7a4630173fd,\n             0x35f82776fd33a403, 0x43dd344b21a8090d, 0x601708befa9bf889, 0x01a9c7307c41355d,\n             0xf0db0602d45783c4, 0x33c9b46ca768f0d7, 0x5c0a089550da90d2, 0xe571d6ffd0619f33,\n             0x8fee54b472c2bb31, 0xe2025828c56c5807, 0xba0adbc1810c033c, 0x6f4fb2682c3bd0da,\n             0xfa2023a98ad18f14, 0xe093cbd0a6777072, 0x2cb96c03f45d6633, 0x79fd8178e3132b6c,\n             0x8bcc3658b4fd3c4b, 0xf6a6551813b55d1a, 0xfbae8f669f4a17ff, 0x4052992e22dd64f4,\n             0xf5f83bc727df97fb, 0xbacf24db23f04bcf, 0x9c543017354f4e82, 0x7828655719074c90,\n             0x078daa9b312a9149, 0xe04eb974c360acaf, 0x8e9c9a5e699e18a9, 0x5a3ffacaabe2742c,\n             0xb1a3e7414a3e97f7, 0x339aecdfeeacc924, 0xe7c8fa89a6d09c97, 0x64bfa5ed3f11a374,\n             0x302f07f185d843a7, 0x34cea7fe17078249, 0xdec5333351d7f552, 0xd809bedbfe2f8baf,\n             0x42b7b8aa7284b21e, 0x6f0287a4f75f6916, 0xea6a4a3bf700d39e, 0x1a3543c4bafa07ab,\n             0xfacf571bb9843617, 0xe35f4337b70142db, 0xb0c1a0c3b85490d9, 0xa6684240522f30a5,\n             0xb1e3c0817eef50f6, 0x87092c229d553a71, 0xf938eb0a52136c6e, 0x7e586080388dc383,\n             0x209d388c4769f544, 0x70e8ad81a712d6c0, 0x18e618db5b241cad, 0xd47f6f3785a190db,\n             0xee33d326db697592, 0xc0133b2c8ab7019d, 0x6212ce9b37597b36, 0x59c94fd8c8ac07b3,\n             0xb75580e20b400235, 0x846f814c92f4db76, 0x52b706f3323f668d, 0x284ccd1e71a1070f,\n             0x42de1e1e7e62e08d, 0xadce75d37937c9f5, 0xf27015671ece558a, 0x22412a56a3559ab9,\n             0xff13d8bbbb1c91cd, 0x83cffaded5dfd327, 0x6656726282256c66, 0xe7f5e6e657da4e9a,\n             0x6dc35a67254252b1, 0x7a1cc8aed3e8b5f5, 0xfb7fe9759517ea1c, 0x35db3f21e8ac587a,\n             0x0a3b32c2b62222c5, 0x86ebc76d20013362, 0xfd22033c16698156, 0x0b7d6878e5d5261f,\n             0x6cb86aab8cade5cc, 0x0186e38a4b93e756, 0x7234ca42a899e20f, 0x2576c2e71a4161e3,\n             0xf8cfdcbdb0c32022, 0xe50a6c345c90f816, 0x4cf69b6e26560f5a, 0xf035d71fb1fe25df,\n             0x39ff0a390ce3f7d4, 0x21928751f4b2140b, 0x63eb9be9cb376caa, 0x61134c6a42f7ff9c,\n             0x5fac915dec874d4a, 0x6cd454e00e9b1b8e, 0xbbad6f4969b3cde4, 0xe781e328c7752927,\n             0x6d543d918ed8ca4d, 0x44b07dff09639568, 0xd3292eb7aae8da20, 0xb548fc70f27ee3ee,\n             0x4ea744f31c981ffc, 0xb979b36fd349e688, 0xc2be28758b0cff1e, 0x4234e72b69160928,\n             0x7525bcc40e3da71c, 0xfae8b088157cd9f0, 0xcd520ef009b862ed, 0x9c684b3206b6e201,\n             0x03a18c124be050e3, 0x8d8d97703dfcd3bb, 0xe1e5128526a918e3, 0x56b1f91bb411b2a3,\n             0xcf129b1be917e949, 0x0aa8968474daefd5, 0xe4b745ada29e731c, 0xd7913c263b25f9a0,\n             0x2d3aaea5dfd84c2f, 0x6cecfd0fce3f273d, 0xd0e5d746b7ab1e82, 0x8d6922bad25001d2,\n             0x97806cc1f157a8f5, 0x26fec2eba7e1b1c9, 0x8c85ee20906a06da, 0xdde12accc358d2f3,\n             0x1e20ed16b8bc5068, 0x01ababa4030758d8, 0xa06f4d1dd75ca9dd, 0xee949588a565b1e9,\n             0x4762bea3bd18edd3, 0x2dba9476212321c3, 0x5a316dfc9118f020, 0x1bec8ace987e46a4,\n             0xab885c69038e875b, 0xa95354d1623ae9b5, 0x95e1cc46c42a9340, 0xa2f839edf76fa7ee,\n             0x2c28d9c8a1db5e7c, 0x948928363f5f90f0, 0x0757fc1e26b6e2b2, 0xf245230b34db888f,\n             0x683f1c2c27e5beb7, 0x3b85f46940197af6, 0x3e46b40a112b6b83, 0x864e7625a88e3ca0,\n             0x7e5984364c466cb2, 0xa9ad10857bd17810, 0xbfadb9f7e045b769, 0xecb502cb00da43d7,\n             0x11e6f043047f54b6, 0x3862f07c4db0abfd, 0xdec212b4ddb23f80, 0x3605c85c47436ecd,\n             0x8b37c80fa80924a4, 0x39c67e11dabeded3, 0x853da3f47532d9d7, 0x2ddac5f96a7000b7,\n             0xc7fe0adfee2a4902, 0x8742e55ab323278a, 0xe2d46fc06d2b72c1, 0x507109efce3767c9,\n             0xa97fa06d5f13c0b5, 0x54d679e5c4b1f6ad, 0xfc26d9ae2c2dc8d6, 0x1c48720ed2d273da,\n             0xa6d6cc35fd24bb9f, 0x237ab4e9ce169be2, 0x53c673e876aa9ceb, 0xa1f5c6a5ee086b6b,\n             0xc3f023805e00b1f4, 0xd68c5aed5c25f8b4, 0xaf88e48d10ec6b61, 0x9ba8b3acf4363c77,\n             0xe1c3bee2560b539b, 0x6381dfb23b78c85d, 0xbe60935c0c68ab71, 0x7247bb4def641456,\n             0xdfd58d5150a6311b, 0xabee54ceccaef468, 0x0b6f4093cef10425, 0xb7b0e8756bd4ef63,\n             0xcfa6156796ce41fe, 0x1640f376d4388478, 0x5b1e8fc28d2a3140, 0x1b2f4ebabb48fe0d,\n             0x50ecad92253d6004, 0xb056dd5ae2bb9a7c, 0x5b7b150bbcc8ced2, 0x2892bbc96a6f54bb,\n             0xfceae6a3aabbd5ab, 0xa4edb52f67c7f721, 0xefc68181d34ce47a, 0x652a946e177a00fc,\n             0x135d154cd28cd2ec, 0xd81321b19eb95fc1, 0xb1123d17eff6c815, 0x10ec163ce6162837,\n             0xd2a8c3a8ddf49b84, 0xb44db8f3396898b8, 0x5cb537c9435dc2cb, 0x6adf1bb4555aa69b,\n             0x2b2b34937603f245, 0x366dc6a366619401, 0x12cb56e84ac63b8f, 0x2cb7bebd22da51a4,\n             0x76c56f58f680110d, 0xf966c92840b3c553, 0x2150fb6ef409243b, 0x1694094dda05a74b,\n             0xec5140ad14ef9474, 0x8ccabec8d608df75, 0x098eb7ef7572439e, 0x4f016099a5413f65),\n            (0xac60f33fef14e9a3, 0x2f7af0c548d5d036, 0xf75513473f00e14d, 0x393d9c31c0ecc664,\n             0x541e6099be2c4250, 0xdd9ea65ecd24e89d, 0xbc4b9108dd636534, 0x0574bef5752184ae,\n             0x72047a70e457b144, 0x456971aa2e9b4c68, 0x76749a98130b3fa0, 0x59292b65b3ad70a0,\n             0x96115ef618a0ea66, 0xbb70457711491b83, 0xc88ab40225a68029, 0xaa2816536bff98e6,\n             0x133fd3e4b42d3348, 0xeef1e04bb4a0c33a, 0x0c78ccb7a380e639, 0x57a6f47e925f7344,\n             0xfe2522a34cc06337, 0xc05ebb3ae14d1226, 0x58e6ec70e09e8418, 0x3c6dc7f848ebf1fa,\n             0x434b1fab03d094e6, 0xfc16d9b69f2ff1f1, 0xe8f644b2cb3c0be4, 0xed6e470a5bc386e0,\n             0xf2d524607afee41d, 0xd9e3a5ce625d3d84, 0x445af03de29f10a9, 0x515653bb5b17f900,\n             0x71a7ad14d7aa923e, 0xcfbcf6978d5d2aa0, 0x60f45e2204bfcdf8, 0x80a33f06a503996d,\n             0x2bfa8a71a020e61c, 0xfde9f1eb96e0e04a, 0x853369f528e68e6c, 0x2ce1daff6bda0093,\n             0x59c7554e279660ec, 0x46d0639b0960b914, 0xfc43f98b728b5e59, 0xfad268f8ac898e31,\n             0x9c225381d33d7da9, 0x8b4e9f2dd3b81b58, 0x0559eb72e0f87165, 0xa3cd793c7555cdc9,\n             0x0094ef30619429e0, 0x93db15cec13296eb, 0x73ef37fe1a9afa57, 0x90de384d4bbb7a9f,\n             0x0d1dfc879a679c27, 0x2e2e9e076f982be0, 0x4095196bab4436eb, 0x938e974569c10ff4,\n             0x16d1af8aab7cff8d, 0xa8a6249c60d53936, 0xa239c82cd46a5ca1, 0x94f362854b20f768,\n             0xbd67e627ca78cbd3, 0xb5884328f108eb21, 0xf2262141e3c75b3b, 0x0b276c57ab60a874,\n             0x6fa8f31190b90807, 0xb0af77f3fd7d1cf8, 0xd20e5dc7232c7a9c, 0xcb8e09ab7a3c99cb,\n             0x8e9073f0ecef2971, 0xa57e01437d524f22, 0xabe3fe24ac1777df, 0x382f0bf3502dd26d,\n             0xef79716628447c1f, 0x919e905491330a7e, 0x082dccdb66ceab89, 0x4b4cb672ff05e12b,\n             0x404f81490729453f, 0xf57b600697c3d5b2, 0x6204a3640312aaae, 0x62f840a82428773a,\n             0x011b7a80e8041ee7, 0xa93dfab562fa5cf8, 0x7a5155414b0b9fa7, 0x34f98c9d960011e3,\n             0xe56330a31e5c8751, 0x539be72a779615ce, 0xa7ebfb8a3814f521, 0xfd125a3da530257a,\n             0xa3552f576f152939, 0x7f3c3f88c38968a1, 0xc4b0bc896f2450e7, 0xd9f4121e3cc3c820,\n             0xd30770eabe841d4b, 0xd732bc49cb84d3e5, 0xb00c5eb51fd0b688, 0x697c104ffe1ae9c9,\n             0x830cf860debf4c2e, 0x6b0f34f759d2a7b8, 0xcd63072f288d0c80, 0xbaef7ba24f1a4258,\n             0xd4707936b3cda587, 0x17ae67fa0ea5045a, 0xae700c86da523649, 0x28140d753d9ef5a5,\n             0xd0aff83f51241c8b, 0x8827bdf2082e5fa0, 0x0f6775e1672feaf1, 0x388b9eb32fa7c616,\n             0x5ebb73c5bd5eee0d, 0xe8d0133c1ec57b90, 0x114504185b735f18, 0xc13dec6c220efeae,\n             0x38e5a8f0ab29cc67, 0x344abc46c78c45b0, 0x1a9739a8aa9bf511, 0xbe9167efe362b077,\n             0x36ff7638878dd932, 0x469b250eadaf7a0c, 0x7ad1f8bcf690ae78, 0x958f348e015e2092,\n             0x9bac0bb6d07100a9, 0x802743a4a901fcdb, 0x60e8d0ea0ea1c6d4, 0xdf54ab4edc3c5fcc,\n             0x381754f9e67e5af2, 0x3c35af9b3c65766a, 0x24b68fe61e4ad469, 0x878ac507e9cb9621,\n             0x370c0e927005fdf4, 0xd5a6d9b8cdb92f15, 0x1836a00e3b57dbd9, 0x43e8ec62f3ec5963,\n             0x88759e780356affc, 0x0397b28c5fe00043, 0x00797c9a4e079e44, 0x3a56946a1276ea3d,\n             0x0c9552cd40bd0824, 0x67477fa426ce0e14, 0x51f70f2ae24905c3, 0xf578516bb7cea7a9,\n             0x1fe4a2b427b8a0d4, 0x0cd38587f8354328, 0x03fdb43ce60edb4f, 0xe57908e768d9885d,\n             0xb8e81c3b0a5d05f7, 0x0b8d1cee48754dfe, 0x7e8e61efa3e49a74, 0xd6a4cfe6d0402285,\n             0x2ef75a157acab606, 0x51bb51361faddb1b, 0x9f8ff918bbfb7f94, 0x381dc83117d9b6d0,\n             0x9c64c64e984a111c, 0x2e3e23e2a2e99b7c, 0x7cb9c08ac71725ba, 0x6af3bd9e4b7c386d,\n             0x733f9184a461f2df, 0x2d179b072da80a3d, 0x327a4b44123691ce, 0x14e307ed70e470ff,\n             0x8408def64a5f0ea8, 0xde8e56787ca750d8, 0x8bdd2556a643bff1, 0xbecf74cbe3c0a6a9,\n             0xc3081555efbab872, 0xeb35c7de8774f7a9, 0xd3860d5e83cfeda7, 0x71ee4189b39f9707,\n             0xb611bf0e352ed4a8, 0xca3eb620b5e48269, 0xf5093fa10fea1d77, 0x31edbb5cad31a827,\n             0x4dd198ebe5f45a4c, 0x66dd6b4d2cba8e16, 0x4909d02e020d6458, 0xf49929d3471655e7,\n             0x5c40710b351974ea, 0xe08910e407caf00a, 0xda5cc7054654d6ad, 0x2dbbf6e58e626b6e,\n             0xe388ce61d37084e5, 0xa2610d1eabddcdc4, 0x7d874631dc3ac7de, 0x9e52b3430539ee00,\n             0x82e7f6c2a8aee4bf, 0xe6c425c7dc3058a3, 0x41521966e6a249c4, 0x27faba6a12753542,\n             0x8e8bc91904f95c27, 0x6b9018032120cac5, 0x5fb646a0ec00c629, 0xe6c01bf7cb5f864e,\n             0xaf49ec6930400e81, 0x7fce854c97c61473, 0x7b5e758fe38eb625, 0x0b5d9c0618b5c989,\n             0xfcc99c5c22bc9482, 0x6b84fca413ca8b68, 0xb554a5194e5bae1a, 0x7d298232c2f6283d,\n             0x05ddb8ba6252b9d4, 0x443d3fc6b30fbe50, 0xdeef5dc29f8e1cf0, 0xa944111642e76525,\n             0xb342b5b24f544a8a, 0x4138adb392e91fe1, 0xb08f54e3a6de964e, 0x6896b210ab7a1772,\n             0x5da9a88179ea1774, 0x020a8f7fa60cb9ed, 0xc25ae22dddd99063, 0xaf5840ca8b5c2cec,\n             0xfc7b449e244339dd, 0x73fbaafe93519e29, 0x6f69d46157cbbb7a, 0xc1b426ed233d55dd,\n             0xfe5f9c65afb8af29, 0x066a31461b2a68a3, 0xd8c5e28da71f37bc, 0xdcbb2d5d24b9d31d,\n             0x9628cd8a30d97bb0, 0xd7419e3d60d9be5d, 0xf010333ef4c82358, 0xf4b6fbdba89dae3c,\n             0x4a47ff5f74bf2d9a, 0xd2b55c8efd0e151b, 0x1ccec79733d50144, 0x680fd540021eb92f,\n             0xa92702ff6872f116, 0x21cd25592baba658, 0xd32fef70dac46306, 0x77922186f30810e7,\n             0x362ed1ead287aa20, 0xb1d14d1f7bf74a6e, 0x37f08d4a70496f59, 0x7187cef7d26b5888,\n             0x406410ebe2546681, 0x9bfceca6f2b4a259, 0x3d7b2e52eff20614, 0x330053eaaab001c2,\n             0xd7c1a87550fae02d, 0xf2f58cc3aa431f66, 0xa917ae293a689836, 0x40defa3b3a47005c,\n             0xa2d46ab5f811fd09, 0x9abb9ee97d7c4d02, 0x444a1d0e3cb8b66d, 0xac8b2a76aafccd70,\n             0x0111c0a9a0715e00, 0xc3f433bbfb5e46d2, 0xafe013a30de78e26, 0xdd0e24b79b03a31b,\n             0x69e6883af93ca504, 0x2af968c9df400dd9, 0x43f3f9c04b2a9237, 0x4579bd2653b7f1ee),\n        )\n\n        mds_16x8s_rhs_0 = (\n            (0x7b5405da4f5ed4e4, 0xf8fd84b900031246, 0xfb022fed7aa7ceaa, 0xdb162985e2acfc02,\n             0x74f753304c9b4fbe, 0xab2fa79df052dad2, 0xcfa9d1a1b5259ad5, 0x806286258a8a459d,\n             0x2d48b6ded05ea7d2, 0x7ae661bfb397cc74, 0xe3bc905c3881b15b, 0x33b9057dce8b5a03,\n             0xb6e6202f32a357f5, 0x64ca3da1f5dd49ca, 0x53cc6be8ebefe332, 0xcca80a945b88ce44,\n             0x0f0075ea3885ae68, 0x97316bd6afbfb1b9, 0x7f329e27f674f1f0, 0x483a70d6f4c75981,\n             0x49686ed711a73e86, 0xb6a79ae82db73cd2, 0xf7867740485d4f34, 0x77cbb448b18a9c24,\n             0x7e0ebe7c7ad1d4e3, 0x9148d7464983a606, 0xe1f44933efee41a2, 0x57f1409e1b8f8825,\n             0x1f811b8bdc1be71d, 0xf5ad0e0277f9d5d4, 0x2f850bc498a62e9b, 0x27ba39a1e752248c,\n             0x1dbfa7f8545d5ebe, 0x838bbf46bf2409ca, 0x0ac3b854cfeb0502, 0x715225dc46964f04,\n             0x029c0e4058387870, 0x6b78087af5eebc42, 0x4fe958357c2cd8d3, 0x634be90a48431c68,\n             0x9b385d7d7875bc0d, 0x09c26b2d3d1330c9, 0x86aa0dbd0f1e9bfd, 0x1d7c6c0220466ef8,\n             0x8870d7f9359e0084, 0x3a812263d72aa96b, 0xc2e2e528a97aab17, 0x7965ca0146dbd2c7,\n             0x804403a5d2380f05, 0xa904bbf3e05a5c50, 0x9e6a207c9f6f37b7, 0x9dc44269898f6e01,\n             0x5f82ca1ad2d2c5a4, 0x72bbcdfada4c570f, 0xcade330ba925cd49, 0x873485ec57ac6569,\n             0x0e0f6753b501cfb2, 0x42fa7a089e97824b, 0x9a589f7dabc0bbbd, 0x17d3c497d5007f7a,\n             0xa150604b8cdd5633, 0xe33dff10e6c5e281, 0x6eff024ad8e026c1, 0xf90e719751845217,\n             0xbb5102da2352de4f, 0x21a981a5bfe52f80, 0xe9bf702f64d37c29, 0x2055dc40943c719f,\n             0xc7eb4e1ecc5c16d2, 0x195a957ed9609823, 0xfcd5a64928cd462b, 0xd4e8246cfbfd14af,\n             0x1bc274a42b3a7097, 0x1fb1bd5f55e7d517, 0xd51bfd86da1e618a, 0xd4d4c7f3a179147f,\n             0x55943280700c1295, 0x4b9e96573ea6e312, 0x90791350e7bd6341, 0x83d07cf43cd922ab,\n             0x46f06a9aff574af4, 0xef548a7dd178d39f, 0x77f4ea8f8e0bcbfd, 0x900afbb292c1b1ef,\n             0x4ecf00f896161bfc, 0x8d619d0036c9d73f, 0xe4f8d71b83eff881, 0xec97917a8d2623cf,\n             0x025d58eeb3292d68, 0x53a5e90aaa48f0b0, 0x72dac7f32bfb6daa, 0x529eb18f5077a1b1,\n             0x50a1dcdfe620b3c9, 0xa56248c279d4416d, 0xe0b0dbf11608f74b, 0x4b2fd92def200429,\n             0x45addd0e6b1f10eb, 0xdcb9b263c254146a, 0xa3ae62f397a83e8c, 0x43cb570af792e8fd,\n             0x838f40dc0aa9360c, 0xcb6a7c6147119c98, 0x4b3a2d52d7e8e8ea, 0xd226339807dde2d3,\n             0x7ff8a2d4f113fb82, 0x3e85ee1d8c83f977, 0xf5b69d102605993c, 0x6e7c6fd5ddc468a7,\n             0x791b948a89f90930, 0x7d295f6345ec09bc, 0xb8896ada129d54bb, 0xeab51c407522dc9a,\n             0x44b1be3b403f318a, 0xce4f6fdb264131e4, 0x9a222b26bbd5acf3, 0xdcbacce86b0b919b,\n             0x00e78ac875367f36, 0xfebf5fe592ede037, 0x6d348734cbebf898, 0x7ccada20861c0e1d,\n             0x45990fb85f886b9c, 0x604e7b9712881fa6, 0x448c5d70a4e87769, 0x19e12df50e5c957b,\n             0xb824e6fdf3464e04, 0xa9bfd6c6fc1565e6, 0xb97513862e1d8e53, 0xf0b10b6401874145,\n             0x98407247b8c08806, 0x448246483c13a393, 0xead1f448292bda60, 0xd90ee1311b47e413,\n             0x69f2c70641dd92f8, 0xb353ce89dd475070, 0xc6930485f04e000a, 0x3376426a9d8c7d3e,\n             0x89a6e5e853719af6, 0xb8c90c9fe3f83fb1, 0x7582c8746d66125b, 0xd47d34339c8727fb,\n             0xda38a8f30aa7982f, 0xc1ad5c530be777a8, 0x1627ddcded1d9f28, 0x6b054644a3833c04,\n             0xca7c89447cdf6aac, 0xdba1d71f2dc29020, 0x0aeab647ab987a32, 0x568a21e5c399430e,\n             0xfa07bfd2d0929145, 0xe13c528cfbbb4672, 0x152a0423e72d3c30, 0xa6f16733fa3eda50,\n             0x783a3336af0e4ed3, 0x6f24a5a36f8ec102, 0x1a9c2c7a8a61b3aa, 0x64ea6282e3c44fed,\n             0x125f7e9ce6c36680, 0xbd92e7c6caecbc61, 0x6384910802ce8184, 0xa4be37009b5068fc,\n             0x4079e8895618fa0b, 0xff4a1c99cc0efbf3, 0x3a5c71681ab257e5, 0x6731622f8ecec4b2,\n             0x8637eb9fce55e605, 0x286148d20db27106, 0x623f4697e3377fb2, 0x3ead1095df86a4ca,\n             0x38d8bcea4f58d873, 0x7b095776db75c5a2, 0xaf688d2eb6ddc956, 0x527ccd607071ef97,\n             0xee0d909e4886e333, 0x62f532208b74625a, 0xb8e86d32c6fae00e, 0x534e104743ffa7fb,\n             0x99951175f6182d1a, 0x4af08112f4db7c5e, 0x736e5c82f8200194, 0x75a01d4b27f49dad,\n             0x9ee9bc2f2c509ec3, 0xefa3c464a2072f27, 0x1aa97940b98a1959, 0x679ceb874f1dc9be,\n             0xb6e4f60ebef750b3, 0x7c3e7a9c4a142d87, 0x8e92a5cfe1e1259a, 0xf89a74b14c1468d5,\n             0x84401d16aea7f4ea, 0x62599cb07c8a9a4b, 0x38db6ecd2975322b, 0x7ce1acf51d719e44,\n             0x1a8a99ae0ca37660, 0x1076138e64bfb63c, 0x9bbc76b47eaade6b, 0x6a1ba01bd9c6ba21,\n             0x52e8905fa31fb7c0, 0x789d2c12bd5fa4ea, 0x15c52922d025c876, 0x79b7955df6555c72,\n             0x5ff888139cfdfd00, 0xcd5708248327e6a4, 0x87af7cf2008ffc15, 0x322221cd5bf0648d,\n             0x3d46288b5ad7f419, 0xa2a9cf6036baf8e5, 0x0fbffffddbfce771, 0x0a22b23227fed985,\n             0x05272d336b17e055, 0xc6d3a2a6864a3129, 0x052153252a2a20e1, 0xdc541a9e0ffe3070,\n             0x3979e4bdf2802ae1, 0x90ac763213322376, 0x7243850c65c9d334, 0x45a61655819f267f,\n             0xc92fed5f61d886fb, 0x7bfe3460ded5ac13, 0xdd6bf7ef8f5e7d6d, 0x08be0cfd70fd1481,\n             0x4bb614fa45ef1ed3, 0x06d01cc60a3ba058, 0x20280f1be2ce9639, 0x491f5e3de4884ef3,\n             0x4ab7c708db3b764c, 0x2fc9ed9d47f82738, 0x7092ec34232476c3, 0x12b46e47e9f302b9,\n             0xcb07a63268042437, 0x215b61e2986886bc, 0x904937f0803ee368, 0xe2476b0bac87dd72,\n             0x6f56e320d447d14e, 0x581c46c7ef86ebb8, 0x7310c73b142c425b, 0xa266517a7c6acc7d,\n             0xfb1ceaa18a6cf0ea, 0x4a7347a7a6e89155, 0x066e8418e37ff2ac, 0x1f998578b3c0a266,\n             0xf13ef4d3f65f724d, 0x66a91808510cca1b, 0xede5e0a875eb2127, 0x90b0a6d4ca49f102,\n             0xa7724c8db3049ea4, 0x933bc3660bf1547e, 0x676d57f6a686fd97, 0x0e21ca4f3c9d322e,\n             0x6672940363d546d5, 0x513500f399bdd1c1, 0x47d0a89ff271f698, 0x9b2b11012c9ade70,\n             0xe851d3963ee9bcad, 0x9e23e30ed7221589, 0x463086e03c14eef2, 0xeac9d721211834c6),\n            (0xd43863a29fce4caf, 0xd1f77c2e61c0ecd8, 0x01f7788ad2eb015a, 0x966af10c5cf1beff,\n             0xe8e7137eb4cf0eb7, 0xb2a439fa2017014c, 0x9b0b78a36de1796f, 0x91f12223e6273a35,\n             0x5947e435e134d548, 0x4a07df1aeabc026b, 0x486eea0975b6aade, 0xdb902085adfacda6,\n             0x71867eccfe2f6d28, 0xb340cdcfb22d7b38, 0x8519fc79a34be08e, 0x59660544fdbc86f8,\n             0x6757fef209eaddea, 0x9388f19f55edae77, 0xcf5405771f31f222, 0xb791072ef03eeb91,\n             0x796d6bb31046d979, 0x70a69af15e8ade39, 0xaac233b370388516, 0x57ac23719198ffff,\n             0xdde1335e79c3cb13, 0xc7ea82ef550e6ad8, 0xb0f05c77ac59464e, 0x53c4801c3a95d7ba,\n             0x06a38b7a8347bba9, 0xaed3b5a5de2d7b8a, 0xcc183e7cfb5fbb29, 0x55de503e98fb8116,\n             0xc8938ac3baea81d4, 0x554f08e865be7945, 0x76280e298219eb63, 0x6c1619f21f533a35,\n             0x488dc03ec1651d7b, 0x68fa3ffa7e4c006c, 0xebe2574d06228d85, 0xbb60ab8cfffbd547,\n             0xf3ee3eb124537ab2, 0xe5c7d4ca22fe50ce, 0x6bf06a74c5222a90, 0x6fe52288be953a3b,\n             0x470c8c5dd3587dff, 0x2d61882ce837899f, 0xc1132ce841b6ece0, 0x3b95af4ec78fb231,\n             0xbc64ba5e09c79bdb, 0xe58a3e48840a572b, 0xb06ddd7df1603abf, 0x24db4c93860fd48b,\n             0x9695113ca974924f, 0x2b532322275453ee, 0x0a002e8eb550989f, 0xed136b8214a76a57,\n             0xf73121a75e93bfb6, 0xcd89db30753678ec, 0xa1ac8eb0e05dc867, 0x50722aba8b18be0f,\n             0xb221e00ee27d41e2, 0x5c6cb6d5929424e7, 0xd293306e7f335786, 0x68237d69a65a7771,\n             0x04b28710cba89102, 0x592dd5c0b511ee48, 0xd19182480755626d, 0x38fe0c1ae869eeb9,\n             0x16290f5d08fbf89a, 0xaba2ed0f6d3ba43e, 0x514beec64682c5c0, 0xdc883413b0b7ff2d,\n             0x1e23d38c8911d1bb, 0x171a6ce65ba94b26, 0xc306e7f4825954b4, 0xb32ff62030b60d54,\n             0x54f8e49f214d2827, 0x110b0edcc507b21d, 0xa0118ad74c2c74a7, 0x67947e4f7a7450af,\n             0x047618f9da2b39ab, 0xffab1ddb88ccd140, 0x300b87f8cf45c038, 0xbd90010489cbd1b2,\n             0x1013fce8b1bc5a25, 0x79da66595e992633, 0x4f03998c0dcd44ee, 0x1f6c3f6c5119f877,\n             0xe0a6e1e128374520, 0x719b9d6cbdce375a, 0xbe8331b9ab75d84f, 0xd6badd6ae474e662,\n             0x5d2240e6658b6613, 0x97fa9cfc9a6ba857, 0xea256a8689c7f0b9, 0xcb83a4bc1f9499f6,\n             0xb11eb43db2e57da9, 0x68e499f61d66cc94, 0x0e6d18c599dd8818, 0x8935ee2e08b44ce3,\n             0x911c628f2fa3360b, 0x638ba97dc5f4a206, 0xc68fc56b2819e1f2, 0xae63c95f76b5874c,\n             0x000d8e628767ca7a, 0xcd5b606b23c4a326, 0xeb3cb092decbc573, 0xc65414f9bfe88187,\n             0xe037249b6c632e57, 0xa1a68dccec6d9cfd, 0xfb517a5568110de9, 0x504991977c9bff46,\n             0xd00436058087e88f, 0xbfe29edfacfd91e9, 0x365c532a2a92aad9, 0x5f94f35832674fd6,\n             0x662989b76237b529, 0xd08b6a1089644f37, 0xc0ad1c1243002312, 0x56ed52bd1f043bc6,\n             0x439b19e58dab04de, 0xc221d4139d7e1e5b, 0xe6f144eebd104125, 0xa931e8a55725ca10,\n             0x3eeb498e6d2dc5fd, 0xcb12122827b85f6e, 0xce76524f0e9bc1a1, 0x35f1c031e7ef0b81,\n             0x37abf9d4986184b7, 0xccd035b261a940e9, 0x8ef8691824b8801b, 0xac7e10852887a5a3,\n             0x5836372db1ab952f, 0xb475ff08be417661, 0x83f3dd426e5a3175, 0xa1e697956c4f2855,\n             0x912c215e372288d4, 0xf9f1ab1e0b8722d9, 0x933694cdf3be5548, 0xa6ceadb7dfa0c1a3,\n             0xb25c74952603d21f, 0x23c2e214d14dadcd, 0x9cc4f666029fb345, 0x590383b005d8821e,\n             0x4ed00f0c3b9e55ce, 0x871740afddb0c984, 0x308d3c0524105fa8, 0x8f3d94989664b39f,\n             0x8fbc2c4c512fc699, 0xc9d0d6474d3192e8, 0x63442f5a7048c7fd, 0x49b37fc9b5445cb4,\n             0x6ebfd4ee67f8d15f, 0x8150ee5543607d61, 0xa60912285d1799ab, 0x46c3551c2751b798,\n             0xc54ae65e22f84091, 0x5b0113f2cf31cf16, 0x35a476e47e01d921, 0x0c6354f0cbedcf8b,\n             0x1a732d689b5ec1d4, 0x7432facd0b5557c0, 0x751f3b9d974a4f10, 0xbfc8dc0e7ced256a,\n             0x0b53a07e6a09fe44, 0x33624b164c66fb6f, 0x3c93d41ec476fa84, 0xc12b3407294f2b4f,\n             0xb31e9f43d49b153a, 0xd52e81ef052573fc, 0xe2305a62880fbae8, 0xe0a9523c17590024,\n             0x2051a121a2c4bbc4, 0x814615ad23bdc77a, 0xe701fd9e2b8d53e6, 0xa0f1b1135c2671b5,\n             0xc20b9f2a6942a174, 0x917c6bee95eded6e, 0x2db5fabbcd0913da, 0xde3e529da4705c4c,\n             0x8eea9b10353b1bc6, 0xeb80b2db7473e4ee, 0x8f00c3a62bb4bf84, 0xd282fb27ffa88a04,\n             0x05935de2aafdfbdc, 0xe441f07d0f3f08a7, 0x3a356eb326948d44, 0x73a5f2eee0699fab,\n             0xf25ef55e5b93a90f, 0x763b4f632293c364, 0x8d8da4d4ed99fa62, 0x9eb41689337b5ac2,\n             0x2acb8d76674d3892, 0xa27f063821025f7d, 0x949873d001ef3210, 0x0c8326aa5fe6166a,\n             0x15425bd94d5df8f2, 0xc9bd96289c1b5656, 0x2fc1bb264eeed1cd, 0x50ed7b3c60445587,\n             0x6749642b54b05c57, 0x0f2058c76c4d4330, 0xb6a97915c10d330d, 0x89a397169815dc95,\n             0x95257d30085d1f77, 0x996ca839cdb80677, 0xe65260b79e0f7396, 0x49216926970451e5,\n             0x54ce6865efd99307, 0x22ece3fe40ddd1f5, 0x3604944a66a5fae6, 0x9a107654fa893440,\n             0x6b60e2f570d459f6, 0xe935e41cd7ba42ef, 0x6f1714641be49d7e, 0xa56dc49ac49e6e4c,\n             0x9537555179eeb30a, 0xe4e80fd3044cd407, 0x2021a190c0791006, 0xb07d410d97d0c2d9,\n             0xba5c9d52e66c1983, 0x9e00876df2c4faf0, 0xb204711935f47c59, 0x9e26c4510b6571ad,\n             0x02360526c218c4be, 0x6cad5fb217f9e8d3, 0xf031356c0301310b, 0xb8a8c5ee78bb81f1,\n             0x31279f7356064f8a, 0xbcb162fc9ef3d102, 0x873a9a1b1b005b20, 0x3a890ccece158054,\n             0x8ccea8ed039eb080, 0x3bbee8c4a60c41bb, 0x6eeaf7174c09c9e7, 0x5ba2e2ce58159174,\n             0x1ea1ae9c1180a540, 0x24524d4cf173f740, 0xd7573147b66a5554, 0x7ccec589c714b586,\n             0x24c4e9319b2ea96a, 0x92640db5c2b47d01, 0xfadcebcd8d3e0a5e, 0x82a3f5fda9bad37f,\n             0xabbcbaca04512f77, 0xcb7d30d04aa7c1b3, 0x0c74f1a0f2b69836, 0xa8f9b0431089e767,\n             0x6301a2346da8c9f7, 0x56353bc8bbcbc8ff, 0x46f217a40146f427, 0x46cd44b4cbdaea73,\n             0xc6783026936ff9ec, 0xe376abb1576c5cd2, 0x6949d69f5ea8c483, 0x394c0b39f10f02c3),\n            (0xf987ce1b7de79c34, 0x89ef6028495653fd, 0xd5c7fd7f395e930d, 0xdb0c980cd98883ea,\n             0x11775433c7a3a517, 0x0b345b26b7d529a3, 0xf297cc2e9688378f, 0x6ffaf6e5165fba89,\n             0x2fade6df306d5e2d, 0x34c6d9e698e1c2fd, 0x46f57ec72b828b4b, 0xc26181f80ac0ef6a,\n             0xdfcd3eb1cdca3306, 0x0ce4b08441ef5246, 0x99a6fd50ed34b608, 0xa004bf4a061b4c7d,\n             0xe1288c03b8402f3d, 0xd424feda3ff7a1f5, 0xb83f9dc40c67ed9e, 0xf62f690aba884e63,\n             0xd69aa1e11aeb238b, 0x76afcd45d6b6743b, 0x0f156a99d72073bf, 0x56f35eb5c92a7e8f,\n             0xd1b77c80ef26c743, 0x4789e8870c67086e, 0x9b65a6c56bf72cc5, 0x842eaed11e8f7532,\n             0x85a121639d0aabcc, 0x5741890139807e12, 0xd3c1dabe78701253, 0x47d3fd902f81c50d,\n             0xe73793709c0e97c3, 0x5cd80fe24e284acd, 0x9cdaf886bc34adaf, 0xd1c88626230d3964,\n             0xa649ef0135eb7743, 0xfa4e5d75fdae1de7, 0xc63c28fca43f5833, 0x626c6f32c7d06ba7,\n             0x7890938153a65ec4, 0xdefef3f714d5d1b6, 0xaa3807c9991714e2, 0xe1d3a0a56b06da34,\n             0x41be8990459a7ecc, 0x9f34d86fb115d61a, 0x100836311a78faa5, 0x5bf5e0fe1a4addcd,\n             0xd5d8163e3ea8cdaf, 0x590d54737fcba052, 0xd905536efc13387d, 0x2507bf019a120ff0,\n             0x6988cd9f1941918c, 0x7cb721166b4bf763, 0x111a086e26e1350a, 0x2fe4fce74c800be2,\n             0x1cdc3e575b115932, 0x81764e96341b6fb4, 0xd8475b6fd8c1c93a, 0xdbc048e39d954afb,\n             0xb39df7d6da996002, 0xf5322d04807585c7, 0x35f55702dbd43521, 0xa1c2cca670496b4a,\n             0xd4a03ba1b99c34be, 0x35f22f6e627797ab, 0x393093b3f44dece3, 0x1f92f76306e4407e,\n             0x69c203b3cd91cd5e, 0x80b888dcf5411643, 0xe9823f72de5e24d8, 0x4e7c6022d2fe926e,\n             0xbb69aed07d4e781b, 0x18009b0716413eb8, 0x130fad5fbc14a109, 0x9fe7c6debbd3292d,\n             0x5057cbca8c8df6e6, 0x09e60c0452703f3f, 0x452f8904c765091c, 0x42cf79a1d3b50780,\n             0x2e822737f0b2e65f, 0x2517fbacda7829ca, 0x6aff5a14c89f95e9, 0xa0cf91e5afacd706,\n             0xd7113a77348d3ae5, 0x403e7038fc5659f6, 0x857b8bc141b72a32, 0xa8e3d50d2b2dac5c,\n             0x87757318d75ade7e, 0xc1f73a4b473a6047, 0x6d637def9cf80b0f, 0xaf1c2b9e14d92e01,\n             0xd0d5315289a0061f, 0xbdcca07023cf38f7, 0xb4475d7cb25c8e87, 0x374a5dbef0036bac,\n             0x3bcae5d0a06ccb7d, 0x93fdf5955c93888a, 0xb57a781e3e603608, 0x32ec12d38c68ecfc,\n             0xeeaae41494c48da6, 0xf07f2a677ba5491d, 0x73b91f54e256bd56, 0x442e20749ff8ec5d,\n             0xcaf159fc7f904888, 0x06d73433459002b0, 0x7eaafb855a6484b3, 0xbd2481c09eb5fa3a,\n             0x496260a0e81b2c46, 0x66d68337a4c8651c, 0xa6b4af65828ab3d8, 0x999a064eea8b3e6c,\n             0x38910586863acfed, 0x6f63d40949877e31, 0x327cc52278e80276, 0x6dbb8a53732d9d2b,\n             0x5b23563622eb32e5, 0x0a64a26d96a30127, 0x3d20c85fe4dca4d0, 0x1d25df176e6956c7,\n             0xa1e0480ad97b95ea, 0x7567ab11c9bf4222, 0x06596b0c1a3c8cc2, 0x5b5a8be8db9943e7,\n             0x0e2c4d8a47ca1f44, 0x4d349a8fe9f302c3, 0xd03dd7b3ccf9f24d, 0x1e265ed3b44cd57c,\n             0x796eee12c3d8dafd, 0x7f534dbf7eaf77b7, 0xeaed78867981a6dc, 0x66cd4fdb8f041d17,\n             0x6a52123f6e65cc12, 0x0dd3003d6bfcf432, 0x2fab1492451569bc, 0xc1c1f7becbed77ed,\n             0xda5ac0c88c84b0e4, 0xac66ca142c7a64e6, 0x39a90859d0367114, 0xea08cdbd2af6416a,\n             0x7096f65dfb91be5f, 0x328b3003cf39b55c, 0xac2a5d20dfeb945d, 0xb629781894d51e99,\n             0x6dd436191156896d, 0x5b77f8904017037c, 0xf597b0db3c2b77be, 0x852cb51886b4c94b,\n             0xefccc501d48fc994, 0x1d7104975de00816, 0x50d3d03f9ee3cc84, 0x70cbeeb9f99dacf3,\n             0x75adb7ef2758bec0, 0x2a14cb5b6e608f6e, 0x03516d82039635fa, 0x9f7885dcd122635c,\n             0x079779e43e364076, 0x5025ed998c5ac0c9, 0x72ca6eb6d550b6f9, 0xcd53d8db38c64d5a,\n             0x466f6acc6661b4b7, 0x54d7e8eea54256ba, 0x6862219ff84c9978, 0xf7a654e0338a2c37,\n             0x8f9645b4c299b845, 0xba7018b7befc74e4, 0x031f90fdffa1e8fb, 0x2ca8ace55f3d49d6,\n             0x4f249eb71889c020, 0xaef307183bfa2ee6, 0xcdfaa776d6bc2d31, 0x8a31e61da5c86831,\n             0x5921bfc7c3799c3d, 0x2726cb7cabc8f6d9, 0x4bb8d9ebf89a8adc, 0x120cc437369eb077,\n             0xed2a23e863f665ac, 0x21a75461636833d2, 0x17147ce594e8706a, 0x3acb409ad45d1612,\n             0xf29b1d44d17d5f42, 0xc45798c29f3f5f0c, 0x61a699424ca2c3c1, 0xc97d8e5f2db3214a,\n             0x4675e89387ee7265, 0x17b326971f8f28fb, 0xbbd41befbfe1f48c, 0xc36636d10d861850,\n             0x71f609b0cf6d2515, 0x9c1707c85f10bf95, 0xd883ddd38480e862, 0x34d67d131a1cb204,\n             0x95e5fd6bdb3e5bb3, 0x05b3f289abed58b6, 0x301ccc825b9bfc62, 0xe3cc0836a38517dc,\n             0x002c38b90c385fd8, 0x9f90c36f990a07c2, 0xb1566b1646232f91, 0xa717b465de39132d,\n             0x5dbeaf0d78afd510, 0x934c0a2a36339574, 0xca825df90a486b3c, 0x85ee009effeabb5e,\n             0x7479516fb8b57885, 0xed69080938dd5ac3, 0xa999752f3c7a1cf6, 0xf0d98bd4798789a1,\n             0xb520f40f2c640546, 0x714c42179a7f66d1, 0x8e574253ecfe14f8, 0x4d226ea04ec9d9b4,\n             0xcb6a76870cb1bb33, 0xd83b952a79288369, 0x36b56685b69ea825, 0xde2e13dad1109304,\n             0xca036cdc2ecd2525, 0x5af5b81cc8bd782b, 0x684d505065707b99, 0xf4827631a966de08,\n             0x138ac651f449474c, 0x13a66326495429c2, 0x974ea67295d0a630, 0x2b18e9f5f5c8d3ab,\n             0xd682630a0f31e9b6, 0x097a83277bd33daf, 0xda3460a7e8817d1a, 0x64bb4bb0002ea83b,\n             0xf4b1f183da9a134c, 0x1338ded8b67342ed, 0x1c6a0c2aa8a6e09c, 0xeb01c62fc7ecf5a9,\n             0x1efb0a59e39fdfe3, 0xaec4128045a2b2df, 0xcc1949c958862357, 0xe6c8f0593ac344b4,\n             0xdf4cf97d2110a0d5, 0xf5ddaa2d4cf81a86, 0x0b41a9b6a8118e54, 0x868a4cc9e9d5ea63,\n             0x5e5254120879697c, 0x2589490ebd6fdeb2, 0x8f2cdba1ed7da07c, 0x399f6cca1a8b8a63,\n             0x80801ffa53037696, 0x8f9db099b5a55518, 0x30482c70f1aff592, 0x73cfb47d90386028,\n             0x53dfd2899f3d6937, 0x33a917a7ef991675, 0x006053437a2e78f3, 0xa797ee98f01ee2e9,\n             0xa0158b16aeee887a, 0xb176a1aa4a52f3b1, 0x44e58752993b76d8, 0xb5b1e72c2293f0c0),\n            (0x4dca1a825300db02, 0xb9343bd268f6bd2d, 0x93daae2b2af1e2c6, 0xf4af6316c3bf64af,\n             0xf2492e73459faac3, 0x3d06bcb9e85eb893, 0x2b927d35681d4af7, 0x1aa685115c4d1d03,\n             0xb76eec2a12c4cb7a, 0x27a6e93ae2fac5b5, 0xe0d100fb52b0b28d, 0x896c6c1882c25322,\n             0xce90a23ac650b354, 0x732b511e15215002, 0xedc310e4dfe7cfb7, 0x1ff7a2801ffd513e,\n             0xcb5369d898a38a43, 0x35ed7a9b1bc63c00, 0x46a86bcbc47a245f, 0xff32b95bd0d994d7,\n             0xb34ad7b95eaa8979, 0x4e9dac9fa9ac657a, 0xb10bc1331d8a97d8, 0xb07aaf3e0b5f98c4,\n             0xfe565051945e1361, 0xe38e09297ebea2da, 0x48efc0ba0eae451a, 0xaf5aa5e74e76bea7,\n             0x9867545d957f0fa1, 0x5aec19fbb0f7f31f, 0xba0dd90eceb1d07b, 0x7748d5df3a89d021,\n             0xd06b63d69b9569f5, 0x80459b4cb6096109, 0xc49fac84267db83c, 0x2bdf4b8adb1dc88f,\n             0x8d298a1785a47700, 0xa1204c985ce35562, 0xcb977ffcb4b6d9f2, 0x5f653878188f404c,\n             0x0cde2bc627bc615a, 0x26a2e6ccf5490dae, 0xae8b5ab13e431213, 0x1a499faef00a014b,\n             0x8d7b6bbf787ec10b, 0x5bf078b658febf76, 0xdc06b46cc52482fd, 0x4a24118085d036bd,\n             0x194ca853179146d9, 0x6d59cbbc46110b15, 0x07ea2bf3d93c00fe, 0x08c4a4b423edefb5,\n             0x8cd1633d0301c30e, 0x8ae5efedcb872a67, 0xfa731883f816d9c7, 0xe773e1fe804ac05c,\n             0x3aeac5e3a28ebb5d, 0x9fb62a187829c56e, 0xbb4681390e72748e, 0x06d68673ac353e66,\n             0xecfa28737fd6d6fd, 0x9db4e81a3f246066, 0x5f1260a51ca423d0, 0xebf80331bc7028c3,\n             0xb8a4842101222847, 0x3eeb7cac75459c74, 0xab15cdb3783bfc70, 0x01777afe877d3a43,\n             0xe537abe872b55bbc, 0x1c0dd002e7005fff, 0x7b91d3143f42cb8f, 0x4bcf48161492e3b5,\n             0x1ae21286c60f3a28, 0xcb0e69314caab217, 0x47363d76585d58a7, 0xcd2312767345f98a,\n             0xd6434ff6466c1615, 0x582ee858bde5c9da, 0xce745f31a836e71f, 0xe45343ef7d3731e2,\n             0x99772c3dda2746b2, 0x8ca2c3467d7564e0, 0x7db814e3e5723b16, 0x91acfae6d12d1c45,\n             0xe6774ca8d4f59a75, 0x219829a3e63ef13d, 0x47ea3c953ed22008, 0x9e4ee4a569346c65,\n             0x6220aeb6a04b3f17, 0xecd6f0d75a4db7a0, 0xd8f2d43a81ae0084, 0xa58cc0c1ede529aa,\n             0x78d531ee93e2e698, 0xd397ce175f0a27dc, 0x14817817feb77286, 0x724f9c7861567855,\n             0xd658024518be7ce3, 0x9e0be6a6c4be7ab9, 0x94cfd2e7e2f50a79, 0x9f73132d46444702,\n             0x5f832eb06080d210, 0xf7ae4d13fd0f013d, 0x8f4ce851d4b94890, 0x4762b29566ca688e,\n             0xf2ed7514fd654743, 0x4ce004d1a5bc5b52, 0x5f64cfa948688fc1, 0xc466d37d6cfdf310,\n             0x6b85f57ab01d9bec, 0xb0caffb1f0cbfd10, 0xcbf58491ed121b71, 0xc0f25264891f921e,\n             0xe63e63d709ca96b2, 0xdc399d6fd29544cf, 0x765fe2917c154fd0, 0xa328f5d5a3528c89,\n             0x694ea8e3b91d2acf, 0xdc9513aadb87c05a, 0x9c1d2ea58e20a5ef, 0x78fc1752de162b1b,\n             0x8b1a9812f62b876a, 0x089f045991fb60c0, 0x14346dc4b32b9a9c, 0x239956efeaa52413,\n             0xcf5593d9701cbb40, 0x1c48feb4a8b50ac6, 0xacf074285fc4eee3, 0x7280cd9421a95450,\n             0xdf1b74580d6f4a1d, 0xd62949bdf87b839d, 0xaae54d7deee3b2c3, 0x7669224de9304206,\n             0x11638085cf914c78, 0x91fdc62bd0b8b3d4, 0x18f9c980a9d7367c, 0x0f0fb48d869ec40d,\n             0xaad4152fa53fbf6d, 0x5c45ec44b363ca61, 0x39a28322a46effb4, 0xf58ed9ddbc4f831e,\n             0x801ded20f9f1a994, 0x21fe23bf1490c4d4, 0x0295dd5e49bcbeb8, 0x8993e1b5e30f4021,\n             0x41270ac9ae891f0b, 0x6b0334a55893b556, 0x370c856168ea69cd, 0x78024bc77d152b20,\n             0x38431962bdce628e, 0xa0f0526f53344319, 0x4664b1bae48205ea, 0xd09d22145b93b783,\n             0x19ef61c56d544a6a, 0x1814f785d9ba7411, 0x6ed26bb559773b9f, 0x52130a50b0a9b9b7,\n             0x9e7f44e60d22092b, 0x741b09a280cdea0a, 0x77d378be36890a65, 0x3fc39d9665e4db6d,\n             0xad7278832795abda, 0x2aaf6f567d8a8c7f, 0xb468c894eb9cde9e, 0x2994d7f89d88be5f,\n             0xe59c5f327f7945ae, 0xbeb4a543a4156313, 0xb3c75d9d166d4e6a, 0xba4ed81c9ad100eb,\n             0xaaab815961165c2a, 0xe0c18303f53113a4, 0x36e0f0558472405c, 0x427da74c44846014,\n             0xc145bceb93c74c9b, 0x7ec8c49276f06a1e, 0xf52796970543a936, 0x6838040ad34bf480,\n             0xeb3dd4509894c76f, 0x88e3827fb1368fd0, 0x549adc52e546824c, 0xfcccb79e3c6bdf3b,\n             0x19bce5c64ed0c97d, 0x0b81c8d285fcfd8b, 0x0fedd0d4e54cc089, 0x5326545c483a6e9d,\n             0xddfe91ea51c0375d, 0x3f45304b3b91abe2, 0xd571dcba54c57910, 0xae04061cca379ddf,\n             0x3091a57358ae0acf, 0x281d46e786d96058, 0xca5ba1a471819be1, 0x4ad023ac32842f04,\n             0xf5524eaa7ef0fc57, 0xe47d219b13ead088, 0x11786f211efc8601, 0x7cab777e435be69b,\n             0x65d36c47ec18eeac, 0x44dcf19b1bd83139, 0xffc70a8189447fbc, 0x6c25fec42789e4f0,\n             0xf031361f7660b542, 0x36572c375f7854b7, 0x0476534008f18314, 0x15f56b377ef8db4e,\n             0x2c5d60c26e1d5b73, 0x9d6233cafd3e8f29, 0xf993c2f5d6d54e98, 0x8df422a4e1977b45,\n             0xf8239c98c8028caf, 0x897bf629544b2065, 0x478d36da56c6ff94, 0x1a6e7baa1431a5d3,\n             0x93cb87f8abc4d5ea, 0xf0b34023d7b3fd64, 0xb2a7da7c1ce31446, 0x9ba93b3fbce31046,\n             0xe6000e4a17a68521, 0x7c42245a9932c590, 0x9bb04b26a1232a50, 0xecfc64847caf1ed9,\n             0xb4b2aaca5efdb265, 0xd23ceddd16c2ec75, 0x0b642e421a6d53f3, 0x6c90c567af3d094b,\n             0xec70d305ebfbdd77, 0x3df1aa03dcead9d6, 0xb220618b3f55cefe, 0x78ca2cced5abb0c7,\n             0xa74cdd64078514f1, 0xdef8b1678069e1ef, 0x88e888ac5bcef390, 0xe1d7548bdc6522ca,\n             0xac9665dbd5a667bb, 0x85459801beb5c5d0, 0x04b4727d8b5d6e80, 0xb8ef83cf166a63d6,\n             0x308561bbf9e1c92e, 0xc2fd7a2a0498967b, 0x6794b01ef8e14af1, 0x4d203020a0fa8b82,\n             0x73e1b7f062570657, 0xa91eb44f0b799ec6, 0xb271aafcffdf56ec, 0x490a0d530d4eda82,\n             0x5ed0ac345e1aecbe, 0x3cdbb6c849599a73, 0xc4b42cbb2e82a921, 0x41c2b3235f74dd25,\n             0xd56728ca00b27e00, 0x3f7dc62b1edfd462, 0x5a493aed9b9d8a4e, 0xa9d8d8d66f8bb4bc,\n             0xe319d3395a6d9caf, 0x4f3deb2eaa6a3cd1, 0x93b57ff0fef5469a, 0x65beba75f7e357dc),\n            (0xbf5bb7aff5363401, 0x9c3ddf3ecf6e48ca, 0xe2d27b1b78479892, 0x2a2d8d13c8a6b4c4,\n             0x0e3e4d92735feb63, 0x2734f1a3fb75a234, 0x4f565b236e43dfbe, 0x9417529599010d99,\n             0x09ead2b8decd5dd6, 0x208b87ed414200c1, 0x0a23ad24cb9dde5f, 0xeda93b2f1ef8ed2f,\n             0x554c86f48765260a, 0x581dfa747cd4856e, 0x42782bdc2f35d2e8, 0x0c72609ce619df16,\n             0xa9838ab3c8a69dbf, 0x04c4080316bf852d, 0x72df9b3a26a78dd7, 0x95e145f6c5f11a31,\n             0xce523ada8ae99282, 0xd53688bb8aa8c33d, 0x3072282aaac91a87, 0x211b3ab247f5a42c,\n             0x6ae30c7b64c04358, 0x345d6ca85c39cfda, 0x941cb04cf007bf5a, 0x5a4aee9c9ea5dace,\n             0x9220411196a65a3c, 0xd052b4539a6a1cbc, 0xadeb6c143d7a3e56, 0x772ff6d3200d2ea9,\n             0x3d2438abc2400945, 0xac2a15c31160a41a, 0x2299cc3118c51b94, 0x4d906bd8cadda908,\n             0xc2a49dfc20fc1658, 0x0af4096ee1057ac1, 0x7e260e75f5d3ef9b, 0x007c917f7d0ede63,\n             0x88b725197c7c3978, 0x6101744459a42280, 0xefff451f0aca4536, 0x07d0d15896d95d2f,\n             0x14e029e9d58d619b, 0xeba34e3474a0fba0, 0x559aaa25768ce06c, 0xbc6bf05387f0ead0,\n             0xa0dbc1b225a8148f, 0xecb1f81f3fd83805, 0x3bf409e325041c28, 0x9bca9a7739e0db6f,\n             0x3d611be40d88028d, 0x6f8e6cc701a742ba, 0x5b2db0fc280d804e, 0x86b671b61d5aeefd,\n             0x5b1d5b698ade55f1, 0xba16e89ec4adca67, 0x5ccb306411d8bbff, 0x8b93c052bb4732be,\n             0xddc5cf73ecfd2443, 0xaff1d7d9c565d760, 0x65c735d271cde51a, 0x29ef9025d1cfced2,\n             0xbc88b130ca8f0305, 0x5a60bf82796583a4, 0xa07cf63d3225b7aa, 0xe2ac3b558fba6bca,\n             0xf4ee1635c4015e70, 0x47f253b434dc7e26, 0x6e85e4ce870289e6, 0xf1622e5c375d4c7c,\n             0xae95cd4cef468fe1, 0x4490c855e17d3dde, 0x9bcc89a628a90c78, 0x9bc0d4964cad6664,\n             0x022c274f0dedca14, 0x99610e91387c11ba, 0xfc8338857634baee, 0x4f332a1212da8f74,\n             0xad5fdffa1bddfcfa, 0xc5a610ed9387c782, 0x999ee466699bc267, 0x490985f68a57c81f,\n             0xb0be3870679832f5, 0x63aaf30aa71bc94c, 0x3b39ff979fef80d2, 0x1b8ab0c01bf1fe7b,\n             0x2ab1412d30e5d3d0, 0x17174d4ca002d38c, 0x3de2fca76e01fb8c, 0x05d19690cdb87b08,\n             0x30463932e56d0c3a, 0x5bd32f42f105166e, 0xa957c1ad4f1e0ce7, 0x9ea15a67e9667f8c,\n             0x8d1cc03669bb73a6, 0x56e97953824428fa, 0x944cad0e7d3a61ba, 0xa28d2a1e44e17383,\n             0x37b15edc4f0a6a88, 0xf70c0e999cbb49d5, 0x959b85df8e4d2bc4, 0xe41ea844c0acf427,\n             0x08ee07cbcf509a2c, 0x4b0ba281445b0f80, 0xce44c8b85333a86d, 0xaeba7c4c831dd0b1,\n             0x8d96f7ff0ccaa3ab, 0x79903323056e801b, 0x1b7b11da9b5faddf, 0x23b38c25a7eaa542,\n             0x19aba628d18ea022, 0x718a80709cd3647f, 0x2e03cb06f89e67de, 0x80565a8869ca5a07,\n             0x990fcbdba7ce7524, 0x1247239364097b87, 0x51f82ac2d79c0443, 0x96e8ce33acb84e9e,\n             0xd31b8ee8bb3cdf06, 0xa614d5f216d7b090, 0xe3aead9e991dc9de, 0x275a5476ca8dcc1e,\n             0xc90284932b75d730, 0xdb88bb9344965f39, 0xeb6210325a39377e, 0x151fef44a7d40511,\n             0xb2e4db0c29bdad41, 0xbbd3d93802d41d84, 0xecafd657edb5fac3, 0x9d9074765e0cdc5c,\n             0x2120a60350871bb0, 0xd8ef2c0a3fe26f48, 0x7abbadfa14658cc7, 0x85ad9f778a67a401,\n             0x1754b8b63d2e4475, 0x6e0f28541b535ed0, 0xb5984c9842f6ea75, 0x7304f55b91c215bb,\n             0x8c2f8b9e9fe34fc1, 0xef3a028b55997260, 0x8dfe9a2a71ea32b4, 0xae32e5977ab05e51,\n             0x817c0277b0957ec7, 0xb3dbf9fb42894c7e, 0xde7c15b3f555ecc6, 0x71bfe3cddb8b0877,\n             0x9b346be5776621d4, 0xcfbeb1c6f0c5888d, 0xecfa8d3c41572a9d, 0xc35cb3c9ed598754,\n             0x72ae23f86e22c4b0, 0x0e50d50ad64ebc4d, 0x0efa589804ecff40, 0xb6fa944e65b458d9,\n             0xd55c7c104e68e42b, 0xfe91e9f9223dbf07, 0x2abc07c3b51bc1d9, 0xd92315feaf04b311,\n             0x9ec6d966b29013ab, 0x9b3f0b580a98fa9a, 0xc955a984b6018e53, 0x8407d2a52ab0fe74,\n             0xb92f8d0d4a06ff77, 0x11f81d5764bbeb8f, 0x9fa0e31fdab84b15, 0x0d61061a8a81f56c,\n             0x535e3554d3e7a683, 0x67567defb540f61b, 0xe64746b4dc62d117, 0x36e9f07c00790379,\n             0x0324a3726dc81c8a, 0x01dd3dfc3e4b7f55, 0x42a4368b26ce291d, 0x472022dfe13db72a,\n             0x5e616553c000ebb4, 0x36731ca0a66396c0, 0xe07160c1b7c9fd73, 0xb44bab7f6205f6cd,\n             0x2a2c832f03040224, 0x4594a635cd4069e1, 0xfdd3f2acd8055b48, 0xedc14c2503a32381,\n             0xaba617bb88e7e1c8, 0xb6c6cee8227b7068, 0x40eb7cf967290837, 0x0947cfc56a4060a2,\n             0xfb6929956cfb289b, 0x214dd72cd4add5e6, 0x8678c57744fd7fa4, 0x7962be8dc9955e58,\n             0x8b1cb2f022c96793, 0x75ddf91d8fef5e2b, 0x34ef97de1a154ec7, 0x8ead5c3c862c6ba5,\n             0x0d07d64183db286f, 0xb56144f8c4a4d971, 0x9d8ab040a2d6a204, 0xde03278ae9af1008,\n             0x874634ce136bdce2, 0xef6931372c48387c, 0x63d71feeb9f98d4e, 0xb4bb6abba50e0e9c,\n             0x50a018992013ebca, 0x4cacf4c7fbfd635b, 0xc20e1c7931e9ebc9, 0xb5c8fd27dccc2923,\n             0x9eb774daa25ef041, 0x494aa25db2adeab8, 0x9e62cfe7a1caf51a, 0xf52e2f71c2b6fca7,\n             0x707d8bfbf23d0dd0, 0x3c60a2abac354fa8, 0x2d108c433eac331d, 0x97419e8f556ed698,\n             0x7008b6375eccb4ab, 0x9d9f78dced7dd9a2, 0xd46072f4542b30c9, 0xd24b7c4cdfa48400,\n             0x9a785d241f2f6287, 0x3d5ac4c8eb2ca4ea, 0x8f7031f6ce346b1e, 0xdd83b4433f34589a,\n             0xb52477e38861f49f, 0x4fb8521eb35e8d59, 0xfd1538346bbad5e3, 0x4619143da06f17ba,\n             0x512b704d547b4273, 0x298165a520f421f8, 0x127b7cf86d43a26b, 0x4f6cd778723ec7ea,\n             0x7cd61a6a896f0ad4, 0x3b943d89ec0a1933, 0x0c466429f3b39849, 0x32fff146f2559ad8,\n             0x54a0d507c56ddc25, 0x358d5381f5c44672, 0x4b9d2dd06bf17ea9, 0x1d02e7bd173f0e41,\n             0x43649b466291defa, 0x98e86710ad256f57, 0xec4fcb54cf9f3785, 0xf6d07e993d8996d6,\n             0x7b7ae354dab3b2c1, 0x6ed6d0844170e398, 0x7e8de8f550ebe178, 0x5c045ebc1222a78e,\n             0x596113eb59f3cf69, 0xee6e98bcb9c9e067, 0x6dfeb6e2d557b611, 0x1c6505311bc9d3b0,\n             0x34d3c8933ee5cea6, 0xcc73b4694344d28b, 0x806e0d3906d87b91, 0x51b0cdeb0f0a12d0),\n            (0xf29a8a91a0750a4d, 0x937ced8661e9bec0, 0xa7dc88eba783114e, 0xb65ec4686b0fac9d,\n             0xc05dde06243020f6, 0x35dff3df2c586145, 0x098cf3c7b6889667, 0xd6a7af4a57c0c8d6,\n             0x9c57b19f0a8fdb09, 0x7b7f1d7ad720076f, 0x06546272f1898004, 0x5cb15e638c48520d,\n             0x4a1e19ed3afda4b2, 0xf53a860e6283f16b, 0x3605077f3a32eaa0, 0x4c60808c1ce8de0c,\n             0x7af701d6fe9640e4, 0xcf7edb4c89cfb979, 0xe443b7768a415d1e, 0xab238f840343e08f,\n             0x64560c5aa03de304, 0x94f5ba6df58e5b6f, 0x89ed49e454d12173, 0xbfedfa5ce82f2901,\n             0x0f3c2c1f9a998455, 0x27af65de99efa76c, 0x252fdb569f4e2b24, 0x7a784408ee74d712,\n             0x4ac2d177626092a5, 0xa2b98d053f617622, 0x6fed52d56a16a217, 0x844fd56166192ecc,\n             0xc62225604a1d8e55, 0x0b27f8494f80f755, 0xc226e6016cb913d7, 0x345145b5d82b6533,\n             0x3e97529f7a39d4a5, 0x5a4243149496bd6c, 0x3c5ed99212e54d5c, 0xd2147fb349c4e345,\n             0x2d1fcb65808d6bfc, 0x134415a4a911001c, 0x32adc1b9c3094f3d, 0xdbb19c2cd0865cd3,\n             0xdaa6a23a70b55c06, 0x797ac16fa44eb177, 0xa16622142a3ba561, 0xb9d5bf184f2bf360,\n             0x3dd7d1b9311df0d3, 0x510069c555dc1383, 0xb93d846fb4b4fbea, 0x75e687ac068f5c16,\n             0xc0adbf9b85e989dd, 0xf3562cab6efe1304, 0x7f9b422736a97fbf, 0xebe0b95fcc1e3653,\n             0xd14f50f76b1f4e1b, 0xbc949e0cb9134cee, 0x3f7124c4c4842eb8, 0xcc6fba244cd48e71,\n             0x1c2bdaf272679639, 0xd66bbe47b6adccd2, 0xd7985b5241711192, 0x63340c32ec3549ee,\n             0xcbee1e0e10b3892a, 0x7a84ae25ea3730ab, 0x4fb09bb763c64249, 0xf8d3e2659f4e763e,\n             0xb4f515eade807671, 0x1b1ee41130eba35a, 0x388ce50c04588384, 0x23fb5b32801b7161,\n             0x4abd5cc68244f18b, 0x7e2d3255d5235b4e, 0xe70a7014993c9b50, 0xca9264c3b51d19dd,\n             0x69ba418094629ae4, 0x69c7fd50333d3ba6, 0x5bd3d0fdf4776cea, 0x6fc20f551d218ec2,\n             0xe4e51f8de0695bde, 0x19be3fb8427a19a8, 0x6ae1bc72ba0786cf, 0x2b64b6c3f4fb96d7,\n             0x739819bbf57b3902, 0x6bb8fcba76922ee4, 0x1191e0253008c889, 0x4d9e6f7b5b961501,\n             0x319a4948f2b5f13b, 0x68cbf5ffc3d2b42d, 0x6c7ff1e5c8681145, 0xc70d64dc0fdca744,\n             0xe145f0da34006e3c, 0x8c028c83b0cb4d88, 0xa3d2e1c600007277, 0x31aa6f699b25e51e,\n             0x3637a6918666791b, 0x0d16744732ce37ae, 0xa333cb314750dddd, 0xed9b0831b11ce6b6,\n             0xae5d00d085f1647d, 0x4fa3de9c0799ecd3, 0xf479d734d66aa341, 0xcca0909a41c93889,\n             0xa90c2e71dad84d9b, 0x7e67bb22c2f4a38c, 0xc4eb203dff1168aa, 0x9cd7cf6be1ee0827,\n             0x35c5ee1be927593b, 0xce9b0a900b9a889e, 0x4b350c5b7dae1652, 0xc3289170cf1ea082,\n             0x6d7e2daef71d440d, 0x3c81174359316f24, 0x174511982caad30f, 0x89e83e25fce17a65,\n             0x70b97405e3d874e5, 0xb7e0542de9f8953c, 0xc3606b5321b89d5a, 0x87f129b0ab87832f,\n             0x747d0a1e22fd859a, 0x73bcc8aa81e4d8df, 0x6eb0087c2f5bf23e, 0xeca70f330a145757,\n             0x9e747c3779e02544, 0xaa00a9595b3c8965, 0x119644292048975b, 0xa6c41e60a824f81c,\n             0xf2aa43b2134dca8f, 0x321cd04b5f83ac42, 0x03f6a5e07b1cb442, 0x06be31c077ff6efa,\n             0xfad864bb4a6c6789, 0x1baaeac01e69e854, 0xdb3e4d269495bc33, 0x0e61d9340a538001,\n             0x147f33a3763d38be, 0xc58f029afd8a86a7, 0x1cfe6ad170c18af8, 0x2cd546a9adbddda6,\n             0x58063cb844de57e8, 0x4e6391c91124a92a, 0x1861f94c7bafdf3d, 0x2869da3f4299dbdc,\n             0xc1bb2fdad04f1880, 0xe8a0b4a517bac896, 0x8f4b2b5ddbd39025, 0xac95ca947d8a6201,\n             0x807cb198f79432eb, 0xa9480e5d6bef579e, 0x1c3fd944b443003d, 0x76f3cde863c6b417,\n             0xdce1d75aeb2c2d6a, 0xff7cfc966f1ebc17, 0x976499d02367cfc7, 0xddb91faae0de3cfb,\n             0xa002469382a28090, 0x7c952039737863c4, 0xaf51610c9aadba71, 0x70e7ce7d56854d64,\n             0x98c43003bab78c9c, 0xd9404ff815ea78a9, 0x8bfe1034816b3b79, 0xde24883516b1bdc8,\n             0xd81ae9f150a855b4, 0x40bac6321139c405, 0x15311c277cd4e14d, 0x8792d6f94a102855,\n             0x4eeb36194f2df70b, 0x3de70f9c83c86057, 0xc9362bd97a60f870, 0x6018ff3644504aba,\n             0xce327aa0068ded51, 0x69045ad6ad2cb735, 0x768f41bc5825b39f, 0xd862472fad944a6b,\n             0xff7f49a7458d1296, 0x449e3609f3eab0fd, 0x0ea15ec431212f06, 0xa47acab8d112810c,\n             0x2648739eaf266d40, 0x74f9eaa523233e14, 0xc4200e4b73845f4e, 0x7378fccac6ed6b5a,\n             0x58ff3886c522b38d, 0x70708a4909f57f9e, 0x901eee9056cdb042, 0xbd2b8fe1a9c1528f,\n             0x78c604c10c5484a4, 0xe714e2decf085c76, 0x57c647c4639a75d3, 0x1d93fb79e93b1469,\n             0xf70a2898d4964e81, 0x0877df4fb718ea42, 0xb43b9ee3dfd832fe, 0x56a87de1d5f825ca,\n             0xfb9fb3634bd71cfd, 0xed4e53c166cfa15a, 0x74f49673683d7eb1, 0x08e92206dda7e969,\n             0xed16f66458422208, 0xe8fbc577d06a1679, 0x8f1d9023bd17e564, 0xec640b8eacadfb25,\n             0x2dfe0d536fae8204, 0xb1c931d830c778c0, 0xa8e0a5c74ef5d8ba, 0xc7faa81ba481976a,\n             0xb2405b58793caeab, 0xd200eef64b5a851f, 0x25d844e3d67ae874, 0x691a89771f137ccd,\n             0xca8f6453f012d613, 0x158a56bffbb6542e, 0x9667b2df43adc18a, 0x82a482cdb82ccd33,\n             0x86f23a6a7d54ee73, 0x10b288302011630c, 0x72f0b5e8108f2e3e, 0xd08816485419d44b,\n             0x292749c4fbc842ad, 0x07fa57fd3f710576, 0xbdfe186fb6e9605e, 0xfdcbc952e08575b4,\n             0x5e1dbd6529d264e3, 0xc73b293a3b75aaea, 0x20e2746b424bff06, 0xbe8dcee4f3793f95,\n             0xfc37bafd71d28d02, 0x146bc82688a600f8, 0xa4e31a7921f4866a, 0x6be384144f50b823,\n             0xd05767e270a2e1a1, 0x41bfd973068a4c4f, 0x1e4873b521193e66, 0x130153168fb5aaa1,\n             0x93fbaec1542cbc12, 0x6e1f19d495c361c5, 0x4329283df219a2c5, 0x672bf020e0c1d4e4,\n             0x3f48a8b31537b316, 0x87668440288d52f9, 0xc8fd2dd7b4b72b4b, 0xb11a3203b4f8f7c9,\n             0xb72a14543a3b9ae9, 0xe51b7042e992ac55, 0xee499e479bf861bf, 0xb04bae711f12d1ea,\n             0x42bcf82439cf0c22, 0xca1614395a48815d, 0x54efb183aea373f1, 0xf67a16a89843e5d8,\n             0x6ed5f88106841757, 0x21d5f0e808994091, 0x451bbbfe4dfa9d92, 0x0b4aa49a1a7a4f1b),\n            (0xdba1a6db9d03c7d9, 0xbeb755b1ae73cc3c, 0x1988659f145c1d8c, 0x274c07aa5123a5fc,\n             0x0ad221abb3826faf, 0xf4a9318402059f40, 0x7b390278b43e57c4, 0xb0ff9ea2672298ad,\n             0x783c161fdd897dab, 0x4260287a0bde44ee, 0x443b90f2dd98abee, 0x0bcca40dfeddad64,\n             0x8330c8c401ffe27b, 0x32c5866a4750c213, 0x5245655283521bdf, 0x41d6b7329ff37fd9,\n             0x0d5df9f5232c5c74, 0xef4e0d30a927627a, 0x0585d814bab77de4, 0x9312658f34327f6f,\n             0x33dfdb7b1e300c26, 0xa1107ce213b370fc, 0xeaf19df730f494cc, 0x4582dea0e7428018,\n             0xc5449280de42fe75, 0xfe6b95ad548ab948, 0x393fefe06f21ab10, 0xde90892ad990e0f3,\n             0xd2e30c290f336f84, 0x2ddde78b6865c65d, 0x04bbd0370c926e83, 0x6cddb9419983a582,\n             0x9231e322f8fcdf5d, 0x10377b0fd20bf266, 0x5154a13903eb47e9, 0x69cf3a796939eef4,\n             0x082cbd2ad26fec3c, 0xf725fbd2534f26b6, 0x5b601e461807a6cb, 0x20a468fc66e8e0af,\n             0xbfc9c06b56da2e16, 0xcb7bbd21f4f37a0b, 0xc1c2a595d07f6fc6, 0x8748ab5f2289128b,\n             0xdcaf70b2a21831b2, 0x35b91d50af5141b4, 0x208bb4889120ea69, 0x85ad8e1ad9ab868b,\n             0x0ba7a0a8d51957db, 0x3ac5ff57b4ae1e4e, 0xeceb63c54a40e4d9, 0x221bb31ae61cf708,\n             0xa7555562d793ffa3, 0xa07ab01631b5937f, 0x3bb3fe79183ce5a1, 0xddcb113e60c5fbb6,\n             0x29d683e168e53782, 0x9a02e59892b2c39a, 0x6329071f09d80fd9, 0x7bf818b62be8ebe7,\n             0x76913be4ce37854e, 0xc80786d5d30a3c0b, 0x822c349d71730f41, 0x1dd3c708bfc04117,\n             0xb6b814d594190e8f, 0x10347607e7b0ea1d, 0x5c9aae9aebc23d64, 0xf13d661425a55e2b,\n             0xe02308f5a5dc5f4d, 0x2460d10affb6ba4d, 0xcc12129caec36255, 0x0896a4e21c2b83ca,\n             0x09cf4f9fcaaaba24, 0x843ccd131956f015, 0x0a23760f57baf4a4, 0x27401e08fc43b587,\n             0x5600e3ac14476e12, 0x024abd19ab8fdf0a, 0xad6f0b4576e82ad5, 0xdcc4f056feebf4a6,\n             0x2d63e08f57c7db99, 0x26bdf096064dca2a, 0x32a1cb0ad5e3a427, 0x1d80c9a23268fdb6,\n             0x9ebc813ffea99923, 0x1961a9811949bc83, 0xd2c118948f835f66, 0xa7778ef1ae0cbfde,\n             0xbe681ab20b681aae, 0xf5edbfc7c8b3383d, 0xb111fb62de87bb1d, 0x689249a67ae8a7b3,\n             0x38e0b6c3909fa0a7, 0x0a2de5a12a26e529, 0x5ea086b878cc3486, 0xe09fbd15339524ca,\n             0x219564e3b22ef108, 0x911d75ad4d239572, 0x4cf9c35a3d6c28eb, 0x01e750d8ff5266ca,\n             0x0b50a9abe6a5d479, 0xdfb823ed3d783ac7, 0x876e4d170e691d21, 0x1667b2b8378b456a,\n             0xe53793eb4f5e1dee, 0x4aea9c48853d73ad, 0x2632a2b0dc982f20, 0x945221a01fd8c169,\n             0xb75e5c4da922b356, 0x5a1a7ede0f59d734, 0x7aecf3b3019490f1, 0xc187366ba239b7c1,\n             0x1ce3c5ca9e0d49b6, 0xb95f5954f25956ad, 0xd7158d7e25906462, 0x1e4d0b59b69a0c6f,\n             0x987e6168bf9fb0ae, 0x46add5103f7dbca7, 0x41ab9d2f951d9f0b, 0x3f6cebc12227d563,\n             0xb31cb2f0b4169683, 0x1cc57c0b0c409c60, 0x8d9f9335eae1b2f8, 0xc12fa4638c2a4210,\n             0xe93950402aabe307, 0xcd571cb16bf81f09, 0x020ba289957936fe, 0xbbc82ce80443c76e,\n             0x1962ce1ed7c04f69, 0x5132a571dd4350ce, 0x1c714f9a34d03f06, 0x7106138554debefe,\n             0xc66866133b80e4e7, 0x3846cabeb8b6f670, 0xe9258d9fcf1d96d4, 0x5afcaa0a17ae66fd,\n             0xe71334bf8f5f1646, 0x82508467aea9d877, 0x76cbc63a883d6a08, 0xfc8f27eea94e8c3a,\n             0xe96b1adfac6c277b, 0xbfc9389b8fb7350f, 0x04ec384f9f264c33, 0xe834f24eeab98f5e,\n             0x8d6f1a744009d5e0, 0xe23381fc46da95e2, 0x9b10773bf64bfc7f, 0x76f4478140c2ea4c,\n             0xfb687a04824d6208, 0xef91fa7c132618fb, 0xb11b008ca4ea937f, 0xfca2e2f6c66f8065,\n             0x481819ddb24f0c82, 0x64b0cf5a6394bf4b, 0x512d9a63f0ef981a, 0x54f2ad79838d0552,\n             0xe2ea9435db0e17e5, 0x5c4c2f06f2f3df06, 0xe9115b96ab390fe6, 0xf71ce5ea5d747f55,\n             0xc320df1bf143f16e, 0xbff59038dfa39bf9, 0x4006d3e07753c04c, 0x781343c38cdb4b6b,\n             0x13a73766a6453470, 0xf459e22033c7546c, 0x68aa9a20670775a7, 0x5e0678ed6d04b048,\n             0x2838bb1e96873975, 0x7107ed53726516e8, 0xe03fbb85382deb83, 0x77a765418ada547d,\n             0x9c58101f7c81b337, 0xf428789abda860b8, 0x50bd03bb87c98869, 0x3a40958fecf1b84b,\n             0xd64960737ff771d3, 0x5e5cd9f5037928ad, 0x050c0df313f3d698, 0x74d882312d04bee8,\n             0xe46d7dc8ce461092, 0x585fd8cfb0cd3340, 0x22480b6f7830bcb7, 0xfdf5c84ce6ed2689,\n             0x08a31565fc904f8f, 0x9c33e2cdb664bd1a, 0x61bf5a1fc92e4e4c, 0xc656cd95bf46e7d0,\n             0x3f965b5137bd3cd0, 0x693e57e031686f68, 0x5f16a18b864a08c7, 0xd90d9514bac21cdf,\n             0x0e9f69772d87961a, 0xa63c41ea522271f5, 0x33dd1742bf48cb69, 0x5f9e93ab95d4a003,\n             0x8811aa89c122f6d4, 0xc7cf93b14d1c3ff5, 0xfacfdee630b4aeb4, 0x35f9c10cedf41e90,\n             0x2db4cc50fe6c0ea9, 0x3e7a241fcb613c3d, 0x9b82bc3751a8ebb3, 0xc6e11185c8fe231d,\n             0x8e913ab258c9cf96, 0xb22289f6b3481888, 0x4312047c3dac6d40, 0xa24cd705f4fa4cc3,\n             0x5b2b37ac67a9e33c, 0xeba946d2ebb6a8ef, 0x7e84cb4bf5a72a46, 0xbdf64b9de64f4826,\n             0x3be96f604de555d9, 0x9a997f0d154cfb0d, 0x1a445450c798849c, 0x559a441390e0a572,\n             0x4b16da28419114f4, 0x1b222eb6c4f6bcdc, 0xa9b5767e0368dc24, 0x5829fb955d05e0bc,\n             0x5b35773563a2570e, 0xf42dae3b54fb849d, 0x10ff2ae1a4352a41, 0x68603aef8fbc1c2c,\n             0x30ffc33d8617b7af, 0xa6884c3017938234, 0x86ce8b5f89d70aec, 0x2fa6b07f2303359c,\n             0x05122025d4ce7012, 0xaee0366c024e91bd, 0xe86552b06751d6b9, 0x5aa33a2c23ffaa71,\n             0xa6d52a9b4e149662, 0xbe7386bf8ce08425, 0x7e359d55881a1265, 0xe6925965c0325717,\n             0x03e7a35cceaed7f9, 0x09710f9214147168, 0x311b86c8d4ee5f46, 0xd7149408a9b70a88,\n             0x8673af6da58ce7fc, 0x4b41bfd656279783, 0xad88f4d8baa2b5a1, 0xed090a2e7896bd39,\n             0x9e55b77f0ea9df30, 0x06a14ba450faf565, 0x538e277d514f5cd7, 0x553ef83ed3d930c4,\n             0x628be1f5401120e0, 0x748a10b2457c2b5c, 0xe74843561286c395, 0x376dfe7d45dee31c,\n             0xda0616758ae4226c, 0x520f40616e96b69b, 0x13af9a7055f0b44b, 0x1fd54758acf80009),\n            (0x1c9ceb260efb4863, 0xb5e64895da4f5677, 0xebf43d472f8942f3, 0x31b59aa2862c2d1a,\n             0x7b602cff0a2c5723, 0x9408dc928c3f2db3, 0xd8f871861f114d25, 0x47d6f1f4a4b1ab85,\n             0x8eab4171e6529724, 0x46a99ee8ebc73c43, 0x1b9f4886c2d1caed, 0x1dce744ac3157036,\n             0x00c7b0f962c06a04, 0x5d310ae7406bcb76, 0xfcdbefb5050c11f6, 0x7593822a4c557e6d,\n             0x8a2d97bf7f265fab, 0x93501bf7692c7501, 0x1821f065cdb26114, 0x44ec3aadcb095a07,\n             0x229d0ac323d5ab09, 0x875910368d8ed0fa, 0x2d5d79a0b94f004b, 0xa15d15079248dc22,\n             0x8c810b38cafc3691, 0xcaf07e2ab87c0258, 0x67dd27b48487e8a1, 0x5471a842fa5bbf5f,\n             0x265890478b12e557, 0xf81f5bda06ae9417, 0x00f86596d7edcded, 0x0030f7852ff9d71c,\n             0x2539c27d89586275, 0xee4a74af3670f093, 0xdda7c30323de09e2, 0x073a367c5db02841,\n             0x1b50ace0779e84cf, 0xe2d428e81a75518c, 0xe4db050d15c36858, 0x169290f8e3fab8c5,\n             0xa1047ceb315bb5b4, 0xd2427b2c39e1f66d, 0xa389c20cdaddda66, 0x3fe0ef0e9f1690e4,\n             0x181426cf6bc6930a, 0x65e0afa1d6d3796e, 0x40d68002b8f495b5, 0x66991d3b2f2cd956,\n             0x0e8f03f33699fc27, 0x15c466e742967cce, 0x99fee8904409a756, 0x8ee27d6df2c298ed,\n             0xa1c4b56252b427e0, 0xe636ba49739e4c17, 0x71cc69cf5afd7dd6, 0x79f7cab33b359fb4,\n             0x51d31fd8ff01fb52, 0x9522d41b433c11b5, 0xcb8ab38e38c8dee9, 0x07486593f8ca03ca,\n             0xf4387de357cd35da, 0xd08c8891d1034c59, 0x9fa078346c5d9de5, 0xb563fb67842a8ac1,\n             0x79c236ac45c40e83, 0xde2b773ec7f775aa, 0x60782783a67275d7, 0x19e824da1d7912cb,\n             0xd6aa9882aade1567, 0xd8639f3d4b67de1d, 0x9917ae518899b980, 0xf287544cedb2ecee,\n             0x51ab50ce1c172c2a, 0x24957d15dacc94cb, 0x0ff852467d881fe4, 0x5175f7d8037fa1c8,\n             0x4c4635177fb8df41, 0xf98124e670c524e8, 0x2e61208ad685f8d7, 0x7a913ef6edf8cbe6,\n             0xfb17e2a30a94fba7, 0x882b441f6c2c2998, 0x426faf5a8ade4d26, 0x67f1823a69ad1445,\n             0x328f18d49b7db179, 0xcce7a451fd097485, 0xcfb9ed933d37d7ec, 0xaf691ade2646298d,\n             0xb9fae9dcf358f8e3, 0xabaa4dbec4d6819d, 0x4f975bee83279f1d, 0xad5245e1005db9c7,\n             0x79f056b64ef71cc9, 0x88b3732cbb8f1d71, 0xb681232346209515, 0x6dda5d47e8f8a443,\n             0x4b02ec20db42fdd7, 0x0507170dec533926, 0x23e2b004a89fc2cd, 0x5b8d60f96e527eb0,\n             0x5b31089aa4820bbc, 0x2a11677b0f6b3020, 0xba8c9040fed3a1bb, 0x1466a4446cb33c0c,\n             0xdb7b32b40c53a9f1, 0x50a567acd661a265, 0xb697d2ca8e9cadc1, 0xcfcca1ee97abcfc8,\n             0x299ce083fc4f1af8, 0x3e0db18b6eb8ef95, 0x98685cc8c1bf21cb, 0x670a3229fe3006d1,\n             0x5217d4075227c253, 0x1657536e2e662bf1, 0x6f747d623ed31eea, 0x58e022afe49b5964,\n             0x1dff848c3758ff16, 0x27906a3903b21cf7, 0x2e14f735660ac57f, 0xe6711122acc1cfde,\n             0x981361e61556bbc8, 0x6ddbe0e2c0463b2d, 0x5650bbecb0057bd2, 0x5581e0628dbf3f91,\n             0x140d54c08e98ee67, 0x6ae633c69d48b304, 0xcf2371f33622ff68, 0xa0251b2559e52f82,\n             0xcd0165b13afe86b8, 0xb9e142b723b2cc6c, 0x9a46a66a5ae6fe31, 0x42379d4aba1d104c,\n             0x47d2179bc036ee92, 0xc030e5091430af0b, 0xa6bc28272f1afa32, 0xd7ac66565c2b4e88,\n             0x3931d78eabb40696, 0x292b8155482f6612, 0x8d3b7c5705235a17, 0xe688091ef33efe07,\n             0x64c2177375c3c069, 0x738c4737ad92b9ee, 0x97b448154c2eb02b, 0x85d3bfb29eb5edd6,\n             0x7d12c9e923b5e330, 0x0dec3056060509b4, 0x5c329afb0708f16b, 0x3a087f4cf16881d3,\n             0x34b3b572c287950a, 0x4709b3ce10791a8f, 0x762de64a09165c99, 0xacd9678cb2604388,\n             0xaa2ac95f4acfc5d7, 0x10b33dd533859362, 0x366aa3dd012f184b, 0x76ded6ef532963d2,\n             0x02957eb65ec79291, 0x36ecb5f9cf7a2464, 0xae398b1adf5b0959, 0x5c8dba6b4797ac80,\n             0xb68d6784f56b595b, 0x50ccf406ef0180fa, 0x803c90965a7329b5, 0x08c9139fb14fe480,\n             0xff23e983abd0e7a8, 0xef64426bc7f34a3b, 0x4b92344b842c24d3, 0x27de77709d3b251d,\n             0x66ede61d436dbb37, 0x5cee38caeca68765, 0x61fabde49a8e4b2c, 0xcb5fbdbf6eb3942a,\n             0x97c61a7a3dac0f0f, 0x99568cfe37427c21, 0xd4d8b10f4ca79c4d, 0xc99b17b21f9bb0f9,\n             0x78fce2d5b949497d, 0x5cc2dedf952bd11b, 0x7c3b120802a2885b, 0xa4aaf4d0c75e3f2f,\n             0x3f3bf1ab4838089d, 0x7f157c23da273fb0, 0x747f4617e50a2b38, 0xc67de91e0729abbd,\n             0xec766c666e2f37e0, 0xd241d030f0c5c9a1, 0x26ba5e3163761972, 0xe4d166acf3bc3a73,\n             0x5af5fc5c953177ba, 0xf80bac4ec52ffdf5, 0x0535e40e0222ed2b, 0xe1d3956e11e28a08,\n             0x3db9a75d62f12f29, 0x81ec42da9af1da3a, 0xdbb44dc0bec9d9ad, 0xd20c5227583d0c9e,\n             0x801c730bfbc819e5, 0x4bdb274da311ffe4, 0x8456ca52190ee3cc, 0x2cfbf4d98148532e,\n             0x3d3964de84036924, 0x48a992691e6691c6, 0x6f90bc13ac87e4cc, 0xd0934edc521fbe3a,\n             0xf739aab91ff97fa9, 0x8210d82c1ea5d4d8, 0x36b65f9f60808070, 0x7c2783dc70301c75,\n             0xe2a897cf0781aac4, 0x21554fd0122a8018, 0x6f14b37d58c4e36a, 0xf16a7bdf721ac27d,\n             0x3d2ecb3fa9ee8f4c, 0x50e260fe66e59749, 0x710ab9b2cc61fa6f, 0xe20cfbaf3a670969,\n             0xcefdeebf79bd58b0, 0xa048e75462f66078, 0x3ee16582f74e36cc, 0x39fa658b4903e708,\n             0x76b8c756a09dc967, 0x1696f5db678bb730, 0xaaed7509014b8d5f, 0x7afa4992e49778d8,\n             0xafa09a650a395974, 0xf9cf8b48502810e3, 0xee04ee85a34b9b98, 0x974443475211c235,\n             0x5e0cbf485b68c912, 0x0ba950e1c4183c7e, 0xb12678f53d6a66e7, 0x28669b636c985d7f,\n             0x79c6bdaab0993317, 0xe442453da404fc48, 0x08cb45985e160edf, 0x2858f31c2796e052,\n             0xcf62b7f1c2c22b9f, 0xf0788972068a4f62, 0x34f9887f76eba575, 0x95c434b64ea81f6d,\n             0x258ca9b0f2f17f14, 0x5de8573df81886c2, 0xb8d99c6ff54b4618, 0x5dd87e7747a2b098,\n             0x7d5ffb65d569a1c1, 0x986e09f219740612, 0x655a6f1639597f41, 0x70423f3dab01a457,\n             0xba24e574338a9020, 0x361df588a5d4ee5c, 0x8d9ffca0bd1a97b2, 0x2855802582629929,\n             0x034d70bf9b925a2b, 0x4fcf470059f750de, 0x2cfe1d4d15048e72, 0xfcdb30c6e791eccf),\n            (0x42af1c2461e205e7, 0x575163c5cc6ea89c, 0x0a5e2231dbd13a7e, 0x052f2656048b3d9a,\n             0xcfca8811d34bbc81, 0x7a6b05722299f06f, 0x09b1731972cb6200, 0x4c83fef43dc6ffdc,\n             0xcf493d7d10a65fab, 0x030924cf1b61d3e8, 0x5a5b3534f9a3b1ac, 0xc93ede4e88e2c3a8,\n             0x54a9479be3eb2262, 0xf295a3a61efa6184, 0xe89292aaa9aa5595, 0x6349754f7cc8a777,\n             0xd6b389a222048d46, 0x55d2389e9659f77c, 0x93ec80e9994c6e0d, 0x0e63628f031b254d,\n             0xede4a35132aed725, 0xd1cdaf18b9f0e8aa, 0x16cd3baa0d9a0a39, 0x83b529a04c7900e9,\n             0xc90084bcbec8f7d5, 0x849cd2e219f6f6cd, 0xe277cb4cc38b851a, 0x6feb04f4c1f813d9,\n             0x190bbcd015ff7318, 0xe45e2db48fb8d45a, 0xfa4cfb3ae5b4bbc4, 0x9af58102f299a42f,\n             0x95e9e75ae76d00fc, 0xa0297e960da629cb, 0xe676ae50bd91f44a, 0x9a1e2d852fe1d296,\n             0x6f0e433828439cd4, 0xa90fb781ffb87580, 0xe7cedbea3a6c1790, 0x87e559e79059af37,\n             0xf2136faa4e5c323b, 0x46959be7c458a6d1, 0x5e3520906f1ba20e, 0x5d87501855a949d4,\n             0xea52b82f62967ccd, 0x6a7032b0dfe7644a, 0x6b73ea2c7231dbb6, 0x583cdcf825d59277,\n             0x704781b5979c4223, 0x3e3fb166357c1d7e, 0x92ac7147c41cadc5, 0x24eb2e0d1baad9b8,\n             0x8c7a85466a8a8da1, 0x8e8d3fa81d46bda9, 0x2869b279c5e01a4a, 0x3a9f00c89a3cccbc,\n             0x1b8ae167bbd11c67, 0x0ffeb7d05f954f4a, 0x5be8eb33187df70c, 0x80fc601151069e1a,\n             0xbcc29bb2e7e6b1d4, 0x62ef511ee8e1dfb8, 0x35c74ab75717626a, 0xb49ccf45e424dbbc,\n             0x05ae4f9b1c30e72d, 0x78bdaa1a88a99472, 0x539e5acd58e30cff, 0xc2cb802ea3ecf9d7,\n             0x3dd8150b45e46891, 0xea9fc6d642be554b, 0xf952d6a5e49814bc, 0x21694e510861d401,\n             0xe7ae0f8fd6f0da78, 0x3796d3bf1898bb84, 0xa9075e588c1b8d9c, 0xece61995ba2c87f8,\n             0xa70aed7e57159651, 0xce8dfb1046ba1234, 0x6ebbe219690eef84, 0xedfb303192440949,\n             0xac9f4a3313d8ebff, 0xe598def435bc34ce, 0x28a2888414730528, 0x57dc9eeab1cc8ded,\n             0x12099528c032c7a9, 0x13cee73289831672, 0x8bb08e6c6e32d73e, 0x76f47a8774c49419,\n             0x7fc05bb3d783f5c0, 0x7b6d0086e94d5105, 0x7d9ae4d4359e5e0a, 0x0792ece3010fdf11,\n             0xa8ff03386e1f6857, 0xa1da1915fc9de751, 0xd06f8a3972f19626, 0x010b60dca0d384d7,\n             0xbfdd5c5f1aec26b1, 0x684c2375819c18cc, 0x3bb5b153bb269a4a, 0x217e7960a13ff22f,\n             0x2c93f2580ec88b5e, 0xbb735b32ca656dd2, 0xcc860be37f19c5c7, 0x8da68c9071221ac0,\n             0x14d2e8365d101c68, 0xad635519b02e6c43, 0x6a59e2f0adaca340, 0xdc20187b5df9e2d9,\n             0xb73fe387a26e44b6, 0xd32f3294c4e283ff, 0x76e1b5e8bf04cce7, 0x57d618d1c73c5cbf,\n             0x36ff07d6559b8789, 0xa942501bea6b5c99, 0x23f8b954897a8a34, 0xfdec0cf58bfd5803,\n             0x455ea0db4d6ae2f6, 0xc787cbe98da8c071, 0xdf713aca5b552a8a, 0xd34293079fd7143c,\n             0x404e6e6595de26df, 0xe545450314552116, 0xb599fb1c0a0cf203, 0x817ca7bd53127a57,\n             0xca0cacdbaa65a933, 0x65da7e15f4801c8c, 0xed826d65f985c801, 0xe124058598f74d7c,\n             0x1c4148d3aa15f0fb, 0xe40da0eed0ffc7cb, 0xd7fb021d5e68c5ed, 0x022e761e51a65629,\n             0x92416761f1d78545, 0xd5eded28964a5dc2, 0x1cbbdd86568b1301, 0x7d1d9c9d5191fa23,\n             0x9c84122a23e787a3, 0xf0aae22438d61d14, 0x767bdcb894e9b5f1, 0xc8e54f085d3e85ad,\n             0x107e80aa2de943ac, 0x9ee3c641f9303797, 0xdbbd06c34163adcb, 0x4ff559a34150f8e4,\n             0xeffed9fcea4d55a6, 0x100d3d521795c966, 0x84a9872617ba987a, 0x8245b0be30851879,\n             0x4a7a00c0cfc62d66, 0x1a9c2f7c0af63c89, 0xc627f1e50eae1edd, 0x27a7e28f2376f50c,\n             0x583b7830d443d79b, 0xe99ea7649a62932a, 0xed6a91b87a7f5398, 0x19207a5c0010f2c1,\n             0x4c9151ec2540092b, 0x9dafeb33ab61373f, 0x6e25827a66c7139b, 0x0695bc78b75b7417,\n             0x91eeb83fb91d0093, 0x487878828a059ccb, 0xa972d875f120beab, 0x9ddcde21e6708ae3,\n             0x1bcbeea1cad06878, 0xd3b35c29b512f927, 0xa21df9bcfaa42752, 0x5d4f6279bc577455,\n             0xc700104604bb7094, 0x13bb0d4d74468a55, 0x98c963425fdaa618, 0x1083bc2b3e7e4169,\n             0x3fc24373f7f14efb, 0x2c806da85c981170, 0x38471408d474e25a, 0x3bcc8b68de988a47,\n             0x7f466e2394095394, 0x5f79fa82cc84b4fe, 0xe4ef25f3a6005a8e, 0x2616c3f5d347b849,\n             0xa91309a99648cc51, 0x3ad18baafa3a3785, 0x646493d438846b93, 0x33cbdafb2f71a5e4,\n             0xf078d4b7316983d4, 0x56c08649ba5ee554, 0xdca51fada3fc2de6, 0xd1bffce0bfe748d6,\n             0xffcc723739d0887b, 0x1c872c55ad37b228, 0x90c1504a645e985e, 0xa74cebf5085c23ac,\n             0xf42c8e93ed09f34e, 0x71209b98f7bb6c11, 0x54b56973d9fe2c21, 0x3ea1209fde2330e4,\n             0x7766c42c4f04cf59, 0x03686a90950de638, 0x78dadf41a9b86257, 0x9a2718692e0c8272,\n             0xb13f41655a094cfb, 0x14c8a7e37255920c, 0xf235feb8f3f47556, 0x3885ebcef31c6408,\n             0xb98fb084dfdd8d03, 0x74f66ecff26f4061, 0x844c37174a0c4372, 0x76f99c708ba74d83,\n             0x4983890bf6c09aaf, 0x9b6fefb3dd0c3174, 0x62f617b31ea74edf, 0x25b21b3cd24cc684,\n             0x04d7ac4c7759fba4, 0x8482fe65c71d6336, 0xfc7861d998e02073, 0xd7f9722db6aacc8f,\n             0x6870ab492b30b3c4, 0x2ece0a7a8a5fed2f, 0xeef1d6c4bb09dcf6, 0x5435ad078617bc61,\n             0xe6379f0e8aeb78eb, 0x6c20e46fa4221ebb, 0x3e46478bd8152093, 0x7123630de738c9ad,\n             0x978ab949e097ced6, 0xd9e7e7e7fc05b3e7, 0x8b39851640afb2fd, 0xda2f9ab8a8daefa1,\n             0x702d92e74a49a01e, 0x8f27c82c59cb4dcc, 0xa02c191c19e50c37, 0xb27067bc3f3699a2,\n             0x3bf3bd9826ed637f, 0x5704a1588c2f9363, 0xb9f98c6b4f32dd38, 0xe5b042e74bb01dec,\n             0x5028dd896bd10768, 0x8c08ce41850b1547, 0x239315793f2ca3bd, 0x0828fdec05cb4523,\n             0xc4c81295367071fe, 0x15e0f0d81954258c, 0xa6088f12f97d8f02, 0xd8d0f216072e98ce,\n             0x726eb08402fe516d, 0xcec857de79f4a362, 0x6a7960a53f296fac, 0x81ca44e6fce0bf94,\n             0x3530e7498f1810fb, 0xd9c441e49a61a487, 0x6da37e884f2ee127, 0x4fe38bcc0e50de75,\n             0x8e6df28b5a2b61ba, 0x7c6c9ad29a009d5c, 0xefabc870b24ee954, 0x35002af7092296fc),\n            (0xd643397f935094cf, 0x870bd92e1f824ec4, 0x34bdf0801de60cf7, 0x0d88ec4692f77eab,\n             0x096f64e22f2b82c0, 0xb53458674eb5723e, 0xf1fc71e1c11345d8, 0x0e964db1ad53757a,\n             0x988a3bdbc77f8978, 0x35e1545894f83b08, 0xe1275b6e6589915c, 0xf4354bf61444cf4a,\n             0xa58d717df825f33c, 0x4326b9b7fd30372f, 0x9814ed164f854d06, 0x4dc8b7c29b22a57c,\n             0x07ab775a341455ce, 0xd4a93150c9420e9f, 0xbeeb68e2fba01f79, 0x0a6a8784da51c85b,\n             0x6dc1cac53356069f, 0x3ec8402647a540b9, 0xabb002be62f631c2, 0xc8578e9eeb8dbcb4,\n             0x72f35b79c1a6d5f6, 0x56127777c0b225fe, 0x8b035e5efed57610, 0xa15af83a006047c5,\n             0xd42bd6d1a406a7c7, 0xf45ac35f8017e304, 0xd8f9d5eee6d21114, 0xae4dc44e7cbaf815,\n             0x76da39c947457f35, 0x6c59b49c36990bb3, 0x81e9cf29dad76c01, 0x018e04d96b5e00f7,\n             0x0d0e0000c582dd99, 0x3a48024755598a84, 0x4f1ea17482332fa4, 0x5b2d5257cf3cc329,\n             0x35b78e8183be6809, 0xb66b74cec64e10be, 0xc43704cdf86c82c7, 0xba20dd2fd22245f9,\n             0xd3f155e74d3c34ef, 0x773386a7f5b97891, 0x7f47bfb5080fabfe, 0x698f0ea424892589,\n             0xe02aeedc1d0465de, 0x397c03a1efe48995, 0xf7391bf919396f17, 0x065b71e10dfc5c78,\n             0x4976dc3d03263662, 0x8ecdc2f3253d965a, 0xabbdfe3331b3a292, 0x77838268923d9e45,\n             0x7aae87626b2f234b, 0xf46129cc031f40df, 0x1f212e0a147417c2, 0x55b6b1aa224dfcb0,\n             0x5133b4500bbe43cd, 0xfbc79204742ce63f, 0x03876309d0e8385f, 0x6febcd9a1f6079a8,\n             0x7ba954c6455054ea, 0xf3d956ebf6bf754c, 0x787136d760fa86ab, 0x03103c0af24ad845,\n             0x3f9bf3a7803d27ed, 0xc7758304e9a1d7dd, 0x68b776103718d679, 0x647918cb0c3b1002,\n             0xe83ffcfc7a293210, 0x1827d2fe3cdb6100, 0xa66a981415a7fe9f, 0x5e3bf0ff95ef70b4,\n             0x31adabfc1ef6d618, 0xba89ee519226ed52, 0xf72d137a34f811d3, 0x36fa9a52547c9d90,\n             0xfa3fdac9426fb713, 0xe075b10c22cb29c9, 0x10e6f71130f4f17c, 0xb6b08ee0ab994e27,\n             0x38eb08e2e96206c0, 0x28ab4ba59aa7f167, 0x6855d4430923669e, 0x15283aac25c5a57b,\n             0x18223fed9f4ab72c, 0x13de014e80359fd5, 0x97b7031627ce8ca6, 0x25534e7038e0be03,\n             0xca53a631b6036a63, 0x615f7f968bba6ec3, 0x3d139c34669ace55, 0x2560953fbc375004,\n             0xf098997f78499943, 0x67b7293962a8e3b3, 0xd4e976b0bb5f200a, 0x88045a1eec3b915f,\n             0x650579c0fd409f13, 0x0f080e3aa4423824, 0x770af774ba6af720, 0x5be15bed26f796e4,\n             0x236490967eb624ba, 0x2b8d21d13c3b7d5b, 0x2d9b375a42fe5ee4, 0xddfdf2d9de6a561a,\n             0x1c2486976109d824, 0xdec3081cdfe358d6, 0xfe951624333136f4, 0xbe686a96a0b52b1d,\n             0xe66e8bce1e364bea, 0x6df104e7bfdf7e91, 0xe7f33ef7311a6099, 0x6b32fffc9718ed4a,\n             0xaa0199b08b186928, 0xcc9f16f855ef9c1a, 0x017092dd07213183, 0x064abbfbc44dd974,\n             0x62bbb46b60f500f5, 0xa1bd0f9095445a46, 0x97ee11dffa92815d, 0x26d12a66ae07d435,\n             0xf7de1e92d1be930c, 0x6616e6c83a5b8f01, 0x2dc4784fa0abad63, 0x66739cb22920f6d0,\n             0x75b41d4c0b6ea297, 0xa4674e33c01b6cb4, 0x2491ee2be9d7e7e2, 0x2bd62ac084f447ad,\n             0xdb9dd852332b8ab3, 0xf256424278e96d76, 0xb95a91ee0dcc405f, 0x101284726a2333c3,\n             0x16267ae96c1574d9, 0x93662e5f54bd05ba, 0xc4a5dcfaffad5a43, 0xe645e365d2e1b59a,\n             0x1204d3ee428de7ac, 0xff8ea450245313a6, 0x2d6d1774b16daa30, 0x73ef7d8e469a4618,\n             0x4bf3aa705a8c2da3, 0xda274e53250d5b5c, 0x00794714fc3fc6c2, 0xf00146dd8c1ee01b,\n             0x47612f7f8fe3848a, 0x2fc781f293466b0e, 0x28e1cdd7147f927c, 0xf5b62e523877e1e6,\n             0xd948975345d7e13d, 0x58d54af4c24bd134, 0x21f3c1bf27507421, 0x2d2f90f8dc746967,\n             0x28dd99817b768a6c, 0x57915a1583ce87d3, 0xac0ab23a40616f11, 0xa65dbfd006915044,\n             0x557c0895a56b4245, 0xfe4f40cd22fc47d8, 0x42c9ce0545f64fdc, 0xb2546279b2330ef6,\n             0xd557684a79886980, 0x1f14fd7add35998c, 0x349abdfb60fd25b2, 0xedacca8c71183fe6,\n             0x5d66f18300f698fa, 0xf82a907433149c24, 0x46d5b460f6fa5d08, 0xf9a0397d4b052203,\n             0xf2f805f60108cd85, 0xac4f73cbb1d4d0db, 0xf4a1e9860cbd7b36, 0x5fabe1ff3943e95e,\n             0xb157d7e510f316d2, 0x29c71cb4dce9c30d, 0xbd1600c8742d913e, 0xf0fad8ac8544166c,\n             0x0e4a3176f004252b, 0xb16042e9722b2d1a, 0xe71c2541a526341d, 0x940969bf250d8683,\n             0x97069a9a389a42be, 0xa1cc8c18cc01b000, 0x0fd4dd012f2f40a5, 0x8a416107beadb308,\n             0x0533a4832ed2b8f0, 0xd15c4d5a6acc8833, 0x06f0bbf439a2df7a, 0x2c9417a7282ff845,\n             0x2c5b9c3a132f2fa2, 0x5bb512e952bcb7ec, 0x793d839a35909222, 0x07f5d8cdf3863822,\n             0x2da8ccf7e602cbb5, 0xeb400de34a6e633d, 0x765975de142722cf, 0x56106b69601e5a71,\n             0x039eba1989e2c864, 0xbecf64aef6421c51, 0x51df9f37865400e0, 0xd1f6cc3e1d125b17,\n             0xd424ece671812913, 0xc2684cdf7860fcaf, 0x2522584ef611555f, 0x63e0f604eff52201,\n             0xe6bce91f1e547ce2, 0x7856ec4341d227e7, 0x674c5be6ca5f2bd2, 0x3d7901ffe4bed041,\n             0x3fe32ab3540e6748, 0x5d200d621dfee900, 0xedd6ac7cfab1d5b5, 0x004d378c84357354,\n             0xa82b91a70d0716b7, 0xb25a34b14222bcb1, 0xca8f24e379ab04ef, 0xcea7a37de4e0044d,\n             0x5a08b0ad0aab8e1b, 0x6bf17b936dbbdb4c, 0xdca48d8a94a3cecd, 0x0c895559f1cfd968,\n             0x889c9d47c765f0e2, 0xac8a0aef36dead83, 0x18744af10d3c269a, 0xbff26b4469ec3d61,\n             0x487e36d51f0b9f86, 0x73f5efe068da0513, 0x5e1c11d9f32cbcf7, 0x851cdcd1e3bee01f,\n             0x56dca724e1e26db3, 0xe831d5508bfc95ee, 0x219a2c6d9d1edee6, 0x1699b9eaa186998c,\n             0x6934dfbc8fbd6fd4, 0x48cc722371320267, 0xb0aedfee9a9715ba, 0x594f6ee424021157,\n             0x142e4edd538c5c1f, 0xa615f2953f111f75, 0x89de86c2261972ec, 0x10cc626499f63bf0,\n             0x4942effa89b2e655, 0x99bcfb8618553cf1, 0x2f1af6b902b3795a, 0x3f56cdfd0e7c83b6,\n             0x9202b3fc89224414, 0x3ceda32cf3708424, 0x93317b7884fbac5f, 0xcc61992cd32685d5,\n             0xbedfc1ed564197e0, 0x33da22dce6730ae2, 0x48d3520aca2906c1, 0x91264a3cbcb0427c),\n            (0x084ffffbb5c696c6, 0xcbe7059301030cca, 0x10dba0a89b7ae484, 0x6c4be36a95bb4173,\n             0xb0700c47b4283978, 0x96a1905e518eb231, 0x5541ae6048b87bd3, 0xebdffdf2ec4a8965,\n             0xe7dac93967257a3c, 0x2e53806d3dff5790, 0x7db8a1b7c2a1aef3, 0x014e4499be9dfc3a,\n             0xf532a41b1a1851cf, 0xd07218ea39b41d88, 0x7e4f56c1c847497d, 0x21cf671753ce6dd0,\n             0x1b94883a9bf080f2, 0x98ee47908c850f29, 0xea6cc9e9d9faf55b, 0xe4a551ab0b7e8776,\n             0x02a62b1b39d35f9a, 0x2007a88147f3e621, 0x3eee06e77958eb5b, 0x20417def7ce2e665,\n             0xb6c688852c50d648, 0x87de5c6b5dad8485, 0xf98939b74fcba7ed, 0x17f3d88e86b881b5,\n             0xd2580044a988599b, 0xfa3561cee6119564, 0xd6c26fcd95868567, 0x234fe27482a48621,\n             0xab8dd0919dd841e1, 0xe6c5b5b21cdd2ca6, 0xbc5f9aa66aabb40a, 0x259b421a4b3a97d8,\n             0x8a77055dac35ffb8, 0x4a81d2e3a067d324, 0xcaab1deef8052774, 0x228341d3379c7353,\n             0x5aa2bd3dc88ba9cb, 0xd3033422daaefa72, 0xcb6b79fdadb6e597, 0xfda6806f00b4d073,\n             0xd08715b956ed48ab, 0xc9feee61fba754df, 0x820c488b911de24a, 0x9ac172eae6b1aee8,\n             0x8f273efc20c0598a, 0x97c4f75a1965ecd0, 0xd38ed06f0267024f, 0x3ed630c7078ebdc6,\n             0x7722dedc161851c1, 0x528f82cb8517e4a5, 0x47b7ebabd8c1ada4, 0xe489c2a875f29fd3,\n             0x23ace5009500964b, 0x7d7334269ea7c026, 0x98d0c89edfb4b624, 0xc818556b98ed63ad,\n             0x484aba554482daef, 0x5e709598872e48d9, 0x80454a5cc07c5208, 0x3059c5b7c3108393,\n             0x8652d42f18215c51, 0x85f204507877bc59, 0x1e9db87d7857e5a8, 0x4c3f1cdb4a71aa80,\n             0x584dc898ad8e843a, 0x1a184498b6a7ea43, 0xd1c0daa5a7df4757, 0xa7c4bf4f6828f1d8,\n             0x8ffa874157444ae3, 0x56801a315748568b, 0x6bb9e29543dac710, 0x57971aacfcec1304,\n             0xa688901e2be3b820, 0xf7efe98c3ff5e067, 0x67b2538b98b97770, 0x46817d416eca68df,\n             0x9e6cf28e916362dd, 0x06e7bdb094d57ac6, 0x6c6bb1fe23ce6509, 0x22804213bfc128db,\n             0xa4589d1a48a638e0, 0x38c7eedf25cc18f3, 0x2a4678ceadaa91d6, 0x4604b7238747672b,\n             0x82523e882e0c598e, 0xe369a168c43a2d03, 0xb49e8ceececf0d1e, 0x17a66c0499a732bc,\n             0xc387ac5f99788e71, 0xfb46d56c604e813e, 0xa9e743ca0d78e71e, 0x34b11c1b86f01fc3,\n             0xe631825b6f03b639, 0xfcc5b829197e4f79, 0x8597bc4ee6fbd911, 0xd862c82d14bdc588,\n             0x91ded91bf232754f, 0x535a9ccd70dd2910, 0x8524f5b5233f357c, 0x1b742e1751d255b5,\n             0xd12726532a84f084, 0x6235d35f0ccaa60a, 0x39c325166b6061a3, 0xd207e962e32ac20f,\n             0x26e70d9ddf841f6b, 0x4824094da830b678, 0x1331c7082c4cdac8, 0x0417d8c7d030e8c8,\n             0x51ed41c4c8488a14, 0xa4e156901d8a4f67, 0x65135a1bba00bdaa, 0x4fed5f5a6a5fa345,\n             0x632a3b3fd4af6f69, 0x59a6dde422be83f4, 0xffe748b5947e037e, 0xe812f59b25594cbc,\n             0xc9dca9c00f9db3ab, 0x8f81991d125f011b, 0x09da8808c57748dd, 0x2171e539d6c2dfc6,\n             0x3b581ddc83d1d949, 0xe8e583b0cbb1fae8, 0x48544b8891d1af18, 0xda82d2b157a455fd,\n             0x780bb515954b0de2, 0xd176d9a017cb4243, 0x0ea83126593f50c3, 0x6cf30f0f0ad18c91,\n             0x9c642774b17c5995, 0x44c55a544e3fad22, 0x2c0058e2585d332e, 0xbce3315de008b756,\n             0xbbaed746efb1b82c, 0xc29eb7dfb59a6cd1, 0xe12751f6e72149d2, 0x90af883bbf9264d1,\n             0xf3ddfab262f75e13, 0xd722f377fc8ded28, 0xaffa5fa4a7ef885d, 0x6a36d972c412eeb2,\n             0xcaf7f49c141bc5fa, 0xb637c407342f6f21, 0xbe1dd4cf7cf16093, 0x2fe8215ed1f51b9c,\n             0xcc8ec810c12b2900, 0x21d3656c80aa2375, 0xce0e08f184c38a94, 0xbb9679c6903eb836,\n             0xbb680ceb9ce9c7c4, 0x97f7f3cb0ca7848d, 0x9e0bf18fcba0055d, 0xb6dd9d6bef26db9e,\n             0x7ca9cc9a2590017a, 0x7eeb34f72cc16be3, 0x52ede7cb7f1c8537, 0x9ea75aaa6749b4bd,\n             0x9792f16570408254, 0x4dd796fb9588162b, 0x7085612d543bcb8b, 0x6b26fc51f73759b5,\n             0xc1689fe5b7d6c1c4, 0x26dff1655657dffd, 0x873d75acdff1e0c7, 0xa2813248ebaf4a3d,\n             0x6e72e8249a82d279, 0x46ce7c09ec6963ca, 0x1ce96baabfac8ff4, 0x50ce053dd535e6aa,\n             0x81d02358596d03e4, 0x277d1ecd00d37cf7, 0x48572038c9c420f4, 0x53b31c9ef3e4fc9d,\n             0xc3f0a26eb2028341, 0x5b5fe659da6de89c, 0xe916b753475f5069, 0x3a9218b4b99a6779,\n             0xa350047ea0d3495b, 0x24dc1575f99c372e, 0xd834152f7df3b27a, 0x8054c58bd47d2989,\n             0x8d6bc5a2fdfdb4d8, 0x4847278629fc7e0c, 0x99c8a0548c5498cb, 0x5ae85634d41cebbb,\n             0x2504128c70a640f4, 0xfe97981373ecbd93, 0xc51fee579294f879, 0x9b722e425909fe6c,\n             0xcb85da2b0b24c681, 0x439453225bafd434, 0x38ecaab092f5c4f7, 0x7adac2ef7141d33b,\n             0x2928d2245ec7d6c9, 0x378bbea38f2e9c3c, 0xde54e18dfcd61349, 0xc3e2d5eeb99da1d4,\n             0x0db0119e1a49f712, 0xdf44a83c5aeac964, 0x9dca2fc7650fc89f, 0x474f8306e2d0a038,\n             0xe034ae0cafde884f, 0x2028a7060404229c, 0x0bf18db570529a7f, 0x8da4e1f979a89418,\n             0xa1155a0d3e9e3580, 0x72e301904d125ddf, 0x7addd9e135d4536c, 0x9ca0de59a162e0f4,\n             0x6a9cdf844b2a728e, 0x9fb99a8e024b16ad, 0xb1d048bdec41a300, 0x85141c031c2af09a,\n             0x2ce594f8e860b414, 0xfc000df5267e26b0, 0xf90606d58d7c9544, 0xfd4f99f8c5f092af,\n             0x411f84ba8a0cd678, 0x38f5d09ddc852396, 0x5ed7cbfec1e480fe, 0xabf50f7e8e98a922,\n             0x6efcb9ebb4217cb9, 0x2c9e09fd2363a2ec, 0x664669c9fe52c790, 0xf8f6bc9998df87e7,\n             0x875c4cd61ce89b3a, 0x172a71d4b3228e18, 0x6138a69668253823, 0xeea2323c7ee068e1,\n             0x078b037fc5eb3378, 0xc6d01ec2e6b70b7b, 0xf9996aa470e99fd3, 0xd4414993552c525d,\n             0x4eafd7f70466637b, 0x193289bc8dd0b3de, 0x6aa965929bed2206, 0x213c372d8a2ca9fe,\n             0x79ac861e1a994af0, 0xad06caa0fc5126d5, 0x48049be7af6bd0c5, 0xd667ed766ee33bd1,\n             0x097cb7e0344f9b37, 0x8f77098ccfd6fa91, 0x3ff2ebb44510a1ca, 0x79c55b63d42592a9,\n             0xd974cd1b268615c8, 0x7d52e5c34dfb7d49, 0x9776105d8b9204a0, 0x0840458b38b14d42,\n             0x1066c46c11e85f3f, 0x7601ead727ab97a1, 0x7b2fbf3ae778c770, 0x38a6d63621daec6a),\n            (0xdf24348581199113, 0x9a7b6c1f3b151829, 0xe4f2fe468e70656f, 0x34b96cc6a061dd43,\n             0xaa7861d8aed5f733, 0x24863c82dbb04e09, 0x0eed2da59932c9cf, 0xff4a665498a8c039,\n             0x3f0b229cd7e87885, 0x1b9e6809c9d696f7, 0xb102222a12f298d8, 0x725a2f0751bf356a,\n             0x692835a3ba1118d6, 0x81e609f5d249df6d, 0xe8f3b161aa4ae7eb, 0x94b12d6492cf94be,\n             0x1e67eea5746ea61e, 0x8ce6c2710a246469, 0x8c99185499237c3f, 0xaefaf8eb2a0a87ba,\n             0xaec223a6ce0ebbd0, 0xf84595cbe9a82180, 0x5470caf43074a23c, 0xe398478e5128ff19,\n             0x25af45b92b3aac01, 0x55495ab6e2116bce, 0x9a5b792c96f9e5ff, 0xae64519bc81d6cc1,\n             0x5a00b476c48dc4ab, 0x92debd7fea7986df, 0xaceebd147e4651d7, 0x86752eb512f0a471,\n             0x4ef1e846d787dec9, 0xb06be0d0985e6b67, 0xb957e6c4ab228053, 0x4573afb5d2cf0755,\n             0xb2ee6f2b9d274518, 0xad2a55d9bc65f216, 0xbfd8a89f0c2f1aac, 0xb2c92d4fc68fbd00,\n             0x9620105253677c37, 0xac92120431c8bcb5, 0xf8c0ce4043433141, 0x89babcb97025f41a,\n             0x13139a8bde9f054e, 0x7355431e6394e54b, 0x94751623df1d61b2, 0xb74989bc03954dce,\n             0xafbc71237e850d1e, 0x42aa31cbb034b90e, 0x4a52cc67d4907ed9, 0x6694861b35a989ab,\n             0xaf43b5c9282de130, 0x9b2524c038094f35, 0xa891d9dc64431766, 0xd6ea4a3692312b3b,\n             0x7b877de1b97265bf, 0xa8ead120be843e63, 0x72d9befdf168d866, 0x6effe0e05c25fe6d,\n             0x50b8701f80433c56, 0x061cd6b0c0d4f0d0, 0x981e14a20819a413, 0xd56a4b8d531fe266,\n             0xe1ae82fbaf09f512, 0x027ebd50377876ea, 0xa13eb84494130fd7, 0x5c60d48c1e0ab4b5,\n             0xef495aa80b2d5672, 0x342f57349c57da99, 0xbef93e7b4a3178ae, 0x03ffdef7946c14b4,\n             0xc90e466017f6e9ae, 0xa01df96a428b0797, 0xe362af0ac7c877ff, 0x2f4ec2db7215aa4a,\n             0xdc817e6771e9bbc8, 0x097df4cc57fa19da, 0xa94939a5fa44bc8e, 0x964d78e85ce6d413,\n             0x05d0cc26358754f8, 0x4a1b690e1cba6999, 0xc796c3cb03285249, 0x623f8404a8d3ae07,\n             0x330abe6f0032bee3, 0x4d5e7454a690a264, 0x88d54f674fcd951a, 0x8c79665da824cd57,\n             0x24c0f3426c661409, 0x55c099f5c0352376, 0x4dfc4bc9c267426a, 0x9745eb304a429e7e,\n             0xdab498cc80d782da, 0x83775c4d5d61e966, 0x8bbfca82d03e9784, 0xf215fa8171365903,\n             0xd8ab9b7a2c48f5de, 0x0d3f4451bfbfa72a, 0x1b576c12562e413b, 0xd7c515ba764227fb,\n             0xdd9feb19e8e2ed91, 0x21b314081fcc5315, 0xa39bd235a1c57d5f, 0x6b2067a259f0d370,\n             0x8cc2cfcd4a10ff70, 0x7803125f3b96c1c6, 0xf12dc1d1abc15ebc, 0x475a2a10cef75bab,\n             0xce466cc75ccae9fc, 0x040995805a98d780, 0xd91feae8c2c1f331, 0x94e4a42ce98e9e8a,\n             0x0be6c20662130247, 0xe8dc46f283d4c7fd, 0x1a478d61e61fe5fe, 0x1fde86528989571e,\n             0xd68feb051e23e5af, 0x1e337a18cc53179b, 0x4ae1edd8ec4fcf32, 0x5c116bebe598fdb1,\n             0x7cd8afd395c12c1d, 0xe7eacb5af7cf0777, 0x45728549d07f5049, 0x2a89af71334aa453,\n             0x11ee66e8e2c74e9b, 0x1b7919c8c6a661ed, 0xb8947b7068fc14d0, 0xe4265054d72106e7,\n             0x9c6527d0723938f5, 0x6153c08ae5f9f638, 0xa8b37c49746eed31, 0x9372fb87535dd818,\n             0xd437a89d0f2112b3, 0x5f87b2c413a1c8e4, 0x2cf986d863a5b4b1, 0x64b17e4099f35a93,\n             0x97c10947a4f3d2d3, 0x14351b6f88fe5d53, 0x93411abafeda8cce, 0xa10ed5d2346ca3a6,\n             0xefe43ba32fc1ab2c, 0x36f3d130f30daff4, 0x54967369ac6dbaaa, 0xbe793498711eef82,\n             0x668fe9c6f5abe761, 0x6387b893754072f3, 0x103bca34315c21e2, 0xa247c616f02648e3,\n             0x67278d2b2ab3cf64, 0x0f3ae903a941d891, 0x55c9dc9cda81ac39, 0x8d2bf9fa036ba37c,\n             0x32a05248578a4057, 0x6abf5c16871596a7, 0x62563b7b963ad490, 0x506aa0ccb59b2ede,\n             0x0a1e902799e9374d, 0xf981495fbf3a4a16, 0x69454a124507bb42, 0x846e8ccbbb287ced,\n             0xe51f185cc9ccb046, 0x0e42a8baa552bbd1, 0xa9c16a27d154ac3f, 0x95093a77632a72ad,\n             0x4b4333abae4f6e62, 0x42421d81960120de, 0x189f7b9a79fb3bae, 0xf6b8849c817854b9,\n             0x49781ba526172a23, 0x752c9fd952ca3858, 0x74de21e5db23a6f9, 0x0ba5a8de0bde499a,\n             0x817b84f0ee955cb4, 0x028b725848f88ae2, 0x48cdb46d1892e832, 0x36b3888b8a7369bf,\n             0xfa375338469f631a, 0x96b3caba829cacb7, 0xacbb6117e1c9a888, 0xb6ffae54262615ac,\n             0x52a207a253c802d1, 0x420cf3acbba8cb3c, 0x1e4a893628bebcc7, 0x879fd2e603cf131e,\n             0x258ded7fa4a5ef27, 0x3a3826a0ba606899, 0x869ccc9f1fd0dbce, 0xf71c614b35fb9b89,\n             0xb0725500c8b36026, 0xa38715eb8d60f4d7, 0x2ddb385582cc588e, 0x96c5105990363a3b,\n             0x4a37eb6a5f39ba75, 0xa557ede9c2a66414, 0xc8c24fb4206506fc, 0x1339c3979636cf3c,\n             0x0faf35529fe6ef91, 0x315caf70a442ea17, 0x8b0e1ba6c4935d0d, 0xbc9d7229b067be13,\n             0x18e52b50a02a9e7c, 0x365e11d0e1753af1, 0x796ef5a69c43b5a6, 0x788485989ac5e029,\n             0xf87a54b3499ef731, 0x954e63f5000bf8b1, 0xde8274450d9faabd, 0xe92daa708134a5a4,\n             0x558155f751b7b7e2, 0x51c9c68cceaec498, 0xab6e00d49b9693a8, 0x8b925bd6af11fa25,\n             0x84e3adeba06dead2, 0x9f4ed5c163ca36c0, 0x68ea05242a18d454, 0xa80690d1298dddbb,\n             0x1dc36a80f1d9e0ca, 0x6206cb0a0e05060b, 0x1b5d2f3d29bdbdc0, 0x4b4686b0686ab19a,\n             0x67eee9f260bd774c, 0x08fbde7aa347ed01, 0xebe62c9a60137a4b, 0x7b7a4c34ef79a5cb,\n             0x81441ee74c209701, 0xaf13008ef29d4342, 0x325c19cd67e762c8, 0xbea2d038f3e3f7c1,\n             0xbe93e3d330f67211, 0xc9b7edf2a2f9d040, 0x5eac7e72fbd51366, 0x3a00e3789dc81285,\n             0x23f52f6679afaaf8, 0x3f2c9f5d1e56e9fe, 0x8e1cab9afd7056ed, 0xc90d41ee1b2f0a2e,\n             0x110895854db39478, 0x2971c3745f85c258, 0x2d7e095b004808e4, 0x5625bf01aa9812eb,\n             0x4a0c0fa579a9022c, 0xc0de1c2eb51c29eb, 0x8f361ecfcec81d38, 0x2312bb5328ad87aa,\n             0x7aabfbdcd230d48e, 0xcc8274f399678965, 0xfa31bdb231e5a075, 0x471969d284c63124,\n             0x2aa5a9393d40101e, 0xc2e69c892318111d, 0x89dc76e1d181ddc7, 0x191929d70209e10a,\n             0xc4886ac30d285b1f, 0x0d522df68c8777c2, 0xcd8047002c5cba8b, 0xab356109cc867f0a),\n            (0x931cb035ac6bb768, 0xbfa80a8d9e4bd8a2, 0x5d137e149618427e, 0xdf95f99904effc3e,\n             0xf92d05d9a179c11d, 0xb9fb18042dcbc3d4, 0x85ff915fac6e73be, 0x2e88eb6a8a08b99d,\n             0x1e6d83fd54d8aa03, 0x9615ce3c686f5784, 0x72ed5048c8ef82a9, 0x82a59f81596c35b8,\n             0xf20d9714ce00f83d, 0x8883ff3ead83dcea, 0xe1ed81d1178f2cc0, 0x1b52c26af375fe82,\n             0x916289ecf7a61041, 0xa90218edb5aa6995, 0x71cea9b75a7d0632, 0x1d84d43e3458f8e8,\n             0x09707011e0cadbc2, 0x976249104898f0bf, 0xae6fb8ce00fc93db, 0x085d1f43ce0ee3e5,\n             0xda50d3e53eecf781, 0xb2ca14a2fda59754, 0x1764ebf11980456d, 0x06767769961474b0,\n             0xfd1532435d668d7f, 0x3db633fd8a9c835e, 0xd9d4a0b8054536d1, 0x9d7d13b8fb606221,\n             0x9dc26b8b7a91ecaa, 0x0385625c645069d6, 0x7634092d0498bf73, 0x2189f48d366f9bea,\n             0x36b750efbf5d6187, 0x162b1e87111c2100, 0xd73dd1dc29990717, 0x7c6c98b663d828e9,\n             0x96c4f32732ad9bff, 0xf7cc3eae1b44924e, 0x0712a9f1e996a8c6, 0x8b6647e631806b2d,\n             0x270f9ccc5b8b680a, 0x08e74b4ef3859fbd, 0x7fb38372ec360c33, 0xe57d880233eef8ae,\n             0x3985811b5fb36e98, 0x84d4ed2ef3e98ddc, 0x944ff191655b5b0a, 0xa12d8a4a68b9ec05,\n             0x12b844cc07dff539, 0x70e01ff9f6ce1f76, 0xad1f84a36a5ff1fe, 0xb47ca4b44bf4b92d,\n             0x2beea21d10be4352, 0x5bd31fb951ae70d6, 0x8e71d877506e628b, 0x2488e100c7f1d5a2,\n             0x209694ecf10291a5, 0x9b09d9057284edc6, 0xf9d26ecb402ed285, 0x44e7aeb448f0af75,\n             0xddb772678239bf63, 0xbc6d35a4af3832bc, 0xd5eb06a718243e68, 0x951a26fc3f178a5e,\n             0x3112d9f0c640c540, 0x492d63e72afda07c, 0xabb49249a02733c4, 0x460fe268a82a2741,\n             0xdd40f0eeb83a6c40, 0x55481f9d73c21db4, 0x856cdcc765d6ecc2, 0x71aea36aabf441b5,\n             0x0fb2828f02938b93, 0x7c88742dad3739c4, 0x0464c4276aa8db82, 0x10dfcb408149115b,\n             0xba138cd6dd725f3a, 0x71fc7feb1db9b1b2, 0x2acc6a2e6765f0f5, 0xfbd0e83246e549b4,\n             0x5527f84219106d3a, 0x40d6e8eb3b0e42e4, 0x573f9704661c0808, 0x5baa6acae3ffa0e7,\n             0xb57f26021ef13b93, 0x328ebf7cc0fc7535, 0x393b11720e5f773a, 0xd26868af6f7d6bdf,\n             0x0bfaeffef33a8e16, 0xca0d0a85554b81af, 0x2cc18103a223fd80, 0x2d2d4999e35fcf33,\n             0x8a0d6f7ca4387829, 0x4d1a4a328bee7622, 0xd888b14cd6d37363, 0x6f0971bb3cf040fb,\n             0x6d922fe33a3f6047, 0xfc2fd28c3ab9c135, 0x15215d4e9b754ee1, 0xf36eaa7c1e0ff208,\n             0xce8e6c1bf059809c, 0xc0f91dc18e3d8513, 0x8ff64a22efccfa29, 0x656a5d009d48dfe3,\n             0xb4b98234b65d9cc3, 0x8896632dc9e06907, 0xe6661a74281f9b59, 0x61cfb97446f9437d,\n             0xb0414f43e6f51fab, 0x0e606f509506c36b, 0x48bf15980d489f55, 0x00f79ac76b1e3567,\n             0x07153c17df813cbc, 0xac503c34b95d52be, 0xaa275bc7ef3c4ab1, 0x3b981db85e7faa56,\n             0xe262bb93fca05c3b, 0x105e0068706d9cf2, 0xeb60a2d3aa4e9917, 0xc60d1774724bc2e8,\n             0xd5a9d18b128e5b71, 0x5fd812bca76c35ac, 0xa79cd46e1691e159, 0xc914bdd00bc862a0,\n             0xdd1ee0a685e6a7a3, 0x6f60e3821a8e6fd7, 0x305691e86fc78f62, 0x5f04cac8da4a1a2a,\n             0x79f08683a3bf7f34, 0xfac08dd0755b005b, 0x9ff5cf7a3e97a0ad, 0x1408969d073d531b,\n             0x8290a0b0898dc84c, 0x3878685a8b4694f6, 0xd8d254eb026ab4ac, 0xbcc26c325570bd36,\n             0x56dbb1f6e2541a9c, 0xb1bdef1f739d2a2a, 0x96e98cdc40c1e395, 0xb007e430a841adca,\n             0x03585cbd563fa3e9, 0x300a86654757c390, 0x48a6e299ed7efeb5, 0x4fdbc7932aae628c,\n             0xfdfe5d4fd9668820, 0x57a40feb0740811d, 0xd2bdbd5f8290c6fa, 0xc91da2ed354a524a,\n             0x7965f42e61c00a80, 0xd9a30f8cf3704b6b, 0x60d50353f72d911c, 0x08b9aa008e78d1c9,\n             0x0a449e76cf39d7a9, 0x2b37438f5cda9b6b, 0x1c0977595d44d097, 0xe9407c7f6b4c76c2,\n             0xb316508087aa285e, 0x90abf9094ecee888, 0x6f76d048a47f7e14, 0x9592a82c1a366410,\n             0xa2e7771c9c3d1813, 0x3cb10c30fbda8d2b, 0xbd4517ef009137e4, 0xce9d59b6b05e7e8f,\n             0x57b735aa4c196549, 0x86427cf2e6a864d7, 0x19bdb39c337dadc2, 0xa3075b3dc2d172de,\n             0xf396c71ea2520809, 0xfc164018f194e85c, 0x7d544962af8becf5, 0xc52db79422c79dad,\n             0xb5b379d8fb23cee8, 0x3510ad4b4025aa99, 0x5c0ac4a2abfe0b26, 0x2cd007eb02a6e2ed,\n             0x983c5b1fa6075285, 0xc162260a8537b2f8, 0x22d65e57d029fcab, 0x794c2262eb4ee66f,\n             0x9f6c5e46c0ef22b0, 0xfc72f9d7732ce448, 0x3b245dbb638125a1, 0x81db6c6d46728a6e,\n             0xb9d7aeee2fc298d5, 0xf4000c6eea0b6d13, 0x42508c1ba6d81262, 0x3580b165a059b0ac,\n             0xa8f619af03486aac, 0xa127e1f044aa3ee4, 0xdfe55950b8eee3f8, 0x393d3190790822a5,\n             0x00e914b409eceb2b, 0x26b2f3952b8a4b0c, 0x39b5cd0fd63be3ab, 0xb240b51052941c78,\n             0xe9ae0fc9ad088fd0, 0x2cc7b5f2b8aaa05a, 0x0662dbceb630050e, 0xc92922f9077a8a6a,\n             0x80f5a00afdcd0079, 0xfc2c1951df5ef4a5, 0x4ac3c7554a958921, 0x00b9954a39d5be94,\n             0x6ba1927024bd5429, 0x46e6f6f1b0d47727, 0x44f62997bddb5665, 0x7e1aafb1cfc5f7b7,\n             0x6c56eb47958a5471, 0xa81b7f65e0936f1c, 0xdcf784250697d675, 0x5e2d1ef2acf4c2be,\n             0x4597fbcac3d403cd, 0x5dae96d2fb2a3eda, 0x1e9408d9d4d83062, 0x50fbabdcb47f3cee,\n             0x39416e9c61a96794, 0x9cc5eb45435d5d9f, 0xc017244b14bf2d02, 0x953ecb4b8bf35ce7,\n             0xa3036e0b52d9e35e, 0x4ddd24c92fb06947, 0xec9d2524db620446, 0x58ed6013a087439e,\n             0x042da7362aef6802, 0xaf9ce2d38e3833e7, 0xe3a469df5275000d, 0x42c5960a748c952a,\n             0xb17cf7245f06f4ec, 0x14154c6af69815ca, 0x65df4c947544ef97, 0x3ced4fc491284e80,\n             0x79cd74b64b4b2adb, 0x2658b0a46a12d2a6, 0x55dd8c0d8a2ef1e7, 0x34b5d9477de45fa2,\n             0x9d930f0fc7393a93, 0x74e423162de06741, 0xcde1fdc705a074c8, 0xe786c32e9fadc3e8,\n             0x9831100ee3fd0ad1, 0x4c94e887d0114d54, 0x335519442cdd8351, 0x957258d721f855eb,\n             0xb9ae7eec017741e8, 0x09c43e84456be8a6, 0x1b6d21ecaf1f43d1, 0xc0398a08479053ca,\n             0x10fa18eaa3056185, 0x5368b7a423934ce8, 0x3d20c4a6fc1f4551, 0xa320930c5539470b),\n            (0x5a5f2b70494307dd, 0x72930b7be37ed0b0, 0xfaf828dda7c1acfe, 0xecc68cb29173ff5c,\n             0xc6375cec82d39856, 0xd8fb2ef8cc253487, 0x15cc8a41be4831a7, 0x97589dfa9d69fd67,\n             0xc8cbe785f4e1734c, 0x7cbdf12d9a9ad679, 0x88a442bb9b75d1a2, 0x5cb283d0b3188693,\n             0x6c64c756ddc2c1e4, 0x8abc13331b7fb87e, 0x37ca21ffe8ec1c67, 0x9c752e9b66569eb0,\n             0x9706bc35662425a8, 0x1b29d3c67aae88b2, 0x20a4e86b441041a5, 0x81cc9158637c5040,\n             0xcb11f4d7d5660299, 0xb3ae3f85ef87523d, 0xa5c6c18ae692c0a6, 0xb72fa98dba822edd,\n             0xf49f60bc02791ebe, 0xafd47f9c33ea0d5d, 0x4177990f9c01f0f1, 0x52c8ae39162dec76,\n             0x76dc6b75ca5f080e, 0xd8b6cf872916877a, 0xc685b8e5613c7ef8, 0x082c5cd7b7929cd0,\n             0x94a797eb33b15625, 0x55a8642c2ccb42fb, 0x1c8993d2f0d09a5d, 0xf5b39dbbf55e8451,\n             0x13c8a4f1df2dc36e, 0x94e69a990b2570b5, 0x20f8f26e5e45fcc0, 0x59e28e6f87a2bddc,\n             0xb4613195ba7666a0, 0xcefc14b159e4f9f4, 0x047df56b60d2db36, 0x54f8ace11a828be5,\n             0x91015b526c14e020, 0xed9773f0247fd60c, 0xebf1caec4ba9b72b, 0x5d117ef513f8f23f,\n             0xbd62b1f323dcefd7, 0xa005492b12a6e137, 0xa3c4f25022f91f83, 0x7359d88f6633fd91,\n             0x8b15de7e0f0d3690, 0xa7453f23bd99f2bb, 0x0308c3829e5942e2, 0x55a4343a422ff513,\n             0x099a77760c67a1c4, 0x6a1e7b6cadbf1026, 0xba0db9a40fc5687a, 0x93f50b1881335b39,\n             0xc88551e546a9dece, 0x811747afa04af6ea, 0x0e995cbf2dd4460d, 0x5156fd6f897398b0,\n             0x5cba9038e42d3719, 0x1b94a90ffb753c8c, 0xeffb4703e9535dde, 0x5a3a25040d2e679c,\n             0x9b488a3d89ea9d87, 0xad2a98c29418535d, 0xc8986d218033e165, 0x4fc690d6de5a58dc,\n             0x8dcf27010b5b03e3, 0x9615fc448f33ad3b, 0xef363eb8921e04f6, 0xa3735ad37fc14eb2,\n             0x4854d39c8a751127, 0xa190db29d7e70371, 0xd5576df11553a604, 0x3d206d8340e07d2b,\n             0x1b8a47c68ba7227d, 0x00db94d6c5b532f3, 0xe171aa2d18ba7fb2, 0x2eb6d6cffc6ad272,\n             0x389280e358a1abf2, 0x2da30d5ce430e7d3, 0x1494483c00f0cdcc, 0x2d459d82da577f2a,\n             0x29043b8b05116b0f, 0x1a7de7eefc8f9125, 0xdf58f0c37abf586d, 0x00de7b4d751b5945,\n             0x2d869810b2518aab, 0x718fd89782454402, 0xe17b7b6d3afcaa02, 0xe8ca8822e8f3149f,\n             0x54e367c8c02ed5cd, 0x4d6b91f02de9c163, 0xdefe44e4883741a9, 0xa549e6727125c604,\n             0x3092a7183577828b, 0x47fdb5df077f39ba, 0x1f321a400a30d97c, 0x78ade03df798ce7e,\n             0x49c942815849a8c9, 0x84c488f9d601f60e, 0x3f259d2397e49e92, 0xea627a3246bf99ee,\n             0x714a38da940b6d41, 0x0bd6c0313bc5d2ac, 0x1efffd15c9997fd0, 0x9605042e69a563d3,\n             0x6fcbe8ac92977801, 0x842f529ebef4e5d6, 0xed59ceb1d99f4329, 0xd23577f8bbe59b98,\n             0x5d657000a922390a, 0xc5634b5dbfd89d46, 0x0c8ff0158a3390f4, 0x9f7d403c614f950d,\n             0x376e7e445951f74d, 0xf114977a656083c3, 0xf544fe83ad9869dd, 0xe2a1f7f4067211a1,\n             0xe20a8f4c53c1d75d, 0x590fa8d9cb0cedfb, 0xf9bdf66b3a348edb, 0xd8b030ef6ac057b0,\n             0x8194f3257de0113b, 0x853fa01bca32dec0, 0xfc24284ac65ec104, 0x4d1a7e4b5bb94c9a,\n             0x4dd58183824bda15, 0x0d2be3143b01d753, 0x154e10ef48807062, 0x6d65b422dc651001,\n             0x80befad40aebd628, 0xc9eadb734dd3bba7, 0x875d8819322b464e, 0xba74670eb4edc9c8,\n             0x4b4171d3095c4633, 0x0151e40f6b1b63d6, 0xfc97c4feab55b135, 0xc6f4c962f1e7f43c,\n             0xd26a1c0df0310a4c, 0x949159fa52b7227f, 0x9ce8f9598f593b81, 0x7609fc84c749a14d,\n             0x261fd19e5fef6891, 0xc774d6a03cf79fdc, 0x00344e64251195c1, 0x90787e833f8647c3,\n             0x727bc4c495bed76f, 0x430912d91400065a, 0x48cac527bf4e941e, 0x6c90e1a4369ec849,\n             0xf120d5256725a207, 0xa38b366f5d1cd376, 0x2bcc30ee411d146f, 0x5248ad95b8e3eb34,\n             0x8bb22d59ea4a28af, 0x3b2b14be1be0256b, 0xd6c771fa9b06f27d, 0x2877faa019e5cead,\n             0x5ee89270979c629d, 0xd961db4ea1940353, 0xacf4b393766e1a58, 0x62d4d67f08ed982f,\n             0x45d11111025cbb48, 0x72de79b796b70e6a, 0x002c828238360087, 0xddd194d72cbefb7f,\n             0xbb2871e6c3dad0ec, 0xc6057ec73a437f34, 0x21da9d18f930d961, 0xe47ec49391742c20,\n             0xb82b8f7685031db5, 0x71655563b75f97b0, 0xe89ef5aacfbf0cf9, 0x14b8e01e96445db2,\n             0x614cac6bb0c63ef8, 0xf4f07e379bef3eab, 0xb83b96684e95a30f, 0x6959ae7b08f4d419,\n             0x30e39f3b7e45283d, 0x15ad0077e6747489, 0x1b06a5db4d644abb, 0x859bc190045e688d,\n             0x37e560aeff805804, 0x4305b906ba22d4fb, 0xce67a3b95f508e32, 0x8e19b1ebab90822e,\n             0x4d3b69bd5aac1fc3, 0x9d0ed93e21a01343, 0x6a3480f5a38b401c, 0xa484f7c000892eb9,\n             0x6245848a614bb023, 0x181a86fe0459f808, 0xe80b0f0cb28857a0, 0x529d39759c3028b9,\n             0xf1a057cf47cc3ba7, 0xecf88df79971a926, 0xf491bda75971d77c, 0xfced9b5292e3d14e,\n             0xd979d8f026416414, 0x05ffb33474e3af7c, 0x59a2fe4e71477dd4, 0x7f835fb951774d60,\n             0x1dabc30f4d614159, 0x6d9662824b02b036, 0x122548c2846cb619, 0x850c795fd0b4c43c,\n             0x83586779377c7ec9, 0xe3e0ee80239c7a5b, 0x40dbdf115bde20bd, 0x61ffab4c796356d4,\n             0xbb7f24feef4d23f9, 0xa83614b05a912745, 0xbaaf881989bb3c9e, 0xeaed7bf486e75172,\n             0x7bbce58b0da1a96a, 0xbd7574a4473e6a3e, 0x523d0b14b7aacb7d, 0xec041de2cc710b1f,\n             0xe6a85da8993b2c12, 0x10be8dd5b51e6f31, 0x046733c636a365be, 0x55de65a1838b4f91,\n             0x93806e289edc2c83, 0x7351c2bd7894e1a0, 0x99fb055f778f2e8b, 0x773b9a425de82c62,\n             0x3717d3bd0620aab5, 0x5f33819c85199fc5, 0x627c635334c7a40e, 0x6339138b8da6d110,\n             0xacd8d57af56c99e7, 0x3931a02164ab8988, 0x31974fc4e9071e72, 0x8dcae4790ad949c1,\n             0xb1e1fb7664d48947, 0xd8c9821f0bdc5f13, 0x45b03c7379209e55, 0xbe052d408273a1b0,\n             0x20719464e8080b0d, 0xfada5e9479d5602c, 0x7cf57599ea5c5392, 0x8fc0d54238cd2c4c,\n             0xd6cdce30cf9c801e, 0x9560761fa928e2ca, 0xbc2c4f8378cfe9a8, 0x323c988ef232455b,\n             0x8f1e430d0d34a6ef, 0x7891ad779e323c47, 0xb2123d58ae0d80c2, 0xd2857d26481fcb53),\n            (0x0cab3d71bf1661d6, 0x3ddcb1aa52ee68c0, 0x546b89a41ec207cf, 0x531803f682e513bd,\n             0xdb2e3de789783ad7, 0x1c66055492f57832, 0x517ece97a71c5b71, 0x404fd190195d10d9,\n             0x231d52a4b165e2ba, 0x5a3891d35a1b64d2, 0xbf790cb7dc0fce5f, 0x14ee58825f7c68f4,\n             0x73f9c9105bfd84eb, 0x219382307fd9a283, 0x7cbc56e77eef89de, 0xc1f5ee71e19beee4,\n             0xd70dd014ac5e524d, 0x7829d95f2d6b92b1, 0x8518e0e48192589a, 0xc826e41089f56eec,\n             0xbabd6a185d578936, 0xc47ace297fa15a50, 0xac7c7f712f907f82, 0x62da660a92233789,\n             0x4b06d6266c796007, 0x088f424108e4c43f, 0x9a87a91151fdaf14, 0xeabcb303b17fe2ff,\n             0x461bbbcc429728b4, 0x12ea009858921e53, 0xeedf5def0559bcfc, 0x9360684d126b14e4,\n             0x6d4dda3cf67ecb6e, 0xeeedddf8d5f76cb0, 0x9e810b40de1da08a, 0x237eae68d2380185,\n             0x1cddafd1b873f849, 0xa2a56b7ee0983815, 0xa9b9bba49e1e9193, 0xaef50aa29833c03d,\n             0x32fb5b9151ba8890, 0x84dd609b177ff5c3, 0xbc00f90427fa2cd6, 0x27e1ed7218bc5417,\n             0x36cfe1ea05ac9222, 0xb545a009de902a1f, 0x553da262173647ea, 0xe79130ec5138727b,\n             0x896239516935f4be, 0x70be82381aa0cfb0, 0x8dc788dffc1f6f67, 0x63cb73dd06c0d0f4,\n             0x795ef45b3d542444, 0x07a9faf5e0c4bf4d, 0x49cbc38eefad68a1, 0x6ab53044df8401c7,\n             0xc20f85e22a87d07e, 0xb6277dbb4ffbb972, 0xcb0c7960c923bf81, 0x1b4e3e4e580e19d8,\n             0x14833df6862ff3db, 0x0dcad4d9ef2b307f, 0xb2f67855732ce6d3, 0xe73b4535674a1f37,\n             0x7148f5b5cf4720a0, 0x4d0a76eaf82a6e0d, 0x0ff70066d543a9f1, 0xffd83a4739aa69f6,\n             0xf2466c1b86cdf3f6, 0x8782e3c7573834cb, 0xf8102f4d17302cfa, 0x5743542f72a36aed,\n             0x3e389a160a9de6fd, 0x300d6df61aa84508, 0x0a2e58978d02b6d4, 0x2fd8cf521f14a1a5,\n             0xe83786ff9d9f68a6, 0xbadbb5d305bb3890, 0xaa38bf55c6a5ec68, 0x45e2a3fda3f7b3c5,\n             0x9f9e8036136f7512, 0xc9830b4b21a95988, 0x0b1dc1ed0ad50661, 0x68f3736316c9d180,\n             0x6d50832521e71e40, 0x9bd1f442d7115c9f, 0x7d18456be814690c, 0xc880ea1440ceacd0,\n             0x7355c2aca7a0f893, 0xfd9efb37e430f59f, 0x087f6f9afd357ebf, 0x61402feadf5d6a00,\n             0xa354f2ca60f5349e, 0x0c2b1dd0d6569ee3, 0x6f1e328f8c1106b3, 0x5c9eba478c47a6d9,\n             0x86e9673b9a4d5a53, 0xaeab1ce726a39885, 0x2e9c50641d0e52ae, 0xc6a20a3f2c8360b5,\n             0xe6790adb6ebcd579, 0x85ded4bd7a731aaa, 0x04767d7d1de8bbd8, 0x3e3335c22917d603,\n             0x7bb8bd1e84247f1f, 0x752c3e809fa18c74, 0x4243814ada5009e9, 0xe150d5f44f7a6363,\n             0x3f34e8b7ee4f3e76, 0xa2a9c149ea3aefab, 0x53f0a631b2639fab, 0x2b474dc79c6319d1,\n             0x0332d38671279325, 0xbb2728ccf07f4e92, 0x07a6b2f0a0e3ca7e, 0xdbce77ce02cd836b,\n             0x7d804bfd2600b5eb, 0x80caee2b12e711b5, 0x60e2f8a7008364f5, 0x04956388fad63494,\n             0xdf39229a3cb17be6, 0x59fac787534f9df4, 0x3674244c4a0c9a4e, 0x245234df35544f16,\n             0x6179f627058c9625, 0xd84381849ad4745b, 0xb20fd54c2b54320f, 0x0d27606f3a3690f2,\n             0x2a85f6d9a335bc17, 0x9cd581a1094bbcd3, 0x16804d4a6ded086d, 0xcd9b5de41c39d2a6,\n             0x0f95daade155526b, 0x7dcdfd0571bcae4b, 0xc18c84c8ee308849, 0xc52112d51899326a,\n             0x3079ef9952a57410, 0xd9f7a222e6abd6c0, 0xa37d042d11a03ac1, 0x6ba676d13fe067de,\n             0x0447e0d951288de1, 0x8e4e96d7900b2911, 0xad8a6d836960502e, 0xc44150a166fb3385,\n             0x020b5d1c535c54a2, 0x127befc0cada76bc, 0x6cd29f272b487385, 0xe08eb02145bac838,\n             0x853707ff2729f612, 0x197fe14dc2d61fe3, 0x5527e5b831c2762d, 0x7d989f1ff4f6c1be,\n             0xe1b8ed6f7e738565, 0x98a9c602ef2f9dce, 0x0f385402a9ff4454, 0x0ab7e0e167a88e19,\n             0xae181850444c3bfe, 0xd12722e7d4db9407, 0xd4f40c25c6ad6e8e, 0xca751d59cc94ac6c,\n             0xd8bf3cafc9ab70e5, 0x7584e890c3d4c392, 0x7ffaf4f138ff3096, 0x37921e6a8cf6f853,\n             0x75ef4a862e659393, 0x71d20c4416e4f428, 0x53016dd6d345018e, 0x6e46324f828683d2,\n             0x49e7fb094eddbfb3, 0x13ea9caf94d725cc, 0x377d89e9ed96c39d, 0x6c6952ab450f4bc4,\n             0x363ce43ab1a1ea8d, 0x0a61e48acf922826, 0xc4563c40e5ae4da3, 0xd17ade584ade38c0,\n             0x2fdc528bf3afc0a2, 0xf5d9b137f5896076, 0x4bdc4fd6aed31609, 0x16344ae7d927afd7,\n             0xb702d85c2efc81e6, 0xd40d676794801f35, 0xff7520be35863160, 0xec547121a523ba9f,\n             0xe969862a41b5b2f9, 0x2f524c322c46fb86, 0x5c6871ba2f89868a, 0x171a03f9da10159c,\n             0x36c179180afe9e2d, 0x764a05a232a8dfc3, 0x1fa125a98f563e07, 0x27582172d1f2340e,\n             0x21952dc880608156, 0x91a189d8e6aa1519, 0x2281cb304f17bd4e, 0xe3d5bf09552b7fca,\n             0x7b9eda98fb344c1b, 0x6c301ee00551ee36, 0xc49a4a4cec63f40b, 0xe40ccb4351cbf563,\n             0xf8cea582dbcd91c5, 0x92a26734b1ebcec7, 0xad136281d02f08bb, 0x7994c1f97d336835,\n             0x1272a65bb58b25f1, 0xf7c5c094042783ac, 0x1bbbd73e194ae179, 0x69e0e8590f883651,\n             0x82eece76f3bf11a8, 0x5064028e9b39bb23, 0xa13ef4ab9f3b178a, 0x8579c8278423023d,\n             0x8deec47144b97d21, 0xe97a84015b8010cc, 0xf157bbdeddf271fe, 0x9067eb9c8c8e3220,\n             0x7c01db8dbd636a71, 0x122eae56b4d6c95a, 0x61b1218d53076b3b, 0x307b8662286d62af,\n             0xefb13b46c5a441ff, 0x861d90605801df8e, 0x7c2534239f61d44f, 0xc828eebc58db32cf,\n             0x49d5591f720cbdd3, 0x4d14a9f768123894, 0xe10c57a74c258e22, 0x43b8142b21a056a2,\n             0xb4b05e871a9c8ee6, 0x9c0eded797b3c78b, 0x4af8e75802d517d3, 0x23bbf79b2705b9b2,\n             0x0b7e93cde839d781, 0x6603feeaced03c5a, 0xc851b09a9d820229, 0x068a21f58f5a6b2c,\n             0x354817e59dca1b00, 0x8a093e7c1c9360eb, 0x4ce12658cf1e3908, 0x2e3ac173bafcbb8f,\n             0x96b25a8f83a38970, 0x28520a713bc19d39, 0x38719cd7c4daf089, 0x64ce9f8be2f082ca,\n             0x8e81a207793f986a, 0x89aa89d72fc4610e, 0x0053aa24cbb14c48, 0x93ee13a94f1fde75,\n             0xd44c1865786b285f, 0xa90400f19779dd17, 0xc4d3bdcc436f42da, 0xa76afd902a011e0f,\n             0x7413cf10ef992d51, 0xfbba460310b78d60, 0x5d5611e3abb7eb32, 0xd8563881cce40b28),\n            (0xc3b69c6e7ad1b521, 0xb83461f504aeb007, 0x24b84f66c30466b2, 0xfe32d834a0176293,\n             0x2c4b4ce462094314, 0xedaa901b0949d6cc, 0x1aab2615e6765bb3, 0x71651ee51f5231d4,\n             0x717c8f152877ddd0, 0xc183ed77f9808e73, 0x4c3f7c59868c0521, 0x11bb872a154aa98a,\n             0xf485ea5aeddfcef8, 0x16b2e2e955acb368, 0x16d5d232e76d5db6, 0xb09af72fb7c1944a,\n             0x9476700470d6c0ee, 0xec4702ea9c3612ef, 0xfa4bde51b07fdd0e, 0x9aa47edef681e779,\n             0xaf71bec8995460e4, 0xba19a70e71b2f73e, 0xd60e9893bfd34e16, 0x2619b3c12d9e4a50,\n             0x4935f0f0886c4936, 0x71beaacba788485a, 0x3236722d27e43147, 0x6c740f1ba4db1de9,\n             0x9fa6beedf9fea8e4, 0xbe9ccbaf01059da7, 0xc072eac3ae089304, 0x22812a4c38e0c179,\n             0x0d4e977f34d1ed93, 0xcc9da626b8a417b3, 0x4e4b62bd7d29331b, 0x7153cc08711c5f8b,\n             0x5154f9dfaf484f41, 0xb87aab01a4b0d356, 0x29b8cdb000eb65f1, 0x04e50b6e32b0a843,\n             0x829a80ffd1145aa8, 0x55811a0944edd201, 0xbc49e444b1c48a03, 0x942794a82735a88b,\n             0xe5108c4bff93a724, 0x945de567aa309cd4, 0x203c019361158735, 0xa708d8accac692a2,\n             0xf62c4a379d793f7f, 0xed3999334bdfb72f, 0x42275cb4acbcf1e4, 0x58a3d3fcda6ba7a7,\n             0x28c6131ad22a3f51, 0xd79c3b6a3926ac7e, 0x00fd64c6d03dc5a5, 0xfe39a19599f3269d,\n             0xde6872d14e1a7579, 0xc52b75a9962133b0, 0x8981ee0996f9ae2b, 0x97e9f3f5c19ef6e8,\n             0xbba6907caf47a70a, 0xfdd66db8893e8e40, 0x56f8adde89d1073f, 0xcf3b478daae1a38c,\n             0x48ce0a4f33fe3546, 0x7ba57efd825296ac, 0xec6eb6e6ceb805f4, 0x24dfc5238c4186be,\n             0xe53782e959495682, 0x143be1ec1defd678, 0x022db48ef1aec14b, 0x3113c66887a09d7b,\n             0xfd232bd4fe1e7d4c, 0xbeae37d742ee8dee, 0x39b020cd05a9f62a, 0xefbd67181d5d1bad,\n             0xaf6eae3864d68701, 0x1a557d677bc23488, 0x5d697a501c6ab311, 0xfa541a4f123f0f62,\n             0xd64a8ed6975819f5, 0x782beed14f7e3cda, 0x0bb642fed4c4b097, 0xa10625c24976982e,\n             0x4b2324366ad654f4, 0xf133aab98f16f8a4, 0x10d21ba98e046d23, 0xfffef3ebf25864e2,\n             0xce96ea05b6246b81, 0x2ff277540aa08e80, 0x1c859fd9a2476216, 0x6f213450584db7de,\n             0xfd475b29c980f789, 0x8dc53e8e2c6990fa, 0xe6ee0fa04050017a, 0xef99d43ba2c77fd6,\n             0x62f4078a96a4d194, 0xa42d2bf32f36a846, 0x5751eac1757dfeeb, 0x327a55aba397e016,\n             0x46510ed598b7b017, 0x14fbfe5f5981df43, 0x884e6da9e63c8d22, 0xdf6609144d900aae,\n             0x2876707ff2e20b4f, 0x16c43f443088f50f, 0xf6169a93127ce177, 0x4fafec7931d44b2b,\n             0x08dd95ee1bc1eea9, 0x646b858af6c5470f, 0x5675d6875f6d12f1, 0x31bf801c8390d095,\n             0x6593eeff9c81e008, 0x315c9d22e09fca07, 0x9b115bf49f3c3421, 0xde4b958decddf48d,\n             0x0304c955b92895ac, 0xf2ff3483f25e6f73, 0x53ddc4f61b87e246, 0x2bd13a56df043d70,\n             0xe0b4964bf75327c3, 0x65ad426a4813b00d, 0x090767d1b2b0706a, 0x4d5d59fbae67df6d,\n             0x6201101d3311d90a, 0xedf65b5596524e50, 0x04e04a78c8d18844, 0x9e009dfcf7391a6c,\n             0x4fd059a2faa35b66, 0xa31529b47d1a9326, 0x529377a47e6beb67, 0xedfbbfab1813d99d,\n             0x29f671ce55586ef6, 0x2f45fb86f9825461, 0x773ab7c4f2ec1f7d, 0x68c3873307d8f6c0,\n             0xdc8878b498b8f07d, 0x6fdb5d5e758edff0, 0x0a2adea78852fbb1, 0xccd21b402b443308,\n             0x8d9092f2f1ffa68f, 0xb6e52b065751669c, 0x8b2c2869a10ce122, 0xa5a9f55b0f094a8b,\n             0xaaf9f14c12c16e2d, 0x733b56395d2baa73, 0x611fec16de26072d, 0xb3b3e72596503247,\n             0x6592fdbc5dc6b421, 0x8418fe6e65d8b814, 0x497302787dcc3561, 0x592b37ae2eb056c4,\n             0x719d042f5ca3d03a, 0x77f4903a2c0e3f6b, 0xc05f96a96e730716, 0x4df942fd615e3c16,\n             0x6bbf741b2ce4df63, 0xd50443df26c087fe, 0x30019611842dc907, 0xd3d96884e7e8b89d,\n             0xcda8cbd3cbca4328, 0x09940773e1e256b5, 0x348184104465c535, 0xecb14daa27da1e69,\n             0xa80f0f64b7465c8c, 0x3070ff21d6a21b10, 0xf825e35805046748, 0x87e874c00729f8b9,\n             0x8d9f6d61bde4806d, 0x311ce5d9bed931fc, 0x54d80b2c7c3a3d49, 0x97dcc311ea2419d2,\n             0xec9e1b80a2151b1a, 0x249a65eadb6ee3b9, 0x581f59c5f9e57c22, 0xf299a67879b9de5e,\n             0xada698e5349ce1fa, 0x3fe96a4e6f58576b, 0x892755c1c17c8a37, 0x0978e35c015ea5df,\n             0xe58cea5361f450fe, 0x8582cc4e9b13fba9, 0x99dccf4ef39e2668, 0x9fef19d85d0b9f95,\n             0x0dad2cd0170776be, 0x29b8ae793c6360ec, 0x556ef3267dfd6efa, 0x21486b06e8e8e12c,\n             0x6ca9d5b7e6c4be80, 0x6a9b1d6cf9bb1cbb, 0x86f5722a5eaec1bf, 0x6c7724b208716b06,\n             0x013ef708482a976a, 0xf04a6ac95c99de3d, 0xe72754d81d84c5a8, 0xdbf01d3958a05a4a,\n             0x48dfcb31567566e7, 0x18721c84a95496a5, 0xcc1955062ff1283e, 0x6f6ae1af34b09d64,\n             0x9192b678f25ad7fc, 0xadf9655ba8019a55, 0x7546b5e819321454, 0x22a161318ededc7e,\n             0xa990d6c3895f474b, 0x886d5da19b88efdc, 0x9afcc8a2c6dcbd80, 0xfbaf28f2df752020,\n             0x92f3fa431f3d5c74, 0x4185507fa796bf0f, 0xcbbd79ab59a1a67d, 0xb222c7a1f41dd966,\n             0x202f4c88ba100c25, 0xb8297aad3eeb65d4, 0x2509be61b580a5b4, 0xb7caf283979f9847,\n             0xc60057b504c4a348, 0xa874cdf5f3f4cb8e, 0x5268f54d7f87f444, 0x1767902717d5f500,\n             0xf6a0054519ab2e79, 0xf3ed8b63a5bfd3eb, 0xcea63ecc54519530, 0x42ce3c2c76f7ec15,\n             0xe7b68d7f862c7fe9, 0x7498cf34b11d0f56, 0x8695310916f3f818, 0x2f4d89f6097b981c,\n             0x0a13905c92cb9c68, 0xcf7483d6df2b8ed5, 0x84be93ea1850a0c7, 0xeb52bb51bb4f4a87,\n             0xccc5bb2c8b37f99f, 0xb26db71e3c159126, 0xa60be3bac2e3b6a9, 0x11aad070e155e0ef,\n             0x756ed7407d54f5f9, 0xbceea2f8838602f9, 0x02895b32052852c1, 0x5aa3ff55e85e239c,\n             0x126ef5701882a941, 0xb29bd590fee8bba2, 0xca959a059366b4c0, 0x60f2e60c9eba7c20,\n             0x359a3f5a6fb1c52b, 0x7aad7a5a66ebf722, 0x08d6cf88cbf0a0a4, 0xc7475c9a11b06767,\n             0xa7c1214aba4c302f, 0x08f5237aa9e38103, 0x269123941e6292bd, 0x75751264077928df,\n             0x4fb574e025d51786, 0xba84b1d412d860a2, 0x6d759898e92a0c3c, 0x68cb09dbe879db67),\n        )\n\n        def __init__(self, data=b\"\"):\n            if self.digest_size is None:\n                raise ValueError(\"digest_size must be defined in subclasses\")\n            self.hashbitlen = self.digest_size * 8\n            self.centre_rounds = self.centre_rounds_for_digest_bits[self.hashbitlen]\n            self.secret_key = [0, 0, 0, 0]\n            self.serial_number = 0\n            self.block_count_high_word = 0\n            self.block_count_low_word = 0\n            self.buf = bytearray()\n            self.finalized = False\n            self.final_bytes = b\"\"\n            self.state_array = self.bytes_to_words_le(bytes(self.sbox_0))\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.secret_key = list(self.secret_key)\n            other.serial_number = self.serial_number\n            other.block_count_high_word = self.block_count_high_word\n            other.block_count_low_word = self.block_count_low_word\n            other.buf = bytearray(self.buf)\n            other.finalized = self.finalized\n            other.final_bytes = bytes(self.final_bytes)\n            other.state_array = list(self.state_array)\n            return other\n\n        def update(self, data):\n            if self.finalized:\n                raise ValueError(\"hash object already finalized\")\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            if isinstance(data, memoryview):\n                data = data.tobytes()\n            else:\n                data = bytes(data)\n            if not data:\n                return self\n            self.buf.extend(data)\n            while len(self.buf) >= self.block_size:\n                block = bytes(self.buf[:self.block_size])\n                del self.buf[:self.block_size]\n                self.process_full_block(block)\n            return self\n\n        def digest(self):\n            if self.finalized:\n                return self.final_bytes\n            other = self.copy()\n            other.finalize()\n            return other.final_bytes\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            if self.finalized:\n                return\n            self.process_final_block(bytes(self.buf))\n            self.finalized = True\n            return\n\n        def rol64(self, x, n):\n            n &= 0x3f\n            return ((x << n) | (x >> (64 - n))) & self.word_modulus_64\n\n        def bytes_to_words_le(self, data):\n            if len(data) % 8 != 0:\n                raise ValueError(\"data length must be a multiple of 8\")\n            if not data:\n                return []\n            return list(struct.unpack(\"<%dQ\" % (len(data) // 8), data))\n\n        def words_to_bytes_le(self, words):\n            if not words:\n                return b\"\"\n            return struct.pack(\"<%dQ\" % len(words), *words)\n\n        def single_mds_8x8s(self, input_vector):\n            tables = self.mds_8x8s_0\n            result = 0\n            result ^= tables[0][input_vector[0]]\n            result ^= tables[1][input_vector[1]]\n            result ^= tables[2][input_vector[2]]\n            result ^= tables[3][input_vector[3]]\n            result ^= tables[4][input_vector[4]]\n            result ^= tables[5][input_vector[5]]\n            result ^= tables[6][input_vector[6]]\n            result ^= tables[7][input_vector[7]]\n            return result\n\n        def single_mds_16x8s(self, input_vector):\n            lhs_tables = self.mds_16x8s_lhs_0\n            rhs_tables = self.mds_16x8s_rhs_0\n            lhs = 0\n            rhs = 0\n            for i in range(16):\n                b = input_vector[i]\n                lhs ^= lhs_tables[i][b]\n                rhs ^= rhs_tables[i][b]\n            return lhs, rhs\n\n        def xor_key_with_state(self, state_array, round_key):\n            for i in range(32):\n                state_array[i] ^= round_key[i]\n            return\n\n        def full_mds_state_update(self, state_array, key_array):\n            self.xor_key_with_state(state_array, key_array)\n            state_bytes = self.words_to_bytes_le(state_array)\n            out_state_array = [0] * 32\n            for i in range(16):\n                start = i * 16\n                lhs, rhs = self.single_mds_16x8s(state_bytes[start:start + 16])\n                out_state_array[i * 2] = lhs\n                out_state_array[i * 2 + 1] = rhs\n            return out_state_array\n\n        def permutate_xlate_buffer(self, xlate_array, key_array, initial_j):\n            sbox = self.sbox_0\n            counter_j = sbox[initial_j]\n            for counter_i in range(256):\n                counter_j = sbox[(counter_j + xlate_array[counter_j] + key_array[counter_i]) & 0xff]\n                s_counter_i = sbox[counter_i]\n                xlate_array[s_counter_i], xlate_array[counter_j] = xlate_array[counter_j], xlate_array[s_counter_i]\n            return\n\n        def xlate_state_mds_8x8s(self, in_state_bytes, xlate_array):\n            tables = self.mds_8x8s_0\n            out_state_array = [0] * 32\n            for loop_counter in range(32):\n                local_loop_counter = loop_counter << 3\n                mds_result = 0\n                mds_result ^= tables[0][in_state_bytes[xlate_array[local_loop_counter + 0]]]\n                mds_result ^= tables[1][in_state_bytes[xlate_array[local_loop_counter + 1]]]\n                mds_result ^= tables[2][in_state_bytes[xlate_array[local_loop_counter + 2]]]\n                mds_result ^= tables[3][in_state_bytes[xlate_array[local_loop_counter + 3]]]\n                mds_result ^= tables[4][in_state_bytes[xlate_array[local_loop_counter + 4]]]\n                mds_result ^= tables[5][in_state_bytes[xlate_array[local_loop_counter + 5]]]\n                mds_result ^= tables[6][in_state_bytes[xlate_array[local_loop_counter + 6]]]\n                mds_result ^= tables[7][in_state_bytes[xlate_array[local_loop_counter + 7]]]\n                out_state_array[loop_counter] = mds_result\n            return out_state_array\n\n        def process_preliminary_key(self, final_block_bit_count):\n            preliminary_key = [0] * 8\n\n            current_word = self.serial_number\n            preliminary_key[0] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.secret_key[0] + preliminary_key[0]) & self.word_modulus_64\n            preliminary_key[1] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.block_count_low_word + preliminary_key[1]) & self.word_modulus_64\n            preliminary_key[2] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.secret_key[1] + preliminary_key[2]) & self.word_modulus_64\n            preliminary_key[3] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (final_block_bit_count + preliminary_key[3]) & self.word_modulus_64\n            preliminary_key[4] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.secret_key[2] + preliminary_key[4]) & self.word_modulus_64\n            preliminary_key[5] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.block_count_high_word + preliminary_key[5]) & self.word_modulus_64\n            preliminary_key[6] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            current_word = (self.secret_key[3] + preliminary_key[6]) & self.word_modulus_64\n            preliminary_key[7] = self.single_mds_8x8s(current_word.to_bytes(8, \"little\"))\n\n            for i in range(8):\n                previous = preliminary_key[i - 1]\n                preliminary_key[i] = (preliminary_key[i] + previous) & self.word_modulus_64\n\n            return preliminary_key\n\n        def pht_a_diffuse(self, state_array):\n            state_array[0] = (state_array[0] + state_array[17]) & self.word_modulus_64\n            state_array[17] = (state_array[17] + state_array[0]) & self.word_modulus_64\n\n            state_array[2] = (state_array[2] + state_array[19]) & self.word_modulus_64\n            state_array[19] = (state_array[19] + state_array[2]) & self.word_modulus_64\n\n            state_array[4] = (state_array[4] + state_array[21]) & self.word_modulus_64\n            state_array[21] = (state_array[21] + state_array[4]) & self.word_modulus_64\n\n            state_array[6] = (state_array[6] + state_array[23]) & self.word_modulus_64\n            state_array[23] = (state_array[23] + state_array[6]) & self.word_modulus_64\n\n            state_array[8] = (state_array[8] + state_array[25]) & self.word_modulus_64\n            state_array[25] = (state_array[25] + state_array[8]) & self.word_modulus_64\n\n            state_array[10] = (state_array[10] + state_array[27]) & self.word_modulus_64\n            state_array[27] = (state_array[27] + state_array[10]) & self.word_modulus_64\n\n            state_array[12] = (state_array[12] + state_array[29]) & self.word_modulus_64\n            state_array[29] = (state_array[29] + state_array[12]) & self.word_modulus_64\n\n            state_array[14] = (state_array[14] + state_array[31]) & self.word_modulus_64\n            state_array[31] = (state_array[31] + state_array[14]) & self.word_modulus_64\n\n            state_array[9] = (state_array[9] + state_array[16]) & self.word_modulus_64\n            state_array[16] = (state_array[16] + state_array[9]) & self.word_modulus_64\n\n            state_array[11] = (state_array[11] + state_array[18]) & self.word_modulus_64\n            state_array[18] = (state_array[18] + state_array[11]) & self.word_modulus_64\n\n            state_array[13] = (state_array[13] + state_array[20]) & self.word_modulus_64\n            state_array[20] = (state_array[20] + state_array[13]) & self.word_modulus_64\n\n            state_array[15] = (state_array[15] + state_array[22]) & self.word_modulus_64\n            state_array[22] = (state_array[22] + state_array[15]) & self.word_modulus_64\n\n            state_array[1] = (state_array[1] + state_array[24]) & self.word_modulus_64\n            state_array[24] = (state_array[24] + state_array[1]) & self.word_modulus_64\n\n            state_array[3] = (state_array[3] + state_array[26]) & self.word_modulus_64\n            state_array[26] = (state_array[26] + state_array[3]) & self.word_modulus_64\n\n            state_array[5] = (state_array[5] + state_array[28]) & self.word_modulus_64\n            state_array[28] = (state_array[28] + state_array[5]) & self.word_modulus_64\n\n            state_array[7] = (state_array[7] + state_array[30]) & self.word_modulus_64\n            state_array[30] = (state_array[30] + state_array[7]) & self.word_modulus_64\n            return\n\n        def pht_b_diffuse(self, state_array):\n            state_array[0] = (state_array[0] + state_array[3]) & self.word_modulus_64\n            state_array[3] = (state_array[3] + state_array[0]) & self.word_modulus_64\n\n            state_array[2] = (state_array[2] + state_array[7]) & self.word_modulus_64\n            state_array[7] = (state_array[7] + state_array[2]) & self.word_modulus_64\n\n            state_array[4] = (state_array[4] + state_array[1]) & self.word_modulus_64\n            state_array[1] = (state_array[1] + state_array[4]) & self.word_modulus_64\n\n            state_array[6] = (state_array[6] + state_array[5]) & self.word_modulus_64\n            state_array[5] = (state_array[5] + state_array[6]) & self.word_modulus_64\n\n            state_array[8] = (state_array[8] + state_array[11]) & self.word_modulus_64\n            state_array[11] = (state_array[11] + state_array[8]) & self.word_modulus_64\n\n            state_array[10] = (state_array[10] + state_array[15]) & self.word_modulus_64\n            state_array[15] = (state_array[15] + state_array[10]) & self.word_modulus_64\n\n            state_array[12] = (state_array[12] + state_array[9]) & self.word_modulus_64\n            state_array[9] = (state_array[9] + state_array[12]) & self.word_modulus_64\n\n            state_array[14] = (state_array[14] + state_array[13]) & self.word_modulus_64\n            state_array[13] = (state_array[13] + state_array[14]) & self.word_modulus_64\n\n            state_array[16] = (state_array[16] + state_array[19]) & self.word_modulus_64\n            state_array[19] = (state_array[19] + state_array[16]) & self.word_modulus_64\n\n            state_array[18] = (state_array[18] + state_array[23]) & self.word_modulus_64\n            state_array[23] = (state_array[23] + state_array[18]) & self.word_modulus_64\n\n            state_array[20] = (state_array[20] + state_array[17]) & self.word_modulus_64\n            state_array[17] = (state_array[17] + state_array[20]) & self.word_modulus_64\n\n            state_array[22] = (state_array[22] + state_array[21]) & self.word_modulus_64\n            state_array[21] = (state_array[21] + state_array[22]) & self.word_modulus_64\n\n            state_array[24] = (state_array[24] + state_array[27]) & self.word_modulus_64\n            state_array[27] = (state_array[27] + state_array[24]) & self.word_modulus_64\n\n            state_array[26] = (state_array[26] + state_array[31]) & self.word_modulus_64\n            state_array[31] = (state_array[31] + state_array[26]) & self.word_modulus_64\n\n            state_array[28] = (state_array[28] + state_array[25]) & self.word_modulus_64\n            state_array[25] = (state_array[25] + state_array[28]) & self.word_modulus_64\n\n            state_array[30] = (state_array[30] + state_array[29]) & self.word_modulus_64\n            state_array[29] = (state_array[29] + state_array[30]) & self.word_modulus_64\n            return\n\n        def quad_diffuse_q0(self, state_array):\n            qd0r0 = 28\n            qd0r1 = 6\n            qd0r2 = 55\n            qdx0 = 9  # noqa: F841\n            qdx1 = 18\n            qdx2 = 27\n            qdx3 = 36\n\n            state_array[0] = (state_array[0] + self.rol64(state_array[0] ^ state_array[14], qd0r0)) & self.word_modulus_64\n            state_array[2] = (state_array[2] + self.rol64(state_array[2] ^ state_array[0], qd0r1)) & self.word_modulus_64\n            state_array[4] = (state_array[4] + self.rol64(state_array[4] ^ state_array[2], qd0r2)) & self.word_modulus_64\n            state_array[6] = (state_array[6] + self.rol64(state_array[6] ^ state_array[4], qd0r0)) & self.word_modulus_64\n            state_array[8] = (state_array[8] + self.rol64(state_array[8] ^ state_array[6], qd0r1)) & self.word_modulus_64\n            state_array[10] = (state_array[10] + self.rol64(state_array[10] ^ state_array[8], qd0r2)) & self.word_modulus_64\n            state_array[12] = (state_array[12] + self.rol64(state_array[12] ^ state_array[10], qd0r0)) & self.word_modulus_64\n            state_array[14] = (state_array[14] + self.rol64(state_array[14] ^ state_array[12], qd0r1)) & self.word_modulus_64\n\n            state_array[0] ^= self.rol64((state_array[0] + state_array[14]) & self.word_modulus_64, qd0r2)\n            state_array[2] ^= self.rol64((state_array[2] + state_array[0]) & self.word_modulus_64, qd0r0)\n            state_array[4] ^= self.rol64((state_array[4] + state_array[2]) & self.word_modulus_64, qd0r1)\n            state_array[6] ^= self.rol64((state_array[6] + state_array[4]) & self.word_modulus_64, qd0r2)\n            state_array[8] ^= self.rol64((state_array[8] + state_array[6]) & self.word_modulus_64, qd0r0)\n            state_array[10] ^= self.rol64((state_array[10] + state_array[8]) & self.word_modulus_64, qd0r1)\n            state_array[12] ^= self.rol64((state_array[12] + state_array[10]) & self.word_modulus_64, qd0r2)\n            state_array[14] ^= self.rol64((state_array[14] + state_array[12]) & self.word_modulus_64, qd0r0)\n\n            state_array[1] ^= self.rol64(state_array[0], qdx1)\n            state_array[3] ^= self.rol64(state_array[2], qdx1)\n            state_array[5] ^= self.rol64(state_array[4], qdx1)\n            state_array[7] ^= self.rol64(state_array[6], qdx1)\n            state_array[9] ^= self.rol64(state_array[8], qdx1)\n            state_array[11] ^= self.rol64(state_array[10], qdx1)\n            state_array[13] ^= self.rol64(state_array[12], qdx1)\n            state_array[15] ^= self.rol64(state_array[14], qdx1)\n\n            state_array[16] ^= self.rol64(state_array[0], qdx2)\n            state_array[18] ^= self.rol64(state_array[2], qdx2)\n            state_array[20] ^= self.rol64(state_array[4], qdx2)\n            state_array[22] ^= self.rol64(state_array[6], qdx2)\n            state_array[24] ^= self.rol64(state_array[8], qdx2)\n            state_array[26] ^= self.rol64(state_array[10], qdx2)\n            state_array[28] ^= self.rol64(state_array[12], qdx2)\n            state_array[30] ^= self.rol64(state_array[14], qdx2)\n\n            state_array[17] ^= self.rol64(state_array[0], qdx3)\n            state_array[19] ^= self.rol64(state_array[2], qdx3)\n            state_array[21] ^= self.rol64(state_array[4], qdx3)\n            state_array[23] ^= self.rol64(state_array[6], qdx3)\n            state_array[25] ^= self.rol64(state_array[8], qdx3)\n            state_array[27] ^= self.rol64(state_array[10], qdx3)\n            state_array[29] ^= self.rol64(state_array[12], qdx3)\n            state_array[31] ^= self.rol64(state_array[14], qdx3)\n            return\n\n        def quad_diffuse_q1(self, state_array):\n            qd1r0 = 36\n            qd1r1 = 58\n            qd1r2 = 9\n            qdx0 = 9\n            qdx2 = 27\n            qdx3 = 36\n\n            state_array[1] = (state_array[1] + self.rol64(state_array[1] ^ state_array[15], qd1r0)) & self.word_modulus_64\n            state_array[3] = (state_array[3] + self.rol64(state_array[3] ^ state_array[1], qd1r1)) & self.word_modulus_64\n            state_array[5] = (state_array[5] + self.rol64(state_array[5] ^ state_array[3], qd1r2)) & self.word_modulus_64\n            state_array[7] = (state_array[7] + self.rol64(state_array[7] ^ state_array[5], qd1r0)) & self.word_modulus_64\n            state_array[9] = (state_array[9] + self.rol64(state_array[9] ^ state_array[7], qd1r1)) & self.word_modulus_64\n            state_array[11] = (state_array[11] + self.rol64(state_array[11] ^ state_array[9], qd1r2)) & self.word_modulus_64\n            state_array[13] = (state_array[13] + self.rol64(state_array[13] ^ state_array[11], qd1r0)) & self.word_modulus_64\n            state_array[15] = (state_array[15] + self.rol64(state_array[15] ^ state_array[13], qd1r1)) & self.word_modulus_64\n\n            state_array[1] ^= self.rol64((state_array[1] + state_array[15]) & self.word_modulus_64, qd1r2)\n            state_array[3] ^= self.rol64((state_array[3] + state_array[1]) & self.word_modulus_64, qd1r0)\n            state_array[5] ^= self.rol64((state_array[5] + state_array[3]) & self.word_modulus_64, qd1r1)\n            state_array[7] ^= self.rol64((state_array[7] + state_array[5]) & self.word_modulus_64, qd1r2)\n            state_array[9] ^= self.rol64((state_array[9] + state_array[7]) & self.word_modulus_64, qd1r0)\n            state_array[11] ^= self.rol64((state_array[11] + state_array[9]) & self.word_modulus_64, qd1r1)\n            state_array[13] ^= self.rol64((state_array[13] + state_array[11]) & self.word_modulus_64, qd1r2)\n            state_array[15] ^= self.rol64((state_array[15] + state_array[13]) & self.word_modulus_64, qd1r0)\n\n            state_array[0] ^= self.rol64(state_array[1], qdx0)\n            state_array[2] ^= self.rol64(state_array[3], qdx0)\n            state_array[4] ^= self.rol64(state_array[5], qdx0)\n            state_array[6] ^= self.rol64(state_array[7], qdx0)\n            state_array[8] ^= self.rol64(state_array[9], qdx0)\n            state_array[10] ^= self.rol64(state_array[11], qdx0)\n            state_array[12] ^= self.rol64(state_array[13], qdx0)\n            state_array[14] ^= self.rol64(state_array[15], qdx0)\n\n            state_array[16] ^= self.rol64(state_array[1], qdx2)\n            state_array[18] ^= self.rol64(state_array[3], qdx2)\n            state_array[20] ^= self.rol64(state_array[5], qdx2)\n            state_array[22] ^= self.rol64(state_array[7], qdx2)\n            state_array[24] ^= self.rol64(state_array[9], qdx2)\n            state_array[26] ^= self.rol64(state_array[11], qdx2)\n            state_array[29] ^= self.rol64(state_array[13], qdx2)\n            state_array[30] ^= self.rol64(state_array[15], qdx2)\n\n            state_array[17] ^= self.rol64(state_array[1], qdx3)\n            state_array[19] ^= self.rol64(state_array[3], qdx3)\n            state_array[21] ^= self.rol64(state_array[5], qdx3)\n            state_array[23] ^= self.rol64(state_array[7], qdx3)\n            state_array[25] ^= self.rol64(state_array[9], qdx3)\n            state_array[27] ^= self.rol64(state_array[11], qdx3)\n            state_array[29] ^= self.rol64(state_array[13], qdx3)\n            state_array[31] ^= self.rol64(state_array[15], qdx3)\n            return\n\n        def quad_diffuse_q2(self, state_array):\n            qd2r0 = 8\n            qd2r1 = 24\n            qd2r2 = 43\n            qd3r0 = 9\n            qd3r1 = 47\n            qd3r2 = 39\n            qdx0 = 9\n            qdx1 = 18\n            qdx3 = 36\n\n            state_array[16] = (state_array[16] + self.rol64(state_array[16] ^ state_array[30], qd2r0)) & self.word_modulus_64\n            state_array[18] = (state_array[18] + self.rol64(state_array[18] ^ state_array[16], qd2r1)) & self.word_modulus_64\n            state_array[20] = (state_array[20] + self.rol64(state_array[20] ^ state_array[18], qd2r2)) & self.word_modulus_64\n            state_array[22] = (state_array[22] + self.rol64(state_array[22] ^ state_array[20], qd2r0)) & self.word_modulus_64\n            state_array[24] = (state_array[24] + self.rol64(state_array[24] ^ state_array[22], qd2r1)) & self.word_modulus_64\n            state_array[26] = (state_array[26] + self.rol64(state_array[26] ^ state_array[24], qd2r2)) & self.word_modulus_64\n            state_array[28] = (state_array[28] + self.rol64(state_array[28] ^ state_array[26], qd2r0)) & self.word_modulus_64\n            state_array[30] = (state_array[30] + self.rol64(state_array[30] ^ state_array[28], qd2r1)) & self.word_modulus_64\n\n            state_array[16] ^= self.rol64((state_array[16] + state_array[30]) & self.word_modulus_64, qd3r2)\n            state_array[18] ^= self.rol64((state_array[18] + state_array[16]) & self.word_modulus_64, qd3r0)\n            state_array[20] ^= self.rol64((state_array[20] + state_array[18]) & self.word_modulus_64, qd3r1)\n            state_array[22] ^= self.rol64((state_array[22] + state_array[20]) & self.word_modulus_64, qd3r2)\n            state_array[24] ^= self.rol64((state_array[24] + state_array[22]) & self.word_modulus_64, qd3r0)\n            state_array[26] ^= self.rol64((state_array[26] + state_array[24]) & self.word_modulus_64, qd3r1)\n            state_array[28] ^= self.rol64((state_array[28] + state_array[26]) & self.word_modulus_64, qd3r2)\n            state_array[30] ^= self.rol64((state_array[30] + state_array[28]) & self.word_modulus_64, qd3r0)\n\n            state_array[0] ^= self.rol64(state_array[16], qdx0)\n            state_array[2] ^= self.rol64(state_array[18], qdx0)\n            state_array[4] ^= self.rol64(state_array[20], qdx0)\n            state_array[6] ^= self.rol64(state_array[22], qdx0)\n            state_array[8] ^= self.rol64(state_array[24], qdx0)\n            state_array[10] ^= self.rol64(state_array[26], qdx0)\n            state_array[12] ^= self.rol64(state_array[28], qdx0)\n            state_array[14] ^= self.rol64(state_array[30], qdx0)\n\n            state_array[1] ^= self.rol64(state_array[16], qdx1)\n            state_array[3] ^= self.rol64(state_array[18], qdx1)\n            state_array[5] ^= self.rol64(state_array[20], qdx1)\n            state_array[7] ^= self.rol64(state_array[22], qdx1)\n            state_array[9] ^= self.rol64(state_array[24], qdx1)\n            state_array[11] ^= self.rol64(state_array[26], qdx1)\n            state_array[13] ^= self.rol64(state_array[28], qdx1)\n            state_array[15] ^= self.rol64(state_array[30], qdx1)\n\n            state_array[17] ^= self.rol64(state_array[1], qdx3)\n            state_array[19] ^= self.rol64(state_array[3], qdx3)\n            state_array[21] ^= self.rol64(state_array[5], qdx3)\n            state_array[23] ^= self.rol64(state_array[7], qdx3)\n            state_array[25] ^= self.rol64(state_array[9], qdx3)\n            state_array[27] ^= self.rol64(state_array[11], qdx3)\n            state_array[29] ^= self.rol64(state_array[13], qdx3)\n            state_array[31] ^= self.rol64(state_array[15], qdx3)\n            return\n\n        def quad_diffuse_q3(self, state_array):\n            qd3r0 = 9\n            qd3r1 = 47\n            qd3r2 = 39\n            qdx0 = 9\n            qdx1 = 18\n            qdx2 = 27\n\n            state_array[17] = (state_array[17] + self.rol64(state_array[17] ^ state_array[31], qd3r0)) & self.word_modulus_64\n            state_array[19] = (state_array[19] + self.rol64(state_array[19] ^ state_array[17], qd3r1)) & self.word_modulus_64\n            state_array[21] = (state_array[21] + self.rol64(state_array[21] ^ state_array[19], qd3r2)) & self.word_modulus_64\n            state_array[23] = (state_array[23] + self.rol64(state_array[23] ^ state_array[21], qd3r0)) & self.word_modulus_64\n            state_array[25] = (state_array[25] + self.rol64(state_array[25] ^ state_array[23], qd3r1)) & self.word_modulus_64\n            state_array[27] = (state_array[27] + self.rol64(state_array[27] ^ state_array[25], qd3r2)) & self.word_modulus_64\n            state_array[29] = (state_array[29] + self.rol64(state_array[29] ^ state_array[27], qd3r0)) & self.word_modulus_64\n            state_array[31] = (state_array[31] + self.rol64(state_array[31] ^ state_array[29], qd3r1)) & self.word_modulus_64\n\n            state_array[17] ^= self.rol64((state_array[17] + state_array[31]) & self.word_modulus_64, qd3r2)\n            state_array[19] ^= self.rol64((state_array[19] + state_array[17]) & self.word_modulus_64, qd3r0)\n            state_array[21] ^= self.rol64((state_array[21] + state_array[19]) & self.word_modulus_64, qd3r1)\n            state_array[23] ^= self.rol64((state_array[23] + state_array[21]) & self.word_modulus_64, qd3r2)\n            state_array[25] ^= self.rol64((state_array[25] + state_array[23]) & self.word_modulus_64, qd3r0)\n            state_array[27] ^= self.rol64((state_array[27] + state_array[25]) & self.word_modulus_64, qd3r1)\n            state_array[29] ^= self.rol64((state_array[29] + state_array[27]) & self.word_modulus_64, qd3r2)\n            state_array[31] ^= self.rol64((state_array[31] + state_array[29]) & self.word_modulus_64, qd3r0)\n\n            state_array[0] ^= self.rol64(state_array[17], qdx0)\n            state_array[2] ^= self.rol64(state_array[19], qdx0)\n            state_array[4] ^= self.rol64(state_array[21], qdx0)\n            state_array[6] ^= self.rol64(state_array[23], qdx0)\n            state_array[8] ^= self.rol64(state_array[25], qdx0)\n            state_array[10] ^= self.rol64(state_array[27], qdx0)\n            state_array[12] ^= self.rol64(state_array[29], qdx0)\n            state_array[14] ^= self.rol64(state_array[31], qdx0)\n\n            state_array[1] ^= self.rol64(state_array[17], qdx1)\n            state_array[3] ^= self.rol64(state_array[19], qdx1)\n            state_array[5] ^= self.rol64(state_array[21], qdx1)\n            state_array[7] ^= self.rol64(state_array[23], qdx1)\n            state_array[9] ^= self.rol64(state_array[25], qdx1)\n            state_array[11] ^= self.rol64(state_array[27], qdx1)\n            state_array[13] ^= self.rol64(state_array[29], qdx1)\n            state_array[15] ^= self.rol64(state_array[31], qdx1)\n\n            state_array[16] ^= self.rol64(state_array[17], qdx2)\n            state_array[18] ^= self.rol64(state_array[19], qdx2)\n            state_array[20] ^= self.rol64(state_array[21], qdx2)\n            state_array[22] ^= self.rol64(state_array[23], qdx2)\n            state_array[24] ^= self.rol64(state_array[25], qdx2)\n            state_array[26] ^= self.rol64(state_array[27], qdx2)\n            state_array[28] ^= self.rol64(state_array[29], qdx2)\n            state_array[30] ^= self.rol64(state_array[31], qdx2)\n            return\n\n        def process_principle_key_single_1_rounds(self, message_block, preliminary_key):\n            temp_array = self.xlate_state_mds_8x8s(self.words_to_bytes_le(message_block), self.sbox_0)\n            temp_array[0] ^= preliminary_key[0]\n            temp_array[2] ^= preliminary_key[1]\n            temp_array[4] ^= preliminary_key[2]\n            temp_array[6] ^= preliminary_key[3]\n            temp_array[8] ^= preliminary_key[4]\n            temp_array[10] ^= preliminary_key[5]\n            temp_array[12] ^= preliminary_key[6]\n            temp_array[14] ^= preliminary_key[7]\n            self.pht_a_diffuse(temp_array)\n            self.quad_diffuse_q0(temp_array)\n            self.pht_b_diffuse(temp_array)\n            principle_key = self.full_mds_state_update(temp_array, list(message_block))\n            return principle_key\n\n        def process_principle_key_pair_1_rounds(self, message_block_left, message_block_right, preliminary_key):\n            principle_key_left = self.process_principle_key_single_1_rounds(message_block_left, preliminary_key)\n            principle_key_right = self.process_principle_key_single_1_rounds(message_block_right, preliminary_key)\n            for i in range(32):\n                principle_key_left[i] = (principle_key_left[i] + principle_key_right[i]) & self.word_modulus_64\n            principle_key = self.process_principle_key_single_1_rounds(principle_key_left, preliminary_key)\n            return principle_key\n\n        def key_extract_x4(self, principle_key_extract, preliminary_key, round_index):\n            rc = self.rc_u64\n            local_round_index_0 = round_index & 0x3f\n            local_round_index_1 = (round_index + 1) & 0x3f\n            local_round_index_2 = (round_index + 2) & 0x3f\n            local_round_index_3 = (round_index + 3) & 0x3f\n            local_round_index_4 = (round_index + 4) & 0x3f\n            local_round_index_5 = (round_index + 5) & 0x3f\n            local_round_index_6 = (round_index + 6) & 0x3f\n            local_round_index_7 = (round_index + 7) & 0x3f\n\n            ke_rotate_1 = (3 + round_index) & 0x3f\n            ke_rotate_2 = (17 + round_index) & 0x3f\n            ke_rotate_3 = (29 + round_index) & 0x3f\n\n            round_key = [0] * 32\n            round_key[0] = principle_key_extract[0] ^ preliminary_key[0] ^ rc[local_round_index_0]\n            round_key[2] = principle_key_extract[1] ^ preliminary_key[1] ^ rc[local_round_index_1]\n            round_key[4] = principle_key_extract[2] ^ preliminary_key[2] ^ rc[local_round_index_2]\n            round_key[6] = principle_key_extract[3] ^ preliminary_key[3] ^ rc[local_round_index_3]\n            round_key[8] = principle_key_extract[4] ^ preliminary_key[4] ^ rc[local_round_index_4]\n            round_key[10] = principle_key_extract[5] ^ preliminary_key[5] ^ rc[local_round_index_5]\n            round_key[12] = principle_key_extract[6] ^ preliminary_key[6] ^ rc[local_round_index_6]\n            round_key[14] = principle_key_extract[7] ^ preliminary_key[7] ^ rc[local_round_index_7]\n\n            round_key[1] = self.rol64(round_key[2], ke_rotate_1)\n            round_key[3] = self.rol64(round_key[0], ke_rotate_1)\n            round_key[5] = self.rol64(round_key[6], ke_rotate_1)\n            round_key[7] = self.rol64(round_key[4], ke_rotate_1)\n            round_key[9] = self.rol64(round_key[10], ke_rotate_1)\n            round_key[11] = self.rol64(round_key[8], ke_rotate_1)\n            round_key[13] = self.rol64(round_key[14], ke_rotate_1)\n            round_key[15] = self.rol64(round_key[12], ke_rotate_1)\n\n            round_key[16] = self.rol64(round_key[6], ke_rotate_2)\n            round_key[18] = self.rol64(round_key[4], ke_rotate_2)\n            round_key[20] = self.rol64(round_key[2], ke_rotate_2)\n            round_key[22] = self.rol64(round_key[0], ke_rotate_2)\n            round_key[24] = self.rol64(round_key[14], ke_rotate_2)\n            round_key[26] = self.rol64(round_key[12], ke_rotate_2)\n            round_key[28] = self.rol64(round_key[10], ke_rotate_2)\n            round_key[30] = self.rol64(round_key[8], ke_rotate_2)\n\n            round_key[17] = self.rol64(round_key[14], ke_rotate_3)\n            round_key[19] = self.rol64(round_key[12], ke_rotate_3)\n            round_key[21] = self.rol64(round_key[10], ke_rotate_3)\n            round_key[23] = self.rol64(round_key[8], ke_rotate_3)\n            round_key[25] = self.rol64(round_key[6], ke_rotate_3)\n            round_key[27] = self.rol64(round_key[4], ke_rotate_3)\n            round_key[29] = self.rol64(round_key[2], ke_rotate_3)\n            round_key[31] = self.rol64(round_key[0], ke_rotate_3)\n            return round_key\n\n        def key_extract_x2(self, principle_key_extract, preliminary_key, round_index):\n            rc = self.rc_u64\n            local_round_index_0 = round_index & 0x3f\n            local_round_index_1 = (round_index + 1) & 0x3f\n            local_round_index_2 = (round_index + 2) & 0x3f\n            local_round_index_3 = (round_index + 3) & 0x3f\n            local_round_index_4 = (round_index + 4) & 0x3f\n            local_round_index_5 = (round_index + 5) & 0x3f\n            local_round_index_6 = (round_index + 6) & 0x3f\n            local_round_index_7 = (round_index + 7) & 0x3f\n\n            ke_rotate_1 = (3 + round_index) & 0x3f\n            ke_rotate_2 = (17 + round_index) & 0x3f\n            ke_rotate_3 = (29 + round_index) & 0x3f\n\n            round_key = [0] * 32\n            round_key[0] = principle_key_extract[0] ^ preliminary_key[0] ^ rc[local_round_index_0]\n            round_key[2] = principle_key_extract[1] ^ preliminary_key[1] ^ rc[local_round_index_1]\n            round_key[4] = principle_key_extract[2] ^ preliminary_key[2] ^ rc[local_round_index_2]\n            round_key[6] = principle_key_extract[3] ^ preliminary_key[3] ^ rc[local_round_index_3]\n            round_key[8] = principle_key_extract[4] ^ preliminary_key[4] ^ rc[local_round_index_4]\n            round_key[10] = principle_key_extract[5] ^ preliminary_key[5] ^ rc[local_round_index_5]\n            round_key[12] = principle_key_extract[6] ^ preliminary_key[6] ^ rc[local_round_index_6]\n            round_key[14] = principle_key_extract[7] ^ preliminary_key[7] ^ rc[local_round_index_7]\n\n            round_key[1] = self.rol64(principle_key_extract[8], ke_rotate_1)\n            round_key[3] = self.rol64(principle_key_extract[9], ke_rotate_1)\n            round_key[5] = self.rol64(principle_key_extract[10], ke_rotate_1)\n            round_key[7] = self.rol64(principle_key_extract[11], ke_rotate_1)\n            round_key[9] = self.rol64(principle_key_extract[12], ke_rotate_1)\n            round_key[11] = self.rol64(principle_key_extract[13], ke_rotate_1)\n            round_key[13] = self.rol64(principle_key_extract[14], ke_rotate_1)\n            round_key[15] = self.rol64(principle_key_extract[15], ke_rotate_1)\n\n            round_key[16] = self.rol64(round_key[2], ke_rotate_2)\n            round_key[18] = self.rol64(round_key[0], ke_rotate_2)\n            round_key[20] = self.rol64(round_key[6], ke_rotate_2)\n            round_key[22] = self.rol64(round_key[4], ke_rotate_2)\n            round_key[24] = self.rol64(round_key[10], ke_rotate_2)\n            round_key[26] = self.rol64(round_key[8], ke_rotate_2)\n            round_key[28] = self.rol64(round_key[14], ke_rotate_2)\n            round_key[30] = self.rol64(round_key[12], ke_rotate_2)\n\n            round_key[17] = self.rol64(round_key[7], ke_rotate_3)\n            round_key[19] = self.rol64(round_key[5], ke_rotate_3)\n            round_key[21] = self.rol64(round_key[3], ke_rotate_3)\n            round_key[23] = self.rol64(round_key[1], ke_rotate_3)\n            round_key[25] = self.rol64(round_key[15], ke_rotate_3)\n            round_key[27] = self.rol64(round_key[13], ke_rotate_3)\n            round_key[29] = self.rol64(round_key[11], ke_rotate_3)\n            round_key[31] = self.rol64(round_key[9], ke_rotate_3)\n            return round_key\n\n        def key_extract_pre_whitening(self, principle_key_extract, preliminary_key):\n            round_key = [0] * 32\n            round_key[0] = principle_key_extract[0] ^ preliminary_key[0]\n            round_key[2] = principle_key_extract[2] ^ preliminary_key[1]\n            round_key[4] = principle_key_extract[4] ^ preliminary_key[2]\n            round_key[6] = principle_key_extract[6] ^ preliminary_key[3]\n            round_key[8] = principle_key_extract[8] ^ preliminary_key[4]\n            round_key[10] = principle_key_extract[10] ^ preliminary_key[5]\n            round_key[12] = principle_key_extract[12] ^ preliminary_key[6]\n            round_key[14] = principle_key_extract[14] ^ preliminary_key[7]\n\n            round_key[1] = principle_key_extract[1] ^ preliminary_key[7]\n            round_key[3] = principle_key_extract[3] ^ preliminary_key[6]\n            round_key[5] = principle_key_extract[5] ^ preliminary_key[5]\n            round_key[7] = principle_key_extract[7] ^ preliminary_key[4]\n            round_key[9] = principle_key_extract[9] ^ preliminary_key[3]\n            round_key[11] = principle_key_extract[11] ^ preliminary_key[2]\n            round_key[13] = principle_key_extract[13] ^ preliminary_key[1]\n            round_key[15] = principle_key_extract[15] ^ preliminary_key[0]\n\n            round_key[16] = principle_key_extract[16]\n            round_key[18] = principle_key_extract[18]\n            round_key[20] = principle_key_extract[20]\n            round_key[22] = principle_key_extract[22]\n            round_key[24] = principle_key_extract[24]\n            round_key[26] = principle_key_extract[26]\n            round_key[28] = principle_key_extract[28]\n            round_key[30] = principle_key_extract[30]\n\n            round_key[17] = principle_key_extract[17]\n            round_key[19] = principle_key_extract[19]\n            round_key[21] = principle_key_extract[21]\n            round_key[23] = principle_key_extract[23]\n            round_key[25] = principle_key_extract[25]\n            round_key[27] = principle_key_extract[27]\n            round_key[29] = principle_key_extract[29]\n            round_key[31] = principle_key_extract[31]\n\n            self.pht_a_diffuse(round_key)\n            return round_key\n\n        def key_extract_post_whitening(self, principle_key_extract, preliminary_key):\n            round_key = [0] * 32\n            round_key[0] = principle_key_extract[0] ^ preliminary_key[0]\n            round_key[2] = principle_key_extract[2] ^ preliminary_key[1]\n            round_key[4] = principle_key_extract[4] ^ preliminary_key[2]\n            round_key[6] = principle_key_extract[6] ^ preliminary_key[3]\n            round_key[8] = principle_key_extract[8] ^ preliminary_key[4]\n            round_key[10] = principle_key_extract[10] ^ preliminary_key[5]\n            round_key[12] = principle_key_extract[12] ^ preliminary_key[6]\n            round_key[14] = principle_key_extract[14] ^ preliminary_key[7]\n\n            round_key[1] = principle_key_extract[1] ^ preliminary_key[7]\n            round_key[3] = principle_key_extract[3] ^ preliminary_key[6]\n            round_key[5] = principle_key_extract[5] ^ preliminary_key[5]\n            round_key[7] = principle_key_extract[7] ^ preliminary_key[4]\n            round_key[9] = principle_key_extract[9] ^ preliminary_key[3]\n            round_key[11] = principle_key_extract[11] ^ preliminary_key[2]\n            round_key[13] = principle_key_extract[13] ^ preliminary_key[1]\n            round_key[15] = principle_key_extract[15] ^ preliminary_key[0]\n\n            round_key[16] = principle_key_extract[16]\n            round_key[18] = principle_key_extract[18]\n            round_key[20] = principle_key_extract[20]\n            round_key[22] = principle_key_extract[22]\n            round_key[24] = principle_key_extract[24]\n            round_key[26] = principle_key_extract[26]\n            round_key[28] = principle_key_extract[28]\n            round_key[30] = principle_key_extract[30]\n\n            round_key[17] = principle_key_extract[17]\n            round_key[19] = principle_key_extract[19]\n            round_key[21] = principle_key_extract[21]\n            round_key[23] = principle_key_extract[23]\n            round_key[25] = principle_key_extract[25]\n            round_key[27] = principle_key_extract[27]\n            round_key[29] = principle_key_extract[29]\n            round_key[31] = principle_key_extract[31]\n\n            self.pht_b_diffuse(round_key)\n            return round_key\n\n        def update_chaining_state_generic(self, preliminary_key, principle_key, block_count_low_word, schedule):\n            xlate_array = bytearray(self.sbox_0)\n            chaining_state_array = list(self.state_array)\n\n            self.permutate_xlate_buffer(xlate_array, self.words_to_bytes_le(principle_key), block_count_low_word & 0xff)\n\n            round_key = self.key_extract_pre_whitening(principle_key, preliminary_key)\n            self.xor_key_with_state(self.state_array, round_key)\n\n            centre_state_array = self.xlate_state_mds_8x8s(self.words_to_bytes_le(self.state_array), xlate_array)\n\n            state = centre_state_array\n            next_is_state_array = True\n\n            for kind, offset, quadrant, round_index in schedule:\n                self.pht_a_diffuse(state)\n                if quadrant == 0:\n                    self.quad_diffuse_q0(state)\n                elif quadrant == 1:\n                    self.quad_diffuse_q1(state)\n                elif quadrant == 2:\n                    self.quad_diffuse_q2(state)\n                else:\n                    self.quad_diffuse_q3(state)\n                self.pht_b_diffuse(state)\n\n                if kind == \"x2\":\n                    round_key = self.key_extract_x2(principle_key[offset:offset + 16], preliminary_key, round_index)\n                else:\n                    round_key = self.key_extract_x4(principle_key[offset:offset + 8], preliminary_key, round_index)\n\n                out_state = self.full_mds_state_update(state, round_key)\n                if next_is_state_array:\n                    self.state_array = out_state\n                    state = self.state_array\n                else:\n                    centre_state_array = out_state\n                    state = centre_state_array\n                next_is_state_array = not next_is_state_array\n\n            self.state_array = self.xlate_state_mds_8x8s(self.words_to_bytes_le(centre_state_array), xlate_array)\n            round_key = self.key_extract_post_whitening(principle_key, preliminary_key)\n            self.xor_key_with_state(self.state_array, round_key)\n            self.xor_key_with_state(self.state_array, chaining_state_array)\n            return\n\n        def update_chaining_state(self, preliminary_key, principle_key):\n            if self.centre_rounds == 4:\n                schedule = [\n                    (\"x4\", 0, 0, 0),\n                    (\"x4\", 8, 1, 1),\n                    (\"x4\", 16, 2, 2),\n                    (\"x4\", 24, 3, 3),\n                ]\n            elif self.centre_rounds == 6:\n                schedule = [\n                    (\"x2\", 0, 0, 0),\n                    (\"x4\", 0, 0, 1),\n                    (\"x4\", 8, 1, 2),\n                    (\"x4\", 16, 2, 3),\n                    (\"x4\", 24, 3, 4),\n                    (\"x4\", 16, 3, 5),\n                ]\n            elif self.centre_rounds == 8:\n                schedule = [\n                    (\"x4\", 0, 0, 0),\n                    (\"x4\", 8, 1, 1),\n                    (\"x4\", 16, 2, 2),\n                    (\"x4\", 24, 3, 3),\n                    (\"x4\", 0, 0, 4),\n                    (\"x4\", 8, 1, 5),\n                    (\"x4\", 16, 2, 6),\n                    (\"x4\", 24, 3, 7),\n                ]\n            else:\n                raise ValueError(\"unsupported centre rounds\")\n            self.update_chaining_state_generic(preliminary_key, principle_key, self.block_count_low_word, schedule)\n            return\n\n        def process_full_block(self, block):\n            if len(block) != self.block_size:\n                raise ValueError(\"full block must be 512 bytes\")\n            block_words = self.bytes_to_words_le(block)\n            preliminary_key = self.process_preliminary_key(0)\n            principle_key = self.process_principle_key_pair_1_rounds(block_words[:32], block_words[32:], preliminary_key)\n            self.update_chaining_state(preliminary_key, principle_key)\n\n            if self.block_count_low_word & 1:\n                self.block_count_high_word = (self.block_count_high_word + 1) & self.word_modulus_64\n            self.block_count_low_word = (self.block_count_low_word + 1) & self.word_modulus_64\n            return\n\n        def finalise_chaining_state(self):\n            state_array = list(self.state_array)\n            if self.hashbitlen <= 512:\n                state_array[0] ^= state_array[1] ^ state_array[16] ^ state_array[17]\n                state_array[2] ^= state_array[3] ^ state_array[18] ^ state_array[19]\n                state_array[4] ^= state_array[5] ^ state_array[20] ^ state_array[21]\n                state_array[6] ^= state_array[7] ^ state_array[22] ^ state_array[23]\n                state_array[8] ^= state_array[9] ^ state_array[24] ^ state_array[25]\n                state_array[10] ^= state_array[11] ^ state_array[26] ^ state_array[27]\n                state_array[12] ^= state_array[13] ^ state_array[28] ^ state_array[29]\n                state_array[14] ^= state_array[15] ^ state_array[30] ^ state_array[31]\n            result = self.words_to_bytes_le(state_array)[:self.digest_size]\n            self.state_array = [0] * 32\n            return result\n\n        def process_final_block(self, tail):\n            if len(tail) > self.block_size:\n                raise ValueError(\"tail too large\")\n            final_block_bit_count = len(tail) * 8\n            padded = tail + (b\"\\x00\" * (self.block_size - len(tail)))\n            padded_words = self.bytes_to_words_le(padded)\n            preliminary_key = self.process_preliminary_key(final_block_bit_count)\n\n            if len(tail) <= 256:\n                principle_key = self.process_principle_key_single_1_rounds(padded_words[:32], preliminary_key)\n            else:\n                principle_key = self.process_principle_key_pair_1_rounds(padded_words[:32], padded_words[32:], preliminary_key)\n\n            self.update_chaining_state(preliminary_key, principle_key)\n            self.final_bytes = self.finalise_chaining_state()\n\n            self.secret_key = [0, 0, 0, 0]\n            self.block_count_high_word = 0\n            self.block_count_low_word = 0\n            self.buf = bytearray()\n            self.serial_number = 0\n            return\n\n    class Sgail224(SgailBase):\n        digest_size = 28\n\n    class Sgail256(SgailBase):\n        digest_size = 32\n\n    class Sgail384(SgailBase):\n        digest_size = 48\n\n    class Sgail512(SgailBase):\n        digest_size = 64\n\n    class Sgail768(SgailBase):\n        digest_size = 96\n\n    class Sgail1024(SgailBase):\n        digest_size = 128\n\n    class Sgail1536(SgailBase):\n        digest_size = 192\n\n    class Sgail2048(SgailBase):\n        digest_size = 256\n\n    class SHAMATABase:\n        block_size = 16\n        digest_size = None\n        hashbitlen = None\n\n        sbox = (\n            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,\n        )\n\n        mul2_table = None\n        mul3_table = None\n\n        @classmethod\n        def ensure_tables(cls):\n            if cls.mul2_table is None:\n                mul2 = []\n                mul3 = []\n                for x in range(256):\n                    y = ((x << 1) & 0xff) ^ (0x1b if (x & 0x80) else 0x00)\n                    mul2.append(y)\n                    mul3.append(y ^ x)\n                cls.mul2_table = tuple(mul2)\n                cls.mul3_table = tuple(mul3)\n            return\n\n        def __init__(self, data=b\"\"):\n            self.__class__.ensure_tables()\n            self.B = [[0, 0, 0, 0] for _ in range(4)]\n            self.K = [[0, 0, 0, 0] for _ in range(12)]\n            self.r = 1 if self.hashbitlen <= 256 else 2\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.block_count = 0\n\n            iv = b\"\\x00\" * 14 + self.hashbitlen.to_bytes(2, \"big\")\n            for i in range(8):\n                self.process_block(iv, i + 1)\n\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.B = [row[:] for row in self.B]\n            other.K = [row[:] for row in self.K]\n            other.r = self.r\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.block_count = self.block_count\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n\n            data = bytes(data)\n            self.msg_len += len(data)\n\n            if self.buf:\n                need = self.block_size - len(self.buf)\n                self.buf.extend(data[:need])\n                data = data[need:]\n                if len(self.buf) == self.block_size:\n                    self.block_count += 1\n                    self.process_block(bytes(self.buf), self.block_count)\n                    self.buf.clear()\n\n            offset = 0\n            limit = len(data) - (len(data) % self.block_size)\n            while offset < limit:\n                self.block_count += 1\n                self.process_block(data[offset:offset + self.block_size], self.block_count)\n                offset += self.block_size\n\n            if offset < len(data):\n                self.buf.extend(data[offset:])\n\n            return self\n\n        def digest(self):\n            other = self.copy()\n            other.finalize()\n            return other.produce_output()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def finalize(self):\n            bit_len = self.msg_len * 8\n            processed = self.block_count\n            rem = bytes(self.buf)\n\n            if len(rem) <= 7:\n                block = rem + b\"\\x80\" + (b\"\\x00\" * (7 - len(rem))) + bit_len.to_bytes(8, \"big\")\n                processed += 1\n                self.process_block(block, processed)\n            else:\n                block1 = rem + b\"\\x80\" + (b\"\\x00\" * (15 - len(rem)))\n                processed += 1\n                self.process_block(block1, processed)\n\n                block2 = (b\"\\x00\" * 8) + bit_len.to_bytes(8, \"big\")\n                processed += 1\n                self.process_block(block2, processed)\n\n            count_block = (b\"\\x00\" * 8) + processed.to_bytes(8, \"big\")\n            for i in range(32):\n                self.process_block(count_block, i + 1)\n\n            self.buf.clear()\n            return\n\n        def produce_output(self):\n            out = bytearray(self.digest_size)\n            for i in range(self.digest_size):\n                out[self.digest_size - 1 - i] = (\n                    self.B[3 - (i // 16)][3 - ((i // 4) % 4)] >> ((8 * i) % 32)\n                ) & 0xff\n            return bytes(out)\n\n        def process_block(self, data, blockno):\n            self.load_data_block(data, blockno)\n            self.clock_register(self.r)\n            return\n\n        def load_data_block(self, data, blockno):\n            mul2 = self.__class__.mul2_table\n            mul3 = self.__class__.mul3_table\n\n            p = [0, 0, 0, 0]\n            q = [0, 0, 0, 0]\n\n            for i in range(4):\n                a = data[i]\n                b = data[i + 4]\n                c = data[i + 8]\n                d = data[i + 12]\n                q[i] = (\n                    ((mul2[a] ^ mul3[b] ^ c ^ d) << 24)\n                    | ((a ^ mul2[b] ^ mul3[c] ^ d) << 16)\n                    | ((a ^ b ^ mul2[c] ^ mul3[d]) << 8)\n                    | (mul3[a] ^ b ^ c ^ mul2[d])\n                )\n\n            for i in range(4):\n                a = data[4 * i]\n                b = data[4 * i + 1]\n                c = data[4 * i + 2]\n                d = data[4 * i + 3]\n                p[i] = (\n                    ((mul2[a] ^ mul3[b] ^ c ^ d) << 24)\n                    | ((a ^ mul2[b] ^ mul3[c] ^ d) << 16)\n                    | ((a ^ b ^ mul2[c] ^ mul3[d]) << 8)\n                    | (mul3[a] ^ b ^ c ^ mul2[d])\n                )\n\n            p2 = [p[2], p[3], q[0], q[1]]\n            q2 = [q[2], q[3], p[0], p[1]]\n\n            self.B[2][0] ^= p[0]\n            self.B[2][1] ^= p[1]\n            self.B[2][2] ^= p[2] ^ (blockno >> 32)\n            self.B[2][3] ^= p[3] ^ (blockno & 0xffff_ffff)\n\n            self.B[3][0] ^= q[0]\n            self.B[3][1] ^= q[1]\n            self.B[3][2] ^= q[2] ^ (blockno >> 32)\n            self.B[3][3] ^= q[3] ^ (blockno & 0xffff_ffff)\n\n            self.K[3][0] ^= p2[0]\n            self.K[3][1] ^= p2[1]\n            self.K[3][2] ^= p2[2]\n            self.K[3][3] ^= p2[3]\n\n            self.K[5][0] ^= q[0]\n            self.K[5][1] ^= q[1]\n            self.K[5][2] ^= q[2]\n            self.K[5][3] ^= q[3]\n\n            self.K[7][0] ^= p[0]\n            self.K[7][1] ^= p[1]\n            self.K[7][2] ^= p[2]\n            self.K[7][3] ^= p[3]\n\n            self.K[11][0] ^= q2[0]\n            self.K[11][1] ^= q2[1]\n            self.K[11][2] ^= q2[2]\n            self.K[11][3] ^= q2[3]\n            return\n\n        def clock_register(self, r):\n            for _ in range(2):\n                tmp = self.B[2][:]\n                for _ in range(r):\n                    tmp = self.arf(tmp)\n\n                feed_k = [tmp[i] ^ self.B[0][i] for i in range(4)]\n                feed_b = [(feed_k[i] ^ self.K[9][i]) ^ self.K[0][i] for i in range(4)]\n\n                self.B[0] = self.B[1][:]\n                self.B[1] = self.B[2][:]\n                self.B[2] = self.B[3][:]\n                self.B[3] = feed_b\n\n                for i in range(11):\n                    self.K[i] = self.K[i + 1][:]\n                self.K[11] = feed_k\n\n            return\n\n        def arf(self, words):\n            sbox = self.__class__.sbox\n            mul2 = self.__class__.mul2_table\n            mul3 = self.__class__.mul3_table\n\n            state = [[0, 0, 0, 0] for _ in range(4)]\n\n            for i in range(4):\n                word = words[i]\n                state[0][i] = (word >> 24) & 0xff\n                state[1][i] = (word >> 16) & 0xff\n                state[2][i] = (word >> 8) & 0xff\n                state[3][i] = word & 0xff\n\n            for i in range(4):\n                for j in range(4):\n                    state[i][j] = sbox[state[i][j]]\n\n            state[1] = state[1][1:] + state[1][:1]\n            state[2] = state[2][2:] + state[2][:2]\n            state[3] = state[3][3:] + state[3][:3]\n\n            out = [0, 0, 0, 0]\n            for i in range(4):\n                a = state[0][i]\n                b = state[1][i]\n                c = state[2][i]\n                d = state[3][i]\n                out[i] = (\n                    ((mul2[a] ^ mul3[b] ^ c ^ d) << 24)\n                    | ((a ^ mul2[b] ^ mul3[c] ^ d) << 16)\n                    | ((a ^ b ^ mul2[c] ^ mul3[d]) << 8)\n                    | (mul3[a] ^ b ^ c ^ mul2[d])\n                )\n\n            return out\n\n    class SHAMATA224(SHAMATABase):\n        digest_size = 28\n        hashbitlen = 224\n\n    class SHAMATA256(SHAMATABase):\n        digest_size = 32\n        hashbitlen = 256\n\n    class SHAMATA384(SHAMATABase):\n        digest_size = 48\n        hashbitlen = 384\n\n    class SHAMATA512(SHAMATABase):\n        digest_size = 64\n        hashbitlen = 512\n\n    class SpectralHashBase:\n        block_size = 64\n        digest_size = None\n        hashbitlen = None\n\n        X_INVERSE_TABLE = [0, 1, 15, 10, 8, 6, 5, 9, 4, 7, 3, 14, 13, 12, 11, 2]\n        AFFINE_TRANSFORM_TABLE = [7, 0, 8, 2, 12, 4, 13, 11, 10, 3, 14, 15, 6, 1, 5, 9]\n\n        SG_TABLES = {\n            128: [0x01, 0x02, 0x04, 0x08],\n            160: [0x03, 0x02, 0x04, 0x08],\n            192: [0x03, 0x06, 0x04, 0x08],\n            224: [0x03, 0x06, 0x0c, 0x08],\n            256: [0x03, 0x07, 0x0c, 0x08],\n            288: [0x03, 0x07, 0x0e, 0x08],\n            320: [0x03, 0x07, 0x0e, 0x0c],\n            352: [0x07, 0x07, 0x0e, 0x0c],\n            384: [0x07, 0x0f, 0x0e, 0x0c],\n            416: [0x07, 0x0f, 0x0f, 0x0c],\n            448: [0x07, 0x0f, 0x0f, 0x0e],\n            480: [0x0f, 0x0f, 0x0f, 0x0e],\n            512: [0x0f, 0x0f, 0x0f, 0x0f],\n        }\n\n        IJ_COLUMNS = []\n        IK_ROWS = []\n        JK_ROWS = []\n\n        @classmethod\n        def build_tables(cls):\n            if cls.IJ_COLUMNS:\n                return\n            for i in range(4):\n                for j in range(4):\n                    cls.IJ_COLUMNS.append([(i << 5) | (j << 3) | k for k in range(8)])\n            for i in range(4):\n                for k in range(8):\n                    cls.IK_ROWS.append([(i << 5) | (j << 3) | k for j in range(4)])\n            for j in range(4):\n                for k in range(8):\n                    cls.JK_ROWS.append([(i << 5) | (j << 3) | k for i in range(4)])\n            return\n\n        def __init__(self, data=b\"\"):\n            self.__class__.build_tables()\n            if self.hashbitlen is None:\n                raise ValueError(\"hashbitlen must be set in subclass\")\n            self.digest_size = self.hashbitlen // 8\n            self.s_prism = [0] * 128\n            self.p_prism = list(range(128))\n            self.h_prism = [0] * 128\n            self.buf = bytearray()\n            self.msg_len = 0\n            self.started = False\n            if data:\n                self.update(data)\n            return\n\n        def copy(self):\n            other = self.__class__()\n            other.s_prism = self.s_prism[:]\n            other.p_prism = self.p_prism[:]\n            other.h_prism = self.h_prism[:]\n            other.buf = bytearray(self.buf)\n            other.msg_len = self.msg_len\n            other.started = self.started\n            return other\n\n        def update(self, data):\n            if not isinstance(data, (bytes, bytearray, memoryview)):\n                raise TypeError(\"data must be bytes-like\")\n            data = bytes(data)\n            self.msg_len += len(data)\n            self.buf.extend(data)\n            while len(self.buf) >= 64:\n                block = bytes(self.buf[:64])\n                del self.buf[:64]\n                self.process_block(block, apply_initial_swap=not self.started)\n                self.started = True\n            return self\n\n        def digest(self):\n            c = self.copy()\n            c.finalize()\n            return c.make_digest()\n\n        def hexdigest(self):\n            return self.digest().hex()\n\n        def process_block(self, block, apply_initial_swap):\n            self.fill_s_prism(block)\n            if apply_initial_swap:\n                self.initial_swap_control()\n            self.compress()\n            return\n\n        def fill_s_prism(self, block):\n            out = self.s_prism\n            n = 0\n            for b in block:\n                out[n] = b >> 4\n                out[n + 1] = b & 0x0f\n                n += 2\n            return\n\n        def initial_swap_control(self):\n            p = self.p_prism\n            s = self.s_prism\n            for i in range(4):\n                base_i = i << 5\n                for j in range(4):\n                    base = base_i | (j << 3)\n                    for k in range(8):\n                        idx = base | k\n                        st = s[idx]\n                        sh = st >> 2\n                        sl = st & 0x03\n                        idx2 = (sh << 5) | (sl << 3) | k\n                        p[idx], p[idx2] = p[idx2], p[idx]\n            return\n\n        def affine_transform(self):\n            table = self.AFFINE_TRANSFORM_TABLE\n            s = self.s_prism\n            for idx in range(128):\n                s[idx] = table[s[idx]]\n            return\n\n        def k1_swap(self):\n            s = self.s_prism\n            p = self.p_prism\n            for i in range(4):\n                base_i = i << 5\n                for j in range(4):\n                    base = base_i | (j << 3)\n                    current = s[base] ^ s[base | 4]\n                    for b in range(4):\n                        if ((current >> b) & 1) == 0:\n                            a = base | b\n                            z = base | (7 - b)\n                            p[a], p[z] = p[z], p[a]\n            return\n\n        def k2_swap(self):\n            s = self.s_prism\n            p = self.p_prism\n            for i in range(4):\n                base_i = i << 5\n                for j in range(4):\n                    base = base_i | (j << 3)\n                    current = s[base | 1]\n                    if (current & 1) == 0:\n                        p[base | 0], p[base | 1] = p[base | 1], p[base | 0]\n                    if ((current >> 1) & 1) == 0:\n                        p[base | 2], p[base | 3] = p[base | 3], p[base | 2]\n                    if ((current >> 2) & 1) == 0:\n                        p[base | 1], p[base | 2] = p[base | 2], p[base | 1]\n                    if ((current >> 3) & 1) == 0:\n                        p[base | 0], p[base | 3] = p[base | 3], p[base | 0]\n            for i in range(4):\n                base_i = i << 5\n                for j in range(4):\n                    base = base_i | (j << 3)\n                    current = s[base | 5]\n                    if (current & 1) == 0:\n                        p[base | 4], p[base | 5] = p[base | 5], p[base | 4]\n                    if ((current >> 1) & 1) == 0:\n                        p[base | 6], p[base | 7] = p[base | 7], p[base | 6]\n                    if ((current >> 2) & 1) == 0:\n                        p[base | 5], p[base | 6] = p[base | 6], p[base | 5]\n                    if ((current >> 3) & 1) == 0:\n                        p[base | 4], p[base | 7] = p[base | 7], p[base | 4]\n            return\n\n        def four_point_dft(self, a0, a1, a2, a3):\n            a = a0 + a2\n            b = a0 - a2\n            c = a1 + a3\n            d = a1 - a3\n            return [\n                (a + c) % 17,\n                (b + d * 4) % 17,\n                (a - c) % 17,\n                (b - d * 4) % 17,\n            ]\n\n        def eight_point_dft(self, c0, c1, c2, c3, c4, c5, c6, c7):\n            t20 = c0 + c4\n            t21 = c0 - c4\n            t22 = c2 + c6\n            t23 = (c2 - c6) * 4\n            t24 = c1 + c5\n            t25 = c1 - c5\n            t26 = c3 + c7\n            t27 = (c3 - c7) * 4\n\n            t0 = t20 + t22\n            t1 = t21 + t23\n            t2 = t20 - t22\n            t3 = t21 - t23\n\n            t4 = t24 + t26\n            t5 = (t25 + t27) * 2\n            t6 = (t24 - t26) * 4\n            t7 = (t25 - t27) * 8\n\n            return [\n                (t0 + t4) % 17,\n                (t1 + t5) % 17,\n                (t2 + t6) % 17,\n                (t3 + t7) % 17,\n                (t0 - t4) % 17,\n                (t1 - t5) % 17,\n                (t2 - t6) % 17,\n                (t3 - t7) % 17,\n            ]\n\n        def apply_k_dft(self):\n            s = self.s_prism\n            for idxs in self.IJ_COLUMNS:\n                out = self.eight_point_dft(\n                    s[idxs[0]], s[idxs[1]], s[idxs[2]], s[idxs[3]],\n                    s[idxs[4]], s[idxs[5]], s[idxs[6]], s[idxs[7]],\n                )\n                for idx, val in zip(idxs, out):\n                    s[idx] = val\n            return\n\n        def j_swap(self):\n            s = self.s_prism\n            p = self.p_prism\n            for i in range(4):\n                base_i = i << 5\n                for k in range(8):\n                    current = s[base_i | 16 | k]\n                    if (((current >> 0) & 1) ^ (k & 1)) == 0:\n                        a = base_i | 0 | k\n                        b = base_i | 8 | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 1) & 1) ^ ((k >> 1) & 1)) == 0:\n                        a = base_i | 16 | k\n                        b = base_i | 24 | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 2) & 1) ^ ((k >> 2) & 1)) == 0:\n                        a = base_i | 8 | k\n                        b = base_i | 16 | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 3) & 1) ^ (i & 1)) == 0:\n                        a = base_i | 0 | k\n                        b = base_i | 24 | k\n                        p[a], p[b] = p[b], p[a]\n            return\n\n        def apply_j_dft(self):\n            s = self.s_prism\n            for idxs in self.IK_ROWS:\n                out = self.four_point_dft(\n                    s[idxs[0]], s[idxs[1]], s[idxs[2]], s[idxs[3]],\n                )\n                for idx, val in zip(idxs, out):\n                    s[idx] = val\n            return\n\n        def i_swap(self):\n            s = self.s_prism\n            p = self.p_prism\n            for j in range(4):\n                base_j = j << 3\n                for k in range(8):\n                    current = s[96 | base_j | k]\n                    if (((current >> 0) & 1) ^ (k & 1)) == 0:\n                        a = 0 | base_j | k\n                        b = 32 | base_j | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 1) & 1) ^ ((k >> 1) & 1)) == 0:\n                        a = 64 | base_j | k\n                        b = 96 | base_j | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 2) & 1) ^ ((k >> 2) & 1)) == 0:\n                        a = 32 | base_j | k\n                        b = 64 | base_j | k\n                        p[a], p[b] = p[b], p[a]\n                    if (((current >> 3) & 1) ^ (j & 1)) == 0:\n                        a = 0 | base_j | k\n                        b = 96 | base_j | k\n                        p[a], p[b] = p[b], p[a]\n            return\n\n        def apply_i_dft(self):\n            s = self.s_prism\n            for idxs in self.JK_ROWS:\n                out = self.four_point_dft(\n                    s[idxs[0]], s[idxs[1]], s[idxs[2]], s[idxs[3]],\n                )\n                for idx, val in zip(idxs, out):\n                    s[idx] = val\n            return\n\n        def nlst(self):\n            s = self.s_prism\n            p = self.p_prism\n            h = self.h_prism\n            xinv = self.X_INVERSE_TABLE\n            new_s = [0] * 128\n            for idx in range(128):\n                stemp = s[idx]\n                ptemp = p[idx]\n                sp = stemp & 0x0f\n                pl = ptemp & 0x0f\n                ph = ((stemp & 0x10) >> 1) | ((ptemp >> 4) & 0x07)\n                spp = s[ptemp] & 0x0f\n                new_s[idx] = xinv[sp ^ pl] ^ xinv[spp ^ ph] ^ h[idx]\n            self.s_prism = new_s\n            self.h_prism = new_s[:]\n            return\n\n        def rubic_rot(self):\n            p = self.p_prism\n            new_p = [0] * 128\n            for i in range(4):\n                base_i = i << 5\n                for j in range(4):\n                    base = base_i | (j << 3)\n                    for k in range(8):\n                        idx = base | k\n                        if (k & 3) == 0:\n                            new_p[idx] = p[idx]\n                        elif (k & 3) == 1:\n                            new_p[idx] = p[((3 - j) << 5) | (i << 3) | k]\n                        elif (k & 3) == 2:\n                            new_p[idx] = p[(j << 5) | (i << 3) | k]\n                        else:\n                            new_p[idx] = p[(j << 5) | ((3 - i) << 3) | k]\n            self.p_prism = new_p\n            return\n\n        def compress(self):\n            self.affine_transform()\n            self.k1_swap()\n            self.k2_swap()\n            self.apply_k_dft()\n            self.j_swap()\n            self.apply_j_dft()\n            self.i_swap()\n            self.apply_i_dft()\n            self.nlst()\n            self.rubic_rot()\n            return\n\n        def pad_block_from_buffer(self):\n            buf = bytearray(self.buf)\n            bit_len = self.msg_len * 8\n            buf.append(0x80)\n            while (len(buf) % 64) != 56:\n                buf.append(0x00)\n            buf.extend(bit_len.to_bytes(8, \"big\"))\n            return [bytes(buf[i:i + 64]) for i in range(0, len(buf), 64)]\n\n        def finalize(self):\n            blocks = self.pad_block_from_buffer()\n            if not blocks:\n                return\n            if len(self.buf) != 0:\n                for block in blocks:\n                    self.process_block(block, apply_initial_swap=True)\n            else:\n                if self.msg_len == 0:\n                    self.process_block(blocks[0], apply_initial_swap=True)\n            return\n\n        def mark_bits(self):\n            sg = self.SG_TABLES[self.hashbitlen]\n            marks = [0] * 128\n            p = self.p_prism\n            for idx in range(128):\n                marks[idx] = sg[p[idx] & 0x03]\n            return marks\n\n        def make_digest(self):\n            marks = self.mark_bits()\n            out = bytearray(self.digest_size)\n            bit_num = 0\n            byte_num = 0\n            for idx in range(128):\n                mark = marks[idx]\n                cell = self.h_prism[idx]\n                for l in range(4):  # noqa: E741\n                    if ((1 << l) & mark) != 0:\n                        out[byte_num] |= ((cell >> l) & 1) << (7 - bit_num)\n                        bit_num += 1\n                        if bit_num >= 8:\n                            byte_num += 1\n                            bit_num = 0\n                            if byte_num >= self.digest_size:\n                                return bytes(out)\n            return bytes(out)\n\n    class SpectralHash128(SpectralHashBase):\n        hashbitlen = 128\n\n    class SpectralHash160(SpectralHashBase):\n        hashbitlen = 160\n\n    class SpectralHash192(SpectralHashBase):\n        hashbitlen = 192\n\n    class SpectralHash224(SpectralHashBase):\n        hashbitlen = 224\n\n    class SpectralHash256(SpectralHashBase):\n        hashbitlen = 256\n\n    class SpectralHash288(SpectralHashBase):\n        hashbitlen = 288\n\n    class SpectralHash320(SpectralHashBase):\n        hashbitlen = 320\n\n    class SpectralHash352(SpectralHashBase):\n        hashbitlen = 352\n\n    class SpectralHash384(SpectralHashBase):\n        hashbitlen = 384\n\n    class SpectralHash416(SpectralHashBase):\n        hashbitlen = 416\n\n    class SpectralHash448(SpectralHashBase):\n        hashbitlen = 448\n\n    class SpectralHash480(SpectralHashBase):\n        hashbitlen = 480\n\n    class SpectralHash512(SpectralHashBase):\n        hashbitlen = 512\n\n\n@register_command\nclass HashCommand(GenericCommand):\n    \"\"\"The base command to calculate hash.\"\"\"\n\n    _cmdline_ = \"hash\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"file\")\n    subparsers.add_parser(\"value\")\n    subparsers.add_parser(\"list\")\n    subparsers.add_parser(\"test\")\n    subparsers.add_parser(\"known-collision\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"[128b/16B] means 128 bits (16 bytes).\",\n        'The salt for BLAKE2s and BLAKE2b is blank.',\n        'The key for KMAC128 and KMAC256 is blank.',\n        'The key for SipHash is \"\\\\0\" * 16.',\n        'The key for HalfSipHash is \"\\\\0\" * 8.',\n        \"To calculate FSB hash, you need the `gmpy2` package (uv pip install gmpy2).\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def get_valid_hash_funcs(self):\n        yield \"hashlib\"\n\n        hashlib_hashes = {\n            \"MD5\": \"md5\",\n            \"SHA1\": \"sha1\",\n            \"MD5-SHA1\": \"md5-sha1\",\n            \"SHA-224\": \"sha224\",\n            \"SHA-256\": \"sha256\",\n            \"SHA-384\": \"sha384\",\n            \"SHA-512\": \"sha512\",\n            \"SHA-512/224\": \"sha512-224\", # May not be usable depending on availability of OpenSSL\n            \"SHA-512/256\": \"sha512-256\", # May not be usable depending on availability of OpenSSL\n            \"SHA3-224\": \"sha3-224\",\n            \"SHA3-256\": \"sha3-256\",\n            \"SHA3-384\": \"sha3-384\",\n            \"SHA3-512\": \"sha3-512\",\n            \"BLAKE2s\": \"blake2s\",\n            \"BLAKE2b\": \"blake2b\",\n            \"SM3\": \"sm3\",\n            \"RIPEMD-160\": \"ripemd160\", # May not be usable depending on availability of OpenSSL\n        }\n        for hname, hname_hashlib in hashlib_hashes.items():\n            try:\n                hfunc = hashlib.new(hname_hashlib)\n            except Exception:\n                continue\n            yield (hname, hfunc)\n\n        class ShakeWrapper:\n            def __init__(self, hname, bits):\n                self.hfunc = hashlib.new(hname)\n                self.bits = bits\n                self.digest_size = bits // 8\n                return\n\n            def hexdigest(self):\n                return self.hfunc.hexdigest(self.bits // 8)\n\n            def __getattr__(self, name):\n                return getattr(self.hfunc, name)\n\n        for hname_base in [\"shake-128\", \"shake-256\"]:\n            for bits in [128, 256, 512]:\n                hname = \"{:s}-{:d}\".format(hname_base.upper().replace(\"-\", \"\"), bits)\n                try:\n                    hfunc = ShakeWrapper(hname_base, bits)\n                except Exception:\n                    continue\n                yield (hname, hfunc)\n\n        # SHA-3 Round3 candidates\n        yield \"SHA3 Round3 candidates\"\n        yield (\"BLAKE-224\", Hash.BLAKE224())\n        yield (\"BLAKE-256\", Hash.BLAKE256())\n        yield (\"BLAKE-384\", Hash.BLAKE384())\n        yield (\"BLAKE-512\", Hash.BLAKE512())\n        yield (\"Groestl-224\", Hash.Groestl224())\n        yield (\"Groestl-256\", Hash.Groestl256())\n        yield (\"Groestl-384\", Hash.Groestl384())\n        yield (\"Groestl-512\", Hash.Groestl512())\n        yield (\"JH-224\", Hash.JH224())\n        yield (\"JH-256\", Hash.JH256())\n        yield (\"JH-384\", Hash.JH384())\n        yield (\"JH-512\", Hash.JH512())\n        yield (\"Keccak-224\", Hash.Keccak224())\n        yield (\"Keccak-256\", Hash.Keccak256())\n        yield (\"Keccak-384\", Hash.Keccak384())\n        yield (\"Keccak-512\", Hash.Keccak512())\n        yield (\"Skein256-256\", Hash.Skein256(digest_bits=256))\n        yield (\"Skein256-512\", Hash.Skein256(digest_bits=512))\n        yield (\"Skein256-1024\", Hash.Skein256(digest_bits=1024))\n        yield (\"Skein512-256\", Hash.Skein512(digest_bits=256))\n        yield (\"Skein512-512\", Hash.Skein512(digest_bits=512))\n        yield (\"Skein512-1024\", Hash.Skein512(digest_bits=1024))\n        yield (\"Skein1024-256\", Hash.Skein1024(digest_bits=256))\n        yield (\"Skein1024-512\", Hash.Skein1024(digest_bits=512))\n        yield (\"Skein1024-1024\", Hash.Skein1024(digest_bits=1024))\n\n        # SHA-3 Round2 candidates\n        yield \"SHA3 Round2 candidates\"\n        yield (\"BMW-224\", Hash.BMW224())\n        yield (\"BMW-256\", Hash.BMW256())\n        yield (\"BMW-384\", Hash.BMW384())\n        yield (\"BMW-512\", Hash.BMW512())\n        yield (\"CubeHash10+1/1+10-256\", Hash.CubeHash(params=\"CubeHash10+1/1+10-256\"))\n        yield (\"CubeHash80+8/1+80-256\", Hash.CubeHash(params=\"CubeHash80+8/1+80-256\"))\n        yield (\"CubeHash160+16/32+160-256\", Hash.CubeHash(params=\"CubeHash160+16/32+160-256\"))\n        yield (\"CubeHash10+1/1+10-512\", Hash.CubeHash(params=\"CubeHash10+1/1+10-512\"))\n        yield (\"CubeHash80+8/1+80-512\", Hash.CubeHash(params=\"CubeHash80+8/1+80-512\"))\n        yield (\"CubeHash160+16/32+160-512\", Hash.CubeHash(params=\"CubeHash160+16/32+160-512\"))\n        yield (\"ECHO-224\", Hash.ECHO224())\n        yield (\"ECHO-256\", Hash.ECHO256())\n        yield (\"ECHO-384\", Hash.ECHO384())\n        yield (\"ECHO-512\", Hash.ECHO512())\n        yield (\"Fugue-224\", Hash.Fugue224())\n        yield (\"Fugue-256\", Hash.Fugue256())\n        yield (\"Fugue-384\", Hash.Fugue384())\n        yield (\"Fugue-512\", Hash.Fugue512())\n        yield (\"Hamsi-224\", Hash.Hamsi224())\n        yield (\"Hamsi-256\", Hash.Hamsi256())\n        yield (\"Hamsi-384\", Hash.Hamsi384())\n        yield (\"Hamsi-512\", Hash.Hamsi512())\n        yield (\"Luffa-224\", Hash.Luffa224())\n        yield (\"Luffa-256\", Hash.Luffa256())\n        yield (\"Luffa-384\", Hash.Luffa384())\n        yield (\"Luffa-512\", Hash.Luffa512())\n        yield (\"Shabal-192\", Hash.Shabal192())\n        yield (\"Shabal-224\", Hash.Shabal224())\n        yield (\"Shabal-256\", Hash.Shabal256())\n        yield (\"Shabal-384\", Hash.Shabal384())\n        yield (\"Shabal-512\", Hash.Shabal512())\n        yield (\"SHAvite3-224\", Hash.SHAvite3_224())\n        yield (\"SHAvite3-256\", Hash.SHAvite3_256())\n        yield (\"SHAvite3-384\", Hash.SHAvite3_384())\n        yield (\"SHAvite3-512\", Hash.SHAvite3_512())\n        yield (\"SIMD-224\", Hash.SIMD224())\n        yield (\"SIMD-256\", Hash.SIMD256())\n        yield (\"SIMD-384\", Hash.SIMD384())\n        yield (\"SIMD-512\", Hash.SIMD512())\n\n        # SHA-3 Round1 candidates\n        yield \"SHA3 Round1 candidates\"\n        yield (\"Abacus-224\", Hash.Abacus224())\n        yield (\"Abacus-256\", Hash.Abacus256())\n        yield (\"Abacus-384\", Hash.Abacus384())\n        yield (\"Abacus-512\", Hash.Abacus512())\n        yield (\"ARIRANG-224\", Hash.ARIRANG224())\n        yield (\"ARIRANG-256\", Hash.ARIRANG256())\n        yield (\"ARIRANG-384\", Hash.ARIRANG384())\n        yield (\"ARIRANG-512\", Hash.ARIRANG512())\n        yield (\"AURORA-224\", Hash.AURORA224())\n        yield (\"AURORA-224M\", Hash.AURORA224M())\n        yield (\"AURORA-256\", Hash.AURORA256())\n        yield (\"AURORA-256M\", Hash.AURORA256M())\n        yield (\"AURORA-384\", Hash.AURORA384())\n        yield (\"AURORA-512\", Hash.AURORA512())\n        yield (\"Blender-224\", Hash.Blender224())\n        yield (\"Blender-256\", Hash.Blender256())\n        yield (\"Blender-384\", Hash.Blender384())\n        yield (\"Blender-384Spec\", Hash.Blender384Spec())\n        yield (\"Blender-512\", Hash.Blender512())\n        yield (\"BOOLE-224\", Hash.BOOLE224())\n        yield (\"BOOLE-256\", Hash.BOOLE256())\n        yield (\"BOOLE-384\", Hash.BOOLE384())\n        yield (\"BOOLE-512\", Hash.BOOLE512())\n        yield (\"Cheetah-224\", Hash.Cheetah224())\n        yield (\"Cheetah-256\", Hash.Cheetah256())\n        yield (\"Cheetah-384\", Hash.Cheetah384())\n        yield (\"Cheetah-512\", Hash.Cheetah512())\n        yield (\"CHI-224\", Hash.CHI224())\n        yield (\"CHI-256\", Hash.CHI256())\n        yield (\"CHI-384\", Hash.CHI384())\n        yield (\"CHI-512\", Hash.CHI512())\n        yield (\"DCH-224\", Hash.DCH224())\n        yield (\"DCH-256\", Hash.DCH256())\n        yield (\"DCH-384\", Hash.DCH384())\n        yield (\"DCH-512\", Hash.DCH512())\n        yield (\"DynamicSHA-224\", Hash.DynamicSHA224())\n        yield (\"DynamicSHA-256\", Hash.DynamicSHA256())\n        yield (\"DynamicSHA-384\", Hash.DynamicSHA384())\n        yield (\"DynamicSHA-512\", Hash.DynamicSHA512())\n        yield (\"DynamicSHA2-224\", Hash.DynamicSHA2_224())\n        yield (\"DynamicSHA2-256\", Hash.DynamicSHA2_256())\n        yield (\"DynamicSHA2-384\", Hash.DynamicSHA2_384())\n        yield (\"DynamicSHA2-512\", Hash.DynamicSHA2_512())\n        yield (\"ECOH-224\", Hash.ECOH224())\n        yield (\"ECOH-256\", Hash.ECOH256())\n        yield (\"ECOH-384\", Hash.ECOH384())\n        yield (\"ECOH-512\", Hash.ECOH512())\n        yield (\"EDONR-224\", Hash.EDONR224())\n        yield (\"EDONR-256\", Hash.EDONR256())\n        yield (\"EDONR-384\", Hash.EDONR384())\n        yield (\"EDONR-512\", Hash.EDONR512())\n        yield (\"EnRUPT-224\", Hash.EnRUPT224())\n        yield (\"EnRUPT-256\", Hash.EnRUPT256())\n        yield (\"EnRUPT-384\", Hash.EnRUPT384())\n        yield (\"EnRUPT-512\", Hash.EnRUPT512())\n        yield (\"ESSENCE-224\", Hash.ESSENCE224())\n        yield (\"ESSENCE-256\", Hash.ESSENCE256())\n        yield (\"ESSENCE-384\", Hash.ESSENCE384())\n        yield (\"ESSENCE-512\", Hash.ESSENCE512())\n        try:\n            # FSB requires a hexadecimal representation of pi.\n            # If gmpy2 is available, it can be calculated quickly,\n            # but if it is not, it will take a long time, so GEF will skip it.\n            __import__(\"gmpy2\")\n            yield (\"FSB-160\", Hash.FSB160())\n            yield (\"FSB-224\", Hash.FSB224())\n            yield (\"FSB-256\", Hash.FSB256())\n            yield (\"FSB-384\", Hash.FSB384())\n            yield (\"FSB-512\", Hash.FSB512())\n        except ImportError:\n            pass\n        yield (\"Khichidi1-224\", Hash.Khichidi1_224())\n        yield (\"Khichidi1-256\", Hash.Khichidi1_256())\n        yield (\"Khichidi1-384\", Hash.Khichidi1_384())\n        yield (\"Khichidi1-512\", Hash.Khichidi1_512())\n        yield (\"Lane-224\", Hash.Lane224())\n        yield (\"Lane-256\", Hash.Lane256())\n        yield (\"Lane-384\", Hash.Lane384())\n        yield (\"Lane-512\", Hash.Lane512())\n        yield (\"Lesamnta-224\", Hash.Lesamnta224())\n        yield (\"Lesamnta-256\", Hash.Lesamnta256())\n        yield (\"Lesamnta-384\", Hash.Lesamnta384())\n        yield (\"Lesamnta-512\", Hash.Lesamnta512())\n        yield (\"LUX-224\", Hash.LUX224())\n        yield (\"LUX-256\", Hash.LUX256())\n        yield (\"LUX-384\", Hash.LUX384())\n        yield (\"LUX-512\", Hash.LUX512())\n        yield (\"MCSSHA3-224\", Hash.MCSSHA3_224())\n        yield (\"MCSSHA3-256\", Hash.MCSSHA3_256())\n        yield (\"MCSSHA3-384\", Hash.MCSSHA3_384())\n        yield (\"MCSSHA3-512\", Hash.MCSSHA3_512())\n        yield (\"MD6-128\", Hash.MD6(d=128))\n        yield (\"MD6-256\", Hash.MD6(d=256))\n        yield (\"MD6-512\", Hash.MD6(d=512))\n        yield (\"MeshHash-224\", Hash.MeshHash224())\n        yield (\"MeshHash-256\", Hash.MeshHash256())\n        yield (\"MeshHash-384\", Hash.MeshHash384())\n        yield (\"MeshHash-512\", Hash.MeshHash512())\n        yield (\"NaSHA-224\", Hash.NaSHA224())\n        yield (\"NaSHA-256\", Hash.NaSHA256())\n        yield (\"NaSHA-384\", Hash.NaSHA384())\n        yield (\"NaSHA-512\", Hash.NaSHA512())\n        yield (\"SANDstorm-224\", Hash.SANDstorm224())\n        yield (\"SANDstorm-256\", Hash.SANDstorm256())\n        yield (\"SANDstorm-384\", Hash.SANDstorm384())\n        yield (\"SANDstorm-512\", Hash.SANDstorm512())\n        yield (\"Sarmal-224\", Hash.Sarmal224())\n        yield (\"Sarmal-256\", Hash.Sarmal256())\n        yield (\"Sarmal-384\", Hash.Sarmal384())\n        yield (\"Sarmal-512\", Hash.Sarmal512())\n        yield (\"Sgail-224\", Hash.Sgail224())\n        yield (\"Sgail-256\", Hash.Sgail256())\n        yield (\"Sgail-384\", Hash.Sgail384())\n        yield (\"Sgail-512\", Hash.Sgail512())\n        yield (\"Sgail-768\", Hash.Sgail768())\n        yield (\"Sgail-1024\", Hash.Sgail1024())\n        yield (\"Sgail-1536\", Hash.Sgail1536())\n        yield (\"Sgail-2048\", Hash.Sgail2048())\n        yield (\"SHAMATA-224\", Hash.SHAMATA224())\n        yield (\"SHAMATA-256\", Hash.SHAMATA256())\n        yield (\"SHAMATA-384\", Hash.SHAMATA384())\n        yield (\"SHAMATA-512\", Hash.SHAMATA512())\n        yield (\"SpectralHash-128\", Hash.SpectralHash128())\n        yield (\"SpectralHash-160\", Hash.SpectralHash160())\n        yield (\"SpectralHash-192\", Hash.SpectralHash192())\n        yield (\"SpectralHash-224\", Hash.SpectralHash224())\n        yield (\"SpectralHash-256\", Hash.SpectralHash256())\n        yield (\"SpectralHash-288\", Hash.SpectralHash288())\n        yield (\"SpectralHash-320\", Hash.SpectralHash320())\n        yield (\"SpectralHash-352\", Hash.SpectralHash352())\n        yield (\"SpectralHash-384\", Hash.SpectralHash384())\n        yield (\"SpectralHash-416\", Hash.SpectralHash416())\n        yield (\"SpectralHash-448\", Hash.SpectralHash448())\n        yield (\"SpectralHash-480\", Hash.SpectralHash480())\n        yield (\"SpectralHash-512\", Hash.SpectralHash512())\n\n        # Other (relatively long)\n        yield \"Relatively long\"\n        yield (\"Ascon-Hash\", Hash.Ascon())\n        yield (\"Ascon-HashA\", Hash.AsconA())\n        yield (\"Ascon-Xof\", Hash.AsconX())\n        yield (\"Ascon-XofA\", Hash.AsconXA())\n        yield (\"BelT Hash\", Hash.BELT())\n        yield (\"BLAKE2sp\", Hash.BLAKE2sp())\n        yield (\"BLAKE2bp\", Hash.BLAKE2bp())\n        yield (\"BLAKE3-128\", Hash.BLAKE3(digest_bits=128))\n        yield (\"BLAKE3-256\", Hash.BLAKE3(digest_bits=256))\n        yield (\"BLAKE3-512\", Hash.BLAKE3(digest_bits=512))\n        yield (\"ED2K-Blue\", Hash.ED2KBlue())\n        yield (\"ED2K-Red\", Hash.ED2KRed())\n        yield (\"ED2K-RedBlue\", Hash.ED2KRedBlue())\n        yield (\"ESCH-256\", Hash.ESCH256())\n        yield (\"ESCH-384\", Hash.ESCH384())\n        yield (\"FNV1-32\", Hash.FNV_32())\n        yield (\"FNV1-64\", Hash.FNV_64())\n        yield (\"FNV1-128\", Hash.FNV_128())\n        yield (\"FNV1-256\", Hash.FNV_256())\n        yield (\"FNV1-512\", Hash.FNV_512())\n        yield (\"FNV1-1024\", Hash.FNV_1024())\n        yield (\"FNV1a-32\", Hash.FNV_32(variant=\"fnv1a\"))\n        yield (\"FNV1a-64\", Hash.FNV_64(variant=\"fnv1a\"))\n        yield (\"FNV1a-128\", Hash.FNV_128(variant=\"fnv1a\"))\n        yield (\"FNV1a-256\", Hash.FNV_256(variant=\"fnv1a\"))\n        yield (\"FNV1a-512\", Hash.FNV_512(variant=\"fnv1a\"))\n        yield (\"FNV1a-1024\", Hash.FNV_1024(variant=\"fnv1a\"))\n        yield (\"FNV0-32\", Hash.FNV_32(variant=\"fnv0\"))\n        yield (\"FNV0-64\", Hash.FNV_64(variant=\"fnv0\"))\n        yield (\"FNV0-128\", Hash.FNV_128(variant=\"fnv0\"))\n        yield (\"FNV0-256\", Hash.FNV_256(variant=\"fnv0\"))\n        yield (\"FNV0-512\", Hash.FNV_512(variant=\"fnv0\"))\n        yield (\"FNV0-1024\", Hash.FNV_1024(variant=\"fnv0\"))\n        yield (\"FNV0a-32\", Hash.FNV_32(variant=\"fnv0a\"))\n        yield (\"FNV0a-64\", Hash.FNV_64(variant=\"fnv0a\"))\n        yield (\"FNV0a-128\", Hash.FNV_128(variant=\"fnv0a\"))\n        yield (\"FNV0a-256\", Hash.FNV_256(variant=\"fnv0a\"))\n        yield (\"FNV0a-512\", Hash.FNV_512(variant=\"fnv0a\"))\n        yield (\"FNV0a-1024\", Hash.FNV_1024(variant=\"fnv0a\"))\n        yield (\"FORK-256\", Hash.FORK256())\n        yield (\"GOST\", Hash.GOST()) # codespell:ignore\n        yield (\"GOST94cp\", Hash.GOST94cp()) # codespell:ignore\n        yield (\"HAS-160\", Hash.HAS160())\n        yield (\"HAVAL-128,3\", Hash.HAVAL(digest_bits=128, passes=3))\n        yield (\"HAVAL-128,4\", Hash.HAVAL(digest_bits=128, passes=4))\n        yield (\"HAVAL-128,5\", Hash.HAVAL(digest_bits=128, passes=5))\n        yield (\"HAVAL-160,3\", Hash.HAVAL(digest_bits=160, passes=3))\n        yield (\"HAVAL-160,4\", Hash.HAVAL(digest_bits=160, passes=4))\n        yield (\"HAVAL-160,5\", Hash.HAVAL(digest_bits=160, passes=5))\n        yield (\"HAVAL-192,3\", Hash.HAVAL(digest_bits=192, passes=3))\n        yield (\"HAVAL-192,4\", Hash.HAVAL(digest_bits=192, passes=4))\n        yield (\"HAVAL-192,5\", Hash.HAVAL(digest_bits=192, passes=5))\n        yield (\"HAVAL-224,3\", Hash.HAVAL(digest_bits=224, passes=3))\n        yield (\"HAVAL-224,4\", Hash.HAVAL(digest_bits=224, passes=4))\n        yield (\"HAVAL-224,5\", Hash.HAVAL(digest_bits=224, passes=5))\n        yield (\"HAVAL-256,3\", Hash.HAVAL(digest_bits=256, passes=3))\n        yield (\"HAVAL-256,4\", Hash.HAVAL(digest_bits=256, passes=4))\n        yield (\"HAVAL-256,5\", Hash.HAVAL(digest_bits=256, passes=5))\n        yield (\"KangarooTwelve128-128\", Hash.KangarooTwelve128(digest_bits=128))\n        yield (\"KangarooTwelve128-256\", Hash.KangarooTwelve128(digest_bits=256))\n        yield (\"KangarooTwelve128-512\", Hash.KangarooTwelve128(digest_bits=512))\n        yield (\"KangarooTwelve256-128\", Hash.KangarooTwelve256(digest_bits=128))\n        yield (\"KangarooTwelve256-256\", Hash.KangarooTwelve256(digest_bits=256))\n        yield (\"KangarooTwelve256-512\", Hash.KangarooTwelve256(digest_bits=512))\n        yield (\"KMAC128-128\", Hash.KMAC128(key=b\"\", digest_bits=128))\n        yield (\"KMAC128-256\", Hash.KMAC128(key=b\"\", digest_bits=256))\n        yield (\"KMAC128-512\", Hash.KMAC128(key=b\"\", digest_bits=512))\n        yield (\"KMAC256-128\", Hash.KMAC256(key=b\"\", digest_bits=128))\n        yield (\"KMAC256-256\", Hash.KMAC256(key=b\"\", digest_bits=256))\n        yield (\"KMAC256-512\", Hash.KMAC256(key=b\"\", digest_bits=512))\n        yield (\"Kupyna-256\", Hash.Kupyna256())\n        yield (\"Kupyna-384\", Hash.Kupyna384())\n        yield (\"Kupyna-512\", Hash.Kupyna512())\n        yield (\"LSH256-224\", Hash.LSH256_224())\n        yield (\"LSH256-256\", Hash.LSH256_256())\n        yield (\"LSH512-224\", Hash.LSH512_224())\n        yield (\"LSH512-256\", Hash.LSH512_256())\n        yield (\"LSH512-384\", Hash.LSH512_384())\n        yield (\"LSH512-512\", Hash.LSH512_512())\n        yield (\"MarsupilamiFourteen\", Hash.MarsupilamiFourteen())\n        yield (\"MD2\", Hash.MD2())\n        yield (\"MD4\", Hash.MD4())\n        yield (\"MDC-2\", Hash.MDC2())\n        yield (\"NTLM hash\", Hash.NTLM())\n        yield (\"Panama\", Hash.Panama())\n        yield (\"ParallelHash-128\", Hash.ParallelHash128())\n        yield (\"ParallelHash-256\", Hash.ParallelHash256())\n        yield (\"ParallelHashXOF-128\", Hash.ParallelHashXOF128())\n        yield (\"ParallelHashXOF-256\", Hash.ParallelHashXOF256())\n        yield (\"PhotonBeetle\", Hash.PhotonBeetle())\n        yield (\"RadioGatun-32\", Hash.RadioGatun32())\n        yield (\"RadioGatun-64\", Hash.RadioGatun64())\n        yield (\"RIPEMD-128\", Hash.RIPEMD128())\n        yield (\"RIPEMD-160\", Hash.RIPEMD160())\n        yield (\"RIPEMD-256\", Hash.RIPEMD256())\n        yield (\"RIPEMD-320\", Hash.RIPEMD320())\n        yield (\"SHA-0\", Hash.SHA0())\n        yield (\"SHA-512/224\", Hash.SHA512_224())\n        yield (\"SHA-512/256\", Hash.SHA512_256())\n        yield (\"Snefru-128\", Hash.Snefru128())\n        yield (\"Snefru-256\", Hash.Snefru256())\n        yield (\"Streebog-256\", Hash.Streebog256())\n        yield (\"Streebog-512\", Hash.Streebog512())\n        yield (\"TIGER-128,3\", Hash.TIGER(digest_bits=128, passes=3))\n        yield (\"TIGER-160,3\", Hash.TIGER(digest_bits=160, passes=3))\n        yield (\"TIGER-192,3\", Hash.TIGER(digest_bits=192, passes=3))\n        yield (\"TIGER-128,4\", Hash.TIGER(digest_bits=128, passes=4))\n        yield (\"TIGER-160,4\", Hash.TIGER(digest_bits=160, passes=4))\n        yield (\"TIGER-192,4\", Hash.TIGER(digest_bits=192, passes=4))\n        yield (\"TIGER2-128,3\", Hash.TIGER(digest_bits=128, passes=3, version=2))\n        yield (\"TIGER2-160,3\", Hash.TIGER(digest_bits=160, passes=3, version=2))\n        yield (\"TIGER2-192,3\", Hash.TIGER(digest_bits=192, passes=3, version=2))\n        yield (\"TupleHash128-128\", Hash.TupleHash128(digest_bits=128))\n        yield (\"TupleHash128-256\", Hash.TupleHash128(digest_bits=256))\n        yield (\"TupleHash128-512\", Hash.TupleHash128(digest_bits=512))\n        yield (\"TupleHash256-128\", Hash.TupleHash256(digest_bits=128))\n        yield (\"TupleHash256-256\", Hash.TupleHash256(digest_bits=256))\n        yield (\"TupleHash256-512\", Hash.TupleHash256(digest_bits=512))\n        yield (\"TurboSHAKE128-128\", Hash.TurboShake128(digest_bits=128))\n        yield (\"TurboSHAKE128-256\", Hash.TurboShake128(digest_bits=256))\n        yield (\"TurboSHAKE128-512\", Hash.TurboShake128(digest_bits=512))\n        yield (\"TurboSHAKE256-128\", Hash.TurboShake256(digest_bits=128))\n        yield (\"TurboSHAKE256-256\", Hash.TurboShake256(digest_bits=256))\n        yield (\"TurboSHAKE256-512\", Hash.TurboShake256(digest_bits=512))\n        yield (\"VSH-1024\", Hash.VSH1024())\n        yield (\"Whirlpool-0\", Hash.Whirlpool0())\n        yield (\"Whirlpool-T\", Hash.WhirlpoolT())\n        yield (\"Whirlpool\", Hash.Whirlpool())\n        yield (\"Xoodyak\", Hash.Xoodyak())\n\n        # Other (relatively short)\n        yield \"Relatively short\"\n        yield (\"CityHash-32\", Hash.CityHash32())\n        yield (\"CityHash-64\", Hash.CityHash64())\n        yield (\"CityHash-128\", Hash.CityHash128())\n        yield (\"FarmHash-32 (fp)\", Hash.FarmHash32())\n        yield (\"FarmHash-64 (fp)\", Hash.FarmHash64())\n        yield (\"FarmHash-128 (fp)\", Hash.FarmHash128())\n        yield (\"FastHash-32\", Hash.FastHash32())\n        yield (\"FastHash-64\", Hash.FastHash64())\n        yield (\"GxHash-32\", Hash.GxHash32())\n        yield (\"GxHash-64\", Hash.GxHash64())\n        yield (\"GxHash-128\", Hash.GxHash128())\n        yield (\"HalfSipHash-32_2_4\", Hash.HalfSipHash32_2_4())\n        yield (\"HalfSipHash-64_2_4\", Hash.HalfSipHash64_2_4())\n        yield (\"HalfTimeHash-64\", Hash.HalfTimeHash64())\n        yield (\"HalfTimeHash-128\", Hash.HalfTimeHash128())\n        yield (\"HalfTimeHash-256\", Hash.HalfTimeHash256())\n        yield (\"HalfTimeHash-512\", Hash.HalfTimeHash512())\n        yield (\"HighwayHash-64\", Hash.HighwayHash64())\n        yield (\"HighwayHash-128\", Hash.HighwayHash128())\n        yield (\"HighwayHash-256\", Hash.HighwayHash256())\n        yield (\"KomiHash\", Hash.KomiHash())\n        yield (\"MetroHash-64\", Hash.MetroHash64())\n        yield (\"MetroHash-128\", Hash.MetroHash128())\n        yield (\"Murmur1\", Hash.MurmurHash1())\n        yield (\"Murmur2\", Hash.MurmurHash2())\n        yield (\"Murmur2a\", Hash.MurmurHash2A())\n        yield (\"Murmur64a\", Hash.MurmurHash64A())\n        yield (\"Murmur64b\", Hash.MurmurHash64B())\n        yield (\"Murmur3a\", Hash.MurmurHash3_x86_32())\n        yield (\"Murmur3c\", Hash.MurmurHash3_x86_128())\n        yield (\"Murmur3f\", Hash.MurmurHash3_x64_128())\n        yield (\"SipHash-64_2_4\", Hash.SipHash64_2_4())\n        yield (\"SipHash-64_1_3\", Hash.SipHash64_1_3())\n        yield (\"SipHash-64_4_8\", Hash.SipHash64_4_8())\n        yield (\"SipHash-128_2_4\", Hash.SipHash128_2_4())\n        yield (\"SipHash-128_4_8\", Hash.SipHash128_4_8())\n        yield (\"SpookyHash-32\", Hash.SpookyHash32())\n        yield (\"SpookyHash-64\", Hash.SpookyHash64())\n        yield (\"SpookyHash-128\", Hash.SpookyHash128())\n        yield (\"T1HA0-32\", Hash.T1HA0_32())\n        yield (\"T1HA1-64\", Hash.T1HA1_64())\n        yield (\"T1HA2-64\", Hash.T1HA2_64())\n        yield (\"T1HA2-128\", Hash.T1HA2_128())\n        yield (\"WYHash-32\", Hash.WYHash32())\n        yield (\"WYHash-64\", Hash.WYHash64())\n        yield (\"xxHash-32\", Hash.XXH32())\n        yield (\"xxHash-64\", Hash.XXH64())\n        yield (\"xxHash3-64\", Hash.XXH3_64())\n        yield (\"xxHash3-128\", Hash.XXH3_128())\n\n        # Checksum\n        yield \"Checksum\"\n        yield (\"RS Hash\", Hash.RSHash())\n        yield (\"JS Hash\", Hash.JSHash())\n        yield (\"PJW Hash\", Hash.PJWHash())\n        yield (\"ELF Hash\", Hash.ELFHash())\n        yield (\"BKDR Hash\", Hash.BKDRHash())\n        yield (\"SDBM Hash\", Hash.SDBMHash())\n        yield (\"DJB2\", Hash.DJB2Hash())\n        yield (\"DEK Hash\", Hash.DEKHash())\n        yield (\"AP Hash\", Hash.APHash())\n        yield (\"JOAAT\", Hash.JOAAT())\n        yield (\"Adler32\", Hash.Adler())\n        yield (\"SuperFastHash\", Hash.SuperFastHash())\n        yield (\"BuzHash\", Hash.BuzHash())\n        yield (\"NHash\", Hash.NHash())\n\n        # MD5/SHA1/SHA256 n-times\n        yield \"MD5/SHA1/SHA256 n-times\"\n        yield (\"MD5 x2 (raw)\", Hash.HASHxN(\"md5\", N=2))\n        yield (\"MD5 x3 (raw)\", Hash.HASHxN(\"md5\", N=3))\n        yield (\"MD5 x4 (raw)\", Hash.HASHxN(\"md5\", N=4))\n        yield (\"MD5 x5 (raw)\", Hash.HASHxN(\"md5\", N=5))\n        yield (\"MD5 x2 (hex)\", Hash.HASHxN(\"md5\", N=2, use_hex=True))\n        yield (\"MD5 x3 (hex)\", Hash.HASHxN(\"md5\", N=3, use_hex=True))\n        yield (\"MD5 x4 (hex)\", Hash.HASHxN(\"md5\", N=4, use_hex=True))\n        yield (\"MD5 x5 (hex)\", Hash.HASHxN(\"md5\", N=5, use_hex=True))\n        yield (\"SHA1 x2 (raw)\", Hash.HASHxN(\"sha1\", N=2))\n        yield (\"SHA1 x3 (raw)\", Hash.HASHxN(\"sha1\", N=3))\n        yield (\"SHA1 x4 (raw)\", Hash.HASHxN(\"sha1\", N=4))\n        yield (\"SHA1 x5 (raw)\", Hash.HASHxN(\"sha1\", N=5))\n        yield (\"SHA1 x2 (hex)\", Hash.HASHxN(\"sha1\", N=2, use_hex=True))\n        yield (\"SHA1 x3 (hex)\", Hash.HASHxN(\"sha1\", N=3, use_hex=True))\n        yield (\"SHA1 x4 (hex)\", Hash.HASHxN(\"sha1\", N=4, use_hex=True))\n        yield (\"SHA1 x5 (hex)\", Hash.HASHxN(\"sha1\", N=5, use_hex=True))\n        yield (\"SHA-256 x2 (raw)\", Hash.HASHxN(\"sha256\", N=2))\n        yield (\"SHA-256 x3 (raw)\", Hash.HASHxN(\"sha256\", N=3))\n        yield (\"SHA-256 x4 (raw)\", Hash.HASHxN(\"sha256\", N=4))\n        yield (\"SHA-256 x5 (raw)\", Hash.HASHxN(\"sha256\", N=5))\n        yield (\"SHA-256 x2 (hex)\", Hash.HASHxN(\"sha256\", N=2, use_hex=True))\n        yield (\"SHA-256 x3 (hex)\", Hash.HASHxN(\"sha256\", N=3, use_hex=True))\n        yield (\"SHA-256 x4 (hex)\", Hash.HASHxN(\"sha256\", N=4, use_hex=True))\n        yield (\"SHA-256 x5 (hex)\", Hash.HASHxN(\"sha256\", N=5, use_hex=True))\n\n        return None\n\n    def make_line(self, hname, hfunc, h):\n        if h is None:\n            byte = hfunc.digest_size\n            bit = byte * 8\n            line = \"{:26s}:[{:4d}b/{:3d}B]\".format(hname, bit, byte)\n            return line\n\n        bit = len(h) * 4\n        byte = bit // 8\n        if hasattr(hfunc, \"digest_normalize\"):\n            hn = hfunc.digest_normalize(h)\n            line = \"{:26s}:[{:4d}b/{:3d}B] {:s} ({:s})\".format(hname, bit, byte, h, hn)\n        else:\n            line = \"{:26s}:[{:4d}b/{:3d}B] {:s}\".format(hname, bit, byte, h)\n        return line\n\n    def should_be_displayed(self, hname, hfunc):\n        if self.args.smart >= 2:\n            if hname not in [\"MD5\", \"SHA1\", \"SHA256\"]:\n                return False\n\n        if self.args.length_filter is not None:\n            if self.args.length_filter != hfunc.digest_size:\n                return False\n\n        if not self.args.filter:\n            return True\n\n        for filt in self.args.filter:\n            if filt.search(hname):\n                return True\n\n        def norm(x):\n            x = x.lower()\n            x = x.replace(\"/\", \"\")\n            x = x.replace(\"-\", \"\")\n            return x\n\n        for filt in self.args.filter:\n            if filt.search(norm(hname)):\n                return True\n        return False\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass HashMemoryCommand(HashCommand, BufferingOutput):\n    \"\"\"Calculate hash from memory values.\"\"\"\n\n    _cmdline_ = \"hash memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for hash calculation.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for hash calculation.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-l\", \"--length-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by hash byte length.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"count\", default=0, help=\"increase output smart level. (-s, -ss)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def calc_hash(self, hfunc, start_address, end_address):\n        # When calculating the hash of a very large range,\n        # it is not practical to store the entire data in memory.\n        # It is preferable to calculate it in blocks.\n\n        step = 0x400 * get_pagesize()\n        if is_qemu_system():\n            step = get_pagesize()\n\n        for chunk_addr in range(start_address, end_address, step):\n            chunk_size = min(end_address - chunk_addr, step)\n            try:\n                mem = read_memory(chunk_addr, chunk_size)\n            except (gdb.MemoryError, MemoryError):\n                err(\"Memory read error\")\n                return False\n            try:\n                hfunc.update(mem)\n            except ValueError:\n                return None\n            del mem\n        return hfunc.hexdigest()\n\n    def process(self):\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        hash_funcs = list(self.get_valid_hash_funcs())\n        pbar = tqdm(hash_funcs, leave=False, total=len(hash_funcs))\n        for elem in pbar:\n            if isinstance(elem, str):\n                if self.args.smart:\n                    if elem != \"hashlib\":\n                        break\n                if not self.args.quiet:\n                    self.out.append(titlify(elem))\n                continue\n\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                continue\n\n            if not self.args.quiet:\n                try:\n                    pbar.set_description(hname)\n                except Exception:\n                    pass\n\n            h = self.calc_hash(hfunc, self.args.location, self.args.location + self.args.size)\n            if h is False:\n                return\n            if h is None:\n                continue\n            line = self.make_line(hname, hfunc, h)\n            self.out.append(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        self.out = []\n        self.out.append(\"Address: {:#x}\".format(args.location))\n        self.out.append(\"Size: {:#x}\".format(args.size))\n        self.process()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass HashFileCommand(HashCommand, BufferingOutput):\n    \"\"\"Calculate hash from file.\"\"\"\n\n    _cmdline_ = \"hash file\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filename\", metavar=\"FILE\", help=\"the filepath for hash calculation.\")\n    parser.add_argument(\"start\", metavar=\"START_POS\", nargs=\"?\", default=0, type=AddressUtil.parse_address,\n                        help=\"the start position for hash calculation.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size for hash calculation.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-l\", \"--length-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by hash byte length.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"count\", default=0, help=\"increase output smart level. (-s, -ss)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def calc_hash(self, hfunc, filename, start_pos, end_pos):\n        # When calculating the hash of a very large range,\n        # it is not practical to store the entire data in memory.\n        # It is preferable to calculate it in blocks.\n\n        step = 0x400 * get_pagesize()\n\n        with open(self.args.filename, \"rb\") as f:\n            f.seek(start_pos)\n            for chunk_pos in range(start_pos, end_pos, step):\n                chunk_size = min(end_pos - chunk_pos, step)\n                data = f.read(chunk_size)\n                try:\n                    hfunc.update(data)\n                except ValueError:\n                    return None\n                del data\n        return hfunc.hexdigest()\n\n    def process(self, filename, start_pos, end_pos):\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        hash_funcs = list(self.get_valid_hash_funcs())\n        pbar = tqdm(hash_funcs, leave=False, total=len(hash_funcs))\n        for elem in pbar:\n            if isinstance(elem, str):\n                if self.args.smart:\n                    if elem != \"hashlib\":\n                        break\n                if not self.args.quiet:\n                    self.out.append(titlify(elem))\n                continue\n\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                continue\n\n            if not self.args.quiet:\n                try:\n                    pbar.set_description(hname)\n                except Exception:\n                    pass\n\n            h = self.calc_hash(hfunc, filename, start_pos, end_pos)\n            if h is False:\n                return\n            if h is None:\n                continue\n            line = self.make_line(hname, hfunc, h)\n            self.out.append(line)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        if not os.path.exists(args.filename):\n            err(\"File not found\")\n            return\n        self.out.append(\"Path: {:s}\".format(args.filename))\n        self.out.append(\"FileSize: {:#x}\".format(os.path.getsize(args.filename)))\n\n        if args.size is None:\n            end_pos = args.start + os.path.getsize(args.filename)\n        else:\n            end_pos = args.start + args.size\n\n        self.process(args.filename, args.start, end_pos)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass HashValueCommand(HashCommand, BufferingOutput):\n    \"\"\"Calculate hash from specified values.\"\"\"\n\n    _cmdline_ = \"hash value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for hash calculation.\")\n    parser.add_argument(\"--hex\", action=\"store_true\", help=\"interpret VALUE as hex. invalid character is ignored.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-l\", \"--length-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by hash byte length.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"count\", default=0, help=\"increase output smart level. (-s, -ss)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x42\\\\\\\\x43\\\\\\\\x44\"',\n        '{0:s} --hex \"41 42 43 44\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_NONE)\n        return\n\n    def process(self, value):\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        hash_funcs = list(self.get_valid_hash_funcs())\n        pbar = tqdm(hash_funcs, leave=False, total=len(hash_funcs))\n        for elem in pbar:\n            if isinstance(elem, str):\n                if self.args.smart:\n                    if elem != \"hashlib\":\n                        break\n                if not self.args.quiet:\n                    self.out.append(titlify(elem))\n                continue\n\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                continue\n\n            if not self.args.quiet:\n                try:\n                    pbar.set_description(hname)\n                except Exception:\n                    pass\n\n            hfunc.update(value)\n            h = hfunc.hexdigest()\n            line = self.make_line(hname, hfunc, h)\n            self.out.append(line)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.hex: # \"41414141\" -> b\"\\x41\\x41\\x41\\x41\"\n            value = GefUtil.fromhex_ignore_invalid(args.value)\n            if not value:\n                return\n        else:\n            try:\n                value = codecs.escape_decode(args.value)[0]\n            except binascii.Error:\n                err('Could not decode \"\\\\xXX\" encoded string')\n                return\n\n        self.out = []\n        self.process(value)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass HashListCommand(HashCommand, BufferingOutput):\n    \"\"\"List hash supported by GEF.\"\"\"\n\n    _cmdline_ = \"hash list\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-l\", \"--length-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by hash byte length.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"count\", default=0, help=\"increase output smart level. (-s, -ss)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_NONE)\n        return\n\n    def process(self):\n        i = 0\n        for elem in self.get_valid_hash_funcs():\n            if isinstance(elem, str):\n                if self.args.smart:\n                    if elem != \"hashlib\":\n                        break\n                self.out.append(titlify(elem))\n                continue\n\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                i += 1\n                continue\n            line = self.make_line(hname, hfunc, None)\n            self.out.append(\"[{:3d}] {:s}\".format(i, line))\n            i += 1\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.process()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass HashTestCommand(HashCommand, BufferingOutput):\n    \"\"\"Calculate and check hash from constant inputs.\"\"\"\n\n    _cmdline_ = \"hash test\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-l\", \"--length-filter\", type=AddressUtil.parse_address,\n                        help=\"filter by hash byte length.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\", help=\"show only failed.\")\n    group = parser.add_mutually_exclusive_group(required=False)\n    group.add_argument(\"-t\", \"--time\", action=\"store_true\",\n                        help=\"measure the time taken to compute the hash using large bytes of data.\")\n    group.add_argument(\"-T\", \"--time-with-sort\", action=\"store_true\",\n                        help=\"measure and sort the time taken to compute the hash using large bytes of data.\")\n    parser.add_argument(\"--size\", type=AddressUtil.parse_address, default=0x1000,\n                        help=\"the data size of 'AAAA...' to measure the time taken to compute the hash.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_NONE)\n        return\n\n    # \"The quick brown fox jumps over the lazy dog\"\n    test_vectors = {\n        # -------------------- hashlib --------------------\n        # hashlib\n        \"MD5\":\n            \"9e107d9d372bb6826bd81d3542a419d6\",\n        \"SHA1\":\n            \"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\",\n        \"MD5-SHA1\":\n            \"9e107d9d372bb6826bd81d3542a419d62fd4e1c67a2d28fced849ee1bb76e7391b93eb12\", \\\n        \"SHA-224\":\n            \"730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525\",\n        \"SHA-256\":\n            \"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592\",\n        \"SHA-384\":\n            \"ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1\",\n        \"SHA-512\":\n            \"07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6\",\n        \"SHA-512/224\":\n            \"944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37\",\n        \"SHA-512/256\":\n            \"dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d\",\n        \"SHA3-224\":\n            \"d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795\",\n        \"SHA3-256\":\n            \"69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04\",\n        \"SHA3-384\":\n            \"7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41\",\n        \"SHA3-512\":\n            \"01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450\",\n        \"BLAKE2s\":\n            \"606beeec743ccbeff6cbcdf5d5302aa855c256c29b88c8ed331ea1a6bf3c8812\",\n        \"BLAKE2b\":\n            \"a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918\",\n        \"SM3\":\n            \"5fdfe814b8573ca021983970fc79b2218c9570369b4859684e2e4c3fc76cb8ea\",\n        \"SHAKE128-128\":\n            \"f4202e3c5852f9182a0430fd8144f0a7\",\n        \"SHAKE128-256\":\n            \"f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e\",\n        \"SHAKE128-512\":\n            \"f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66eb5585ec6f86021cacf272c798bcf97d368b886b18fec3a571f096086a523717a\",\n        \"SHAKE256-128\":\n            \"2f671343d9b2e1604dc9dcf0753e5fe1\",\n        \"SHAKE256-256\":\n            \"2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca\",\n        \"SHAKE256-512\":\n            \"2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca1d01d1369a23539cd80f7c054b6e5daf9c962cad5b8ed5bd11998b40d5734442\",\n        # -------------------- SHA3 Round3 candidates --------------------\n        # https://crashdemons.github.io/BLAKE-wasm/\n        \"BLAKE-224\":\n            \"c8e92d7088ef87c1530aee2ad44dc720cc10589cc2ec58f95a15e51b\",\n        \"BLAKE-256\":\n            \"7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7\",\n        \"BLAKE-384\":\n            \"67c9e8ef665d11b5b57a1d99c96adffb3034d8768c0827d1c6e60b54871e8673651767a2c6c43d0ba2a9bb2500227406\",\n        \"BLAKE-512\":\n            \"1f7e26f63b6ad25a0896fd978fd050a1766391d2fd0471a77afb975e5034b7ad2d9ccf8dfb47abbbe656e1b82fbc634ba42ce186e8dc5e1ce09a885d41f43451\",\n        # https://hashing.tools/groestl\n        \"Groestl-224\":\n            \"8ce3ce0f7092cada755be8f614fd6d5e5738ff1f6cd5dabe42404c46\",\n        \"Groestl-256\":\n            \"8c7ad62eb26a21297bc39c2d7293b4bd4d3399fa8afab29e970471739e28b301\",\n        \"Groestl-384\":\n            \"9330aeb62a1fc0a464dd70ac27b57075e00ae5d627f9bd6ff72952b3857aba2cfbcc4345af9a04fcc13eb346829e4088\",\n        \"Groestl-512\":\n            \"badc1f70ccd69e0cf3760c3f93884289da84ec13c70b3d12a53a7a8a4a513f99715d46288f55e1dbf926e6d084a0538e4eebfc91cf2b21452921ccde9131718d\",\n        # https://hashing.tools/jh\n        \"JH-224\":\n            \"bb21255e4a6bcbd3ddbf8694df2e7f41b74a69c1a7e1c2d36a3fd405\",\n        \"JH-256\":\n            \"6a049fed5fc6874acfdc4a08b568a4f8cbac27de933496f031015b38961608a0\",\n        \"JH-384\":\n            \"de44fe5f835f5518c603aec9d67363466d9f3a5b54d4cfbd4083b055f95a21a2562abaa59b830b3bc4e023d0b52a1268\",\n        \"JH-512\":\n            \"043f14e7c0775e7b1ef5ad657b1e858250b21e2e61fd699783f8634cb86f3ff938451cabd0c8cdae91d4f659d3f9f6f654f1bfedca117ffba735c15fedda47a3\",\n        # https://hashing.tools/keccak\n        \"Keccak-224\":\n            \"310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe\",\n        \"Keccak-256\":\n            \"4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15\",\n        \"Keccak-384\":\n            \"283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3\",\n        \"Keccak-512\":\n            \"d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609\",\n        # https://hashing.tools/skein\n        \"Skein256-256\":\n            \"c0fbd7d779b20f0a4614a66697f9e41859eaf382f14bf857e8cdb210adb9b3fe\",\n        \"Skein256-512\":\n            \"f8138e72cdd9e11cf09e4be198c234acb0d21a9f75f936e989cf532f1fa9f4fb21d255811f0f1592fb3617d04704add875ae7bd16ddbbeaed4eca6eb9675d2c6\",\n        \"Skein256-1024\":\n            \"20151f29d6e0c8bae62710bf8bd0ae97c9d8b20c0df932874bba412bb89b4420d910680ef9021e3fe8f7473ddce3cc01ec55b0d9c419c807339786e328b081c6\" \\\n            \"0bbdeb57dc4f568e457a997c6cb91667d21c7183ddb9b6d6e7e733fa759cc9d86e4ebd273d0f105d3961f928c00b65ab43e62b33af851c42e3894917302801f1\",\n        \"Skein512-256\":\n            \"b3250457e05d3060b1a4bbc1428bc75a3f525ca389aeab96cfa34638d96e492a\",\n        \"Skein512-512\":\n            \"94c2ae036dba8783d0b3f7d6cc111ff810702f5c77707999be7e1c9486ff238a7044de734293147359b4ac7e1d09cd247c351d69826b78dcddd951f0ef912713\",\n        \"Skein512-1024\":\n            \"9a8faf76b15cb3335bbc1c2ef953d48916511eb3e07294d1d43087c47e78d753885623794963e66233cf3938912f6bad1d5b3c34dd1a2123be2afbd6bd45aed8\" \\\n            \"12b44b4ea78cb7f7fd76e0b3daea51009c8ce44dea427bbae1c2e7200eab150bd88dd85e72980c98108c13671cbc1a66e866a0cdde8dc1ddfe58ba6140e8924f\",\n        \"Skein1024-256\":\n            \"054922d4393e36af62143986221555bee407671f6e57631bd7273e215a714833\",\n        \"Skein1024-512\":\n            \"a40ba71fa36a8c1d152bfc68b79782ef206d2e74b9a072b11aa874e6ec2148d937e9acd4ca1026ad636fed1a88b740112d782e2ca0e6c3bbe0dd2704a60a10a5\",\n        \"Skein1024-1024\":\n            \"4cf6152f1a7e598098d28f04e13d7742ba39b7fadbbcf2167bda4e1615d551f3f6b4edbbb391ffa09e6cc0a4af1eb366b30b5f107b437e2ea5cb586afb0341bd\" \\\n            \"97dabe7cc46e7be3a054aa605395e43b243654c01ffc14c8b5443488f35d80b504a612f3d29d767106d0d9249aaa4fd99b67a94fb8661a3520004501192d84fa\",\n        # -------------------- SHA3 Round2 candidates --------------------\n        # https://github.com/aidansteele/sphlib\n        \"BMW-224\":\n            \"278f7e6db8fd7c9353fc181d840bf20351e3a45229ff42983ac26697\",\n        \"BMW-256\":\n            \"ca0981a78ac2c97ecb358267f6d8d88216366024ef0d7137938b5a3165898dff\",\n        \"BMW-384\":\n            \"ca60ffd15eab7f4809f1b8f8daa5687f2192f872cc554303181403626cf5311be3c8f86e49aab330278f8e1b411d3c60\",\n        \"BMW-512\":\n            \"2998d4cb31323e1169b458ab03a54d0b68e411a3c7cc7612adbf05bf901b8197dfd852c1c0099c09717d2fad3537207e737c6159c31d377d1ab8f5ed1ceeea06\",\n        # self\n        \"CubeHash10+1/1+10-256\":\n            \"217a4876f2b24cec489c9171f85d53395cc979156ea0254938c4c2c59dfdf8a4\",\n        \"CubeHash80+8/1+80-256\":\n            \"94e0c958d85cdfaf554919980f0f50b945b88ad08413e0762d6ff0219aff3e55\",\n        \"CubeHash160+16/32+160-256\":\n            \"5151e251e348cbbfee46538651c06b138b10eeb71cf6ea6054d7ca5fec82eb79\",\n        \"CubeHash10+1/1+10-512\":\n            \"eb7f5f80706e8668c61186c3c710ce57f9094fbfa1dbdc7554842cdbb4d10ce42fce72736d10b152f6216f23fc648bce810a7af4d58e571ec1b852fa514a0a8e\",\n        \"CubeHash80+8/1+80-512\":\n            \"ca942b088ed9103726af1fa87b4deb59e50cf3b5c6dcfbcebf5bba22fb39a6be9936c87bfdd7c52fc5e71700993958fa4e7b5e6e2a3672122475c40f9ec816ba\",\n        \"CubeHash160+16/32+160-512\":\n            \"bdba44a28cd16b774bdf3c9511def1a2baf39d4ef98b92c27cf5e37beb8990b7cdb6575dae1a548330780810618b8a5c351c1368904db7ebdf8857d596083a86\",\n        # https://github.com/aidansteele/sphlib\n        \"ECHO-224\":\n            \"ea7548f1186079bea3b7002f7651b60cb1fd559191f3dde26700f069\",\n        \"ECHO-256\":\n            \"3c3c10b84e818cbddfd71e1aefc6cb9cd7fd1b84acb5765813e716734a97d422\",\n        \"ECHO-384\":\n            \"d045abb41ef43012e0436855f10f1a115eeec1f346ff119e86bf96cf427f453b625f0df8ee2b123e335a9a38446702c6\",\n        \"ECHO-512\":\n            \"fe61eba97bdfcaa027ded44a5f883fcb900b97449596d7b4a7187c76e71ad750e6117b529bd69992bec015bef862d16d62c384b600cb300d486e565f94202abf\",\n        # https://github.com/jonelo/jacksum\n        \"Fugue-224\":\n            \"6e8e3280e6e3a4d8fcf27a82ea81d66f66f94b73dc3a85a361740b78\",\n        \"Fugue-256\":\n            \"4b2c2011fc9e5f5d6aed35dd20ce151af631db61aad0b2a5e12e17e01538d5ca\",\n        \"Fugue-384\":\n            \"3a327a7b4a05f05d0e5a06e2f1eb49a0e837a9e07bf60b5eeefe5fc8ca98cf85578ce856b60d6f3828b81c5eb051ace8\",\n        \"Fugue-512\":\n            \"ee1e53e892bedd72d753bd4c9f704201708fb9b79177816051ebca1dc1af7ee928b8996df0862bbea24503be2781b1a036079a88627d4d248f2d0ec77b579b7f\",\n        # https://github.com/aidansteele/sphlib\n        \"Hamsi-224\":\n            \"0e0bd268a3c7d9ca55b12a03ae18d4322394178d042d0e28c8b7da9b\",\n        \"Hamsi-256\":\n            \"415e7fa87a20d942012c9b458507c247498043e09381a165a893e4d22c52246c\",\n        \"Hamsi-384\":\n            \"810b536315560820b2a4ebaf4680ba4fd77b577ade9b326029d1d4954b4d203fd9ab519ca8ebf1132369d3926e4e4572\",\n        \"Hamsi-512\":\n            \"d7453c84a10eab2d4eef9d8862ced59e0640fe0f3fb088812a8b71ac5ac68953b213492ce3d83415f22c7033573b66e28417da0cb728a18e8914e08140d0948c\",\n        # https://github.com/jonelo/jacksum\n        \"Luffa-224\":\n            \"49ac0a3651e0dbf30224e2b0a8b7f24450c8b49f21e6eef9fc7968c3\",\n        \"Luffa-256\":\n            \"49ac0a3651e0dbf30224e2b0a8b7f24450c8b49f21e6eef9fc7968c33e25bef7\",\n        \"Luffa-384\":\n            \"e67f459e496dfe04a0091a2e2c253e5f48883472dc21dce1d6a0bb0359867fc11815d8e0f868bbfb102f412e24075107\",\n        \"Luffa-512\":\n            \"459e2280a7cdb0c721d8d9dbeb9ed339659dc9e7b158e9dd2d328d946cb21474dc9177edfc93602f1aadb31944c795c9b5df859a3dc6132d4f0a4c476aaf797f\",\n        # https://hashing.tools/shabal\n        \"Shabal-192\":\n            \"c0629db89b2911e0febaabd7618a5da22ad6ea2638e13d40\",\n        \"Shabal-224\":\n            \"0afa60c76a61bcc73773ec8e2694862506f7782a088ce8a30ba5e789\",\n        \"Shabal-256\":\n            \"cdee2d6e35a1aa235c09e3d1a94e59207459c8da37cfaed0c2d51fab9a59f932\",\n        \"Shabal-384\":\n            \"c08623c184f728d3e35c15bd74a27f0480de3a837f3a14bef7df70edc0e4a9500e100092d3e3f3b464ed18cbc1121bc5\",\n        \"Shabal-512\":\n            \"f12f6893f4535d360b07ec15be706e5921b0358d736e61cb2e7ffd2157cd119dc1aeecbf2f1ac73552dc052ad4edcf8cbe87073a4db4d1b4f6a31e39edf5a96d\",\n        # https://github.com/aidansteele/sphlib\n        \"SHAvite3-224\":\n            \"12a8401b9f8465ef01201698b66a21d3fb030c995f237da20377bafe\",\n        \"SHAvite3-256\":\n            \"eb43e5be6d6cab5d81910dec375120106936879e55e27188735e240144a36a66\",\n        \"SHAvite3-384\":\n            \"67e488432df469c810797aaa65c7e6622096c094439fedebba892ccab1547332f9fa506f9ea1ecf6d150a896141eeba6\",\n        \"SHAvite3-512\":\n            \"4dbd97835c4e5cfa14799884a7adc96688dd808ff53d5c4cfe7db89a55ee98d0260791ec0c9b5466482ab3f6f236da7e65e1cb6d1ee624f61a5b2b79f63c4120\",\n        # https://github.com/aidansteele/sphlib\n        \"SIMD-224\":\n            \"964ff29db5c3d88794c6c488b274d77c52d5ff07509c5aa8d67a14b8\",\n        \"SIMD-256\":\n            \"c9deb40282ee7b66a6fc1c8e240ce73aac4252c30b48d247e8d8693ad8ae2e34\",\n        \"SIMD-384\":\n            \"f4f9ba9a4e4e870079c69cf61b5e52c39bab522782fda17d093d8757231539f2bfb72c8dbbe36bea8321520f59a2d378\",\n        \"SIMD-512\":\n            \"ca493ce78cc2a63b5a48393e61d113d59a930b3e76d062ab58177345c48b59890a08661d04dd6160a1b42d215f1e303d97ab0abb54e65f758f79aee2b182b34b\",\n        # -------------------- SHA3 Round1 candidates --------------------\n        # If the link is dead, use these.\n        # https://web.archive.org/web/20170404095802/http://csrc.nist.gov/groups/ST/hash/sha-3/Round1/submissions_rnd1.html\n        # https://web.archive.org/web/20170211075400/http://csrc.nist.gov/groups/ST/hash/sha-3/Round2/submissions_rnd2.html\n        # https://web.archive.org/web/20170211075442/http://csrc.nist.gov/groups/ST/hash/sha-3/Round3/submissions_rnd3.html\n\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Abacus.zip\n        \"Abacus-224\":\n            \"2d4c4d46c6198fc5646345f78011e9c07ebf81a354acf40090dab750\",\n        \"Abacus-256\":\n            \"666cb308c69caa6d5043292be664218c9b928957703a04a3be89ffabfbbdb00f\",\n        \"Abacus-384\":\n            \"e7ee677abdc304988e76d96f1a44fbf9f71b57f1411456f3bd9459061e124919a5f5cc0d986c73694b639b00c8578a26\",\n        \"Abacus-512\":\n            \"0e115823ebeb52ed3d8d0280e1ae1c1204f5b74bc4644fc74a21c53fb4358c233a230f9bc012d8471d4acfde2b3ddb529dc5e39fb1315c45adcd90e9edaa41a3\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/ARIRANGUpdate.zip\n        \"ARIRANG-224\":\n            \"84c24ed54d07dd09f6168c0f9ebfa79a334e7c26de49d5db26b2623f\",\n        \"ARIRANG-256\":\n            \"16ac451d0a5af18cad3218e8e6638b46db5637b6221efcc014b3062ade373ed8\",\n        \"ARIRANG-384\":\n            \"374f750f62f5d75c1a93cda8fff30cead2a5e1985dc4b7a45c9f6f758b48f3269db90a346412914f0c282608c568b870\",\n        \"ARIRANG-512\":\n            \"e9b2975ddea2a06e1a9d18ae9b8c64c78e3351140b2b1ea8c13f6cc59f42771b7d64ac2f53d3308d8cfa952be0f8e99687e2a8e6fb3878c0d88c32cd956d79c8\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/AURORA.zip\n        \"AURORA-224\":\n            \"906d1d3a48807021fe633a69729f8635a91ae00c0f761cc088bfc5c7\",\n        \"AURORA-224M\":\n            \"6675d1dc85079a3615322dfa4b7c30a1ac1c954c622cf6fda307f5e3\",\n        \"AURORA-256\":\n            \"b8ed2c7f4de46220e9f0b8128a80dec4c610db13c8be6f0037ab67a878e44444\",\n        \"AURORA-256M\":\n            \"84e70ab7424da2030b95229895318e371153b20b831860e6453379a079a00f90\",\n        \"AURORA-384\":\n            \"9bfb11ee28694460da9cf58edb869c89b6f3bb1e403bcfd820839e5e033de214a06fc7f385f39a985d74e0e25c0ceb8f\",\n        \"AURORA-512\":\n            \"ca358e3ebf5b86d933eb29789180d0554b5187acc3aea4d2a9953a56d15b5486c74c210b66af8d71a8d9698d115b71c9915df9e82708fd6667ee3199005f3b7b\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Blender.zip\n        \"Blender-224\":\n            \"f22751ae660fdf910c58e9e0f5411a1f4c75047be98ee0ec227cf9c9\",\n        \"Blender-256\":\n            \"1e57c8b0a331abc5a89a4ac540f69473be495aa4cbfd1970783d4919d12be26c\",\n        \"Blender-384\":\n            \"bafe74892a4842b96807fbef086d923ebbe54e3b1d32c366abac2cc2f9a54e97ebf7e6b0826cd402e5854b1ab40baa9b\",\n        \"Blender-384Spec\":\n            \"d36e625afb6a617a54e195c138504ac85f6cdf17fb1e32e0d48182a1497bd3e5a7fd8f2fed89288f8c87fc9c23a5d27f\",\n        \"Blender-512\":\n            \"a70415a188effe1092f2c3eb164d2f19f4e09ad739eba9aee7b0c5df751f01bf0ecac5a73c278df009ab7f946461a654d4f893a364894d40d9bb728cea737296\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/BOOLE.zip\n        \"BOOLE-224\":\n            \"4e8a0e1652f4ad9e6f9a69d22e68501e4d38152a9beb059a1367781f\",\n        \"BOOLE-256\":\n            \"bb6b6b1bc99d2a79ff1c78db3c2933395dde77053ec1a5b48b97ab034534a346\",\n        \"BOOLE-384\":\n            \"9acbd9b59a683e378227ebb02f2b9d1dc8141b7d8f583aa1d12fed2f6a577a36e8116c7010a1a4138baec994165bf5c2\",\n        \"BOOLE-512\":\n            \"ccbae29b9f0315207475991aaefbd873ebc07721a489dfe1aeaf0447a3808fe01966d3cf9cdb6f24377e8925aac446ddc07d5166b61228ce733371228b72ea4a\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Cheetah.zip\n        \"Cheetah-224\":\n            \"351e1feb561a84ce5b207a944131e240abda27a23227240790d131b5\",\n        \"Cheetah-256\":\n            \"2076a857145dffe17b2b7003f045daea62ab5efd7f9629897e0d912d55ca1b64\",\n        \"Cheetah-384\":\n            \"501341c228f121fbb1abd3b682c5b23ba7f06987fecedd3d09ca3c9855f611e64e8c6daf13ee0c5e5ef8f4d04e6751fa\",\n        \"Cheetah-512\":\n            \"b6888c9afc8f60cd62252571da8009ae10fa8458778f0fb596deb542fec9e1771171879a4c0e38410e257d119305d201b39c8d4c106c03756ee05e62635c5e7e\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/CHI.zip\n        \"CHI-224\":\n            \"b3a3ba88e77c107ed348e077cdfe67fdd915f7bd5396f4463ac916d3\",\n        \"CHI-256\":\n            \"9473b99489da9a8e6b23a1477c287940125caeab3b3eeeab4d2ac2520a9c1049\",\n        \"CHI-384\":\n            \"f03857ce38f1b57eb8c23259741913d0728a2be831250df71824c5154cb68970b5c320c3f15904dfb3ff11d2b37dfc5d\",\n        \"CHI-512\":\n            \"0da90851211d39c54cc6c1ea0ba550877a28d436a8f8afa6108ee63337aa6af85926d5f9a4e11053493f5c260dda1022fb6fc69a407f2bbff6e004325d459d95\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/DCH.zip\n        \"DCH-224\":\n            \"c41e268388c7a893269d4a0e8c92a1861cacd0abc5a96dacd29ddd01\",\n        \"DCH-256\":\n            \"c41e268388c7a893269d4a0e8c92a1861cacd0abc5a96dacd29ddd016f2d28a3\",\n        \"DCH-384\":\n            \"c41e268388c7a893269d4a0e8c92a1861cacd0abc5a96dacd29ddd016f2d28a388fd581dccfd6cdcf7bf7b1c252c1d01\",\n        \"DCH-512\":\n            \"c41e268388c7a893269d4a0e8c92a1861cacd0abc5a96dacd29ddd016f2d28a388fd581dccfd6cdcf7bf7b1c252c1d01d9a70791e900449340ed3e964aa7f23a\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/DyamicSHA.zip\n        \"DynamicSHA-224\":\n            \"51c03bad3caca3a8c81b1d617c69c2b4ee0e3bab0933e1a63e2f1629\",\n        \"DynamicSHA-256\":\n            \"2d068470cc3877ed6b629a75b9b9927cae15068e8a369322c5a2511e7a9193c8\",\n        \"DynamicSHA-384\":\n            \"81e6601ae16b2e908c0efbe4313626d56648763319d38413b4f50fbbb712984ae36e8d1ee970c9da04bb8e2d9bba86ad\",\n        \"DynamicSHA-512\":\n            \"8f8063e1c54b851a38d9b2733ef2e02d5e4abe4c71d7040a3af7fc605a5bcc6c87450d326d93c3b90a98298aacac3c4d959766fa825d220e06aca799fa607e59\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/DynamicSHA_2.zip\n        \"DynamicSHA2-224\":\n            \"09e20b9f90ac1c0b6253d54bf74c4736cbf81b0b8ce24a014adbb3b4\",\n        \"DynamicSHA2-256\":\n            \"fa27eba9050c38f21d9041c04c05b5ca0c26af46d4055dc5fa93aefd30ea0d39\",\n        \"DynamicSHA2-384\":\n            \"b02fe0c132d100f470101a3f38c15628ef19324962d536272bf84f93f9a8a9da5c4f397dc4401e661bb0adf35c223327\",\n        \"DynamicSHA2-512\":\n            \"48d905ed7644bb9dfe721ce5691543a844eeb53560f5cbb3a877fefab28ff639762bece763b8b3cf4cae870f1b25758877277a3b73657497030e77d1c2b46838\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/ECOH.zip\n        \"ECOH-224\":\n            \"98d9adc87f734194b6f6e0e16df18428964acf76b34a816c1bcf3f06\",\n        \"ECOH-256\":\n            \"fc81d47498d9adc87f734194b6f6e0e16df18428964acf76b34a816c1bcf3f06\",\n        \"ECOH-384\":\n            \"17f8383d44dd29ae3290fda4c7a6ac2550ce82c3f53f736212d07d99e365d12627a79e3c92fc2eb177065ad884bde1da\",\n        \"ECOH-512\":\n            \"a7e9114eac54cc2d2014c5c976849739d66ad7f049fcd4047992f0bed1e7022e864cf12a2581254a44163b64156930632e28fca145c612d551507503734cd89c\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/EDON-R.zip\n        \"EDONR-224\":\n            \"8f2cf96634e6be40f2534a9ab9e5ff18070f2ecd0e2040b2d1ebda4a\",\n        \"EDONR-256\":\n            \"42201941c0020a52cca6772d31fefddfc4db45deb64c7b7dc9e8e8f82cd7ad1e\",\n        \"EDONR-384\":\n            \"8c2bfcee0c7224d576c8153046d684ce1152c2db137228d3dc0dbe9f14f8ce8c32d7f0e3bb19c6de864865f0a8f2f7a6\",\n        \"EDONR-512\":\n            \"7d7bc0c23e810d16916f392738c9f58139bea582096517672963aae6608f3945f8ab1a7c6b32823a07b71dca57694230c88a708476696e220da6ca2a6a20ad56\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/EnRUPT.zip\n        \"EnRUPT-224\":\n            \"18766355483f44a5789b2ed7d1c2cff79ec56913a7a0d83c80be55f4\",\n        \"EnRUPT-256\":\n            \"677177abac538e141964d7243ef6ad12ef1963f5471cc768da953340bec91502\",\n        \"EnRUPT-384\":\n            \"6b2ce288c98e161e8e41c3f5cb50a60eed3e71510c5f2fdc69e92f32ee6a01b57339c2652c875ff70de62d204e5a0906\",\n        \"EnRUPT-512\":\n            \"394803b9596ef8de269b0186f3926f7dbccc393a99bbebe535a0fb7d7ab8469be0efcdf369f8a45dc1edde5dc5e7474d431daed6e0c1f260286eeba6b1b6eb0f\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/ESSENCE.zip\n        \"ESSENCE-224\":\n            \"a7a2791842a881db4abc4f8c0abe8b4c4df56cb7db7130d9b0f39e7c\",\n        \"ESSENCE-256\":\n            \"5ac3b1d03e501a31f34c94ff418a1b6612b375635de49a96132ae01885d0f33e\",\n        \"ESSENCE-384\":\n            \"1649cca251bacb951c0f69c8e3822eeeb9871537ef3d4d0517fd392e1b966cb7ff48aa14858cff9619ed1d32b2d750e7\",\n        \"ESSENCE-512\":\n            \"76b17eb4550e8a544e6a20a4f491d9489f5d875cc87c98ec3bdb9d7cd668628cd71d730ed697db4e9a8dfbf0855a725d14b442fb56b268694d59b5c329cb875f\",\n        # https://hashing.tools/fsb\n        \"FSB-160\":\n            \"a25f6e24c6fb67533f0a25233ac5cc09d5793e8a\",\n        \"FSB-224\":\n            \"1dd28d92cad63335fcca4c64a5e1133ccaa8c3e6083ad15591280701\",\n        \"FSB-256\":\n            \"a0751229aac5aeba6aeb1c0533988302e5084bb11029e7bb0ada7a653491df24\",\n        \"FSB-384\":\n            \"4983ecfa3930e3cf61ac4c82695c01a394016b39cf22b5d6dcba447ef8cbcda46ac341ccf5835f331fed0abe73e9bf1c\",\n        \"FSB-512\":\n            \"6f87b9dc051330bfb0dd7ad35c05d6a2040e9a6110b06886368934d6ae25694fd9790b1bf1086af9da4b15619609b688fa576376f136adbd3b5a51ae1a1f2158\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Khichidi-1.zip\n        \"Khichidi1-224\":\n            \"0d0ae72a091bb130665bb1bfcd159c97e2b62eb0ebb56dca336faa9b\",\n        \"Khichidi1-256\":\n            \"5bc619118d9a4c4ca0b14504b22ffd68c5f35f760b327fb8d3e10029511617df\",\n        \"Khichidi1-384\":\n            \"3bbbddb487b42f0f65092f58717da7cf4c4112eff32e3bbf78530f212f40b799220f4408ac00789ae67432848b9157d1\",\n        \"Khichidi1-512\":\n            \"cb516489f37b2d9c26adfd9e99b06e855ac72903fd416dfd0216c5732228e503d961c853b2e80b70bdb6c5178aaf377bb8b755ac8f06bcbc3b31e04849deb59b\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/LANE.zip\n        \"Lane-224\":\n            \"35ff2f82ede8c86f9ba7823a7d2363805ed72d748a5308a1c5242607\",\n        \"Lane-256\":\n            \"710ba632ed2581206fab281eb3ac8a4acd0b3cdfb1af8dc1b7a6b1679e9161e0\",\n        \"Lane-384\":\n            \"1d326d45b84a8a0db4733b91f68fa46cd16dc5004e28843b72333ffbcf5a528564558d3e4fe3d7723f46f9c242e4c489\",\n        \"Lane-512\":\n            \"bb8fcd93dddc1fe2c283dde8dff248ab69d67368146155cbcfa118e4e81a89d2e3455a5252f0cef43b177ec9d9de656b8c1b5fd7d8088241a7a73688ade0fb56\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Lesamnta.zip\n        \"Lesamnta-224\":\n            \"a99d16d2c059138b050658739b80e6528bb13714f7c6ff54042fa700\",\n        \"Lesamnta-256\":\n            \"55082b0519ca42ccf44ff280a8dbb35dfc38d232be64ab0709abb38b98ed963d\",\n        \"Lesamnta-384\":\n            \"5b9c850f8a4b648c3b2c3bd3e81bb03364679a52eaecbea95d47264f7dfb5da88d58754b6613e955ca79b9233c01a494\",\n        \"Lesamnta-512\":\n            \"4cc281facf12b10b086aa54d5e6293e8491e5cf4434ff1339f778869da59408ac78b59c6773826d66ee6e69bc1fce6036af60ada4b7735eb522cb8553db59e9e\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/LUX.zip\n        \"LUX-224\":\n            \"1675a8d124c3d6b8fd51f586e3b2442ea41030f1b5352aa542fd9cad\",\n        \"LUX-256\":\n            \"1675a8d124c3d6b8fd51f586e3b2442ea41030f1b5352aa542fd9cade855521c\",\n        \"LUX-384\":\n            \"ef0398a401a0d275e6a6b46a71b376f31eeb66ad2856aa2c5c1537cc8103c06bb83c4b2853a29ffc887b4dbe777987de\",\n        \"LUX-512\":\n            \"ef0398a401a0d275e6a6b46a71b376f31eeb66ad2856aa2c5c1537cc8103c06bb83c4b2853a29ffc887b4dbe777987deefc5d80e2634a84987b69cfc3f1aa0d1\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/MCSSHA3.zip\n        \"MCSSHA3-224\":\n            \"35d5ca41238a6dce20356e5f52567ad03bbe21e52e7015f0d1a79f2d\",\n        \"MCSSHA3-256\":\n            \"202285d5c2e3a90b4b8a982917a0e50b800757755a3f6c1888d75bf7de9f4872\",\n        \"MCSSHA3-384\":\n            \"a4a166d865205ed2fda693451c703d26e1d68edcd66a9cd123d9b1361b95b1504b92c90873cd0d44e657c946501062f2\",\n        \"MCSSHA3-512\":\n            \"db83972358b44966e8ab3ee23185d8de95c92aa410516d70646b8b144d9e30cb7990be8a752875263dd1e6d7bdac56616b7206a516f208805b1c6459a94a5f22\",\n        # https://www.browserling.com/tools/md6-hash\n        \"MD6-128\":\n            \"7b428f5ec47e0174faf31dc7c89590c6\",\n        \"MD6-256\":\n            \"977592608c45c9923340338450fdcccc21a68888e1e6350e133c5186cd9736ee\",\n        \"MD6-512\":\n            \"dcba0c6593fbd83a0f5f148588baa79530579c1f5e7f19d500fe282d137bff465106f25c9f0619b4082a730683d5f58311c0c1913068e91b0ebdf9ace3ff5b9e\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/MeshHash.zip\n        \"MeshHash-224\":\n            \"d282dbd98285891d65912cde56bccb031a03187f4b348ec649da9893\",\n        \"MeshHash-256\":\n            \"d7478933b34ee26b1c71d049f8eb3b42e72b142b2c63c6ebb14d87eb9c00506f\",\n        \"MeshHash-384\":\n            \"e79aadab0a169cfd4386188285fb9f62abeb78f1aaa9409f4074228ff48862b7a709bfb2c09a2045b249e54f9f2374f5\",\n        \"MeshHash-512\":\n            \"d479629fe2423dd5ca291731c76f805344d45a3ca5daf7f734d08af8157fcc315968aa9fe10560c57a0a5cef5f3848b4e9ea678f8fd2ce5706226259d76f48b5\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/NaSHA.zip\n        \"NaSHA-224\":\n            \"32040ebcae67fb698ab2037dcb2d42b4b05405173b44b821ff611fcd\",\n        \"NaSHA-256\":\n            \"7c97fbe05876c7da8bb5eb8fa9ab45d6457e5796fda873b38b3e5e20bdef07aa\",\n        \"NaSHA-384\":\n            \"53ce208a677e8fcfe6c8a42f72e67cf0f9324f7c98651fea2c56a9e16f46fa4a546ec55d3bdd3d65a421e53d0b58b3a2\",\n        \"NaSHA-512\":\n            \"90c2bbf5379133e3468497a711d769afb18549d564063baf047802f5830fecec5be33b0d9d688345344c071341a923c721c9cf8e4a7d53c1dc3048f8f9e12aa9\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/SANDstorm.zip\n        \"SANDstorm-224\":\n            \"e2ae7dbf4649c65e0ae19de85b3b4d2565862645146282ec57a64ef4\",\n        \"SANDstorm-256\":\n            \"607ac39b7cd6c1912e7934cdbbfceeea1fe5e8155a9726b36c96895c93e6056d\",\n        \"SANDstorm-384\":\n            \"e0fb1925617466e876152d6c632b4751829ee61036d1bccbe0d481ea5b0eab7f0a020c7cb9423cd7382a18b738609e5d\",\n        \"SANDstorm-512\":\n            \"c50794660a3672279018ec7ab26559bdea6565e191ba892ef4cc579c96fb33804255ad18a4b2f6604b34d5e2a4ca5d4dd1fc6fee882727ac54f6273706ea9ff6\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Sarmal.zip\n        \"Sarmal-224\":\n            \"5f208b2ba6bc33ebe5328ee21b604d31f18f06c511072decd5b55de7\",\n        \"Sarmal-256\":\n            \"0905b8e53840dcae98f19f7686cda237fc9e9eafa2ba3972fc057ada111daa59\",\n        \"Sarmal-384\":\n            \"f35e366df171e039a21b5554d8b8362272db97a927f87a881cf909106144215e337c714849a4d04a6f44d9bbd0aeea29\",\n        \"Sarmal-512\":\n            \"184b3f2413d62a802a653ac225595251b6db64802bb5728563f363595a0b4caaae56c1cc56c083dd4ef9cae016e9ffa44aac3006b67466e3018cc135ec97b61e\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/sgail.zip\n        \"Sgail-224\":\n            \"b4d3cf522c909a4934bea1e08867a78121faa14fadb6b6652066e232\",\n        \"Sgail-256\":\n            \"b4d3cf522c909a4934bea1e08867a78121faa14fadb6b6652066e23274b5ffb2\",\n        \"Sgail-384\":\n            \"b4d3cf522c909a4934bea1e08867a78121faa14fadb6b6652066e23274b5ffb2b379c5cdba636a3e9c604d395b2b4c97\",\n        \"Sgail-512\":\n            \"b4d3cf522c909a4934bea1e08867a78121faa14fadb6b6652066e23274b5ffb2b379c5cdba636a3e9c604d395b2b4c97c68524b005dd53ebae00556630f35a6f\",\n        \"Sgail-768\":\n            \"9433dfc30b18390c21823cb0a47b615a57a5b8e283d6aec98b516656b2c986ae59d2bf74fd0b4d35b4f031d47512ce397e9739da43c127a793824b17700388fc\" \\\n            \"b8346293f8052146f5ba35de4c22898ad945790c1a4f9f3ab4cb5f0e22b4acf6\",\n        \"Sgail-1024\":\n            \"9433dfc30b18390c21823cb0a47b615a57a5b8e283d6aec98b516656b2c986ae59d2bf74fd0b4d35b4f031d47512ce397e9739da43c127a793824b17700388fc\" \\\n            \"b8346293f8052146f5ba35de4c22898ad945790c1a4f9f3ab4cb5f0e22b4acf6b9b6310fba3c3e7d1cd92e28829027d719c8de200d259e72de636f412e0804b2\",\n        \"Sgail-1536\":\n            \"103c7e0f4e3b8e1adfdfe2be45d19abe02cd115028d403427efd3af2d13f58e832af09f5bf60ba48716620cc62a4642a78965840b40df659e5cdfc6779458cfe\" \\\n            \"8ebc3d37baa144d6d5548d76e952a3c8422566d1b2391bb886e4fb3c3321b141ec7adcc874b0945896dc838b7598eab99484c35fc3be4a690a030db275d32688\" \\\n            \"b64741949fd0bbb48db227422751a8497862bf09335d8a80935d5a0660f292eda0f449c5cf6e130183e0c7e98e935c4b614e6460505b3bacdd3772ae360d2a24\",\n        \"Sgail-2048\":\n            \"103c7e0f4e3b8e1adfdfe2be45d19abe02cd115028d403427efd3af2d13f58e832af09f5bf60ba48716620cc62a4642a78965840b40df659e5cdfc6779458cfe\" \\\n            \"8ebc3d37baa144d6d5548d76e952a3c8422566d1b2391bb886e4fb3c3321b141ec7adcc874b0945896dc838b7598eab99484c35fc3be4a690a030db275d32688\" \\\n            \"b64741949fd0bbb48db227422751a8497862bf09335d8a80935d5a0660f292eda0f449c5cf6e130183e0c7e98e935c4b614e6460505b3bacdd3772ae360d2a24\" \\\n            \"c391b1835e8d9d460b582597ba141143fd1c8a0705cf8cc91ccbcaa325013d8adb9e576efc15a37e9005c6c523f9aedaedb6dc33d01dd71274945ef514b212bf\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/SHAMATA.zip\n        \"SHAMATA-224\":\n            \"c48da545eedb1b8d4ac6c92386ad8c1a5e14bca851634c9e7d59813b\",\n        \"SHAMATA-256\":\n            \"8eec361426176970f3ca307e298c985487466868cedbb981571158d6d1509a6b\",\n        \"SHAMATA-384\":\n            \"d866c0438ebd8dfe792008c5826a9534c43368809b3da8a7fceb3c77ac37c60ee3f5278b2b043f31c0caa6d5a9c17906\",\n        \"SHAMATA-512\":\n            \"fd3c751fd59dcd6fe2b381cf325bb11ec6a9172c4e1592df06bdd8ede7dbc182281b87e1e5fbe25753c098ca49c9997e50f88012c3cb0106f5566138a0b2e8bd\",\n        # https://csrc.nist.rip/groups/ST/hash/sha-3/Round1/documents/Spectral_Hash.zip\n        \"SpectralHash-128\":\n            \"457b59f8e79683508275d50c4a8de4d4\",\n        \"SpectralHash-160\":\n            \"4051d7767e1abcb592d20c09db968639519e32ac\",\n        \"SpectralHash-192\":\n            \"4068ebb99fc0dad936e44a90b009a6e674ae9cd219e395da\",\n        \"SpectralHash-224\":\n            \"20347d739d75c076bb09b7112b22b4422a6f33b15eae6482cf8e2bba\",\n        \"SpectralHash-256\":\n            \"201a3eb9c76eb403bad609bdc421591ad8922c9bd55d94be5719902cf8714b72\",\n        \"SpectralHash-288\":\n            \"900d0dd69c79bdb400eebae04dee1085725acc24c2c9beaaf629764b8e660266e1d296b2\",\n        \"SpectralHash-320\":\n            \"900c86e5d38f9beda801ddba70137b84217732d3309312c8c7d55ee29bb25e1cc68098ae8f492d66\",\n        \"SpectralHash-352\":\n            \"9092ca5baad3e3e6fb6a00b9d5d38094f706185dce2d31844c4b238fb55d714dd92f4398d0132ae47d2a5b66\",\n        \"SpectralHash-384\":\n            \"9092e52dd569f1f9bf6d5005cf57470154fbc18b04ee7168c6488c4b10e3eda56b8b3bd917a1e69a0132ae47e95276ca\",\n        \"SpectralHash-416\":\n            \"4849729bbaae9f1fe6f6ed500373d4e8f40aa7de862c13bce368c332238ab10e2f6d2b6e1677990bd0f9a3405195b91f92a4ecca\",\n        \"SpectralHash-448\":\n            \"4849714dddabd3e3ee6db732a006e7ace97a02a9f7a18b047bcf1b530cc88e1ab12795eda56d6166bcc85e51f3432814669b88fa4a49d992\",\n        \"SpectralHash-480\":\n            \"48222716777557d378fb9b6dcca801dcfa674bd01527ef6185811ef3e1b5306646386ac49f2bd5a566b0b35e642faa3e6865028ca9b947e92c93b192\",\n        \"SpectralHash-512\":\n            \"4822278b3bba55fa6f1f39b36eb95003b9f46745e88549fbd86160436f3f0da4c19918e86ac44f457ab4acdb0b32f3217d2c7cd06240a3251b923fa4b9276322\",\n        # -------------------- relatively long --------------------\n        # https://hashing.tools/ascon\n        \"Ascon-Hash\":\n            \"3375fb43372c49cbd48ac5bb6774e7cf5702f537b2cf854628edae1bd280059e\",\n        \"Ascon-HashA\":\n            \"f40d49f17c5b7efc22ef8a623c4117f532a94c60faff439d5b5f02a31e8933c6\",\n        \"Ascon-Xof\":\n            \"c100696bd70a3e731873bdc8a76ffb53b6cca80b694473b320d436883bbbc300dd5abfebcfdfdee1a6671a51f181543c3933b533e7e132e186bb557515b898cb\" \\\n            \"d92d86ce999d979f25face87e00e9eea869a328f12537b8be359ec3a5064b4f03b95a1e4ecb85763fad1b29fed3415831602313f0687eef75d26aa56c3a03aca\",\n        \"Ascon-XofA\":\n            \"5c32bbe73bd8ea9191435d72cc973a2bb2d8f40410de6188e06c65b78401759c30a3f1b24ea251b12d468d729aad6570883b82438e798020d0ebb3e920490629\" \\\n            \"051c64fe2ddb2ff14b89e9d2352cfda9bbffe4601d0e5bffb6c4b8165c44172cc0dc76430d7a38fbb5b57134936c53648989c49e79052fb1040a8b0a7f43e0ad\",\n        # https://hashing.tools/belt\n        \"BelT Hash\":\n            \"b0333d1bb3c391893a5a1df907eaf2b5cc60e993bd4fa0cdd865d09a243183cd\",\n        # https://github.com/jonelo/jacksum\n        \"BLAKE2sp\":\n            \"cf192976714bb648e72b29fa90e6bf0fbc5bf2efe7d5c26ed8ff34e855368691\",\n        \"BLAKE2bp\":\n            \"f10e0523631699102c63412c0701fa19f6550fbac0e9c035803c6033b50465222bb92ee0af0dad53edca32f0e08a72c077a6cafc6f4d24a7fb649079d47ce089\",\n        # https://emn178.github.io/online-tools/blake3/\n        \"BLAKE3-128\":\n            \"2f1514181aadccd913abd94cfa592701\",\n        \"BLAKE3-256\":\n            \"2f1514181aadccd913abd94cfa592701a5686ab23f8df1dff1b74710febc6d4a\",\n        \"BLAKE3-512\":\n            \"2f1514181aadccd913abd94cfa592701a5686ab23f8df1dff1b74710febc6d4ac0615cd845be939b4ef6aec25e799aaa450c63f8d9e333cdb0dd79b70ee69879\",\n        # https://github.com/Kimundi/ed2k\n        \"ED2K-Blue\":\n            \"1bee69a46ba811185c194762abaeae90\",\n        \"ED2K-Red\":\n            \"1bee69a46ba811185c194762abaeae90\",\n        \"ED2K-RedBlue\":\n            \"1bee69a46ba811185c194762abaeae901bee69a46ba811185c194762abaeae90\",\n        # https://github.com/jonelo/jacksum\n        \"ESCH-256\":\n            \"d43f87a0fe60fc5925064880c6116c136b6d94fa24a93dffcb35d178c3af932c\",\n        \"ESCH-384\":\n            \"0a8167a616fc8dbca06b877427c15fd27b7db3430f86794742394a5db6838d916843d739ac821c6b0b7df538aa4554ea\",\n        # https://fnvhash.github.io/fnv-calculator-online/\n        \"FNV1-32\":\n            \"e9c86c6e\",\n        \"FNV1-64\":\n            \"a8b2f3117de37ace\",\n        \"FNV1-128\":\n            \"185adb693e7c97844ecfa9497cb529b6\",\n        \"FNV1-256\":\n            \"5484a6fda3cdc44b211d89bcc7aba23d3db53b8d4a1c4f181452bea38d5e407e\",\n        \"FNV1-512\":\n            \"116c3e885f0cddf9a9c30a3f45515050f0bcc29201becf78ddd2cebfc099cbc8db9fbebdc5b4f08169eb705d8fbf92b2b7b9121d2991b91374b428901c2965ca\",\n        \"FNV1-1024\":\n            \"3a4d50796fdfef4453da11fd40f3e795c7335d9c1a76f44ec522a26cf89030ab56d73d675114a4d0448067000000002c78c4ffbd2756340f2832a6ab43a50f84\" \\\n            \"596efc9c7ce1ea25ed87cfae6f9618346680553973accf6176f84a30253b45f8bfbd52c3e21ab215feaebe3dccd33670146f723b0bc667774d094a5e8ed2a36c\",\n        \"FNV1a-32\":\n            \"048fff90\",\n        \"FNV1a-64\":\n            \"f3f9b7f5e7e47110\",\n        \"FNV1a-128\":\n            \"68cce4cd885ea04239f02af30e297870\",\n        \"FNV1a-256\":\n            \"de8de01f19056b20fd89451c1046c67801f99f71264e4fff078e67f490022ab0\",\n        \"FNV1a-512\":\n            \"cd74f564c0520cbd816ee4a6a9efebce4865dd1c4152d79ecbb3acbb2e55d860bc17f0b55ae4686537b02bced854f29c3cc8785e72d030249267163b61128df8\",\n        \"FNV1a-1024\":\n            \"0480a708ee10a2217801aad08aa2c906aca079f6094db1580606e97a3f6e984598ccdba1e41d93a0ed3a40000000002c78c4ffbd2756340f2832a6ab43a50f84\" \\\n            \"596efc9c7ce1ea25ed87cfae6f9618346863feabd80d9e025589dc2c79905a9f4a72e8adca100c3d2adf5090e1da90932a039a0112125dc44de5ba7fe1234040\",\n        # https://github.com/jonelo/jacksum\n        \"FNV0-32\":\n            \"89074759\",\n        \"FNV0-64\":\n            \"1f7224b4c8a7bbb9\",\n        \"FNV0-128\":\n            \"517098213d50cd2fedca83d32b0c6e31\",\n        \"FNV0-256\":\n            \"1a723f286142d2b2969e1fef7bb017bede69fd112d7d28d967152bbe7feb60a9\",\n        \"FNV0-512\":\n            \"a6ace7075d8d3c8af92b4dcf579326ed4746b569286e16a8b960f80ec899f597dca8d79d4a538e6a92973bf13004bcae60b9b34435b916d6fc33a01fd246516d\",\n        \"FNV0-1024\":\n            \"c871a1311e02a022b212e0617ffa4e2095d93af593a4ddf83a96b4e0bec00845f41e576c181ff9f385eba7000000000000000000000000000000000000000000\" \\\n            \"000000000000000000000000000000000001f7ee241391f3aa67eb21b33f526d0461ca0d711dea56c28ef23c9d2ae40acc520b2e03defb70f19bcbc6d8518dab\",\n        # self\n        \"FNV0a-32\":\n            \"0f75511b\",\n        \"FNV0a-64\":\n            \"16b01830f503fb5b\",\n        \"FNV0a-128\":\n            \"08b63d54a36c79f9983034d5f84b964b\",\n        \"FNV0a-256\":\n            \"29966e65f4d5ec26c8a6f2188530edae6cf9eed2148fa579f25ba92b63670a5b\",\n        \"FNV0a-512\":\n            \"42d98f9b069cd7e71d3af9e52d255b8a9f8f563698805c1060ec5bcec6480e78a638e3be95f3d0ca68a150275658cda398cf3063fafd9a0be92b8aa2bc37190b\",\n        \"FNV0a-1024\":\n            \"ebc8ecd5f1fd778166986437d8f535f97fcac598859e7690069a8b5421d8027f720903930562657effffa6000000000000000000000000000000000000000000\" \\\n            \"00000000000000000000000000000000030d7c4df25956df4327a342f932d30fcba656d86b64688bb7ada7ffbb83a4bedb3b565c00cbee26ae9b035d7678b22f\",\n        # https://github.com/jonelo/jacksum\n        \"FORK-256\":\n            \"290f4a3bc99dd6edc87400af4d4daa10362b0fea41d7cd41710f4e9fe0964428\",\n        # https://github.com/jonelo/jacksum\n        \"GOST\": # codespell:ignore\n            \"77b7fa410c9ac58a25f49bca7d0468c9296529315eaca76bd1a10f376d1f4294\",\n        \"GOST94cp\":\n            \"9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76\",\n        # https://gchq.github.io/CyberChef/\n        \"HAS-160\":\n            \"abe2b8c711f9e8579aa8eb40757a27b4ef14a7ea\",\n        # https://www.webutils.pl/index.php?idx=haval\n        \"HAVAL-128,3\":\n            \"713502673d67e5fa557629a71d331945\",\n        \"HAVAL-128,4\":\n            \"6eece560a2e8d6b919e81fe91b0e7156\",\n        \"HAVAL-128,5\":\n            \"696f02111f2e1da5c21d50eb782b7e8f\",\n        \"HAVAL-160,3\":\n            \"b338ac397e8bccadcccd96549cadd4882d834107\",\n        \"HAVAL-160,4\":\n            \"6e739d01f5739ceed94da1a115b52d5951280560\",\n        \"HAVAL-160,5\":\n            \"ecce9fa8a428866304ff082af2f9062637d36b23\",\n        \"HAVAL-192,3\":\n            \"58e6ced002e311172483d434ba738ad033e7fa950e431503\",\n        \"HAVAL-192,4\":\n            \"228ee09bc7e36151c6f285f558e6aede66ad38c8341592b9\",\n        \"HAVAL-192,5\":\n            \"023d045f75d4bf051fd6e50f7b7417bf9949c4b5d2b4b7ef\",\n        \"HAVAL-224,3\":\n            \"e1d5792306f56b22419662b06d1885a66dca3eba01f53274c89aeaeb\",\n        \"HAVAL-224,4\":\n            \"dddd6689885f6db4ad91e35a35e1f4498446510df798d4fd54b8654f\",\n        \"HAVAL-224,5\":\n            \"03d953298c8e56b46385c6761cd4b2e377889a75c97eaea475421c73\",\n        \"HAVAL-256,3\":\n            \"9446028f42b3768a41bd873ca69b0c006341d986613567f39eb61f96ca683300\",\n        \"HAVAL-256,4\":\n            \"c0d4c6ea514105fd1a9c38a238553fb7fa21d4127eb1a3035a75ce9d06a83d96\",\n        \"HAVAL-256,5\":\n            \"b89c551cdfe2e06dbd4cea2be1bc7d557416c58ebb4d07cbc94e49f710c55be4\",\n        # https://marekknapek.github.io/hash/\n        \"KangarooTwelve128-128\":\n            \"b4f249b4f77c58df170aa4d1723db112\",\n        \"KangarooTwelve128-256\":\n            \"b4f249b4f77c58df170aa4d1723db1127d82f1d98d25ddda561ada459cd11a48\",\n        \"KangarooTwelve128-512\":\n            \"b4f249b4f77c58df170aa4d1723db1127d82f1d98d25ddda561ada459cd11a489242e112dbfb1f99a1de1d7e830d457778a66d1dc2aa44d61a1da91655122fb7\",\n        \"KangarooTwelve256-128\":\n            \"1848a4799bb4f5ca08ad8b1992fc9077\",\n        \"KangarooTwelve256-256\":\n            \"1848a4799bb4f5ca08ad8b1992fc9077998b4ad3f1f986d5c10da59de9f23e75\",\n        \"KangarooTwelve256-512\":\n            \"1848a4799bb4f5ca08ad8b1992fc9077998b4ad3f1f986d5c10da59de9f23e755c21f5e72959d76ff3b65e2347769d67393914bca74f42069062774e3776715c\",\n        # https://emn178.github.io/online-tools/kmac128/\n        \"KMAC128-128\":\n            \"b12d497a01f3b5c9faf89eab268ee7b0\",\n        \"KMAC128-256\":\n            \"d26ce5ceb3a1bccd03e454835b4b611aa0d5eba4c9940d05fae3deee7a7206b7\",\n        \"KMAC128-512\":\n            \"ba68f09ebe1332dfb1eedde4d47ddf9835bbb9723f429ec815b8e7d63c48828272cc9a16749b14f20f3e8ab865d8a5d82932947d53c01ccdd8d8c032b9fd1873\",\n        # https://emn178.github.io/online-tools/kmac256/\n        \"KMAC256-128\":\n            \"ab61345a6ca76d9f54f46b75acb150c4\",\n        \"KMAC256-256\":\n            \"19a6c774bfee80202736556b7aa0474e79bb1df95c62674c6e1246dc036c821e\",\n        \"KMAC256-512\":\n            \"c212695c45a612147c87e14d70890dd154af5704bbbe6e6f78aa6c08a1560eeccb1c9450a7ab0398625c7bd699557bc5c487a66d92a422626041aaa4a77a34e0\",\n        # https://github.com/jonelo/jacksum\n        \"Kupyna-256\":\n            \"996899f2d7422ceaf552475036b2dc120607eff538abf2b8dff471a98a4740c6\",\n        \"Kupyna-384\":\n            \"0956d8afa9653b5231614decb1cceb8162ae5b8ff2dc3b02417f86dc4df621d0ca5b1ff399d494766c93a6d2513cae3a\",\n        \"Kupyna-512\":\n            \"d1b469f43e0963735b6cd08a6e75fc370956d8afa9653b5231614decb1cceb8162ae5b8ff2dc3b02417f86dc4df621d0ca5b1ff399d494766c93a6d2513cae3a\",\n        # https://github.com/jonelo/jacksum\n        \"LSH256-224\":\n            \"6375aab1e1a1a446aa8d55a3c3f03e85edb96ab886649a34d1f1e876\",\n        \"LSH256-256\":\n            \"f8025b61eb10d80a7f03ccfb906222a0645bb175fdeee9595f223936edbf7070\",\n        \"LSH512-224\":\n            \"3b7d9fc1a1356755abefb5c4c24543068f0cd8d71b57129e8fb53dda\",\n        \"LSH512-256\":\n            \"5e4ebe2017e84f35420bda7486ebbd791e0ece579cc18e49341b9a526466e633\",\n        \"LSH512-384\":\n            \"f7c6f97cd902658ab17ba5696aa7bf79d49d36b46aeb9a8a563917a37459c8e28fe299cc8821d76fe6b94dfd5cfc8bc2\",\n        \"LSH512-512\":\n            \"bc0a2b9a0c99bdf2c8a83418c4bef13791c97cef25bd2be8fadbbb0f0807c44163085bde435cf7d41db0104dc87eb5cd47cf21698683375647bff65e2ef51e51\",\n        # https://github.com/jonelo/jacksum\n        \"MarsupilamiFourteen\":\n            \"3611bcaa666347770dbffd4562f137c5adfe2e09f3c4268ef7c7d7c0e6c5d59c21fa67c4cfdba29e449c944b1a16c4583f2be8a75fb4f7649df6b98698708ecf\",\n        # https://marekknapek.github.io/hash/\n        \"MD2\":\n            \"03d85a0d629d2c442e987525319fc471\",\n        # https://marekknapek.github.io/hash/\n        \"MD4\":\n            \"1bee69a46ba811185c194762abaeae90\",\n        # https://github.com/jonelo/jacksum\n        \"MDC-2\":\n            \"000ed54e093d61679aefbeae05bfe33a\",\n        # https://www.browserling.com/tools/ntlm-hash\n        \"NTLM hash\":\n            \"4e6a076ae1b04a815fa6332f69e2e231\",\n        # https://github.com/jonelo/jacksum\n        \"Panama\":\n            \"5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1\",\n        # https://github.com/damaki/ksum\n        \"ParallelHash-128\":    # ./bin/ksum --parallelhash128 --output-size=32 --block-size=8 -\n            \"a6eb1bcdfd9531a193e65ea9c58a1902fbb51ea575e482ef9096049055db520f\",\n        \"ParallelHashXOF-128\": # ./bin/ksum --parallelhash128 --output-size=32 --block-size=8 --xof -\n            \"762ca8cf752e88ebaf69c5b9c24728b0f63c95a2238cb9196998d282140d2989\",\n        \"ParallelHash-256\":    # ./bin/ksum --parallelhash256 --output-size=64 --block-size=8 -\n            \"3f975d80fce91ea04f39e66052c6d35fc5bc8222c124063cbdb1328ea584c863bfbd4a41f667dfaf491564d244f1b1fce9c50767555655b3120ca253df50cda0\",\n        \"ParallelHashXOF-256\": # ./bin/ksum --parallelhash256 --output-size=64 --block-size=8 --xof -\n            \"b9fa18ce16f8b6a4da80deee19e3fb24b51cf4e5c3087a79faf7764a5428faa785b9602e569f011dc1f557dc969529d513c166a36bcccc082b0692cd14f515af\",\n        # https://github.com/jonelo/jacksum\n        \"PhotonBeetle\":\n            \"5ced20c8d747c62114bf691739821516135aa8413997cf34b4b8e40a25489762\",\n        # https://github.com/jonelo/jacksum\n        \"RadioGatun-32\":\n            \"191589005fec1f2a248f96a16e9553bf38d0aee1648ffa036655ce29c2e229ae\",\n        \"RadioGatun-64\":\n            \"6219fb8dad92ebe5b2f7d18318f8da13cecbf13289d79f5abf4d253c6904c807\",\n        # https://www.webutils.pl/index.php?idx=ripemd\n        \"RIPEMD-128\":\n            \"3fa9b57f053c053fbe2735b2380db596\",\n        \"RIPEMD-160\":\n            \"37f332f68db77bd9d7edd4969571ad671cf9dd3b\",\n        \"RIPEMD-256\":\n            \"c3b0c2f764ac6d576a6c430fb61a6f2255b4fa833e094b1ba8c1e29b6353036f\",\n        \"RIPEMD-320\":\n            \"e7660e67549435c62141e51c9ab1dcc3b1ee9f65c0b3e561ae8f58c5dba3d21997781cd1cc6fbc34\",\n        # https://marekknapek.github.io/hash/\n        \"SHA-0\":\n            \"b03b401ba92d77666221e843feebf8c561cea5f7\",\n        # https://md5hashing.net/hash/snefru\n        \"Snefru-128\":\n            \"59d9539d0dd96d635b5bdbd1395bb86c\",\n        # https://md5hashing.net/hash/snefru256\n        \"Snefru-256\":\n            \"674caa75f9d8fd2089856b95e93a4fb42fa6c8702f8980e11d97a142d76cb358\",\n        # https://asecuritysite.com/hash/gost # codespell:ignore\n        \"Streebog-256\":\n            \"3e7dea7f2384b6c5a3d0e24aaa29c05e89ddd762145030ec22c71a6db8b2c1f4\",\n        \"Streebog-512\":\n            \"d2b793a0bb6cb5904828b5b6dcfb443bb8f33efc06ad09368878ae4cdc8245b97e60802469bed1e7c21a64ff0b179a6a1e0bb74d92965450a0adab69162c00fe\",\n        # https://www.webutils.pl/index.php?idx=tiger\n        \"TIGER-128,3\":\n            \"6d12a41e72e644f017b6f0e2f7b44c62\",\n        \"TIGER-160,3\":\n            \"6d12a41e72e644f017b6f0e2f7b44c6285f06dd5\",\n        \"TIGER-192,3\":\n            \"6d12a41e72e644f017b6f0e2f7b44c6285f06dd5d2c5b075\",\n        \"TIGER-128,4\":\n            \"c1f3a704e9f6267e9f75fa47191f83c3\",\n        \"TIGER-160,4\":\n            \"c1f3a704e9f6267e9f75fa47191f83c354100a04\",\n        \"TIGER-192,4\":\n            \"c1f3a704e9f6267e9f75fa47191f83c354100a04c4f1dc6f\",\n        # https://marekknapek.github.io/hash/\n        \"TIGER2-128,3\":\n            \"976abff8062a2e9dcea3a1ace966ed9c\",\n        \"TIGER2-160,3\":\n            \"976abff8062a2e9dcea3a1ace966ed9c19cb8555\",\n        \"TIGER2-192,3\":\n            \"976abff8062a2e9dcea3a1ace966ed9c19cb85558b4976d8\",\n        # pycryptodome\n        \"TupleHash128-128\":\n            \"b0b09f20d5e98972f1f8272e700cf912\",\n        \"TupleHash128-256\":\n            \"1f223cc030a7f9e63d5207e191660e8d71d0773a50178bd63646a8767555bfdd\",\n        \"TupleHash128-512\":\n            \"fa5a91dd0ef12c48f23e035a3ed51502a4ade0524a30d834d28201535a111952c4b56dfd30937577dd955fbdd4128d277c0e3f364bd81d5a727abc5c3cc78fbf\",\n        \"TupleHash256-128\":\n            \"e20429d277603b218025dcba37c230e4\",\n        \"TupleHash256-256\":\n            \"ee14da8f09fd9a3dfd91ee0b84f75f96d57b979b934981b2cd631522e7279a3a\",\n        \"TupleHash256-512\":\n            \"9cd329b4ac886b3aab5c09e19dbd5368c33dbc9a48e57e918873e8d95096d43b390bd805d5b6be5d75e0549908861f5bcaf1d0857818eb9b3b2bc6249a333b5f\",\n        # https://marekknapek.github.io/hash/\n        \"TurboSHAKE128-128\":\n            \"76a1720a4848ab64e67e563f16b8c5aa\",\n        \"TurboSHAKE128-256\":\n            \"76a1720a4848ab64e67e563f16b8c5aa492b698a4d93429735fd02354657fbf7\",\n        \"TurboSHAKE128-512\":\n            \"76a1720a4848ab64e67e563f16b8c5aa492b698a4d93429735fd02354657fbf7a0689ec77b4c795fda9daab410c63092f54200846c34120ff2b253e9fd8d9fc4\",\n        \"TurboSHAKE256-128\":\n            \"b6e91a412c262c7936b069f67bd21c2f\",\n        \"TurboSHAKE256-256\":\n            \"b6e91a412c262c7936b069f67bd21c2f8ecc48bda8dc6eebfbaf6fcaa82191c3\",\n        \"TurboSHAKE256-512\":\n            \"b6e91a412c262c7936b069f67bd21c2f8ecc48bda8dc6eebfbaf6fcaa82191c3974462707ab2a5c5d704b0e874860a2a3fddb588f507c9b4f0417e2b66316090\",\n        # https://github.com/jonelo/jacksum\n        \"VSH-1024\":\n            \"45f3882692a07aa2fd6c76815ac5f784453e09297a4c9374fb3b6a647b6569f8951c519676f89a7d7bb7f44faa025bea88900d3efcc3a4f739a748ac93f66c1f\" \\\n            \"6391daf3daa5e73ae1aaef031b87f11ecd5b778f884cbe397a57ad61fc039981b7cea94843be90fab35c4b92e274343dc9b1b4d24bec6154b416b9597ad52bbe\",\n        # https://asecuritysite.com/javascript/js04\n        \"Whirlpool-0\":\n            \"4f8f5cb531e3d49a61cf417cd133792ccfa501fd8da53ee368fed20e5fe0248c3a0b64f98a6533cee1da614c3a8ddec791ff05fee6d971d57c1348320f4eb42d\",\n        \"Whirlpool-T\":\n            \"3ccf8252d8bbb258460d9aa999c06ee38e67cb546cffcf48e91f700f6fc7c183ac8cc3d3096dd30a35b01f4620a1e3a20d79cd5168544d9e1b7cdf49970e87f1\",\n        \"Whirlpool\":\n            \"b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35\",\n        # https://github.com/jonelo/jacksum\n        \"Xoodyak\":\n            \"087376b970c53ed0339a4fe54f4462f0f34e4e50ed09b4314ed24b32ba9822cb\",\n        # -------------------- relatively short --------------------\n        # https://asecuritysite.com/hash/smh\n        \"CityHash-32\":\n            \"a339c810\",\n        \"CityHash-64\":\n            \"c268724928feca7d\",\n        \"CityHash-128\":\n            \"a7f9a86a2d60c968bf1498f876dbe279\",\n        # https://asecuritysite.com/hash/smh # fp: fingerprint\n        \"FarmHash-32 (fp)\":\n            \"ec998320\",\n        \"FarmHash-64 (fp)\":\n            \"abbe83f33b1b5134\",\n        \"FarmHash-128 (fp)\":\n            \"bf1498f876dbe279a7f9a86a2d60c968\",\n        # https://github.com/ztanml/fast-hash\n        \"FastHash-32\":\n            \"136bd7e4\",\n        \"FastHash-64\":\n            \"4611ffb633a627d2\",\n        # https://github.com/ogxd/gxhash\n        \"GxHash-32\":\n            \"0bc03dd6\",\n        \"GxHash-64\":\n            \"0bc03dd6b35d0186\",\n        \"GxHash-128\":\n            \"0bc03dd6b35d01867892d3b59509300d\",\n        # https://pypi.org/project/siphash-cffi/\n        \"HalfSipHash-32_2_4\":\n            \"ed285d61\",\n        \"HalfSipHash-64_2_4\":\n            \"31f20e6c986fe414\",\n        # https://asecuritysite.com/hash/smh_Halftime\n        \"HalfTimeHash-64\":\n            \"45bf6c18f4c47ad1\",\n        \"HalfTimeHash-128\":\n            \"08f19709c03904d6\",\n        \"HalfTimeHash-256\":\n            \"4761c86ed217c2e0\",\n        \"HalfTimeHash-512\":\n            \"8dc86dd14f852fe8\",\n        # https://asecuritysite.com/hash/smh\n        \"HighwayHash-64\":\n            \"552d6e674e35333e\",\n        \"HighwayHash-128\":\n            \"d59d55e677071404dcded33a97cfee4b\",\n        \"HighwayHash-256\":\n            \"40e0a9717f9dee85a7c86aadee4e2bd884656a3eec42a8172d340faa3cb127de\",\n        # https://github.com/avaneev/komihash\n        \"KomiHash\":\n            \"4d86bedb30f8641c\",\n        # https://asecuritysite.com/hash/smh\n        \"MetroHash-64\":\n            \"37b871151974389c\", # need byte swap\n        \"MetroHash-128\":\n            \"97d78a67ac6c62e9870198793485d405\", # need byte swap\n        # https://asecuritysite.com/hash/smh\n        \"Murmur1\":\n            \"851e251a\", # need int->hex (LE)\n        # https://www.ciphertools.org/tools/murmur2/text\n        \"Murmur2\":\n            \"d0292721\", # need int->hex (LE)\n        \"Murmur2a\":\n            \"e5b5e153\", # need int->hex (LE)\n        \"Murmur64a\":\n            \"1b862a0433ca8955\", # need int->hex(LE)\n        \"Murmur64b\":\n            \"51b7c28fccd78d75\", # need int->hex(LE)\n        # https://murmurhash.shorelabs.com/\n        \"Murmur3a\":\n            \"23f74f2e\", # need int->hex (LE)\n        \"Murmur3c\":\n            \"c383152f\" \"672ceeec\" \"6cf67b5d\" \"2c1de9e5\", # need 4-byte swap\n        \"Murmur3f\":\n            \"6c1b07bc7bbc4be3\" \"47939ac4a93c437a\", # need 8-byte swap\n        # https://pypi.org/project/siphash-cffi/\n        \"SipHash-64_2_4\":\n            \"0de4702506520059\",\n        \"SipHash-64_1_3\":\n            \"1e450cd0d376f68d\",\n        \"SipHash-64_4_8\":\n            \"ed013f3fab3d1abd\",\n        \"SipHash-128_2_4\":\n            \"df8c5ce876c57f25c03f1bb5df591ab2\",\n        \"SipHash-128_4_8\":\n            \"23e0a6e8aae3f2e571ba3536bfbea2ff\",\n        # https://asecuritysite.com/hash/smh\n        \"SpookyHash-32\":\n            \"c79306aa\", # need byte swap\n        \"SpookyHash-64\":\n            \"c79306aa46e8122b\", # need byte swap\n        \"SpookyHash-128\":\n            \"c79306aa46e8122b1b340724747e361d\",\n        # https://asecuritysite.com/hash/smh_t1ha\n        \"T1HA0-32\":\n            \"d0e6c0a9\",\n        \"T1HA1-64\":\n            \"86235f2773f9ada1\",\n        \"T1HA2-64\":\n            \"1f1d052e973ff69d\",\n        \"T1HA2-128\":\n            \"5891d221cdf479758dd36078748f9731\",\n        # https://asecuritysite.com/hash/smh\n        \"WYHash-32\":\n            \"88ca02ad\",\n        \"WYHash-64\":\n            \"d986947fb5be3867\",\n        # https://www.coderstool.com/xxh-hash-generator\n        \"xxHash-32\":\n            \"e85ea4de\",\n        \"xxHash-64\":\n            \"0b242d361fda71bc\",\n        \"xxHash3-64\":\n            \"ce7d19a5418fb365\",\n        \"xxHash3-128\":\n            \"ddd650205ca3e7fa24a1cc2e3a8a7651\",\n        # -------------------- checksum --------------------\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"RS Hash\":\n            \"29a4500b\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"JS Hash\":\n            \"dfeffe38\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"PJW Hash\":\n            \"04280c57\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"ELF Hash\":\n            \"04280c57\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"BKDR Hash\":\n            \"c5181667\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"SDBM Hash\":\n            \"8ca77173\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"DJB2\":\n            \"34cc38de\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"DEK Hash\":\n            \"ea0e6658\",\n        # https://www.partow.net/programming/hashfunctions/ (C implementation)\n        \"AP Hash\":\n            \"a18caec3\",\n        # https://md5calc.com/hash/joaat/\n        \"JOAAT\":\n            \"519e91f5\",\n        # https://md5calc.com/hash/adler32/\n        \"Adler32\":\n            \"5bdc0fda\",\n        # https://github.com/mjethani/superfasthash\n        \"SuperFastHash\":\n            \"e37cbf05\",\n        # https://github.com/silvasur/buzhash\n        \"BuzHash\":\n            \"69ef5bad\",\n        # https://metacpan.org/release/MOOLI/Algorithm-Nhash-0.002/source/lib/Algorithm/Nhash.pm\n        \"NHash\":\n            \"03f831\",\n        # -------------------- MD5/SHA1/SHA256 n-times --------------------\n        # self\n        \"MD5 x2 (raw)\":\n            \"a5f6bc8c547364db2a98ccb9386ea241\",\n        \"MD5 x3 (raw)\":\n            \"7b99681999eccbd5f4cdbd87d3335691\",\n        \"MD5 x4 (raw)\":\n            \"842b4b942deaef9cb727bd067b9a20d1\",\n        \"MD5 x5 (raw)\":\n            \"55522480f27438c9b1afe39ee24dda1c\",\n        \"MD5 x2 (hex)\":\n            \"883c631dbcaca4373e1428a73c6cb19d\",\n        \"MD5 x3 (hex)\":\n            \"4381d02b989be5b7812e4d15c7d02b27\",\n        \"MD5 x4 (hex)\":\n            \"0903fc4520b46c84e0eb563036941e15\",\n        \"MD5 x5 (hex)\":\n            \"c9681bee6c4ab3bd0ea4b03e27341be6\",\n        \"SHA1 x2 (raw)\":\n            \"a4e4d26fd0c6455e23e2187c3aabe844332aa1b3\",\n        \"SHA1 x3 (raw)\":\n            \"ae3924f937127c28eb67b3c287416da8f7222b09\",\n        \"SHA1 x4 (raw)\":\n            \"22ce3d415294049921a5973b14cf86561d6a1020\",\n        \"SHA1 x5 (raw)\":\n            \"5410a01a85a03f60921eb5ae6fcf8bf219916385\",\n        \"SHA1 x2 (hex)\":\n            \"efc4fe664cbe7cec1a06f73305a414b55d7034d3\",\n        \"SHA1 x3 (hex)\":\n            \"ff5b671f805069f47c0446296f9043d27123d52c\",\n        \"SHA1 x4 (hex)\":\n            \"959bb6a982ae22b8dc7476b6a5099df4d449255e\",\n        \"SHA1 x5 (hex)\":\n            \"58464ba20599b425cbf762947a512ffeef6433da\",\n        \"SHA-256 x2 (raw)\":\n            \"6d37795021e544d82b41850edf7aabab9a0ebe274e54a519840c4666f35b3937\",\n        \"SHA-256 x3 (raw)\":\n            \"c9280b1eecf03730cd24fbf25fbb482e0efd423c1d8824f54056cf8390fdf445\",\n        \"SHA-256 x4 (raw)\":\n            \"0059752a917970d20f26f075a203df21a43416a9336fc1a40a7d74cb995898a0\",\n        \"SHA-256 x5 (raw)\":\n            \"03d5962dde4a1fc73e8351e3a659deeebd4b580649d344b8290473ecd5f47bde\",\n        \"SHA-256 x2 (hex)\":\n            \"d5074362d20d3c33a1a3e7235632271c276818ff686e25196cb6d89d98363f43\",\n        \"SHA-256 x3 (hex)\":\n            \"cb990af233d0d01de6f42683086b99b13332f26dc5e8d98991a97659be090b58\",\n        \"SHA-256 x4 (hex)\":\n            \"506d96a7ee221c2881cd0e73d7f9c8923ce26cfa189ffaf447807c3b8519bcf9\",\n        \"SHA-256 x5 (hex)\":\n            \"fb26873649b20d04274ebc569a8b6a06a5d80fcae6025b9631ecb25bc5f22a7c\",\n    }\n\n    def hash_check_one(self, hname, h):\n        bit = len(h) * 4\n        byte = bit // 8\n\n        expected = self.test_vectors.get(hname, None)\n        if expected is None:\n            self.err_add_out(\"{:26s}:[{:4d}b/{:3d}B] {:s}\".format(hname, bit, byte, \"Not found\"))\n            return\n\n        if expected != h:\n            self.err_add_out(\"{:26s}:[{:4d}b/{:3d}B] {:s}\".format(hname, bit, byte, \"Failed\"))\n            return\n\n        if not self.args.smart:\n            self.info_add_out(\"{:26s}:[{:4d}b/{:3d}B] {:s}\".format(hname, bit, byte, \"Success\"))\n        return\n\n    def hash_test(self):\n        value = b\"The quick brown fox jumps over the lazy dog\"\n        self.out.append(titlify(\"Hash({!r})\".format(value)))\n\n        for elem in self.get_valid_hash_funcs():\n            if isinstance(elem, str):\n                self.out.append(titlify(elem))\n                continue\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                continue\n            hfunc.update(value)\n            h = hfunc.hexdigest()\n            self.hash_check_one(hname, h)\n        return\n\n    def hash_test_time(self):\n        value = b\"A\" * self.args.size\n        category = None\n        result = []\n\n        tqdm = GefUtil.get_tqdm()\n        hash_funcs = list(self.get_valid_hash_funcs())\n        pbar = tqdm(hash_funcs, leave=False, total=len(hash_funcs))\n        for i, elem in enumerate(pbar):\n            if isinstance(elem, str):\n                category = elem\n                continue\n\n            hname, hfunc = elem\n            if not self.should_be_displayed(hname, hfunc):\n                continue\n\n            try:\n                pbar.set_description(hname)\n            except Exception:\n                pass\n\n            start_time_real = time.perf_counter()\n            hfunc.update(value)\n            h = hfunc.hexdigest()\n            end_time_real = time.perf_counter()\n\n            bit = len(h) * 4\n            byte = bit // 8\n            elapsed = end_time_real - start_time_real\n\n            if hasattr(hfunc, \"USE_CFFI\"):\n                if hfunc.USE_CFFI:\n                    cffi = \" (CFFI=True)\"\n                else:\n                    cffi = \" (CFFI=False)\"\n            else:\n                cffi = \"\"\n            result.append([elapsed, i, category, hname, bit, byte, cffi])\n\n        if self.args.time_with_sort:\n            result = sorted(result, key=lambda x: (-x[0], x[1]))\n\n        cumulative_time = 0.0\n        prev_category = None\n        for elapsed, _, category, hname, bit, byte, cffi in result:\n            cumulative_time += elapsed\n            if self.args.time:\n                if prev_category != category:\n                    self.out.append(titlify(category))\n                    prev_category = category\n            self.out.append(\"{:26s}:[{:4d}b/{:3d}B] {:.6f} sec (total: {:.6f} sec){:s}\".format(\n                hname, bit, byte, elapsed, cumulative_time, cffi\n            ))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        if args.time or args.time_with_sort:\n            self.hash_test_time()\n        else:\n            self.hash_test()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass HashKnownCollisionCommand(HashCommand, BufferingOutput):\n    \"\"\"Show hash collision example.\"\"\"\n\n    _cmdline_ = \"hash known-collision\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_NONE)\n        return\n\n    def make_cmp(self, data1, data2, show_full=True):\n        diff_found = False\n        asterisk = False\n\n        hex_pad_len = {\n            1: 37,\n            2: 35,\n            3: 32,\n            4: 30,\n            5: 27,\n            6: 25,\n            7: 22,\n            8: 20,\n            9: 17,\n            10: 15,\n            11: 12,\n            12: 9,\n            13: 7,\n            14: 5,\n            15: 2,\n            16: 0,\n        }\n\n        for pos in range(0, len(data1), 16):\n            # determining continuity\n            f1_bin = data1[pos : pos + 16]\n            f2_bin = data2[pos : pos + 16]\n            if not show_full:\n                if f1_bin == f2_bin:\n                    if asterisk is False:\n                        self.out.append(\"*\")\n                        asterisk = True\n                    continue\n\n            diff_found = True\n            asterisk = False\n\n            # coloring\n            f1_hex = []\n            f2_hex = []\n            f1_ascii = []\n            f2_ascii = []\n            for i in range(min(len(f1_bin), 16)):\n                if f1_bin[i] == f2_bin[i]:\n                    color_func = lambda x: x\n                else:\n                    color_func = Color.boldify\n                f1_hex.append(color_func(\"{:02x}\".format(f1_bin[i])))\n                f2_hex.append(color_func(\"{:02x}\".format(f2_bin[i])))\n                f1_ascii.append(color_func(chr(f1_bin[i]) if 0x20 <= f1_bin[i] < 0x7f else \".\"))\n                f2_ascii.append(color_func(chr(f2_bin[i]) if 0x20 <= f2_bin[i] < 0x7f else \".\"))\n\n            # formatting\n            # [\"00\", \"00\", \"00\" \"00\", ...] -> [\"0000\", \"0000\", ...]\n            f1_hex2 = [\"\".join(x) for x in slicer(f1_hex, 2)]\n            f2_hex2 = [\"\".join(x) for x in slicer(f2_hex, 2)]\n\n            # padding\n            # [\"0000\", \"0000\", ...] -> \"0000 0000 ...\"\n            f1_hex_s = \" \".join(f1_hex2) + \" \" * hex_pad_len[len(f1_hex)]\n            f2_hex_s = \" \".join(f2_hex2) + \" \" * hex_pad_len[len(f2_hex)]\n            # [\".\", \".\", ...] -> \"................\"\n            f1_ascii_s = \"\".join(f1_ascii) + \" \" * (16 - len(f1_ascii))\n            f2_ascii_s = \"\".join(f2_ascii) + \" \" * (16 - len(f2_ascii))\n\n            # make line\n            self.out.append(\"{:#06x}: {:s} |{:s}| {:s} |{:s}|\".format(\n                pos, f1_hex_s, f1_ascii_s, f2_hex_s, f2_ascii_s,\n            ))\n\n        if diff_found is False:\n            self.info_add_out(\"No difference\")\n        return\n\n    def get_hex_colored(self, data1, data2):\n        data1_hex_colored = \"\"\n        data2_hex_colored = \"\"\n        for d1, d2 in zip(data1, data2):\n            if d1 == d2:\n                data1_hex_colored += \"{:02x}\".format(d1)\n                data2_hex_colored += \"{:02x}\".format(d2)\n            else:\n                data1_hex_colored += Color.boldify(\"{:02x}\".format(d1))\n                data2_hex_colored += Color.boldify(\"{:02x}\".format(d2))\n        return data1_hex_colored, data2_hex_colored\n\n    def show_hash_info(self, data1, data2, hash_name):\n        if hash_name == \"md5\":\n            hash_func = hashlib.md5\n        elif hash_name == \"sha1\":\n            hash_func = hashlib.sha1\n\n        self.make_cmp(data1, data2)\n\n        data1_hex_colored, data2_hex_colored = self.get_hex_colored(data1, data2)\n        self.out.append(\"data1: {:s}\".format(data1_hex_colored))\n        self.out.append(\"data2: {:s}\".format(data2_hex_colored))\n\n        bold_yellow = lambda x: Color.colorify(x, \"bold yellow\")\n        self.out.append(\"{:13s}: {:s}\".format(hash_name + \"(data1)\", bold_yellow(hash_func(data1).hexdigest())))\n        self.out.append(\"{:13s}: {:s}\".format(hash_name + \"(data2)\", bold_yellow(hash_func(data2).hexdigest())))\n        self.out.append(\"sha256(data1): {:s}\".format(hashlib.sha256(data1).hexdigest()))\n        self.out.append(\"sha256(data2): {:s}\".format(hashlib.sha256(data2).hexdigest()))\n        return\n\n    def show_md5_hash_collision(self):\n        self.out.append(titlify(\"MD5 (md5-1block-collision-attack)\"))\n        self.out.append(\n            \"https://marc-stevens.nl/research/md5-1block-collision/message1.bin \"\n            \"(https://github.com/corkami/collisions/blob/master/examples/single-ipc1.bin)\"\n        )\n        self.out.append(\n            \"https://marc-stevens.nl/research/md5-1block-collision/message2.bin \"\n            \"(https://github.com/corkami/collisions/blob/master/examples/single-ipc2.bin)\"\n        )\n        md5_1 = bytes.fromhex(\n            \"4d c9 68 ff 0e e3 5c 20 95 72 d4 77 7b 72 15 87\"\n            \"d3 6f a7 b2 1b dc 56 b7 4a 3d c0 78 3e 7b 95 18\"\n            \"af bf a2 00 a8 28 4b f3 6e 8e 4b 55 b3 5f 42 75\"\n            \"93 d8 49 67 6d a0 d1 55 5d 83 60 fb 5f 07 fe a2\"\n        )\n        md5_2 = bytes.fromhex(\n            \"4d c9 68 ff 0e e3 5c 20 95 72 d4 77 7b 72 15 87\"\n            \"d3 6f a7 b2 1b dc 56 b7 4a 3d c0 78 3e 7b 95 18\"\n            \"af bf a2 02 a8 28 4b f3 6e 8e 4b 55 b3 5f 42 75\"\n            \"93 d8 49 67 6d a0 d1 d5 5d 83 60 fb 5f 07 fe a2\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (HashClash)\"))\n        self.out.append(\n            \"https://marc-stevens.nl/research/hashclash/SingleBlock/downloads/sbcpc1.bin \"\n            \"(https://github.com/corkami/collisions/blob/master/examples/single-cpc1.bin)\"\n        )\n        self.out.append(\n            \"https://marc-stevens.nl/research/hashclash/SingleBlock/downloads/sbcpc2.bin \"\n            \"(https://github.com/corkami/collisions/blob/master/examples/single-cpc2.bin)\"\n        )\n        md5_1 = bytes.fromhex(\n            \"4f 64 65 64 20 47 6f 6c 64 72 65 69 63 68 0a 4f\"\n            \"64 65 64 20 47 6f 6c 64 72 65 69 63 68 0a 4f 64\"\n            \"65 64 20 47 6f 6c 64 72 65 69 63 68 0a 4f 64 65\"\n            \"64 20 47 6f d8 05 0d 00 19 bb 93 18 92 4c aa 96\"\n            \"dc e3 5c b8 35 b3 49 e1 44 e9 8c 50 c2 2c f4 61\"\n            \"24 4a 40 64 bf 1a fa ec c5 82 0d 42 8a d3 8d 6b\"\n            \"ec 89 a5 ad 51 e2 90 63 dd 79 b1 6c f6 7c 12 97\"\n            \"86 47 f5 af 12 3d e3 ac f8 44 08 5c d0 25 b9 56\"\n        )\n        md5_2 = bytes.fromhex(\n            \"4e 65 61 6c 20 4b 6f 62 6c 69 74 7a 0a 4e 65 61\"\n            \"6c 20 4b 6f 62 6c 69 74 7a 0a 4e 65 61 6c 20 4b\"\n            \"6f 62 6c 69 74 7a 0a 4e 65 61 6c 20 4b 6f 62 6c\"\n            \"69 74 7a 0a 75 b8 0e 00 35 f3 d2 c9 09 af 1b ad\"\n            \"dc e3 5c b8 35 b3 49 e1 44 e8 8c 50 c2 2c f4 61\"\n            \"24 4a 40 e4 bf 1a fa ec c5 82 0d 42 8a d3 8d 6b\"\n            \"ec 89 a5 ad 51 e2 90 63 dd 79 b1 6c f6 fc 11 97\"\n            \"86 47 f5 af 12 3d e3 ac f8 44 08 dc d0 25 b9 56\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (FastColl)\"))\n        self.out.append(\"https://github.com/corkami/collisions/README.md\")\n        md5_1 = bytes.fromhex(\n            \"37 75 c1 f1 c4 a7 5a e7 9c e0 de 7a 5b 10 80 26\"\n            \"02 ab d9 39 c9 6c 5f 02 12 c2 7f da cd 0d a3 b0\"\n            \"8c ed fa f3 e1 a3 fd b4 ef 09 e7 fb b1 c3 99 1d\"\n            \"cd 91 c8 45 e6 6e fd 3d c7 bb 61 52 3e f4 e0 38\"\n            \"49 11 85 69 eb cc 17 9c 93 4f 40 eb 33 02 ad 20\"\n            \"a4 09 2d fb 15 fa 20 1d d1 db 17 cd dd 29 59 1e\"\n            \"39 89 9e f6 79 46 9f e6 8b 85 c5 ef de 42 4f 46\"\n            \"c2 78 75 9d 8b 65 f4 50 ea 21 c5 59 18 62 ff 7b\"\n        )\n        md5_2 = bytes.fromhex(\n            \"37 75 c1 f1 c4 a7 5a e7 9c e0 de 7a 5b 10 80 26\"\n            \"02 ab d9 b9 c9 6c 5f 02 12 c2 7f da cd 0d a3 b0\"\n            \"8c ed fa f3 e1 a3 fd b4 ef 09 e7 fb b1 43 9a 1d\"\n            \"cd 91 c8 45 e6 6e fd 3d c7 bb 61 d2 3e f4 e0 38\"\n            \"49 11 85 69 eb cc 17 9c 93 4f 40 eb 33 02 ad 20\"\n            \"a4 09 2d 7b 15 fa 20 1d d1 db 17 cd dd 29 59 1e\"\n            \"39 89 9e f6 79 46 9f e6 8b 85 c5 ef de c2 4e 46\"\n            \"c2 78 75 9d 8b 65 f4 50 ea 21 c5 d9 18 62 ff 7b\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (FastColl)\"))\n        self.out.append(\"https://github.com/corkami/collisions/blob/master/examples/fastcoll1.bin\")\n        self.out.append(\"https://github.com/corkami/collisions/blob/master/examples/fastcoll2.bin\")\n        md5_1 = bytes.fromhex(\n            \"2f 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 5c\"\n            \"7c 20 20 20 49 64 65 6e 74 69 63 61 6c 00 00 7c\"\n            \"7c 20 20 20 20 50 72 65 66 69 78 20 00 00 20 7c\"\n            \"5c 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 2f\"\n            \"37 9a e6 c3 dc 19 ed f5 72 5b b4 e4 73 df 31 bc\"\n            \"c6 31 6c 9e df af 6c 7c 51 ce 44 4a c6 b3 a7 d4\"\n            \"6d a2 fb e6 ea 6e 46 a5 4b 2a 5a 3c 8a 6b 6c be\"\n            \"21 7f 84 d2 ae 75 06 11 da dc 4c 56 87 f3 78 b6\"\n            \"64 c4 15 0a c4 b2 d1 c2 aa c9 57 3d 6f 35 7e 48\"\n            \"28 6e 79 3b 25 c6 3e 27 c9 1a 76 39 ec 46 02 66\"\n            \"1e 64 a6 57 04 d0 fa 4e 88 83 44 b7 f1 dc c2 ec\"\n            \"e6 95 a7 9e 6d 52 bf 6b ba 60 99 02 a8 9e c3 9e\"\n        )\n        md5_2 = bytes.fromhex(\n            \"2f 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 5c\"\n            \"7c 20 20 20 49 64 65 6e 74 69 63 61 6c 00 00 7c\"\n            \"7c 20 20 20 20 50 72 65 66 69 78 20 00 00 20 7c\"\n            \"5c 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 3d 2d 2f\"\n            \"37 9a e6 c3 dc 19 ed f5 72 5b b4 e4 73 df 31 bc\"\n            \"c6 31 6c 1e df af 6c 7c 51 ce 44 4a c6 b3 a7 d4\"\n            \"6d a2 fb e6 ea 6e 46 a5 4b 2a 5a 3c 8a eb 6c be\"\n            \"21 7f 84 d2 ae 75 06 11 da dc 4c d6 87 f3 78 b6\"\n            \"64 c4 15 0a c4 b2 d1 c2 aa c9 57 3d 6f 35 7e 48\"\n            \"28 6e 79 bb 25 c6 3e 27 c9 1a 76 39 ec 46 02 66\"\n            \"1e 64 a6 57 04 d0 fa 4e 88 83 44 b7 f1 5c c2 ec\"\n            \"e6 95 a7 9e 6d 52 bf 6b ba 60 99 82 a8 9e c3 9e\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (UniColl)\"))\n        self.out.append(\"https://github.com/corkami/collisions/README.md\")\n        md5_1 = bytes.fromhex(\n            \"55 6e 69 43 6f 6c 6c 20 31 20 70 72 65 66 69 78\"\n            \"20 32 30 62 f5 48 34 b9 3b 1c 01 9f c8 6b e6 44\"\n            \"fe f6 31 3a 63 db 99 3e 77 4d c7 5a 6e b0 a6 88\"\n            \"04 05 fb 39 33 21 64 bf 0d a4 fe e2 a6 9d 83 36\"\n            \"4b 14 d7 f2 47 53 84 ba 12 2d 4f bb 83 78 6c 70\"\n            \"c6 eb 21 f2 f6 59 9a 85 14 73 04 dd 57 5f 40 3c\"\n            \"e1 3f b0 db e8 b4 aa b0 d5 56 22 af b9 04 26 fc\"\n            \"9f d2 0c 00 86 c8 ed de 85 7f 03 7b 05 28 d7 0f\"\n        )\n        md5_2 = bytes.fromhex(\n            \"55 6e 69 43 6f 6c 6c 20 31 21 70 72 65 66 69 78\"\n            \"20 32 30 62 f5 48 34 b9 3b 1c 01 9f c8 6b e6 44\"\n            \"fe f6 31 3a 63 db 99 3e 77 4d c7 5a 6e b0 a6 88\"\n            \"04 05 fb 39 33 21 64 bf 0d a4 fe e2 a6 9d 83 36\"\n            \"4b 14 d7 f2 47 53 84 ba 12 2c 4f bb 83 78 6c 70\"\n            \"c6 eb 21 f2 f6 59 9a 85 14 73 04 dd 57 5f 40 3c\"\n            \"e1 3f b0 db e8 b4 aa b0 d5 56 22 af b9 04 26 fc\"\n            \"9f d2 0c 00 86 c8 ed de 85 7f 03 7b 05 28 d7 0f\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (Hashclash)\"))\n        self.out.append(\"https://github.com/corkami/collisions/README.md\")\n        md5_1 = bytes.fromhex(\n            \"79 65 73 0a 3d 62 84 11 01 75 d3 4d eb 80 93 de\"\n            \"31 c1 d9 30 45 fb be 1e 71 f0 0a 63 75 a8 30 aa\"\n            \"98 17 ca e3 a2 6b 8e 3d 44 a9 8f f2 0e 67 96 48\"\n            \"97 25 a6 fb 00 00 00 00 49 08 09 33 f0 62 c4 e8\"\n            \"d5 f1 54 cd ca a1 42 90 7f 9d 3d 9a 67 c4 1b 0f\"\n            \"04 9f 19 e8 92 c3 aa 19 43 31 1a db da 96 01 54\"\n            \"85 b5 9a 88 d8 a5 0e fb cd 66 9a da 4f 20 8a aa\"\n            \"ba e3 9c f0 78 31 8f d1 14 5f 3e b9 0f 9f 3e 19\"\n            \"09 9c bb a9 45 89 ba a8 03 e6 c0 31 a0 54 d6 26\"\n            \"3f 80 4c 06 0f c7 d9 19 09 d3 da 14 fd cb 39 84\"\n            \"1f 0d 77 5f 55 aa 7a 07 4c 24 8b 13 0a 54 a2 bc\"\n            \"c5 12 7d 4f e0 5e f2 23 c5 07 61 e4 80 91 b2 13\"\n            \"e7 79 07 2a cf 1b 66 39 8c f0 8e 7e 75 25 22 1d\"\n            \"a7 3b 49 4a 32 a4 3a 07 61 26 64 ea 6b 83 a2 8d\"\n            \"be a3 ff be 4e 71 ae 18 e2 d0 86 4f 20 00 30 26\"\n            \"0a 71 de 1f 40 b4 f4 8f 9c 50 5c 78 dd cd 72 89\"\n            \"ba d1 bf f9 96 80 e3 06 96 f3 b9 7c 77 2d eb 25\"\n            \"1e 56 70 d7 14 1f 55 4d ec 11 58 59 92 45 e1 33\"\n            \"3e 0e a1 6e ff d9 90 ad f6 a0 ad 0e c6 d6 88 12\"\n            \"b8 74 f2 9e dd 53 f7 88 19 73 85 39 aa 9b e0 8d\"\n            \"82 bf 9c 5e 58 42 1e 3b 94 cf 5b 54 73 5f a8 4a\"\n            \"fd 5b 64 cf 59 d1 96 74 14 b3 0c af 11 1c f9 47\"\n            \"c5 7a 2c f7 d5 24 f5 eb be 54 3e 12 b0 24 67 3f\"\n            \"01 dd 95 76 8d 0d 58 fb 50 23 70 3a bd ed be ac\"\n            \"b8 32 db ae e8 dc 3a 83 7a c8 d5 0f 08 90 1d 99\"\n            \"2d 7d 17 34 4e a8 21 98 61 1a 65 da fc 9b a4 ba\"\n            \"e1 42 2b 86 0c 94 2a f6 d6 a4 81 b5 2b 0b e9 37\"\n            \"44 d2 e4 23 14 7c 16 b8 84 90 8b e0 a1 a7 bd 27\"\n            \"c7 7e e6 17 1a 93 c5 ee 59 70 91 26 4e 9d c7 7c\"\n            \"1d 3d ab f1 b4 f4 f1 d9 86 48 75 77 6e fe 98 84\"\n            \"ef 3c 1c c7 16 5a 1f 83 60 ec 5c fe ca 17 0c 74\"\n            \"eb 8e 9d f6 90 a3 cd 08 65 d5 5a 4c 2e c6 be 54\"\n        )\n        md5_2 = bytes.fromhex(\n            \"6e 6f 0a e5 5f d0 83 01 9b 4d 55 06 61 ab 88 11\"\n            \"8a fa 4d 34 b3 75 59 46 56 97 ef 6c 4a 07 90 cc\"\n            \"fe 19 d7 cf 6f 92 03 9c 91 aa a5 da 56 92 c1 04\"\n            \"e6 4c 08 a3 00 00 00 00 8d b6 4e 47 ff af 7a 3c\"\n            \"d5 f1 54 cd ca a1 42 90 7f 9d 3d 9a 67 c4 1b 0f\"\n            \"04 9f 19 e8 92 c3 aa 19 43 31 1a db da 96 01 54\"\n            \"85 b5 9a 88 d8 a5 0e fb cd 66 9a da 4f 20 8a a9\"\n            \"ba e3 9c f0 78 31 8f d1 14 5f 3e b9 0f 9f 3e 19\"\n            \"09 9c bb a9 45 89 ba a8 03 e6 c0 31 a0 54 d6 26\"\n            \"3f 80 4c 06 0f c7 d9 19 09 d3 da 14 fd cb 39 84\"\n            \"1f 0d 77 5f 55 aa 7a 07 4c 24 8b 13 0a 54 b2 bc\"\n            \"c5 12 7d 4f e0 5e f2 23 c5 07 61 e4 80 91 b2 13\"\n            \"e7 79 07 2a cf 1b 66 39 8c f0 8e 7e 75 25 22 1d\"\n            \"a7 3b 49 4a 32 a4 3a 07 61 26 64 ea 6b 83 a2 8d\"\n            \"be a3 ff be 4e 71 ae 18 e2 d0 86 4f 20 00 30 22\"\n            \"0a 71 de 1f 40 b4 f4 8f 9c 50 5c 78 dd cd 72 89\"\n            \"ba d1 bf f9 96 80 e3 06 96 f3 b9 7c 77 2d eb 25\"\n            \"1e 56 70 d7 14 1f 55 4d ec 11 58 59 92 45 e1 33\"\n            \"3e 0e a1 6e ff d9 90 ad f6 a0 ad 0e ca d6 88 12\"\n            \"b8 74 f2 9e dd 53 f7 88 19 73 85 39 aa 9b e0 8d\"\n            \"82 bf 9c 5e 58 42 1e 3b 94 cf 5b 54 73 5f a8 4a\"\n            \"fd 5b 64 cf 59 d1 96 74 14 b3 0c af 11 1c f9 47\"\n            \"c5 7a 2c f7 d5 24 f5 eb be 54 3e 12 70 24 67 3f\"\n            \"01 dd 95 76 8d 0d 58 fb 50 23 70 3a bd ed be ac\"\n            \"b8 32 db ae e8 dc 3a 83 7a c8 d5 0f 08 90 1d 99\"\n            \"2d 7d 17 34 4e a8 21 98 61 1a 65 da fc 9b a4 ba\"\n            \"e1 42 2b 86 0c 94 2a f6 d6 a4 81 b5 2b 2b e9 37\"\n            \"44 d2 e4 23 14 7c 16 b8 84 90 8b e0 a1 a7 bd 27\"\n            \"c7 7e e6 17 1a 93 c5 ee 59 70 91 26 4e 9d c7 7c\"\n            \"1d 3d ab f1 b4 f4 f1 d9 86 48 75 77 6e fe 98 84\"\n            \"ef 3c 1c c7 16 5a 1f 83 60 ec 5c fe ca 17 0c 54\"\n            \"eb 8e 9d f6 90 a3 cd 08 65 d5 5a 4c 2e c6 be 54\"\n        )\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n\n        self.out.append(titlify(\"MD5 (TextColl)\"))\n        self.out.append(\"https://github.com/cr-marcstevens/hashclash\")\n        md5_1 = b\"TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak\"\n        md5_2 = b\"TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak\"\n        self.show_hash_info(md5_1, md5_2, \"md5\")\n        return\n\n    def show_sha1_hash_collision(self):\n        self.out.append(titlify(\"SHA-1 (SHAttered)\"))\n        self.out.append(\"https://shattered.io/static/shattered-1.pdf (The first 320 bytes of 422435 bytes)\")\n        self.out.append(\"https://shattered.io/static/shattered-2.pdf (The first 320 bytes of 422435 bytes)\")\n        sha1_1 = bytes.fromhex(\n            \"2550 4446 2d31 2e33 0a25 e2e3 cfd3 0a0a\"\n            \"0a31 2030 206f 626a 0a3c 3c2f 5769 6474\"\n            \"6820 3220 3020 522f 4865 6967 6874 2033\"\n            \"2030 2052 2f54 7970 6520 3420 3020 522f\"\n            \"5375 6274 7970 6520 3520 3020 522f 4669\"\n            \"6c74 6572 2036 2030 2052 2f43 6f6c 6f72\"\n            \"5370 6163 6520 3720 3020 522f 4c65 6e67\"\n            \"7468 2038 2030 2052 2f42 6974 7350 6572\"\n            \"436f 6d70 6f6e 656e 7420 383e 3e0a 7374\"\n            \"7265 616d 0aff d8ff fe00 2453 4841 2d31\"\n            \"2069 7320 6465 6164 2121 2121 2185 2fec\"\n            \"0923 3975 9c39 b1a1 c63c 4c97 e1ff fe01\"\n            \"7346 dc91 66b6 7e11 8f02 9ab6 21b2 560f\"\n            \"f9ca 67cc a8c7 f85b a84c 7903 0c2b 3de2\"\n            \"18f8 6db3 a909 01d5 df45 c14f 26fe dfb3\"\n            \"dc38 e96a c22f e7bd 728f 0e45 bce0 46d2\"\n            \"3c57 0feb 1413 98bb 552e f5a0 a82b e331\"\n            \"fea4 8037 b8b5 d71f 0e33 2edf 93ac 3500\"\n            \"eb4d dc0d ecc1 a864 790c 782c 7621 5660\"\n            \"dd30 9791 d06b d0af 3f98 cda4 bc46 29b1\"\n        )\n        sha1_2 = bytes.fromhex(\n            \"2550 4446 2d31 2e33 0a25 e2e3 cfd3 0a0a\"\n            \"0a31 2030 206f 626a 0a3c 3c2f 5769 6474\"\n            \"6820 3220 3020 522f 4865 6967 6874 2033\"\n            \"2030 2052 2f54 7970 6520 3420 3020 522f\"\n            \"5375 6274 7970 6520 3520 3020 522f 4669\"\n            \"6c74 6572 2036 2030 2052 2f43 6f6c 6f72\"\n            \"5370 6163 6520 3720 3020 522f 4c65 6e67\"\n            \"7468 2038 2030 2052 2f42 6974 7350 6572\"\n            \"436f 6d70 6f6e 656e 7420 383e 3e0a 7374\"\n            \"7265 616d 0aff d8ff fe00 2453 4841 2d31\"\n            \"2069 7320 6465 6164 2121 2121 2185 2fec\"\n            \"0923 3975 9c39 b1a1 c63c 4c97 e1ff fe01\"\n            \"7f46 dc93 a6b6 7e01 3b02 9aaa 1db2 560b\"\n            \"45ca 67d6 88c7 f84b 8c4c 791f e02b 3df6\"\n            \"14f8 6db1 6909 01c5 6b45 c153 0afe dfb7\"\n            \"6038 e972 722f e7ad 728f 0e49 04e0 46c2\"\n            \"3057 0fe9 d413 98ab e12e f5bc 942b e335\"\n            \"42a4 802d 98b5 d70f 2a33 2ec3 7fac 3514\"\n            \"e74d dc0f 2cc1 a874 cd0c 7830 5a21 5664\"\n            \"6130 9789 606b d0bf 3f98 cda8 0446 29a1\"\n        )\n        self.show_hash_info(sha1_1, sha1_2, \"sha1\")\n\n        self.out.append(titlify(\"SHA-1 (Shambles)\"))\n        self.out.append(\"https://sha-mbles.github.io/messageA\")\n        self.out.append(\"https://sha-mbles.github.io/messageB\")\n        sha1_1 = bytes.fromhex(\n            \"99 04 0d 04 7f e8 17 80 01 20 00 ff 4b 65 79 20\"\n            \"69 73 20 70 61 72 74 20 6f 66 20 61 20 63 6f 6c\"\n            \"6c 69 73 69 6f 6e 21 20 49 74 27 73 20 61 20 74\"\n            \"72 61 70 21 79 c6 1a f0 af cc 05 45 15 d9 27 4e\"\n            \"73 07 62 4b 1d c7 fb 23 98 8b b8 de 8b 57 5d ba\"\n            \"7b 9e ab 31 c1 67 4b 6d 97 43 78 a8 27 73 2f f5\"\n            \"85 1c 76 a2 e6 07 72 b5 a4 7c e1 ea c4 0b b9 93\"\n            \"c1 2d 8c 70 e2 4a 4f 8d 5f cd ed c1 b3 2c 9c f1\"\n            \"9e 31 af 24 29 75 9d 42 e4 df db 31 71 9f 58 76\"\n            \"23 ee 55 29 39 b6 dc dc 45 9f ca 53 55 3b 70 f8\"\n            \"7e de 30 a2 47 ea 3a f6 c7 59 a2 f2 0b 32 0d 76\"\n            \"0d b6 4f f4 79 08 4f d3 cc b3 cd d4 83 62 d9 6a\"\n            \"9c 43 06 17 ca ff 6c 36 c6 37 e5 3f de 28 41 7f\"\n            \"62 6f ec 54 ed 79 43 a4 6e 5f 57 30 f2 bb 38 fb\"\n            \"1d f6 e0 09 00 10 d0 0e 24 ad 78 bf 92 64 19 93\"\n            \"60 8e 8d 15 8a 78 9f 34 c4 6f e1 e6 02 7f 35 a4\"\n            \"cb fb 82 70 76 c5 0e ca 0e 8b 7c ca 69 bb 2c 2b\"\n            \"79 02 59 f9 bf 95 70 dd 8d 44 37 a3 11 5f af f7\"\n            \"c3 ca c0 9a d2 52 66 05 5c 27 10 47 55 17 8e ae\"\n            \"ff 82 5a 2c aa 2a cf b5 de 64 ce 76 41 dc 59 a5\"\n            \"41 a9 fc 9c 75 67 56 e2 e2 3d c7 13 c8 c2 4c 97\"\n            \"90 aa 6b 0e 38 a7 f5 5f 14 45 2a 1c a2 85 0d dd\"\n            \"95 62 fd 9a 18 ad 42 49 6a a9 70 08 f7 46 72 f6\"\n            \"8e f4 61 eb 88 b0 99 33 d6 26 b4 f9 18 74 9c c0\"\n            \"27 fd dd 6c 42 5f c4 21 68 35 d0 13 4d 15 28 5b\"\n            \"ab 2c b7 84 a4 f7 cb b4 fb 51 4d 4b f0 f6 23 7c\"\n            \"f0 0a 9e 9f 13 2b 9a 06 6e 6f d1 7f 6c 42 98 74\"\n            \"78 58 6f f6 51 af 96 74 7f b4 26 b9 87 2b 9a 88\"\n            \"e4 06 3f 59 bb 33 4c c0 06 50 f8 3a 80 c4 27 51\"\n            \"b7 19 74 d3 00 fc 28 19 a2 e8 f1 e3 2c 1b 51 cb\"\n            \"18 e6 bf c4 db 9b ae f6 75 d4 aa f5 b1 57 4a 04\"\n            \"7f 8f 6d d2 ec 15 3a 93 41 22 93 97 4d 92 8f 88\"\n            \"ce d9 36 3c fe f9 7c e2 e7 42 bf 34 c9 6b 8e f3\"\n            \"87 56 76 fe a5 cc a8 e5 f7 de a0 ba b2 41 3d 4d\"\n            \"e0 0e e7 1e e0 1f 16 2b db 6d 1e af d9 25 e6 ae\"\n            \"ba ae 6a 35 4e f1 7c f2 05 a4 04 fb db 12 fc 45\"\n            \"4d 41 fd d9 5c f2 45 96 64 a2 ad 03 2d 1d a6 0a\"\n            \"73 26 40 75 d7 f1 e0 d6 c1 40 3a e7 a0 d8 61 df\"\n            \"3f e5 70 71 88 dd 5e 07 d1 58 9b 9f 8b 66 30 55\"\n            \"3f 8f c3 52 b3 e0 c2 7d a8 0b dd ba 4c 64 02 0d\"\n        )\n        sha1_2 = bytes.fromhex(\n            \"99 03 0d 04 7f e8 17 80 01 18 00 ff 50 72 61 63\"\n            \"74 69 63 61 6c 20 53 48 41 2d 31 20 63 68 6f 73\"\n            \"65 6e 2d 70 72 65 66 69 78 20 63 6f 6c 6c 69 73\"\n            \"69 6f 6e 21 1d 27 6c 6b a6 61 e1 04 0e 1f 7d 76\"\n            \"7f 07 62 49 dd c7 fb 33 2c 8b b8 c2 b7 57 5d be\"\n            \"c7 9e ab 2b e1 67 4b 7d b3 43 78 b4 cb 73 2f e1\"\n            \"89 1c 76 a0 26 07 72 a5 10 7c e1 f6 e8 0b b9 97\"\n            \"7d 2d 8c 68 52 4a 4f 9d 5f cd ed cd 0b 2c 9c e1\"\n            \"92 31 af 26 e9 75 9d 52 50 df db 2d 4d 9f 58 72\"\n            \"9f ee 55 33 19 b6 dc cc 61 9f ca 4f b9 3b 70 ec\"\n            \"72 de 30 a0 87 ea 3a e6 73 59 a2 ee 27 32 0d 72\"\n            \"b1 b6 4f ec c9 08 4f c3 cc b3 cd d8 3b 62 d9 7a\"\n            \"90 43 06 15 0a ff 6c 26 72 37 e5 23 e2 28 41 7b\"\n            \"de 6f ec 4e cd 79 43 b4 4a 5f 57 2c 1e bb 38 ef\"\n            \"11 f6 e0 0b c0 10 d0 1e 90 ad 78 a3 be 64 19 97\"\n            \"dc 8e 8d 0d 3a 78 9f 24 c4 6f e1 ea ba 7f 35 b4\"\n            \"c7 fb 82 72 b6 c5 0e da ba 8b 7c d6 55 bb 2c 2f\"\n            \"c5 02 59 e3 9f 95 70 cd a9 44 37 bf fd 5f af e3\"\n            \"cf ca c0 98 12 52 66 15 e8 27 10 5b 79 17 8e aa\"\n            \"43 82 5a 34 1a 2a cf a5 de 64 ce 7a f9 dc 59 b5\"\n            \"4d a9 fc 9e b5 67 56 f2 56 3d c7 0f f4 c2 4c 93\"\n            \"2c aa 6b 14 18 a7 f5 4f 30 45 2a 00 4e 85 0d c9\"\n            \"99 62 fd 98 d8 ad 42 59 de a9 70 14 db 46 72 f2\"\n            \"32 f4 61 f3 38 b0 99 23 d6 26 b4 f5 a0 74 9c d0\"\n            \"2b fd dd 6e 82 5f c4 31 dc 35 d0 0f 71 15 28 5f\"\n            \"17 2c b7 9e 84 f7 cb a4 df 51 4d 57 1c f6 23 68\"\n            \"fc 0a 9e 9d d3 2b 9a 16 da 6f d1 63 40 42 98 70\"\n            \"c4 58 6f ee e1 af 96 64 7f b4 26 b5 3f 2b 9a 98\"\n            \"e8 06 3f 5b 7b 33 4c d0 b2 50 f8 26 bc c4 27 55\"\n            \"0b 19 74 c9 20 fc 28 09 86 e8 f1 ff c0 1b 51 df\"\n            \"14 e6 bf c6 1b 9b ae e6 c1 d4 aa e9 9d 57 4a 00\"\n            \"c3 8f 6d ca 5c 15 3a 83 41 22 93 9b f5 92 8f 98\"\n            \"c2 d9 36 3e 3e f9 7c f2 53 42 bf 28 f5 6b 8e f7\"\n            \"3b 56 76 e4 85 cc a8 f5 d3 de a0 a6 5e 41 3d 59\"\n            \"ec 0e e7 1c 20 1f 16 3b 6f 6d 1e b3 f5 25 e6 aa\"\n            \"06 ae 6a 2d fe f1 7c e2 05 a4 04 f7 63 12 fc 55\"\n            \"41 41 fd db 9c f2 45 86 d0 a2 ad 1f 11 1d a6 0e\"\n            \"cf 26 40 6f f7 f1 e0 c6 e5 40 3a fb 4c d8 61 cb\"\n            \"33 e5 70 73 48 dd 5e 17 65 58 9b 83 a7 66 30 51\"\n            \"83 8f c3 4a 03 e0 c2 6d a8 0b dd b6 f4 64 02 1d\"\n        )\n        self.show_hash_info(sha1_1, sha1_2, \"sha1\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.show_md5_hash_collision()\n        self.show_sha1_hash_collision()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass JsonCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to pretty print for JSON.\"\"\"\n\n    _cmdline_ = \"json\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass JsonMemoryCommand(JsonCommand):\n    \"\"\"Pretty print JSON from memory values.\"\"\"\n\n    _cmdline_ = \"json memory\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for json.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rdi\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def read_json(self, loc):\n        pos = 0\n        s = b\"\"\n        while True:\n            try:\n                blob = read_memory(loc + pos, 1)\n            except gdb.MemoryError:\n                err(\"Memory read error\")\n                break\n            if blob == b\"\\x00\":\n                break\n            s += blob\n            pos += 1\n        return s\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        j = self.read_json(args.location)\n        if not j:\n            err(\"Could not find JSON\")\n            return\n\n        try:\n            jstr = json.dumps(json.loads(j), indent=2)\n        except (json.JSONDecodeError, UnicodeDecodeError):\n            err(\"Invalid JSON\")\n            return\n\n        self.out = []\n        self.out.append(jstr)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass JsonValueCommand(JsonCommand):\n    \"\"\"Pretty print JSON from specified value.\"\"\"\n\n    _cmdline_ = \"json value\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string of JSON.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \\'[\"foo\", {{\"bar\": [\"baz\", null, 1.0, 2]}}]\\'',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        try:\n            jstr = json.dumps(json.loads(self.args.value), indent=2)\n        except (json.JSONDecodeError, UnicodeDecodeError):\n            err(\"Invalid JSON\")\n            return\n\n        self.out = []\n        self.out.append(jstr)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass CrcCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to calculate crc.\"\"\"\n\n    _cmdline_ = \"crc\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"file\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"[32b/04B] means 32 bits (4 bytes).\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def get_valid_crc_funcs(self):\n        import crccheck\n        for cname in crccheck.crc.__dict__:\n            if self.args.filter and not any(filt.search(cname) for filt in self.args.filter):\n                continue\n            if not cname.startswith(\"Crc\"):\n                continue\n            if cname.startswith(\"Crccheck\"):\n                continue\n            try:\n                cfunc = getattr(crccheck.crc, cname)()\n            except TypeError:\n                continue\n            yield (cname, cfunc)\n\n        class Crc32kWrapper:\n            def __init__(self):\n                self.buf = b\"\"\n                return\n\n            def cfunc(self, data):\n                # CRC-32K (Koopman) polynomial:\n                # normal:   0x741B8CD7\n                # reflected 0xEB31D82E  (LSB-first bit processing)\n                poly_reflected = 0xeb31_d82e\n                init = 0xffff_ffff\n                xorout = 0xffff_ffff\n\n                crc = init & 0xffff_ffff\n                for b in data:\n                    crc ^= b\n                    for _ in range(8):\n                        if crc & 1:\n                            crc = (crc >> 1) ^ poly_reflected\n                        else:\n                            crc >>= 1\n                        crc &= 0xffff_ffff\n\n                crc ^= xorout\n                return crc & 0xffff_ffff\n\n            def process(self, value):\n                self.buf += value\n                return\n\n            def calchex(self, value):\n                crc = self.cfunc(value)\n                return \"{:08x}\".format(crc)\n\n            def finalhex(self):\n                crc = self.cfunc(self.buf)\n                return \"{:08x}\".format(crc)\n\n            def width(self):\n                return 32\n\n            def bytewidth(self):\n                return 4\n\n        for cname in [\"Crc32K\", \"Crc32Koopman\"]:\n            if self.args.filter and not any(filt.search(cname) for filt in self.args.filter):\n                continue\n            yield (cname, Crc32kWrapper())\n        return None\n\n    def make_line(self, cname, cfunc, crc):\n        bit = cfunc.width()\n        byte = cfunc.bytewidth()\n        line = \"{:20s}:[{:2d}b/{:2d}B] {:s}\".format(cname, bit, byte, crc)\n        return line\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass CrcMemoryCommand(CrcCommand):\n    \"\"\"Calculate crc from memory values.\"\"\"\n\n    _cmdline_ = \"crc memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for crc calculation.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for crc calculation.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def calc_crc(self, cfunc, start_address, end_address):\n        # When calculating the crc of a very large range,\n        # it is not practical to store the entire data in memory.\n        # It is preferable to calculate it in blocks.\n\n        step = 0x400 * get_pagesize()\n        if is_qemu_system():\n            step = get_pagesize()\n\n        for chunk_addr in range(start_address, end_address, step):\n            if chunk_addr + step > end_address:\n                chunk_size = end_address - chunk_addr\n            else:\n                chunk_size = step\n            try:\n                mem = read_memory(chunk_addr, chunk_size)\n            except (gdb.MemoryError, MemoryError):\n                err(\"Memory read error\")\n                return False\n            try:\n                cfunc.process(mem)\n            except ValueError:\n                return None\n            del mem\n        return cfunc.finalhex()\n\n    @parse_args\n    @only_if_gdb_running\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        self.out = []\n        self.out.append(\"Address: {:#x}\".format(args.location))\n        self.out.append(\"Size: {:#x}\".format(args.size))\n\n        for cname, cfunc in self.get_valid_crc_funcs():\n            crc = self.calc_crc(cfunc, args.location, args.location + args.size)\n            if crc is False:\n                return\n            if crc is None:\n                continue\n            line = self.make_line(cname, cfunc, crc)\n            self.out.append(line)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass CrcFileCommand(CrcCommand):\n    \"\"\"Calculate crc from file.\"\"\"\n\n    _cmdline_ = \"crc file\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filename\", metavar=\"FILE\", help=\"the filepath for crc calculation.\")\n    parser.add_argument(\"start\", metavar=\"START_POS\", nargs=\"?\", default=0, type=AddressUtil.parse_address,\n                        help=\"the start position for crc calculation.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size for crc calculation.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def calc_crc(self, cfunc, filename, start_pos, end_pos):\n        # When calculating the crc of a very large range,\n        # it is not practical to store the entire data in memory.\n        # It is preferable to calculate it in blocks.\n\n        step = 0x400 * get_pagesize()\n\n        with open(self.args.filename, \"rb\") as f:\n            f.seek(start_pos)\n            for chunk_pos in range(start_pos, end_pos, step):\n                chunk_size = min(end_pos - chunk_pos, step)\n                data = f.read(chunk_size)\n                try:\n                    cfunc.process(data)\n                except ValueError:\n                    return None\n                del data\n        return cfunc.finalhex()\n\n    @parse_args\n    @only_if_gdb_running\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        self.out = []\n        if not os.path.exists(args.filename):\n            err(\"File not found\")\n            return\n        self.out.append(\"Path: {:s}\".format(args.filename))\n        self.out.append(\"FileSize: {:#x}\".format(os.path.getsize(args.filename)))\n\n        if args.size is None:\n            end_pos = args.start + os.path.getsize(args.filename)\n        else:\n            end_pos = args.start + args.size\n\n        for cname, cfunc in self.get_valid_crc_funcs():\n            crc = self.calc_crc(cfunc, args.filename, args.start, end_pos)\n            if crc is False:\n                return\n            if crc is None:\n                continue\n            line = self.make_line(cname, cfunc, crc)\n            self.out.append(line)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass CrcValueCommand(CrcCommand):\n    \"\"\"Calculate hash from specified values.\"\"\"\n\n    _cmdline_ = \"crc value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for crc calculation.\")\n    parser.add_argument(\"--hex\", action=\"store_true\", help=\"interpret VALUE as hex. invalid character is ignored.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", type=re.compile, default=[], action=\"append\",\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x42\\\\\\\\x43\\\\\\\\x44\"',\n        '{0:s} --hex \"41 42 43 44\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        if args.hex: # \"41414141\" -> b\"\\x41\\x41\\x41\\x41\"\n            value = GefUtil.fromhex_ignore_invalid(args.value)\n            if not value:\n                return\n        else:\n            try:\n                value = codecs.escape_decode(args.value)[0]\n            except binascii.Error:\n                err('Could not decode \"\\\\xXX\" encoded string')\n                return\n\n        self.out = []\n        for cname, cfunc in self.get_valid_crc_funcs():\n            try:\n                crc = cfunc.calchex(value)\n            except ValueError:\n                continue\n            line = self.make_line(cname, cfunc, crc)\n            self.out.append(line)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass Crc32revCommand(GenericCommand, BufferingOutput):\n    \"\"\"Perform CRC32 reverse calculation limited to ASCII character range.\"\"\"\n\n    _cmdline_ = \"crc32rev\"\n    _category_ = \"07-e. Misc - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-p\", \"--poly\", type=lambda x: int(x, 16), help=\"generator polynomial in MSB form.\")\n    parser.add_argument(\"--poly-reflected\", action=\"store_true\",\n                        help=\"treat --poly as already reflected (LSB form, e.g., 0xedb88320).\")\n    parser.add_argument(\"-i\", \"--init-value\", type=lambda x: int(x, 16), help=\"initial CRC register value.\")\n    parser.add_argument(\"-o\", \"--xorout\", type=lambda x: int(x, 16), help=\"final XOR value applied after output reflection.\")\n    parser.add_argument(\"--refin\", action=\"store_true\", help=\"enable input reflection (LSB-first).\")\n    parser.add_argument(\"--no-refin\", action=\"store_true\", help=\"disable input reflection (MSB-first).\")\n    parser.add_argument(\"--refout\", action=\"store_true\", help=\"enable output reflection.\")\n    parser.add_argument(\"--no-refout\", action=\"store_true\", help=\"disable output reflection.\")\n    parser.add_argument(\"--preset\", choices=[\n        \"\", \"base\", \"ieee\", \"isohdlc\", \"adccp\", \"v42\", \"xz\", \"pkzip\",\n        \"aixm\", \"q\",\n        \"autosar\",\n        \"base91d\", \"d\",\n        \"bzip2\", \"aal5\", \"dectb\", \"b\",\n        \"cdromedc\",\n        \"cksum\", \"posix\",\n        \"iscsi\", \"base91c\", \"castagnoli\", \"interlaken\", \"c\", \"nvme\",\n        \"jamcrc\",\n        \"mef\",\n        \"mpeg2\", \"ether\",\n        \"xfer\",\n        \"koopman\", \"k\",\n    ], default=\"\", help=\"quick parameter presets, explicit flags override preset values.\")\n    parser.add_argument(\"--list\", action=\"store_true\", help=\"print CRC presets.\")\n    parser.add_argument(\"wanted_crc\", metavar=\"WANTED_CRC\", nargs=\"?\", type=lambda x: int(x, 16),\n                        help=\"target CRC value (hex).\")\n    parser.add_argument(\"--prefix\", default=\"\", help=\"prefix string (ASCII).\")\n    parser.add_argument(\"--suffix\", default=\"\", help=\"suffix string (ASCII).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} --list\",\n        \"{0:s} 0x41414141\",\n        \"{0:s} 0x41414141 --prefix AAAA --suffix BBBB\",\n        \"{0:s} 0x41414141 --preset mpeg2\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    preset_dic = {\n        # https://reveng.sourceforge.io/crc-catalogue/all.htm\n        # preset name: (poly,        init_value,  xorout,      refin, refout, alias)\n        \"\":            (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   False),\n        \"base\":        (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"ieee\":        (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"isohdlc\":     (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"adccp\":       (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"v42\":         (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"xz\":          (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"pkzip\":       (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"aixm\":        (0x8141_41ab, 0x0000_0000, 0x0000_0000, False, False,  False),\n        \"q\":           (0x8141_41ab, 0x0000_0000, 0x0000_0000, False, False,  True),\n        \"autosar\":     (0xf4ac_fb13, 0xffff_ffff, 0xffff_ffff, True,  True,   False),\n        \"base91d\":     (0xa833_982b, 0xffff_ffff, 0xffff_ffff, True,  True,   False),\n        \"d\":           (0xa833_982b, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"bzip2\":       (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, False, False,  False),\n        \"aal5\":        (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, False, False,  True),\n        \"dectb\":       (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, False, False,  True),\n        \"b\":           (0x04c1_1db7, 0xffff_ffff, 0xffff_ffff, False, False,  True),\n        \"cdromedc\":    (0x8001_801b, 0x0000_0000, 0x0000_0000, True,  True,   False),\n        \"cksum\":       (0x04c1_1db7, 0x0000_0000, 0xffff_ffff, False, False,  False),\n        \"posix\":       (0x04c1_1db7, 0x0000_0000, 0xffff_ffff, False, False,  True),\n        \"iscsi\":       (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   False),\n        \"base91c\":     (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"castagnoli\":  (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"interlaken\":  (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"c\":           (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"nvme\":        (0x1edc_6f41, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n        \"jamcrc\":      (0x04c1_1db7, 0xffff_ffff, 0x0000_0000, True,  True,   False),\n        \"mef\":         (0x741b_8cd7, 0xffff_ffff, 0x0000_0000, True,  True,   False),\n        \"mpeg2\":       (0x04c1_1db7, 0xffff_ffff, 0x0000_0000, False, False,  False),\n        \"ether\":       (0x04c1_1db7, 0xffff_ffff, 0x0000_0000, False, False,  True),\n        \"xfer\":        (0x0000_00af, 0x0000_0000, 0x0000_0000, False, False,  False),\n        \"koopman\":     (0x741b_8cd7, 0xffff_ffff, 0xffff_ffff, True,  True,   False),\n        \"k\":           (0x741b_8cd7, 0xffff_ffff, 0xffff_ffff, True,  True,   True),\n    }\n\n    def print_preset_dict(self):\n        fmt = \"{:<10s}  {:<10s}  {:<10s}  {:<10s}  {:<10s}  {:5s}  {:6s}  {:5s}\"\n        legend = [\"name\", \"poly\", \"rpoly\", \"init_value\", \"xorout\", \"refin\", \"refout\", \"alias\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for k, v in self.preset_dic.items():\n            if v[5]:\n                alias = \"(alias)\"\n            else:\n                alias = \"\"\n            self.out.append(\"{:10s}  {:#010x}  {:#010x}  {:#010x}  {:#010x}  {!s:5s}  {!s:6s}  {:s}\".format(\n                k or \"''\", v[0], self.reflect32(v[0]), v[1], v[2], v[3], v[4], alias),\n            )\n        return\n\n    def reflect32(self, x):\n        \"\"\"bit reverse.\"\"\"\n        return int(\"{:032b}\".format(x)[::-1], 2) & 0xffff_ffff\n\n    def build_crc(self):\n        \"\"\"Apply preset parameters if requested. Explicit CLI flags override these.\"\"\"\n        poly, init_value, xorout, refin, refout, _ = self.preset_dic[self.args.preset]\n        # override from CLI\n        if self.args.poly is not None:\n            poly = self.args.poly & 0xffff_ffff\n        if self.args.poly_reflected:\n            poly = self.reflect32(poly)\n        rpoly = self.reflect32(poly)\n        if self.args.init_value is not None:\n            init_value = self.args.init_value & 0xffff_ffff\n        if self.args.xorout is not None:\n            xorout = self.args.xorout & 0xffff_ffff\n        if self.args.refin:\n            refin = True\n        if self.args.no_refin:\n            refin = False\n        if self.args.refout:\n            refout = True\n        if self.args.no_refout:\n            refout = False\n        assert refin == refout\n        # build\n        CRC = collections.namedtuple(\"CRC\", [\"poly\", \"rpoly\", \"init_value\", \"xorout\", \"refin\", \"refout\"])\n        self.CRC = CRC(poly, rpoly, init_value, xorout, refin, refout)\n        return\n\n    def build_tables(self):\n        \"\"\"Build forward / reverse table and the inverse index used by backward steps.\"\"\"\n        self.FT = [] # used always\n        self.RT = [] # used when refin == refout == True\n        self.inv_idx = [0] * 256 # used when refin == refout == False\n\n        if not self.CRC.refin and not self.CRC.refout:\n            for i in range(256):\n                fwd = i << 24\n                for _ in range(8):\n                    if fwd & 0x8000_0000:\n                        fwd = ((fwd << 1) ^ self.CRC.poly) & 0xffff_ffff\n                    else:\n                        fwd = (fwd << 1) & 0xffff_ffff\n                self.FT.append(fwd)\n            for i in range(256):\n                self.inv_idx[self.FT[i] & 0xff] = i\n        else:\n            for i in range(256):\n                fwd = i\n                rev = i << 24\n                for _ in range(8):\n                    if fwd & 1:\n                        fwd = ((fwd >> 1) ^ self.CRC.rpoly) & 0xffff_ffff\n                    else:\n                        fwd = (fwd >> 1) & 0xffff_ffff\n                    if (rev >> 31) & 1:\n                        rev = (((rev ^ self.CRC.rpoly) << 1) | 1) & 0xffff_ffff\n                    else:\n                        rev = (rev << 1) & 0xffff_ffff\n                self.FT.append(fwd)\n                self.RT.append(rev)\n        return\n\n    def calc_forward(self, accum, data_bytes):\n        crc = accum\n        if not self.CRC.refin and not self.CRC.refout:\n            for c in data_bytes:\n                idx = ((crc >> 24) ^ c) & 0xff\n                crc = ((crc << 8) & 0xffff_ffff) ^ self.FT[idx]\n        else:\n            for c in data_bytes:\n                idx = (crc ^ c) & 0xff\n                crc = (crc >> 8) ^ self.FT[idx]\n        return crc\n\n    def calc_backward(self, wanted, data_bytes):\n        crc = wanted\n        if not self.CRC.refin and not self.CRC.refout:\n            for c in data_bytes[::-1]:\n                b = self.inv_idx[crc & 0xff]\n                prev_top = b ^ c\n                q = crc ^ self.FT[b]\n                crc = ((q >> 8) & 0xffff_ffff) | ((prev_top & 0xff) << 24)\n        else:\n            for c in data_bytes[::-1]:\n                idx = crc >> 24\n                crc = ((crc << 8) & 0xffff_ffff) ^ self.RT[idx] ^ c\n        return crc\n\n    def calc_crc32(self, msg_bytes):\n        crc = self.CRC.init_value\n        crc = self.calc_forward(crc, msg_bytes)\n        return crc ^ self.CRC.xorout\n\n    def find_bridge(self, init_value, wanted_crc, prefix, suffix):\n        \"\"\"Compute a 4-byte bridge so that CRC(prefix + bridge + suffix) == wanted_crc.\"\"\"\n        # forward state after prefix (raw)\n        fwd_crc = self.calc_forward(init_value, prefix)\n\n        # map external wanted -> raw wanted (invert output formatting)\n        wanted_raw = wanted_crc ^ self.CRC.xorout\n\n        # rewind suffix to get the raw state right before suffix\n        bkd_crc = self.calc_backward(wanted_raw, suffix)\n\n        def state_bytes(x):\n            if not self.CRC.refin and not self.CRC.refout:\n                xs = [(x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, (x >> 0) & 0xff]\n                return xs\n            else:\n                xs = [(x >> 0) & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff]\n                return xs\n\n        # 4-byte exact bridge between fwd_crc and bkd_crc\n        bridge_word = self.calc_backward(bkd_crc, state_bytes(fwd_crc))\n        bridge_bytes = state_bytes(bridge_word)\n\n        # sanity check\n        test_seq = prefix + bridge_bytes + suffix\n        assert self.calc_crc32(test_seq) == wanted_crc\n        return bridge_bytes\n\n    def find_reverse(self, prefix, suffix):\n        \"\"\"Search ASCII-only bridges of length 4..6(+7).\"\"\"\n        self.build_crc()\n        self.build_tables()\n\n        init_value = self.CRC.init_value\n        wanted_crc = self.args.wanted_crc & 0xffff_ffff\n\n        ascii_range = b\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_\"\n        solutions = []\n\n        # 4 bytes\n        bridge = self.find_bridge(init_value, wanted_crc, prefix, suffix)\n        if all(c in ascii_range for c in bridge):\n            solutions.append(bridge)\n        # 5 bytes\n        for b in ascii_range:\n            new_prefix = prefix + [b]\n            bridge = self.find_bridge(init_value, wanted_crc, new_prefix, suffix)\n            if all(c in ascii_range for c in bridge):\n                solutions.append([b] + bridge)\n        # 6 bytes\n        for b1 in ascii_range:\n            for b2 in ascii_range:\n                new_prefix = prefix + [b1, b2]\n                bridge = self.find_bridge(init_value, wanted_crc, new_prefix, suffix)\n                if all(c in ascii_range for c in bridge):\n                    solutions.append([b1, b2] + bridge)\n\n        if solutions:\n            return solutions\n\n        # 7 bytes\n        for b1 in ascii_range:\n            for b2 in ascii_range:\n                for b3 in ascii_range:\n                    new_prefix = prefix + [b1, b2, b3]\n                    bridge = self.find_bridge(init_value, wanted_crc, new_prefix, suffix)\n                    if all(c in ascii_range for c in bridge):\n                        solutions.append([b1, b2, b3] + bridge)\n        return solutions\n\n    @parse_args\n    def do_invoke(self, args):\n        if self.args.list == (self.args.wanted_crc is not None):\n            self.usage()\n            return\n\n        self.out = []\n\n        if self.args.list:\n            self.print_preset_dict()\n            self.print_output(check_terminal_size=True)\n            return\n\n        prefix = [ord(c) for c in self.args.prefix]\n        suffix = [ord(c) for c in self.args.suffix]\n\n        sols = self.find_reverse(prefix, suffix)\n        if sols:\n            for sol in sols:\n                msg = prefix + sol + suffix\n                crc = self.calc_crc32(msg)\n                self.out.append(\"{}: CRC32({}) = {:#010x}\".format(bytes(sol), bytes(msg), crc))\n        else:\n            self.err_add_out(\"No ASCII-only bridge found under given constraints.\")\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass BaseNDecodeCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to decode baseN.\"\"\"\n\n    _cmdline_ = \"base-n-decode\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    baseN = [\n        \"base1\", \"base2\", \"base3\", \"base4\", \"base8\", \"base10\", \"base16\", \"base26\",\n        \"base32\", \"base32-crockford\", \"base32-geohash\", \"base32-hex\", \"base32-z\",\n        \"base36\", \"base45\", \"base58-bitcoin\", \"base58-flickr\", \"base58-ripple\",\n        \"base62\", \"base63\", \"base64\", \"base64-url\", \"base67\", \"base85\",\n        \"base85-adobe\", \"base85-ipv6\", \"base85-xml\", \"base85-xbtoa\", \"base85-zeromq\",\n        \"base91\", \"base100\", \"base122\",\n    ]\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def get_valid_base_decode_funcs(self):\n        import codext\n        for bname in self.baseN:\n            bfunc = lambda x, bname=bname: codext.decode(x, bname)\n            yield (bname, bfunc)\n        return None\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass BaseNDecodeMemoryCommand(BaseNDecodeCommand):\n    \"\"\"Decode baseN from memory values.\"\"\"\n\n    _cmdline_ = \"base-n-decode memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for baseN decoding.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for baseN decoding.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @ModuleLoader.load_codext\n    def do_invoke(self, args):\n        self.out = []\n        self.out.append(\"Address: {:#x}\".format(args.location))\n        self.out.append(\"Size: {:#x}\".format(args.size))\n\n        try:\n            mem = read_memory(args.location, args.size)\n        except (gdb.MemoryError, MemoryError):\n            err(\"Memory read error\")\n            return False\n\n        for bname, bfunc in self.get_valid_base_decode_funcs():\n            try:\n                b = bfunc(mem)\n                self.out.append(\"{:17s}: {!s}\".format(bname, b))\n            except ValueError:\n                self.out.append(\"{:17s}: ERROR\".format(bname))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass BaseNDecodeValueCommand(BaseNDecodeCommand):\n    \"\"\"Decode baseN from specified values.\"\"\"\n\n    _cmdline_ = \"base-n-decode value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for baseN decoding.\")\n    parser.add_argument(\"--hex\", action=\"store_true\", help=\"interpret VALUE as hex. invalid character is ignored.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"\\\\\\\\x51\\\\\\\\x55\\\\\\\\x46\\\\\\\\x42\"',\n        '{0:s} --hex \"51 55 46 42\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        if args.hex: # \"41414141\" -> b\"\\x41\\x41\\x41\\x41\"\n            value = GefUtil.fromhex_ignore_invalid(args.value)\n            if not value:\n                return\n        else:\n            try:\n                value = codecs.escape_decode(args.value)[0]\n            except binascii.Error:\n                err('Could not decode \"\\\\xXX\" encoded string')\n                return\n\n        self.out = []\n        for bname, bfunc in self.get_valid_base_decode_funcs():\n            try:\n                b = bfunc(value)\n                self.out.append(\"{:17s}: {!s}\".format(bname, b))\n            except ValueError:\n                self.out.append(\"{:17s}: ERROR\".format(bname))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass BaseNEncodeCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to encode baseN.\"\"\"\n\n    _cmdline_ = \"base-n-encode\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    baseN = [\n        \"base1\", \"base2\", \"base3\", \"base4\", \"base8\", \"base10\", \"base16\", \"base26\",\n        \"base32\", \"base32-crockford\", \"base32-geohash\", \"base32-hex\", \"base32-z\",\n        \"base36\", \"base45\", \"base58-bitcoin\", \"base58-flickr\", \"base58-ripple\",\n        \"base62\", \"base63\", \"base64\", \"base64-url\", \"base67\", \"base85\",\n        \"base85-adobe\", \"base85-ipv6\", \"base85-xml\", \"base85-xbtoa\", \"base85-zeromq\",\n        \"base91\", \"base100\", \"base122\",\n    ]\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def get_valid_base_encode_funcs(self):\n        import codext\n        for bname in self.baseN:\n            bfunc = lambda x, bname=bname: codext.encode(x, bname)\n            yield (bname, bfunc)\n        return None\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass BaseNEncodeMemoryCommand(BaseNEncodeCommand):\n    \"\"\"Encode baseN from memory values.\"\"\"\n\n    _cmdline_ = \"base-n-encode memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for baseN encoding.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for baseN encoding.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @ModuleLoader.load_codext\n    def do_invoke(self, args):\n        self.out = []\n        self.out.append(\"Address: {:#x}\".format(args.location))\n        self.out.append(\"Size: {:#x}\".format(args.size))\n\n        try:\n            mem = read_memory(args.location, args.size)\n        except (gdb.MemoryError, MemoryError):\n            err(\"Memory read error\")\n            return False\n\n        for bname, bfunc in self.get_valid_base_encode_funcs():\n            if bname == \"base1\":\n                self.out.append(\"{:17s}: Skipped because too long\".format(bname))\n                continue\n            try:\n                b = bfunc(mem)\n                self.out.append(\"{:17s}: {!s}\".format(bname, b))\n            except ValueError:\n                self.out.append(\"{:17s}: ERROR\".format(bname))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass BaseNEncodeValueCommand(BaseNEncodeCommand):\n    \"\"\"Encode baseN from specified values.\"\"\"\n\n    _cmdline_ = \"base-n-encode value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for baseN encoding.\")\n    parser.add_argument(\"--hex\", action=\"store_true\", help=\"interpret VALUE as hex. invalid character is ignored.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x42\\\\\\\\x43\\\\\\\\x44\"',\n        '{0:s} --hex \"41 42 43 44\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        if args.hex: # \"41414141\" -> b\"\\x41\\x41\\x41\\x41\"\n            value = GefUtil.fromhex_ignore_invalid(args.value)\n            if not value:\n                return\n        else:\n            try:\n                value = codecs.escape_decode(args.value)[0]\n            except binascii.Error:\n                err('Could not decode \"\\\\xXX\" encoded string')\n                return\n\n        self.out = []\n        for bname, bfunc in self.get_valid_base_encode_funcs():\n            if bname == \"base1\":\n                self.out.append(\"{:17s}: Skipped because too long\".format(bname))\n                continue\n            try:\n                b = bfunc(value)\n                self.out.append(\"{:17s}: {!s}\".format(bname, b))\n            except ValueError:\n                self.out.append(\"{:17s}: ERROR\".format(bname))\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass MorseDecodeCommand(GenericCommand):\n    \"\"\"The base command to decode morse code.\"\"\"\n\n    _cmdline_ = \"morse-decode\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass MorseDecodeMemoryCommand(MorseDecodeCommand):\n    \"\"\"Decode morse code from memory values.\"\"\"\n\n    _cmdline_ = \"morse-decode memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for morse code decoding.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for morse code decoding.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        gef_print(\"Address: {:#x}\".format(args.location))\n        gef_print(\"Size: {:#x}\".format(args.size))\n\n        try:\n            mem = read_memory(args.location, args.size)\n        except (gdb.MemoryError, MemoryError):\n            err(\"Memory read error\")\n            return False\n\n        decoded = String.morse_decode(mem)\n        gef_print(\"{!s}\".format(decoded))\n        return\n\n\n@register_command\nclass MorseDecodeValueCommand(MorseDecodeCommand):\n    \"\"\"Decode morse code from specified values.\"\"\"\n\n    _cmdline_ = \"morse-decode value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for morse code decoding.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} -- \".- -... -.-. -..\"',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        decoded = String.morse_decode(args.value)\n        gef_print(\"{!s}\".format(decoded))\n        return\n\n\n@register_command\nclass MorseEncodeCommand(GenericCommand):\n    \"\"\"The base command to encode morse code.\"\"\"\n\n    _cmdline_ = \"morse-encode\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"value\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass MorseEncodeMemoryCommand(MorseEncodeCommand):\n    \"\"\"Encode morse code from memory values.\"\"\"\n\n    _cmdline_ = \"morse-encode memory\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address for morse code encoding.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address,\n                        help=\"the size for morse code encoding.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        gef_print(\"Address: {:#x}\".format(args.location))\n        gef_print(\"Size: {:#x}\".format(args.size))\n\n        try:\n            mem = read_memory(args.location, args.size)\n        except (gdb.MemoryError, MemoryError):\n            err(\"Memory read error\")\n            return False\n\n        encoded = String.morse_encode(mem)\n        gef_print(\"{!s}\".format(encoded))\n        return\n\n\n@register_command\nclass MorseEncodeValueCommand(MorseEncodeCommand):\n    \"\"\"Encode morse code from specified values.\"\"\"\n\n    _cmdline_ = \"morse-encode value\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"the string for morse code encoding.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} AAAA',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        encoded = String.morse_encode(args.value)\n        gef_print(\"{!s}\".format(encoded))\n        return\n\n\n@register_command\nclass IsMemoryZeroCommand(GenericCommand):\n    \"\"\"Check if all the memory in the specified range is 0x00, 0xff.\"\"\"\n\n    _cmdline_ = \"is-mem-zero\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\", help=\"treat ADDRESS as a physical address.\")\n    parser.add_argument(\"addr\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"target address for checking.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", type=AddressUtil.parse_address, help=\"the size for checking.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def memcheck(self, phys_mode, addr, size):\n        page_size = get_pagesize()\n        start = addr\n        end = addr + size\n        is_zero = True\n        is_ff = True\n        current = addr\n        while current < end:\n            read_size = min(end - current, page_size)\n            try:\n                if phys_mode:\n                    data = read_physmem(current, read_size)\n                else:\n                    data = read_memory(current, read_size)\n            except (gdb.MemoryError, ValueError, OverflowError):\n                err(\"Read error {:#x}\".format(current))\n                return\n            if data == b\"\\0\" * len(data):\n                is_ff = False\n            elif data == b\"\\xff\" * len(data):\n                is_zero = False\n            else:\n                is_zero = False\n                is_ff = False\n            if is_zero is False and is_ff is False:\n                end = current + read_size\n                break\n            current += read_size\n\n        if is_zero:\n            info(\"{:#x} - {:#x} is {:s}\".format(start, end, Color.colorify(\"All 0x00\", \"bold yellow\")))\n            return\n\n        if is_ff:\n            info(\"{:#x} - {:#x} is {:s}\".format(start, end, Color.colorify(\"All 0xFF\", \"bold yellow\")))\n            return\n\n        # find non-zero address\n        for i, d in enumerate(data):\n            if d != 0:\n                found_addr = ProcessMap.lookup_address(current + i)\n                break\n        else:\n            warn(\"Scan failed to find non-zero byte unexpectedly\")\n            return\n        info(\"{:#x} - {:#x} is {:s}\".format(start, end, Color.colorify(\"NON-ZERO\", \"bold red\")))\n        info(\"Around {!s} is NON-ZERO\".format(found_addr))\n        info(\"Length of 0x00: {:d}\".format(found_addr.value - start))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.size == 0:\n            info(\"The size is zero, maybe wrong\")\n\n        self.memcheck(args.phys, args.addr, args.size)\n        return\n\n\n@register_command\nclass StringLengthCommand(GenericCommand):\n    \"\"\"Detect the length of the string.\"\"\"\n\n    _cmdline_ = \"strlen\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\", help=\"treat ADDRESS as a physical address.\")\n    parser.add_argument(\"addr\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"target address for checking.\")\n    _syntax_ = parser.format_help()\n\n    def check(self, phys_mode, addr):\n        count = 0\n        current = addr\n        while True:\n            # calc read_size\n            if current & get_pagesize_mask_low():\n                read_size = align_to_pagesize(current) - current\n            else:\n                read_size = get_pagesize()\n            # read\n            try:\n                if phys_mode:\n                    data = read_physmem(current, read_size)\n                else:\n                    data = read_memory(current, read_size)\n            except (gdb.MemoryError, ValueError, OverflowError):\n                err(\"Read error {:#x}\".format(addr))\n                return None\n            # count\n            idx = data.find(b\"\\0\")\n            if idx != -1:\n                return count + idx\n            # goto next\n            count += len(data)\n            current += len(data)\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        length = self.check(args.phys, args.addr)\n        if length is None:\n            return\n\n        gef_print(\"{:s} bytes\".format(Color.colorify_hex(length, \"bold\")))\n        return\n\n\n@register_command\nclass SequenceLengthCommand(GenericCommand):\n    \"\"\"Detect consecutive length of the same sequence.\"\"\"\n\n    _cmdline_ = \"seq-length\"\n    _category_ = \"03-e. Memory - Calculation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--phys\", action=\"store_true\", help=\"treat ADDRESS as a physical address.\")\n    parser.add_argument(\"addr\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"target address for checking.\")\n    parser.add_argument(\"unit\", metavar=\"UNIT\", nargs=\"?\", type=AddressUtil.parse_address, default=1,\n                        help=\"the size for a target value (default: %(default)s).\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def check(self, phys_mode, addr, unit):\n        target = None\n        data = b\"\"\n        count = 0\n        current = addr\n        while True:\n            # calc read_size\n            if current & get_pagesize_mask_low():\n                read_size = align_to_pagesize(current) - current\n            else:\n                read_size = get_pagesize()\n            while read_size < unit:\n                read_size += get_pagesize()\n            # read\n            try:\n                if phys_mode:\n                    data += read_physmem(current, read_size)\n                else:\n                    data += read_memory(current, read_size)\n            except (gdb.MemoryError, ValueError, OverflowError):\n                err(\"Read error {:#x}\".format(addr))\n                return None\n            # init target\n            if target is None:\n                target = data[:unit]\n            # count\n            for elem in slicer(data, unit):\n                if elem == target:\n                    # Equal in length and content\n                    count += 1\n                elif len(elem) == len(target):\n                    # The length is sufficient, but the content is different.\n                    return count, target\n            # Consider the case where the length of the final element is insufficient\n            if len(elem) != len(target):\n                data = elem\n            else:\n                data = b\"\"\n            # goto next\n            current += read_size\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.phys:\n            if not is_qemu_system():\n                err(\"Unsupported `--phys` option in this gdb mode\")\n                return\n\n        if args.unit >= 0x100_000:\n            err(\"Too large unit size\")\n            return\n\n        addr = ProcessMap.lookup_address(args.addr)\n        info(\"Check from {!s} in units of {:s} bytes\".format(\n            addr, Color.colorify_hex(args.unit, \"bold\"),\n        ))\n\n        ret = self.check(args.phys, args.addr, args.unit)\n        if ret is None:\n            return\n\n        count, target = ret\n        size = args.unit * count\n        end = ProcessMap.lookup_address(args.addr + size)\n\n        if len(target) > 0x100:\n            target = target[:0x100] + b\"...\"\n\n        gef_print(\"{!s} - {!s} is same value\".format(addr, end))\n        gef_print(\"{!s} is found {:s} times, {:s} bytes\".format(\n            target,\n            Color.colorify_hex(count, \"bold\"),\n            Color.colorify_hex(size, \"bold\"),\n        ))\n        return\n\n\n@register_command\nclass MultiLineCommand(GenericCommand):\n    \"\"\"Execute multiple GDB commands in sequence.\"\"\"\n\n    _cmdline_ = \"multi-line\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n    _aliases_ = [\"ml\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"cmd\", metavar=\"GDB_CMD;\", nargs=\"+\", help=\"semicolon-separated gdb command.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} x/4xg $rax; x/4xg $rbx\",\n        \"{0:s} x/4xg $rax; -; x/4xg $rbx         # `-`:   newline separator\",\n        \"{0:s} x/4xg $rax; --; x/4xg $rbx        # `--`:  bold white line (`-`) separator\",\n        \"{0:s} x/4xg $rax; ---; x/4xg $rbx       # `---`: bold white line (`=`) separator\",\n        \"{0:s} x/4xg $rax; -t TAG; x/4xg $rbx    # `-t TAG`:   newline separator with TAG\",\n        \"{0:s} x/4xg $rax; --t TAG; x/4xg $rbx   # `--t TAG`:  bold white line (`-`) separator with TAG\",\n        \"{0:s} x/4xg $rax; ---t TAG; x/4xg $rbx  # `---t TAG`: bold white line (`=`) separator with TAG\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_COMMAND)\n        return\n\n    def do_command(self, commands):\n        if commands == []:\n            return True\n\n        # make comnand string\n        cmd = \"\"\n        for c in commands:\n            if \"\\\\\" in c or \" \" in c:\n                cmd += \" \" + repr(c)\n            else:\n                cmd += \" \" + c\n        cmd = cmd.strip()\n\n        # blank command, so skip\n        if cmd.replace(\" \", \"\") == \"\":\n            return True\n\n        # separator 1\n        if cmd == \"-\":\n            gef_print(\"\")\n            return True\n        if cmd.startswith(\"-t\"):\n            gef_print(Color.boldify(cmd[2:].strip()))\n            return True\n\n        # separator 2\n        if cmd == \"--\":\n            gef_print(titlify(\"\", color=\"bold\"))\n            return True\n        if cmd.startswith(\"--t\"):\n            gef_print(titlify(cmd[3:].strip(), color=\"bold\", msg_color=\"bold\"))\n            return True\n\n        # separator 3\n        if cmd == \"---\":\n            gef_print(titlify(\"\", color=\"bold\", horizontal_line=\"=\"))\n            return True\n        if cmd.startswith(\"---t\"):\n            gef_print(titlify(cmd[4:].strip(), color=\"bold\", msg_color=\"bold\", horizontal_line=\"=\"))\n            return True\n\n        gef_print(titlify(cmd))\n        try:\n            gdb.execute(cmd)\n        except gdb.error as e:\n            gef_print(e)\n            return False # fail\n        return True\n\n    # Need not @parse_args because argparse can't stop interpreting options for user specified command.\n    def do_invoke(self, argv):\n        if len(argv) == 1 and argv[0] == \"-h\":\n            self.usage()\n            return\n\n        commands = []\n        for arg in argv:\n            if arg.endswith(\";\"):\n                commands.append(arg.rstrip(\";\").lstrip(\";\"))\n                if self.do_command(commands) is False:\n                    break\n                commands = []\n            elif arg.startswith(\";\"):\n                if self.do_command(commands) is False:\n                    break\n                commands = []\n                commands.append(arg.lstrip(\";\"))\n            elif arg == \";\":\n                if self.do_command(commands) is False:\n                    break\n                commands = []\n            else:\n                commands.append(arg)\n        else:\n            self.do_command(commands)\n        return\n\n\n@register_command\nclass TimeCommand(GenericCommand):\n    \"\"\"Measure the time of the GDB command.\"\"\"\n\n    _cmdline_ = \"time\"\n    _category_ = \"01-c. Debugging Support - Basic Command Extension\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"cmd\", metavar=\"GDB_CMD\", help=\"gdb command.\")\n    parser.add_argument(\"arg\", metavar=\"ARG\", nargs=\"*\", help=\"arguments of gdb command.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_COMMAND)\n        return\n\n    # Need not @parse_args because argparse can't stop interpreting options for user specified command.\n    def do_invoke(self, argv):\n        if len(argv) == 1 and argv[0] == \"-h\":\n            self.usage()\n            return\n\n        start_time_real = time.perf_counter()\n        start_time_proc = time.process_time()\n\n        cmd = \"\"\n        for c in argv:\n            if \"\\\\\" in c or \" \" in c:\n                cmd += \" \" + repr(c)\n            else:\n                cmd += \" \" + c\n        cmd = cmd.strip()\n\n        gef_print(titlify(cmd))\n        try:\n            gdb.execute(cmd)\n        except gdb.error:\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            gef_print(exc_value)\n            return\n\n        end_time_real = time.perf_counter()\n        end_time_proc = time.process_time()\n        gef_print(titlify(\"time elapsed\"))\n        gef_print(\"Real: {:.3f} s\".format(end_time_real - start_time_real))\n        gef_print(\"CPU:  {:.3f} s\".format(end_time_proc - start_time_proc))\n        return\n\n\n@register_command\nclass SaveOutputCommand(GenericCommand):\n    \"\"\"Save the command outputs.\"\"\"\n\n    _cmdline_ = \"saveo\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"cmd\", metavar=\"GDB_CMD\", help=\"gdb command.\")\n    parser.add_argument(\"arg\", metavar=\"ARG\", nargs=\"*\", help=\"arguments of gdb command.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Saving the output of external commands is unsupported (e.g., pipe, !ls).\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_COMMAND)\n        return\n\n    # Need not @parse_args because argparse can't stop interpreting options for user specified command.\n    def do_invoke(self, argv):\n        if len(argv) == 1 and argv[0] == \"-h\":\n            self.usage()\n            return\n\n        # get settings\n        always_no_pager = Config.get_gef_setting(\"gef.always_no_pager\")\n\n        # parse command\n        cmd = \"\"\n        for c in argv:\n            if \"\\\\\" in c or \" \" in c:\n                cmd += \" \" + repr(c)\n            else:\n                cmd += \" \" + c\n        cmd = cmd.strip()\n        if not cmd:\n            self.usage()\n            return\n\n        # do the command\n        try:\n            Config.set_gef_setting(\"gef.always_no_pager\", True) # change temporarily\n            current_output = Color.remove_color(gdb.execute(cmd, to_string=True))\n            Config.set_gef_setting(\"gef.always_no_pager\", always_no_pager) # revert settings\n        except gdb.error:\n            Config.set_gef_setting(\"gef.always_no_pager\", always_no_pager) # revert settings\n            exc_type, exc_value, exc_traceback = sys.exc_info()\n            gef_print(exc_value)\n            return\n\n        # remove clear_screen code\n        if current_output.startswith(\"\\x1b[H\\x1b[2J\"):\n            current_output = current_output[7:]\n\n        # save\n        dloc = os.path.join(GEF_TEMP_DIR, \"diff\")\n        if not os.path.exists(dloc):\n            os.mkdir(dloc)\n        tmp_fd, tmp_path = GefUtil.mkstemp(dir=dloc, suffix=\".txt\")\n        os.fdopen(tmp_fd, \"w\").write(current_output)\n        open(tmp_path[:-4] + \".cmd\", \"w\").write(cmd)\n        info(\"The output is saved to {:s}.(txt|cmd)\".format(tmp_path[:-4]))\n\n        # print\n        gef_print(current_output, less=not always_no_pager)\n        return\n\n\n@register_command\nclass DiffOutputCommand(GenericCommand):\n    \"\"\"The base command to diff of the command outputs.\"\"\"\n\n    _cmdline_ = \"diffo\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"colordiff\")\n    subparsers.add_parser(\"git-diff\")\n    subparsers.add_parser(\"list\")\n    subparsers.add_parser(\"clear\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        self.add_setting(\"colordiff_option\", \"--left-column -y -W 200\", \"The option used by colordiff.\")\n        return\n\n    def get_saved_files(self):\n        dloc = os.path.join(GEF_TEMP_DIR, \"diff\")\n        if not os.path.exists(dloc):\n            return []\n\n        saved_files = []\n        for path in GefUtil.walk(dloc):\n            if not path.endswith(\".txt\"):\n                continue\n            saved_files.append(path)\n\n        return sorted(saved_files, key=lambda x:os.path.getmtime(x[:-4] + \".cmd\"))\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass DiffOutputColordiffCommand(DiffOutputCommand):\n    \"\"\"Diff the two outputs by colordiff.\"\"\"\n\n    _cmdline_ = \"diffo colordiff\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"n1\", metavar=\"N\", type=int, help=\"first diff target got from `diffo list`.\")\n    parser.add_argument(\"n2\", metavar=\"M\", type=int, help=\"second diff target got from `diffo list`.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0 1  # diff between 0 and 1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"You can check the available indexes with `diffo list`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def make_diff(self, path1, path2):\n        option = Config.get_gef_setting(\"diffo.colordiff_option\")\n        cmd = \"{:s} {:s} '{:s}' '{:s}'\".format(self.colordiff, option, path1, path2)\n        result = subprocess.getoutput(cmd)\n        return result\n\n    @parse_args\n    def do_invoke(self, args):\n        try:\n            self.colordiff = GefUtil.which(\"colordiff\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        saved_files = self.get_saved_files()\n        try:\n            f1 = saved_files[args.n1]\n            f2 = saved_files[args.n2]\n        except IndexError:\n            err(\"Out of index error\")\n            return\n\n        if not os.path.exists(f1):\n            err(\"Could not find {:s}\".format(f1))\n            return\n        if not os.path.exists(f2):\n            err(\"Could not find {:s}\".format(f2))\n            return\n\n        output = self.make_diff(f1, f2)\n\n        if output:\n            gef_print(output, less=not args.no_pager)\n        else:\n            gef_print(\"No difference\")\n        return\n\n\n@register_command\nclass DiffOutputGitDiffCommand(DiffOutputCommand):\n    \"\"\"Diff the two outputs by git.\"\"\"\n\n    _cmdline_ = \"diffo git-diff\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"n1\", metavar=\"N\", type=int, help=\"first diff target got from `diffo list`.\")\n    parser.add_argument(\"n2\", metavar=\"M\", type=int, help=\"second diff target got from `diffo list`.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0 1  # diff between 0 and 1\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"You can check the available indexes with `diffo list`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def make_diff(self, path1, path2):\n        cmd = \"{:s} diff --color=always '{:s}' '{:s}'\".format(self.git, path1, path2)\n        result = subprocess.getoutput(cmd)\n        return result\n\n    @parse_args\n    def do_invoke(self, args):\n        try:\n            self.git = GefUtil.which(\"git\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        saved_files = self.get_saved_files()\n        try:\n            f1 = saved_files[args.n1]\n            f2 = saved_files[args.n2]\n        except IndexError:\n            err(\"Out of index error\")\n            return\n\n        if not os.path.exists(f1):\n            err(\"Could not find {:s}\".format(f1))\n            return\n        if not os.path.exists(f2):\n            err(\"Could not find {:s}\".format(f2))\n            return\n\n        output = self.make_diff(f1, f2)\n\n        if output:\n            gef_print(output, less=not args.no_pager)\n        else:\n            gef_print(\"No difference\")\n        return\n\n\n@register_command\nclass DiffOutputListCommand(DiffOutputCommand):\n    \"\"\"List saved outputs.\"\"\"\n\n    _cmdline_ = \"diffo list\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        file_list = self.get_saved_files()\n        max_path = max([len(fname) for fname in file_list] + [40])\n\n        fmt = \"{:<3s}  {:26s}  {:{:d}s}  {:<7s}  {:s}\"\n        legend = [\"#\", \"mtime\", \"path\", max_path, \"size\", \"command\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        for idx, path in enumerate(file_list):\n            data = open(path, \"rb\").read()\n            size = len(data)\n            mtime = datetime.datetime.fromtimestamp(os.path.getmtime(path))\n            cmd = open(path[:-4] + \".cmd\", \"rb\").read()\n            cmd = String.bytes2str(cmd)\n            gef_print(\"{:<3d}  {}  {:{:d}s}  {:<7d}  {:s}\".format(idx, mtime, path, max_path, size, cmd))\n        return\n\n\n@register_command\nclass DiffOutputClearCommand(DiffOutputCommand):\n    \"\"\"Clear all saved outputs.\"\"\"\n\n    _cmdline_ = \"diffo clear\"\n    _category_ = \"07-f. Misc - Diff\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"n\", metavar=\"N\", type=int, nargs=\"*\", help=\"index to be deleted.\")\n    parser.add_argument(\"--all\", action=\"store_true\", help=\"delete everything.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.all:\n            for path in self.get_saved_files():\n                os.unlink(path)\n                os.unlink(path[:-4] + \".cmd\")\n        elif args.n:\n            for i, path in enumerate(self.get_saved_files()):\n                if i in args.n:\n                    os.unlink(path)\n                    os.unlink(path[:-4] + \".cmd\")\n        else:\n            self.usage()\n            return\n\n        info(\"Removed\")\n        return\n\n\n@register_command\nclass IiCommand(GenericCommand):\n    \"\"\"Shortcut `x/50i $pc` with opcode bytes.\"\"\"\n\n    _cmdline_ = \"ii\"\n    _category_ = \"01-e. Debugging Support - Assemble\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the dump start address.\")\n    parser.add_argument(\"-l\", \"--length\", type=AddressUtil.parse_address, default=50,\n                        help=\"the dump instruction length.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def ii(self, addr, N):\n        try:\n            res = read_memory(addr, N)\n        except gdb.MemoryError:\n            err(\"Memory read error\")\n            return\n\n        if N >= 50 and res[0:1] * N == res:\n            info(\"all targeted area is {:#04x}\".format(res[0]))\n            return\n\n        # get instruction size\n        try:\n            res = gdb.execute(\"x/{:d}i {:#x}\".format(N + 1, addr), to_string=True)\n        except gdb.MemoryError:\n            err(\"Memory read error\")\n            return\n        addrs = []\n        for line in res.splitlines():\n            # [x64]\n            # \"=> 0x55555555aac0:      endbr64\"\n            # \"   0x55555555aac4:      xor    ebp,ebp\"\n            # [arm]\n            # \"=> 0x10340 <_start>:    mov.w   r11, #0\"\n            # \"   0x10344 <_start+4>:  mov.w   lr, #0\"\n            r = re.search(\"^(?:=>|  ) (0x[0-9a-f]+)\", line)\n            if r:\n                addrs.append(int(r.group(1), 16))\n        insn_sizes = [(x, y - x) for x, y in zip(addrs[:-1], addrs[1:])]\n        max_insn_width = max(x[1] for x in insn_sizes) * 2\n\n        # print\n        for i, line in enumerate(res.splitlines()[:-1]):\n            addr, size = insn_sizes[i]\n            bytecode = read_memory(addr, size)\n            bytecode_hex = \"{:{:d}s}\".format(bytecode.hex(), max_insn_width)\n\n            line = line.rstrip()\n            line = line.expandtabs(8)\n\n            # get position to split\n            # [x64]\n            # \"0x55555555aac0:      endbr64\"\n            # \"0x55555555aac4:      xor    ebp,ebp\"\n            #                ^\n            # [arm]\n            # \"0x10340 <_start>:    mov.w   r11, #0\"\n            # \"0x10344 <_start+4>:  mov.w   lr, #0\"\n            #         ^\n            # Since it depends on the presence or absence of symbols, it must be calculated line by line each time.\n            pos = None\n            r = re.search(\"[: ]\", line[3:])\n            if r:\n                pos = 3 + r.span()[0]\n\n            if pos is None:\n                # somethinig is wrong\n                gef_print(line)\n            else:\n                gef_print(line[:pos] + \": \" + bytecode_hex + \" \" + line[pos:])\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.location is None:\n            location = current_arch.pc\n        else:\n            location = args.location\n\n        self.ii(location, args.length)\n        return\n\n\n@register_command\nclass ConstGrepCommand(GenericCommand):\n    \"\"\"Grep for lines with #define in files under /usr/include.\"\"\"\n\n    _cmdline_ = \"constgrep\"\n    _category_ = \"07-b. Misc - Search\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"pattern\", metavar=\"GREP_PATTERN\", help=\"filter by regex.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} '__NR_*'\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def read_normalize(self, path):\n        try:\n            content = open(path, \"rb\").read()\n        except (FileNotFoundError, IsADirectoryError):\n            return None\n        content = content.replace(b\"\\\\\\n\", b\"GEF_MARKER\")\n        content = content.replace(b\"\\t\", b\" \")\n        for i in range(0x80, 0x100):\n            content = content.replace(bytes([i]), b\"\")\n        try:\n            content = content.decode(\"UTF-8\")\n        except UnicodeDecodeError:\n            err(\"Decode error: \" + path)\n            return None\n        return content\n\n    @parse_args\n    def do_invoke(self, args):\n        srcdir = \"/usr/include\"\n        pattern = re.compile(r\"^#define\\s+\\S*\" + args.pattern)\n        for path in GefUtil.walk(srcdir):\n            content = self.read_normalize(path)\n            if content is None:\n                continue\n            for line in content.splitlines():\n                if pattern.search(line):\n                    line = line.replace(\"GEF_MARKER\", \"\\\\\\n\")\n                    gef_print(\"{:s}: {:s}\".format(Color.redify(path), line))\n        return\n\n\n@register_command\nclass SlubDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump SLUB free-list.\"\"\"\n\n    _cmdline_ = \"slub-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-hs\", \"--help-for-slab-virtual\", action=\"store_true\",\n                        help=\"show ASCII diagram for CONFIG_SLAB_VIRTUAL=y.\")\n    parser.add_argument(\"cache_name\", metavar=\"SLUB_CACHE_NAME\", nargs=\"*\",\n                        help=\"filter by specific slub cache name.\")\n    parser.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"list all slub cache names.\")\n    parser.add_argument(\"-L\", \"--list-no-sort\", action=\"store_true\", help=\"list all slub cache names without sort.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"--cpu\", type=int, help=\"filter by specific cpu.\")\n    parser.add_argument(\"-R\", \"--reverse-walk\", action=\"store_true\", help=\"reverse order walk for slab_caches->list_head.\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"skip displaying layout and freelist.\")\n    parser.add_argument(\"-v\", \"--verbose\", \"--partial\", action=\"store_true\", help=\"dump with partial pages.\")\n    parser.add_argument(\"-vv\", \"--vverbose\", \"--node\", action=\"store_true\", help=\"dump with partial pages and node pages.\")\n    group = parser.add_mutually_exclusive_group(required=False)\n    group.add_argument(\"--only-partial\", action=\"store_true\", help=\"dump only partial pages.\")\n    group.add_argument(\"--only-node\", action=\"store_true\", help=\"dump only node pages.\")\n    parser.add_argument(\"--skip-sheaf\", action=\"store_true\", help=\"skip to dump sheaf (6.18~).\")\n    parser.add_argument(\"--hexdump-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--hexdump-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"--slub-debug-y\", action=\"store_true\",\n                        help=\"assumes `CONFIG_SLUB_DEBUG=y` and dumps kmem_cache_cpu->full slabs.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cached offset.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    parser.add_argument(\"--tlbflush-queue\", action=\"store_true\",\n                        help=\"dump `slub_tlbflush_queue` (x86-64 only && CONFIG_SLAB_VIRTUAL=y).\")\n    parser.add_argument(\"--skip-page2virt\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] used internally in gef, please don't use it.\")\n    parser.add_argument(\"--no-xor\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] skip xor to chunk->next when `kmem_cache.random` is falsely detected.\")\n    parser.add_argument(\"--no-byte-swap\", action=\"store_true\", default=None,\n                        help=\"[FOR DEVELOPER] skip byteswap to chunk->next when `kmem_cache.random` is falsely detected.\")\n    parser.add_argument(\"--offset-random\", type=AddressUtil.parse_address,\n                        help=\"[FOR DEVELOPER] user-specified offsetof(kmem_cache, random) when `kmem_cache.random` is falsely detected.\")\n    parser.add_argument(\"--offset-node\", type=AddressUtil.parse_address,\n                        help=\"[FOR DEVELOPER] user-specified offsetof(kmem_cache, node) when `kmem_cache.node` is falsely detected.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} kmalloc-256             # dump kmalloc-256 from all cpus\",\n        \"{0:s} kmalloc-256 --cpu 1     # dump kmalloc-256 from cpu 1\",\n        \"{0:s} kmalloc-256 --partial   # show active pages and partial pages\",\n        \"{0:s} kmalloc-256 --node      # show active pages, partial pages and node pages\",\n        \"{0:s} --list                  # list slub cache names\",\n        \"{0:s} -vv --offset-node 0xc8  # user specified offsetof(kmem_cache, node)\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified SLUB structure:\",\n        \"\",\n        \"                         +-kmem_cache----------+         +-kmem_cache--+   +-kmem_cache--+\",\n        \"                         | cpu_slab            |---+     | cpu_slab    |   | cpu_slab    |\",\n        \"                         | cpu_sheaves (6.18~) |---|-+   | cpu_sheaves |   | cpu_sheaves |\",\n        \"                         | flags               |   | |   | flags       |   | flags       |\",\n        \"                         | size                |   | |   | size        |   | size        |\",\n        \"                         | object_size         |   | |   | object_size |   | object_size |\",\n        \"                         | offset              |   | |   | offset      |   | offset      |\",\n        \"       +-slab_caches-+   | name                |   | |   | name        |   | name        |\",\n        \" ...<->| list_head   |<->| list_head           |<------->| list_head   |<->| list_head   |<-> ...\",\n        \"       +-------------+   | random              |   | |   | random      |   | random      |\",\n        \"                         | node[]              |-+ | |   | node[]      |   | node[]      |\",\n        \"                         +---------------------+ | | |   +-------------+   +-------------+\",\n        \"                                                 | | |\",\n        \"                                                 | | |     [sheaf/barn (the fastest path)]\",\n        \"    +--------------------------------------------+ | |                     +-->+-slab_sheaf-+\",\n        \"    |   +------------------------------------------+ |                     |   | barn_list  |\",\n        \"    |   |                               +------------+                     |   | size       |\",\n        \"    |   |     +-__per_cpu_offset-+      |                                  |   | objects[]  |\",\n        \"    |   +-----| cpu0_offset      |------+------->+-slub_percpu_sheaves-+   |   |  ptr       |->chunk\",\n        \"    |   |     | cpu1_offset      |               | main                |---+   |  ptr       |->chunk\",\n        \"    |   |     | cpu2_offset      |               | spare               |-->... |  ...       |\",\n        \"    |   |     | ...              |               +---------------------+       +------------+\",\n        \"    |   |     +------------------+\",\n        \"    |   |                                                  [active page freelist (fast path)]\",\n        \"    |   |                                                    +-chunk---+  +-chunk---+\",\n        \"    |   |                                                    | ^       |  | ^       |\",\n        \"    |   |                                                    | |offset |  | |offset |\",\n        \"    |   |                                                    | v       |  | v       |\",\n        \"    |   |                  +-------------------------------->| next    |->| next    |->NULL\",\n        \"    |   v                  |                                 +---------+  +---------+\",\n        \"    |  +-kmem_cache_cpu-+  |\",\n        \"    |  | freelist       |--+                               [active page freelist (slow path)]\",\n        \"    |  | page/slab      |---->+-page/slab(active)--+         +-chunk---+  +-chunk---+\",\n        \"    |  | partial        |--+  | freelist           |----+    | ^       |  | ^       |\",\n        \"    |  +----------------+  |  |                    |    |    | |offset |  | |offset |\",\n        \"    |                      |  +------------------ -+    |    | v       |  | v       |\",\n        \"    |                      |                            +--->| next    |->| next    |->NULL\",\n        \"    |                      |                                 +---------+  +---------+\",\n        \"    |                      |\",\n        \"    |                      |                               [partial page freelist]\",\n        \"    |                      +->+-page/slab(partial)-+         +-chunk---+  +-chunk---+\",\n        \"    |                         | freelist           |----+    | ^       |  | ^       |\",\n        \"    |                         | next               |--+ |    | |offset |  | |offset |\",\n        \"    |                         +--------------------+  | |    | v       |  | v       |\",\n        \"    |                                                 | +--->| next    |->| next    |->NULL\",\n        \"    |                           +---------------------+      +---------+  +---------+\",\n        \"    |                           |\",\n        \"    |                           v                          [partial page freelist]\",\n        \"    |                         +-page/slab(partial)-+         +-chunk---+  +-chunk---+\",\n        \"    |                         | freelist           |----+    | ^       |  | ^       |\",\n        \"    |                         | next               |--+ |    | |offset |  | |offset |\",\n        \"    |                         +--------------------+  | |    | v       |  | v       |\",\n        \"    |                                                 | +--->| next    |->| next    |->NULL\",\n        \"    |                           +---------------------+      +---------+  +---------+\",\n        \"    |                           |\",\n        \"    |                           v\",\n        \"    +--+                       ...\",\n        \"       |                                                    [numa node partial page freelist]\",\n        \"       v                      +-page/slab(numa-node)+         +-chunk---+  +-chunk---+\",\n        \"      +-kmem_cache_node-+     | freelist            |----+    | ^       |  | ^       |\",\n        \"      | partial         |---->| next                |--+ |    | |offset |  | |offset |\",\n        \"      | (full)          |     +---------------------+  | |    | v       |  | v       |\",\n        \"  +---| barn (6.18~)    |                              | +--->| next    |->| next    |->NULL\",\n        \"  |   +-----------------+  +---------------------------+      +---------+  +---------+\",\n        \"  |   | ...             |  |\",\n        \"  |   |                 |  |                                [numa node partial page freelist]\",\n        \"  |   +-----------------+  |  +-page/slab(numa-node)+         +-chunk---+  +-chunk---+\",\n        \"  |                        |  | freelist            |----+    | ^       |  | ^       |\",\n        \"  |                        +->| next                |--+ |    | |offset |  | |offset |\",\n        \"  |                           +---------------------+  | |    | v       |  | v       |\",\n        \"  |                                                    | +--->| next    |->| next    |->NULL\",\n        \"  |                        +---------------------------+      +---------+  +---------+\",\n        \"  |                        |\",\n        \"  +----+                   v\",\n        \"       |                  ...\",\n        \"       v\",\n        \"      +-node_barn-----+         +-slab_sheaf-+    +-slab_sheaf-+\",\n        \"      | sheaves_full  |<------->| barn_list  |<-->| barn_list  |<-->\",\n        \"      | sheaves_empty |<-->...  | ...        |    | ...        |\",\n        \"      +---------------+         +------------+    +------------+\",\n        \"\",\n        \"* `struct page` has been split into `struct page` and `struct slab` since kernel 5.17.\",\n        \"  The structure name used for SLUB has been changed to `struct slab`.\",\n        \"* If all chunks in certain page (or slab) are in use, they will not be displayed by this command.\",\n        \"  This is because they cannot be reached by parsing from `slab_caches`.\",\n        \"  So use `slab-contains` (if you know the address) or `kvmmap` (if you want to see all slabs even if it takes time).\",\n        \"* `slab_sheaf`/`barn` introduced in 6.18 is not used by default, but used by setting it when calling `kmem_cache_create`.\",\n        \"  `slab_sheaf.objects[]` is a stack that grows downwards and caches freed addresses.\",\n        \"  The top of the stack is represented by `slab_sheaf.size`.\",\n        \"* To see the CONFIG_SLAB_VIRTUAL ASCII diagram, execute `slub-dump --help-for-slab-virtual`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    _note2_ = [\n        \"* A mitigation called CONFIG_SLAB_VIRTUAL was proposed in September 2023 to prevent cross-cache attacks.\",\n        \"  This config is not merged into mainline as of May 2025, but is used in KernelCTF@Google Security Research.\",\n        \"* A unique feature of CONFIG_SLAB_VIRTUAL is that in addition to the existing SLUB structure,\",\n        \"  it also has a structure for managing released slab structures.\",\n        \"\",\n        \"Structures in `CONFIG_SLAB_VIRTUAL=y`\",\n        \"- v6.1-based, v6.12-based\",\n        \"                                 +---slab----------+    +---slab----------+   +---slab----------+\",\n        \"       (Temporary Lists)         | backing_folio   |    | backing_folio   |   | backing_folio   |\",\n        \"       +-slub_tlbflush_queue-+   | oo              |    | oo              |   | oo              |\",\n        \" ...<->| list_head           |<->| flush_list_elem |<-->| flush_list_elem |<->| flush_list_elem |<->...\",\n        \"       +---------------------+   | slab_list       |    | slab_list       |   | slab_list       |\",\n        \"                                 | slab_cache      |-+  | slab_cache      |   | slab_cache      |\",\n        \"                                 | ...             | |  | ...             |   | ...             |\",\n        \"                                 +-----------------+ |  +-----------------+   +-----------------+\",\n        \"                                                     |\",\n        \"                             +-----------------------+\",\n        \"                             |\",\n        \"                             v\",\n        \"                         +---kmem_cache-------+             +---kmem_cache-------+\",\n        \"                         | cpu_slab           |----+        | cpu_slab           |\",\n        \"                         | flags              |    |        | flags              |\",\n        \"                         | size               |    |        | size               |\",\n        \"                         | object_size        |    |        | object_size        |\",\n        \"                         | offset             |    |        | offset             |\",\n        \"                         | min                |    |        | min                |\",\n        \"                         | oo                 |    |        | oo                 |\",\n        \"                         | freed_slabs_normal |<---------+  | freed_slabs_normal |\",\n        \"                         | freed_slabs_min    |<------+  |  | freed_slabs_min    |\",\n        \"       +-slab_caches-+   | name               |    |  |  |  | name               |\",\n        \" ...<->| list_head   |<->| list_head          |<------|--|->| list_head          |<->...\",\n        \"       +-------------+   | random             |    |  |  |  | random             |\",\n        \"                         | node[]             |-+  |  |  |  | node[]             |\",\n        \"                         +--------------------+ |  |  |  |  +--------------------+\",\n        \"                                                |  |  |  |\",\n        \"    +-------------------------------------------+  |  |  |   +---slab----+   +---slab----+\",\n        \"    |                                              |  |  |   | ...       |   | ...       |\",\n        \"    |    +-----------------------------------------+  |  |   | oo        |   | oo        |\",\n        \"    |    |                                            |  +-->| slab_list |<->| slab_list |<->...\",\n        \"    |    |     +-__per_cpu_offset-+                   |      | ...       |   | ...       |\",\n        \"    |    +-----| ...              |                   |      +-----------+   +-----------+\",\n        \"    |    |     +------------------+                   |\",\n        \"    |    v                                            |      +---slab----+   +---slab----+\",\n        \"    |    +-kmem_cache_cpu-+                           |      | ...       |   | ...       |\",\n        \"    |    | ...            |                           |      | oo        |   | oo        |\",\n        \"    |    +----------------+                           +----->| slab_list |<->| slab_list |<->...\",\n        \"    v                                                        | ...       |   | ...       |\",\n        \"    +-kmem_cache_node-+                                      +-----------+   +-----------+\",\n        \"    | ...             |\",\n        \"    +-----------------+\",\n        \"\",\n        \"\",\n        \"- v6.6-based\",\n        \"                                 +-virtual_slab-+     +-virtual_slab-+   +-virtual_slab-+\",\n        \"       (Temporary Lists)         | ...          |     | ...          |   | ...          |\",\n        \"       +-slub_tlbflush_queue-+   | slab_cache   |--+  | slab_cache   |   | slab_cache   |\",\n        \" ...<->| list_head           |<->| slab_list    |<-|->| slab_list    |<->| slab_list    |<->...\",\n        \"       +---------------------+   | oo           |  |  | oo           |   | oo           |\",\n        \"                                 | ...          |  |  | ...          |   | ...          |\",\n        \"                                 +--------------+  |  +--------------+   +--------------+\",\n        \"                                                   |\",\n        \"                             +---------------------+\",\n        \"                             |\",\n        \"                             v\",\n        \"                         +-kmem_cache------+             +-kmem_cache------+\",\n        \"                         | cpu_slab        |----+        | cpu_slab        |\",\n        \"                         | flags           |    |        | flags           |\",\n        \"                         | size            |    |        | size            |\",\n        \"                         | object_size     |    |        | object_size     |\",\n        \"                         | offset          |    |        | offset          |\",\n        \"                         | oo              |    |        | oo              |\",\n        \"                         | min             |    |        | min             |\",\n        \"                         | freed_slabs     |<---------+  | freed_slabs     |\",\n        \"                         | freed_slabs_min |<------+  |  | freed_slabs_min |\",\n        \"                         | nr_freed_pages  |    |  |  |  | nr_freed_pages  |\",\n        \"       +-slab_caches-+   | name            |    |  |  |  | name            |\",\n        \" ...<->| list_head   |<->| list_head       |<------|--|->| list_head       |<->...\",\n        \"       +-------------+   | random          |    |  |  |  | random          |\",\n        \"                         | node[]          |-+  |  |  |  | node[]          |\",\n        \"                         +-----------------+ |  |  |  |  +-----------------+\",\n        \"                                             |  |  |  |\",\n        \"    +----------------------------------------+  |  |  |   +-virtual_slab-+   +-virtual_slab-+\",\n        \"    |                                           |  |  |   | ...          |   | ...          |\",\n        \"    |    +--------------------------------------+  |  +-->| slab_list    |<->| slab_list    |<->...\",\n        \"    |    |                                         |      | oo           |   | oo           |\",\n        \"    |    |     +-__per_cpu_offset-+                |      | ...          |   | ...          |\",\n        \"    |    +-----| ...              |                |      +--------------+   +--------------+\",\n        \"    |    |     +------------------+                |\",\n        \"    |    v                                         |      +-virtual_slab-+   +-virtual_slab-+\",\n        \"    |    +-kmem_cache_cpu-+                        |      | ...          |   | ...          |\",\n        \"    |    | ...            |                        +----->| slab_list    |<->| slab_list    |<->...\",\n        \"    |    +----------------+                               | oo           |   | oo           |\",\n        \"    v                                                     | ...          |   | ...          |\",\n        \"    +-kmem_cache_node-+                                   +--------------+   +--------------+\",\n        \"    | ...             |\",\n        \"    +-----------------+\",\n        \"\",\n        \"* The freed slab structure is initially connected to `slub_tlbflush_queue`.\",\n        \"  It is then reconnected to kmem_cache->freed_slabs_normal or freed_slabs_min or freed_slabs.\",\n        \"* If oo_order(virtual_slab->slab.oo) == oo_order(kmem_cache->min),\",\n        \"  `slub_tlbflush_worker` uses `kmem_cache->freed_slabs_min` as freelist of pages for the `kmem_cache`.\",\n        \"  Otherwise, it uses `kmem_cache->freed_slabs`.\",\n    ]\n    _note2_ = \"\\n\".join(_note2_)\n\n    @Cache.cache_until_next\n    def parse_kmem_caches_for_initialize(self):\n        seen = [self.slab_caches]\n        current = self.slab_caches\n        while True:\n            current = read_int_from_memory(current)\n            if current in seen:\n                break\n            seen.append(current)\n        kmem_caches = seen[1:] # skip slab_caches itself\n        return kmem_caches\n\n    def resolve_kmem_cache_offset_list(self):\n        \"\"\"\n        struct kmem_cache {\n            struct kmem_cache_cpu *cpu_slab;         // In fact, the offset value, not the pointer\n            struct lock_class_key {                            // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                union {                                        // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                    struct hlist_node hash_entry;              // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                    struct lockdep_subclass_key {              // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                        char __one_byte;                       // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                    } __attribute__ ((__packed__)) subkeys[8]; // CONFIG_LOCKDEP=y && 6.18 <= kernel\n                };                                             // CONFIG_LOCKDEP=y && 6.18 <= kernel\n            } lock_key;                                        // CONFIG_LOCKDEP=y && 6.18 <= kernel\n            struct slub_percpu_sheaves __percpu *cpu_sheaves;  // 6.18 <= kernel\n            slab_flags_t flags;                      // unsigned int (+ padding 4 byte)\n            unsigned long min_partial;\n            unsigned int size;\n            unsigned int object_size;\n            struct reciprocal_value {                //\n                u32 m;                               //\n                u8 sh1, sh2;                         // (+ padding 2 byte)\n            } reciprocal_size;                       // if 5.9 <= kernel\n            unsigned int offset;\n            unsigned int cpu_partial;                // if CONFIG_SLUB_CPU_PARTIAL=y\n            unsigned int cpu_partial_slabs;          // if CONFIG_SLUB_CPU_PARTIAL=y && 5.16 <= kernel\n            struct kmem_cache_order_objects oo;\n            struct kmem_cache_order_objects max;     // if kernel < 5.19\n            struct kmem_cache_order_objects min;\n            gfp_t allocflags;                        // unsigned int\n            int refcount;\n            void (*ctor)(void *);\n            unsigned int inuse;\n            unsigned int align;\n            unsigned int red_left_pad;\n            const char *name;\n            struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n        \"\"\"\n\n        # fast path\n        try:\n            self.kmem_cache_offset_list = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).list\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        self.kmem_cache_offset_list = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        # This value should be at most 0x70 by default. However, cases using offset 0x98 have been observed.\n        # This occurs when CONFIG_SLAB_VIRTUAL=y, which is not in the mainline but is introduced by some kernels.\n        # Therefore, the search range is expanded.\n        max_offset = 0x100\n        for candidate_offset in range(current_arch.ptrsize * 2, max_offset, current_arch.ptrsize):\n            # backward search for the start of `struct kmem_cache`\n            found = True\n            seen = []\n            for kmem_cache in kmem_caches:\n                val = read_int_from_memory(kmem_cache - candidate_offset)\n                if val in [0, 0xffff_ffff, 0xffff_ffff_ffff_ffff]:\n                    found = False\n                    break\n                if val in seen:\n                    found = False\n                    break\n                else:\n                    seen.append(val)\n\n                for cpuoff in self.cpu_offset:\n                    if not is_valid_addr(AddressUtil.align_address(val + cpuoff)):\n                        found = False\n                        break\n\n            if found:\n                self.kmem_cache_offset_list = candidate_offset\n                return\n        return\n\n    def resolve_kmem_cache_offset_random(self):\n        # fast path\n        try:\n            # find kmem_cache.random\n            self.kmem_cache_offset_random = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).random\")\n            )\n            return\n        except gdb.error:\n            try:\n                # kmem_cache exists but has no random member\n                gdb.parse_and_eval(\"(struct kmem_cache*)0\")\n                self.kmem_cache_offset_random = None\n                return\n            except gdb.error:\n                pass\n\n        # slow path\n        if self.args.no_xor:\n            self.kmem_cache_offset_random = None\n            return\n\n        if self.args.offset_random is not None:\n            self.kmem_cache_offset_random = self.args.offset_random\n            return\n\n        self.kmem_cache_offset_random = None # CONFIG_SLAB_FREELIST_HARDENED=n\n\n        \"\"\"\n        struct kmem_cache {\n            ...\n            struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n            struct kobject kobj;                     // if CONFIG_SYSFS=y\n            struct work_struct kobj_remove_work;     // if CONFIG_SYSFS=y && kernel < 5.9\n            struct memcg_cache_params memcg_params;  // if CONFIG_MEMCG=y && kernel < 5.9\n            unsigned int max_attr_size;              // if CONFIG_MEMCG=y && kernel < 5.9\n            struct kset *memcg_kset;                 // if CONFIG_MEMCG=y && CONFIG_SYSFS=y && kernel < 5.9\n            unsigned long random;                    // if CONFIG_SLAB_FREELIST_HARDENED=y\n            unsigned int remote_node_defrag_ratio;   // if CONFIG_NUMA=y\n            unsigned int *random_seq;                // if CONFIG_SLAB_FREELIST_RANDOM=y\n            struct kasan_cache {\n                int alloc_meta_offset;\n                int free_meta_offset;\n                bool is_kmalloc;\n            } kasan_info;                            // if CONFIG_KASAN=y\n            unsigned int useroffset;                 // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n            unsigned int usersize;                   // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n            struct kmem_cache_node *node[MAX_NUMNODES];\n        };\n        \"\"\"\n\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        for i in range(2, 0x40):\n            candidate_offset = current_arch.ptrsize * i\n            found = True\n            count = 0\n            seen = []\n            for kmem_cache in kmem_caches:\n                if not is_valid_addr(kmem_cache + candidate_offset):\n                    found = False\n                    break\n\n                val = read_int_from_memory(kmem_cache + candidate_offset)\n                # random may happen to be a valid address, so some are acceptable\n                if is_valid_addr(val):\n                    count += 1\n                    if count >= 3:\n                        found = False\n                        break\n                else:\n                    if val > 0xff_ffff:\n                        count -= 1\n\n                # The probability of the same random value appearing multiple times is negligible\n                if val != 0:\n                    if val in seen:\n                        found = False\n                        break\n                    seen.append(val)\n\n            if found:\n                # Too few random numbers\n                if len(seen) < 10:\n                    found = False\n\n                # Occurrences of non-negative small integers are stochastically rare\n                elif sum([0 < x < 0x10_0000 for x in seen]) >= 3:\n                    found = False\n\n                # Occurrences of big integers are stochastically rare\n                elif sum([0xffff_0000_0000_0000 < x <= 0xffff_ffff_ffff_ffff for x in seen]) >= 3:\n                    found = False\n\n                # Occurrences of 0xXXXX000 are stochastically rare\n                elif sum([x and (x & 0xfff) == 0 for x in seen]) >= 3:\n                    found = False\n\n            if found:\n                # search for `struct kmem_cache_node *node` or `unsigned int *random_seq`\n                for i in range(1, 9):\n                    maybe_ptrs = []\n                    for kmem_cache in kmem_caches:\n                        v = read_int_from_memory(kmem_cache + candidate_offset + current_arch.ptrsize * i)\n                        maybe_ptrs.append(v)\n                    # they should be at the same offset\n                    if all(is_valid_addr(p) for p in maybe_ptrs):\n                        break\n                else:\n                    found = False\n\n            if found:\n                self.kmem_cache_offset_random = self.kmem_cache_offset_list + candidate_offset\n                return\n        return\n\n    def resolve_kmem_cache_offset_node(self):\n        # fast path\n        try:\n            self.kmem_cache_offset_node = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).node\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        if self.args.offset_node is not None:\n            self.kmem_cache_offset_node = self.args.offset_node\n            return\n\n        self.kmem_cache_offset_node = None\n        kversion = Kernel.kernel_version()\n\n        \"\"\"\n        struct kmem_cache {\n            ...\n            unsigned int object_size;\n            ...\n            struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n            struct kobject kobj;                     // if CONFIG_SYSFS=y\n            struct work_struct kobj_remove_work;     // if CONFIG_SYSFS=y && kernel < 5.9\n            struct memcg_cache_params memcg_params;  // if CONFIG_MEMCG=y && kernel < 5.9\n            unsigned int max_attr_size;              // if CONFIG_MEMCG=y && kernel < 5.9\n            struct kset *memcg_kset;                 // if CONFIG_MEMCG=y && CONFIG_SYSFS=y && kernel < 5.9\n            unsigned long random;                    // if CONFIG_SLAB_FREELIST_HARDENED=y\n            unsigned int remote_node_defrag_ratio;   // if CONFIG_NUMA=y (<-- maybe 1000)\n            unsigned int *random_seq;                // if CONFIG_SLAB_FREELIST_RANDOM=y\n            struct kasan_cache {\n                int alloc_meta_offset;\n                int free_meta_offset;\n                bool is_kmalloc;\n            } kasan_info;                            // if CONFIG_KASAN=y\n            unsigned int useroffset;                 // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n            unsigned int usersize;                   // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n            struct kmem_cache_node *node[MAX_NUMNODES]; <-- this includes SPINLOCK_MAGIC if CONFIG_DEBUG_SPINLOCK=y\n        }\n        \"\"\"\n\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n\n        # heuristic way 1 (SPINLOCK_MAGIC)\n        if is_64bit():\n            # kmem_cache_node[0]->list_lock has SPINLOCK_MAGIC when CONFIG_DEBUG_SPINLOCK=y\n            start_offset = self.kmem_cache_offset_list + current_arch.ptrsize * 2 # sizeof(kmem_cache.list)\n            search_range = 0x100 if \"5.9\" <= kversion else 0x200\n            for candidate_offset in range(start_offset, start_offset + search_range, current_arch.ptrsize):\n                kmem_cache_top = kmem_caches[0] - self.kmem_cache_offset_list\n\n                x = read_int_from_memory(kmem_cache_top + candidate_offset)\n                if not is_valid_addr(x):\n                    continue\n                y = read_int_from_memory(x)\n                if y != 0xdead_4ead_0000_0000: # SPINLOCK_MAGIC\n                    continue\n\n                # found\n                self.quiet_info(\"offset of node is found by heuristic way1\")\n                self.kmem_cache_offset_node = candidate_offset\n                return\n\n        # helper functions (for way2, way4)\n\n        def get_next_valid_ptr_offset(addr, in_range=5):\n            \"\"\"Return the nearest valid pointer within a specified range.\"\"\"\n            # Depending on the configuration, the offset where the address exists will vary,\n            # so we need to find the closest valid address.\n            for i in range(in_range):\n                candidate_offset = current_arch.ptrsize * i\n                v = read_int_from_memory(addr + candidate_offset)\n                if is_valid_addr(v):\n                    return candidate_offset\n            return None\n\n        def is_random_seq(addr, N=8):\n            # What random_seq points to is a rearrangement of sequential numbers of type u32.\n            # Therefore, no two values will be the same. If the first some elements contain\n            # the same value, we can determine that it is not random_seq but node[0].\n            #\n            # kmem_cache_node example\n            # 0xffff888003c40180|+0x0000|+000: 0xb7f638bb00000000\n            # 0xffff888003c40188|+0x0008|+001: 0x000000000000000a\n            # 0xffff888003c40190|+0x0010|+002: 0xffffea000012da90\n            # 0xffff888003c40198|+0x0018|+003: 0xffffea0000118710\n            # 0xffff888003c401a0|+0x0020|+004: 0x0000000000000010\n            # 0xffff888003c401a8|+0x0028|+005: 0x0000000000000800\n            # random_seq example\n            # 0xffff8f9d8104c400|+0x0000|+000: 0x00000e8000000b40\n            # 0xffff8f9d8104c408|+0x0008|+001: 0x00000f4000000080\n            # 0xffff8f9d8104c410|+0x0010|+002: 0x000000a000000ae0\n            # 0xffff8f9d8104c418|+0x0018|+003: 0x00000bc0000001e0\n            # 0xffff8f9d8104c420|+0x0020|+004: 0x0000020000000360\n            # 0xffff8f9d8104c428|+0x0028|+005: 0x0000024000000320\n            # random_seq another example\n            # 0xffff89c3ce772240|+0x0000|+000: 0x00000000000019e0\n            # 0xffff89c3ce772248|+0x0008|+001: 0x00005a9000004da0\n            # 0xffff89c3ce772250|+0x0010|+002: 0x00000cf0000026d0\n            # 0xffff89c3ce772258|+0x0018|+003: 0x00006780000040b0\n            # 0xffff89c3ce772260|+0x0020|+004: 0x00000000000033c0\n            # 0xffff89c3ce772268|+0x0028|+005: 0x0000000000000000\n            # 0xffff89c3ce772270|+0x0030|+006: 0x0000000000000000\n            sizeof_uint32 = 4\n            data = read_memory(addr, sizeof_uint32 * N)\n            data = slice_unpack(data, sizeof_uint32)\n            if len(set(data)) != N:\n                return False\n            if any(x & 0x80000000 for x in data):\n                return False\n            return True\n\n        # helper functions end\n\n        # heuristic way 2 (remote_node_defrag_ratio == 1000)\n        if is_64bit():\n            # Find the offset that has the initial value of 1000 for remote_node_defrag_ratio.\n            # The first valid pointer encountered after that is either random_seq or node[0].\n            # We look at the contents to determine whether the pointer is random_seq.\n            start_offset = self.kmem_cache_offset_list + current_arch.ptrsize * 2 # sizeof(kmem_cache.list)\n            search_range = 0x100 if \"5.9\" <= kversion else 0x200\n            for candidate_offset in range(start_offset, start_offset + search_range, current_arch.ptrsize):\n                # First, we search remote_node_defrag_ratio.\n                remote_node_defrag_ratio_1000_count = 0\n                for kmem_cache in kmem_caches:\n                    kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n                    remote_node_defrag_ratio = read_int32_from_memory(kmem_cache_top + candidate_offset)\n                    if remote_node_defrag_ratio == 0x3e8:\n                        remote_node_defrag_ratio_1000_count += 1\n                if remote_node_defrag_ratio_1000_count < len(kmem_caches) // 10: # heuristic threshold: 10%\n                    continue\n                offset_remote_node_defrag_ratio = candidate_offset\n                offset_random_seq = offset_remote_node_defrag_ratio + current_arch.ptrsize\n\n                # Check the value next to remote_node_defrag_ratio whether pointer or not.\n                kmem_cache_0_top = kmem_caches[0] - self.kmem_cache_offset_list\n                x = read_int_from_memory(kmem_cache_0_top + offset_random_seq)\n                if is_valid_addr(x):\n                    # At this point, x is random_seq or node[0]\n                    if not is_random_seq(x):\n                        # x is not random_seq, but node[0]\n                        self.quiet_info(\"offset of node is found by heuristic way2-1\")\n                        self.kmem_cache_offset_node = offset_random_seq\n                        return\n                    else:\n                        # x is random_seq, so skip it\n                        start_offset_node_search = offset_random_seq + current_arch.ptrsize\n                else:\n                    # x is kasan_info or user_offset\n                    start_offset_node_search = offset_random_seq\n\n                extend_offset = get_next_valid_ptr_offset(kmem_cache_0_top + start_offset_node_search)\n                if extend_offset is not None:\n                    offset_node = start_offset_node_search + extend_offset\n                    y = read_int_from_memory(kmem_cache_0_top + offset_node)\n                    if is_valid_addr(y) and not is_random_seq(y):\n                        self.quiet_info(\"offset of node is found by heuristic way2-2\")\n                        self.kmem_cache_offset_node = offset_node\n                        return\n\n        # heuristic way 3 (relationship of user_offset, user_size, and object_size)\n        # This method is valid for kernel < 6.2, or (CONFIG_HARDENED_USERCOPY=y and 6.2 <= kernel).\n        start_offset = self.kmem_cache_offset_list + current_arch.ptrsize * 2 # sizeof(kmem_cache.list)\n        search_range = 0x100 if \"5.9\" <= kversion else 0x200\n        for candidate_offset in range(start_offset, start_offset + search_range, current_arch.ptrsize):\n            found = True\n            user_offset_user_size_non_zero_flag = False\n            for kmem_cache in kmem_caches:\n                kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n\n                # Check whether user_offset, user_size, and object_size satisfy some relationships\n                user_offset = read_int32_from_memory(kmem_cache_top + candidate_offset)\n                user_size = read_int32_from_memory(kmem_cache_top + candidate_offset + 4)\n                object_size = read_int32_from_memory(kmem_cache_top + self.kmem_cache_offset_object_size)\n\n                if user_offset == user_size == 0:\n                    continue\n                user_offset_user_size_non_zero_flag = True\n\n                if user_offset != 0 and user_size == 0:\n                    found = False\n                    break\n                if object_size < user_size:\n                    found = False\n                    break\n\n                # And check that the immediately following node is a valid address\n                node_offset = candidate_offset + 4 + 4\n                node_addr = read_int_from_memory(kmem_cache_top + node_offset)\n                if not is_valid_addr(node_addr):\n                    found = False\n                    break\n\n            if user_offset_user_size_non_zero_flag is False:\n                found = False\n\n            if found:\n                self.quiet_info(\"offset of node is found by heuristic way3\")\n                self.kmem_cache_offset_node = node_offset\n                return\n\n        # heuristic way 4 (detect random_seq)\n        if is_64bit() and self.kmem_cache_offset_random:\n            # user_offset and user_size probably don't exist.\n            # remote_node_defrag_ratio does not exist either.\n            # Search random_seq from random, then go like heuristic way 2.\n            offset_random_seq = self.kmem_cache_offset_random + current_arch.ptrsize\n\n            kmem_cache_0_top = kmem_caches[0] - self.kmem_cache_offset_list\n            x = read_int_from_memory(kmem_cache_0_top + offset_random_seq)\n            if is_valid_addr(x):\n                # At this point, x is random_seq or node[0]\n                if not is_random_seq(x):\n                    # x is not random_seq, but node[0]\n                    self.quiet_info(\"offset of node is found by heuristic way4-1\")\n                    self.kmem_cache_offset_node = offset_random_seq\n                    return\n                else:\n                    # x is random_seq, so skip it\n                    start_offset_node_search = offset_random_seq + current_arch.ptrsize\n            else:\n                # x is kasan_info or user_offset\n                start_offset_node_search = offset_random_seq\n\n            # not found\n            extend_offset = get_next_valid_ptr_offset(kmem_cache_0_top + start_offset_node_search)\n            if extend_offset is not None:\n                offset_node = start_offset_node_search + extend_offset\n                y = read_int_from_memory(kmem_cache_0_top + offset_node)\n                if is_valid_addr(y) and not is_random_seq(y):\n                    self.quiet_info(\"offset of node is found by heuristic way4-2\")\n                    self.kmem_cache_offset_node = offset_node\n                    return\n\n        # heuristic way 5 (consecutive kmem_cache)\n        # A kmem_cache may itself be allocated contiguously.\n        # It may be possible to find a node from this relationship.\n        #          +-kmem_cache-+\n        #          | ...        |\n        #    ...-->| list       |-->...(*)  (1) detect consecutive kmem_cache\n        #          | ...        |  -------^\n        #          | node       |         | (2) search this area\n        #          | (padding)  |         |\n        #          +-kmem_cache-+  -------v\n        #          | ...        |\n        # (*)...-->| list       |-->...\n        #          | ...        |\n        #          | node       |\n        #          | (padding)  |\n        #          +------------+\n\n        # Find the two nearest pairs and count the number of cases\n        min_diff_pairs = []\n        min_diff = 0xffff_ffff_ffff_ffff\n        for km1, km2 in itertools.combinations(kmem_caches, 2):\n            diff = abs(km1 - km2)\n            if diff < min_diff:\n                min_diff_pairs = [(min(km1, km2), max(km1, km2))]\n                min_diff = diff\n                continue\n            if diff == min_diff:\n                min_diff_pairs.append((min(km1, km2), max(km1, km2)))\n                continue\n\n        # If there are enough such cases, we can determine that they are likely arranged consecutively\n        if len(min_diff_pairs) >= 10:\n            # Specifies the maximum traversal range for scanning node locations\n            # Note that these are kmem_cache.list addresses\n            km0_0, km0_1 = min_diff_pairs[0]\n            km0_1_top = km0_1 - self.kmem_cache_offset_list\n            km0_0_after_list = km0_0 + current_arch.ptrsize * 2\n            max_search_range = km0_1_top - km0_0_after_list\n\n            # Check that the address is valid for all pairs\n            for i in range(max_search_range // current_arch.ptrsize):\n                candidate_offset = current_arch.ptrsize * (i + 1)\n                found = True\n                for _, m in min_diff_pairs:\n                    m_top = m - self.kmem_cache_offset_list\n                    x = read_int_from_memory(m_top - candidate_offset)\n                    if not is_valid_addr(x):\n                        found = False\n                        break\n                if found:\n                    offset_node_from_after_list = max_search_range - candidate_offset\n                    offset_after_list = self.kmem_cache_offset_list + current_arch.ptrsize * 2\n                    maxlen = len(list(itertools.combinations(kmem_caches, 2)))\n                    msg = \"min_diff_pairs:{:d}/{:d}, \".format(len(min_diff_pairs), maxlen)\n                    msg += \"min_diff:{:#x}\".format(min_diff)\n                    self.quiet_info(\"offset of node is found by heuristic way5 ({:s})\".format(msg))\n                    self.kmem_cache_offset_node = offset_after_list + offset_node_from_after_list\n                    return\n        return\n\n    def resolve_for_CONFIG_SLAB_VIRTUAL(self):\n        kversion = Kernel.kernel_version()\n\n        # Feature: CONFIG_SLAB_VIRTUAL (this patchset is supported x86-64 only).\n        # See https://lwn.net/Articles/944647/.\n        if not is_x86_64():\n            self.slab_virtual_enabled = False\n        elif kversion < \"6.1\":\n            self.slab_virtual_enabled = False\n        elif not Symbol.get_ksymaddr(\"slub_tlbflush_worker\"):\n            self.slab_virtual_enabled = False\n        else:\n            # Heuristic detection that CONFIG_SLAB_VIRTUAL is enabled or not from `struct kmem_cache`.\n            # If enabled, `struct kmem_cache` has 2 doubly-link-lists above `kmem_cache->name`.\n            #     - kmem_cache->freed_slabs_normal (6.1.56 <= kernel)\n            #     - kmem_cache->freed_slabs (kernel < 6.1.56)\n            #     - kmem_cache->freed_slabs_min\n\n            def has_freed_slabs_lists(freed_slabs_normal, freed_slabs_min):\n                return is_double_link_list(freed_slabs_normal) and is_double_link_list(freed_slabs_min)\n\n            kmem_caches = self.parse_kmem_caches_for_initialize()\n            top = kmem_caches[0] - self.kmem_cache_offset_list\n\n            offset_freed_slabs_normal = current_arch.ptrsize * 9\n            offset_freed_slabs_min = current_arch.ptrsize * 11\n            self.slab_virtual_enabled = has_freed_slabs_lists(\n                top + offset_freed_slabs_normal, top + offset_freed_slabs_min,\n            )\n\n            # cares CONFIG_SLUB_CPU_PARTIAL=n\n            if not self.slab_virtual_enabled:\n                offset_freed_slabs_normal = current_arch.ptrsize * 8\n                offset_freed_slabs_min = current_arch.ptrsize * 10\n                self.slab_virtual_enabled = has_freed_slabs_lists(\n                    top + offset_freed_slabs_normal, top + offset_freed_slabs_min,\n                )\n\n        # parse kmem_cache for CONFIG_SLAB_VIRTUAL\n        if self.slab_virtual_enabled:\n            self.quiet_info(\"CONFIG_SLAB_VIRTUAL: detected\")\n\n            # 1. get global queue buffering freed slabs\n            self.slub_tlbflush_queue = KernelAddressHeuristicFinder.get_slub_tlbflush_queue()\n            if not self.slub_tlbflush_queue:\n                return False\n            self.quiet_info(\"slub_tlbflush_queue: {:#x}\".format(self.slub_tlbflush_queue))\n\n            # 2. parse extra members of kmem_cache\n            #   - kmem_cache->nr_freed_pages (6.1-based, 6.12-based) or kmem_cache->virtual.nr_freed_pages (6.6-based)\n            #   - kmem_cache->freed_slabs_normal (6.1-based, 6.12-based) or kmem_cache->virtual.freed_slabs (6.6-based)\n            #   - kmem_cache->freed_slabs_min (6.1-based, 6.12-based) or kmem_cache->virtual.freed_slabs_min (6.6-based)\n\n            # offsetof(kmem_cache, nr_freed_pages)\n            if kversion < \"6.1.56\":\n                self.kmem_cache_offset_nr_freed_pages = offset_freed_slabs_normal - current_arch.ptrsize * 1\n            else:\n                self.kmem_cache_offset_nr_freed_pages = offset_freed_slabs_min + current_arch.ptrsize * 2\n            self.quiet_info(\"offsetof(kmem_cache, nr_freed_pages): {:#x}\".format(\n                self.kmem_cache_offset_nr_freed_pages,\n            ))\n\n            # offsetof(kmem_cache, freed_slabs_normal)\n            self.kmem_cache_offset_freed_slabs_normal = offset_freed_slabs_normal\n            self.quiet_info(\"offsetof(kmem_cache, freed_slabs_normal): {:#x}\".format(\n                self.kmem_cache_offset_freed_slabs_normal,\n            ))\n\n            # offsetof(kmem_cache, freed_slabs_min)\n            self.kmem_cache_offset_freed_slabs_min = offset_freed_slabs_min\n            self.quiet_info(\"offsetof(kmem_cache, freed_slabs_min): {:#x}\".format(\n                self.kmem_cache_offset_freed_slabs_min,\n            ))\n        else:\n            if self.args.tlbflush_queue:\n                warn(\"CONFIG_SLAB_VIRTUAL is not enabled (maybe), option `--tlbflush-queue` is ignored.\")\n        return\n\n    def resolve_kmem_cache_node_offset_partial(self):\n        # fast path\n        try:\n            self.kmem_cache_node_offset_partial = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache_node*)0).partial\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        if self.kmem_cache_offset_node is None:\n            self.kmem_cache_node_offset_partial = None\n            return\n\n        self.kmem_cache_node_offset_partial = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        top = kmem_caches[0] - self.kmem_cache_offset_list\n\n        node = read_int_from_memory(top + self.kmem_cache_offset_node)\n        for i in range(1, 16):\n            offset_partial = current_arch.ptrsize * i\n            if is_double_link_list(node + offset_partial):\n                self.kmem_cache_node_offset_partial = offset_partial\n                return\n        return\n\n    def get_slub_percpu_sheaves(self, addr, cpu):\n        cpu_sheaves = read_int_from_memory(addr + self.kmem_cache_offset_cpu_sheaves)\n        if cpu_sheaves == 0:\n            return None\n        if len(self.cpu_offset) > 0:\n            slub_percpu_sheaves = cpu_sheaves + self.cpu_offset[cpu]\n        else:\n            slub_percpu_sheaves = cpu_sheaves\n        return AddressUtil.align_address(slub_percpu_sheaves)\n\n    def resolve_slub_percpu_sheaves_offset_main(self):\n        self.slub_percpu_sheaves_offset_main = None\n\n        if self.kmem_cache_offset_cpu_sheaves is None:\n            return\n\n        # fast path\n        try:\n            self.slub_percpu_sheaves_offset_main = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct slub_percpu_sheaves*)0).main\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        \"\"\"\n        struct slub_percpu_sheaves {\n            struct {\n            #ifdef CONFIG_DEBUG_LOCK_ALLOC\n                struct lockdep_map {\n                    struct lock_class_key *key;\n                    struct lock_class *class_cache[2];\n                    const char *name;\n                    u8 wait_type_outer;\n                    u8 wait_type_inner;\n                    u8 lock_type;\n                #ifdef CONFIG_LOCK_STAT\n                    int cpu;\n                    unsigned long ip;\n                #endif\n                } dep_map;\n                struct task_struct *owner;\n            #endif\n                u8 acquired;\n            } local_trylock_t lock;\n            struct slab_sheaf *main;\n            struct slab_sheaf *spare;\n            struct slab_sheaf *rcu_free;\n        };\n        \"\"\"\n\n        # slow path\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        for kmem_cache in kmem_caches:\n            kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n            for cpu in range(self.ncpus):\n                slub_percpu_sheaves = self.get_slub_percpu_sheaves(kmem_cache_top, cpu)\n                if slub_percpu_sheaves is None:\n                    continue\n\n                # CONFIG_DEBUG_LOCK_ALLOC=n\n                acquired = read_int_from_memory(slub_percpu_sheaves)\n                main = read_int_from_memory(slub_percpu_sheaves + current_arch.ptrsize)\n                if acquired in [0, 1] and is_valid_addr(main):\n                    self.slub_percpu_sheaves_offset_main = current_arch.ptrsize\n                    return\n\n                # CONFIG_DEBUG_LOCK_ALLOC=y\n                for i in range(8):\n                    v = read_int_from_memory(slub_percpu_sheaves + current_arch.ptrsize * i)\n                    if v == kmem_cache: # owner\n                        self.slub_percpu_sheaves_offset_main = current_arch.ptrsize * (i + 2)\n                        return\n        return\n\n    def resolve_kmem_cache_node_offset_barn(self):\n        self.kmem_cache_node_offset_barn = None\n\n        if self.kmem_cache_offset_node is None:\n            return\n\n        # fast path\n        try:\n            self.kmem_cache_node_offset_barn = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache_node*)0).barn\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        \"\"\"\n        struct kmem_cache_node {\n            spinlock_t list_lock;\n            unsigned long nr_partial;\n            struct list_head partial;\n            atomic_long_t nr_slabs;                  // if CONFIG_SLUB_DEBUG=y\n            atomic_long_t total_objects;             // if CONFIG_SLUB_DEBUG=y\n            struct list_head full;                   // if CONFIG_SLUB_DEBUG=y\n            struct node_barn *barn;                  // 6.18 <= kernel\n        };\n        \"\"\"\n\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        for kmem_cache in kmem_caches:\n            kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n            for cpu in range(self.ncpus):\n                # is kmem_cache enabled sheaves?\n                slub_percpu_sheaves = self.get_slub_percpu_sheaves(kmem_cache_top, cpu)\n                if slub_percpu_sheaves is None:\n                    continue\n\n                # get kmem_cache_node\n                kmem_cache_node_array = kmem_cache_top + self.kmem_cache_offset_node\n                if not is_valid_addr(kmem_cache_node_array):\n                    continue\n                kmem_cache_node = read_int_from_memory(kmem_cache_node_array)\n                if not is_valid_addr(kmem_cache_node): # check 1st element is enough\n                    continue\n\n                # search list_head\n                for i in range(0x20):\n                    offset_candidate_list_head = current_arch.ptrsize * i\n                    if is_double_link_list(kmem_cache_node + offset_candidate_list_head):\n                        offset_candidate = offset_candidate_list_head + current_arch.ptrsize * 2\n                        # search valid pointer which locates next to it\n                        if is_valid_addr_addr(kmem_cache_node + offset_candidate):\n                            self.kmem_cache_node_offset_barn = offset_candidate\n                            return\n        return\n\n    def resolve_node_barn_offset_sheaves_full(self):\n        self.node_barn_offset_sheaves_full = None\n\n        if self.kmem_cache_offset_node is None:\n            return\n\n        # fast path\n        try:\n            self.node_barn_offset_sheaves_full = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct node_barn*)0).sheaves_full\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        \"\"\"\n        struct node_barn {\n            spinlock_t lock;\n            struct list_head sheaves_full;\n            struct list_head sheaves_empty;\n            unsigned int nr_full;\n            unsigned int nr_empty;\n        };\n        \"\"\"\n\n        # slow path\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        for kmem_cache in kmem_caches:\n            kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n            for cpu in range(self.ncpus):\n                # is kmem_cache enabled sheaves?\n                slub_percpu_sheaves = self.get_slub_percpu_sheaves(kmem_cache_top, cpu)\n                if slub_percpu_sheaves is None:\n                    continue\n\n                # get kmem_cache_node\n                kmem_cache_node_array = kmem_cache_top + self.kmem_cache_offset_node\n                if not is_valid_addr(kmem_cache_node_array):\n                    continue\n                kmem_cache_node = read_int_from_memory(kmem_cache_node_array)\n                if not is_valid_addr(kmem_cache_node): # check 1st element is enough\n                    continue\n\n                # get barn\n                barn = read_int_from_memory(kmem_cache_node + self.kmem_cache_node_offset_barn)\n                if is_valid_addr(barn):\n                    # search list_head\n                    for i in range(0x20):\n                        offset_candidate = current_arch.ptrsize * i\n                        if is_double_link_list(barn + offset_candidate):\n                            self.node_barn_offset_sheaves_full = offset_candidate\n                            return\n        return\n\n    def resolve_sheaves(self):\n        self.sheaves_enabled = False\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"6.18\":\n            return\n\n        if self.kmem_cache_offset_cpu_sheaves is None:\n            return\n        if self.kmem_cache_offset_node is None:\n            return\n\n        # offsetof(slub_percpu_sheaves, main)\n        self.resolve_slub_percpu_sheaves_offset_main()\n        if self.slub_percpu_sheaves_offset_main is None:\n            self.quiet_info(\"offsetof(slub_percpu_sheaves, main): Not found\")\n            return\n        self.quiet_info(\"offsetof(slub_percpu_sheaves, main): {:#x}\".format(self.slub_percpu_sheaves_offset_main))\n\n        # offsetof(kmem_cache_node, barn)\n        self.resolve_kmem_cache_node_offset_barn()\n        if self.kmem_cache_node_offset_barn is None:\n            self.quiet_info(\"offsetof(kmem_cache_node, barn): Not found\")\n            return\n        self.quiet_info(\"offsetof(kmem_cache_node, barn): {:#x}\".format(self.kmem_cache_node_offset_barn))\n\n        # offsetof(node_barn, sheaves_full)\n        self.resolve_node_barn_offset_sheaves_full()\n        if self.node_barn_offset_sheaves_full is None:\n            self.quiet_info(\"offsetof(node_barn, sheaves_full): Not found\")\n            return\n        self.quiet_info(\"offsetof(node_barn, sheaves_full): {:#x}\".format(self.node_barn_offset_sheaves_full))\n\n        # offsetof(slub_percpu_sheaves, spare)\n        self.slub_percpu_sheaves_offset_spare = self.slub_percpu_sheaves_offset_main + current_arch.ptrsize\n\n        \"\"\"\n        struct slab_sheaf {\n            union {\n                struct rcu_head rcu_head;\n                struct list_head barn_list;\n                unsigned int capacity; /* only used for prefilled sheafs */\n            };\n            struct kmem_cache *cache;\n            unsigned int size;\n            int node; /* only used for rcu_sheaf */\n            void *objects[];\n        };\n        \"\"\"\n        # offsetof(slab_sheaf, barn_list)\n        self.slab_sheaf_offset_barn_list = 0\n        # offsetof(slab_sheaf, kmem_cache)\n        self.slab_sheaf_offset_kmem_cache = self.slab_sheaf_offset_barn_list + current_arch.ptrsize * 2\n        # offsetof(slab_sheaf, size)\n        self.slab_sheaf_offset_size = self.slab_sheaf_offset_kmem_cache + current_arch.ptrsize\n        # offsetof(slab_sheaf, objects)\n        self.slab_sheaf_offset_objects = self.slab_sheaf_offset_size + current_arch.ptrsize\n\n        # offsetof(node_barn, sheaves_empty)\n        self.node_barn_offset_sheaves_empty = self.node_barn_offset_sheaves_full + current_arch.ptrsize * 2\n\n        self.sheaves_enabled = True\n        return\n\n    # CONFIG_SLAB_VIRTUAL=n\n    \"\"\"\n    struct kmem_cache {\n        struct kmem_cache_cpu *cpu_slab;         // In fact, the offset value, not the pointer\n        struct lock_class_key {                            // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n            union {                                        // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n                struct hlist_node hash_entry;              // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n                struct lockdep_subclass_key {              // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n                    char __one_byte;                       // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n                } __attribute__ ((__packed__)) subkeys[8]; // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n            };                                             // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n        } lock_key;                                        // if CONFIG_LOCKDEP=y && 6.18 <= kernel\n        struct slub_percpu_sheaves __percpu *cpu_sheaves;  // if 6.18 <= kernel\n        slab_flags_t flags;                      // unsigned int (+ padding 4 byte)\n        unsigned long min_partial;\n        unsigned int size;\n        unsigned int object_size;\n        struct reciprocal_value {                //\n            u32 m;                               //\n            u8 sh1, sh2;                         // (+ padding 2 byte)\n        } reciprocal_size;                       // if 5.9 <= kernel\n        unsigned int offset;\n        unsigned int cpu_partial;                // if CONFIG_SLUB_CPU_PARTIAL=y\n        unsigned int cpu_partial_slabs;          // if CONFIG_SLUB_CPU_PARTIAL=y && 5.16 <= kernel\n        struct kmem_cache_order_objects oo;\n        struct kmem_cache_order_objects max;     // if kernel < 5.19\n        struct kmem_cache_order_objects min;\n        gfp_t allocflags;                        // unsigned int\n        int refcount;\n        void (*ctor)(void *);\n        unsigned int inuse;\n        unsigned int align;\n        unsigned int red_left_pad;\n        const char *name;\n        struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n        struct kobject kobj;                     // if CONFIG_SYSFS=y\n        struct work_struct kobj_remove_work;     // if CONFIG_SYSFS=y && kernel < 5.9\n        struct memcg_cache_params memcg_params;  // if CONFIG_MEMCG=y && kernel < 5.9\n        unsigned int max_attr_size;              // if CONFIG_MEMCG=y && kernel < 5.9\n        struct kset *memcg_kset;                 // if CONFIG_MEMCG=y && CONFIG_SYSFS=y && kernel < 5.9\n        unsigned long random;                    // if CONFIG_SLAB_FREELIST_HARDENED=y\n        unsigned int remote_node_defrag_ratio;   // if CONFIG_NUMA=y\n        unsigned int *random_seq;                // if CONFIG_SLAB_FREELIST_RANDOM=y\n        struct kasan_cache {\n            int alloc_meta_offset;\n            int free_meta_offset;\n            bool is_kmalloc;\n        } kasan_info;                            // if CONFIG_KASAN=y\n        unsigned int useroffset;                 // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n        unsigned int usersize;                   // kernel < 6.2 || (6.2 <= kernel && CONFIG_HARDENED_USERCOPY=y)\n        struct kmem_cache_node *node[MAX_NUMNODES];\n    };\n\n    struct kmem_cache_cpu {\n        void **freelist;\n        unsigned long tid;\n        struct page *page;                       // if kernel < 5.17\n        struct page *partial;                    // if kernel < 5.17 && CONFIG_SLUB_CPU_PARTIAL=y\n        struct slab *slab;                       // if 5.17 <= kernel\n        struct slab *partial;                    // if 5.17 <= kernel && CONFIG_SLUB_CPU_PARTIAL=y\n        local_lock_t lock;                       // if 5.15 <= kernel\n        unsigned stat[NR_SLUB_STAT_ITEMS];       // if CONFIG_SLUB_STATS=y\n    };\n\n    struct page {                                // if kernel < 4.18\n        unsigned long flags;\n        union { };                               // long\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        atomic_t _refcount;                      // if kernel < 4.16\n        struct page *next;\n        int pages;                               // if 64bit else `short pages`\n        int pobjects;                            // if 64bit else `short pobjects`\n        struct kmem_cache *slab_cache;\n        struct mem_cgroup *mem_cgroup;           // if CONFIG_MEMCG=y\n        void *virtual;                           // if CONFIG_WANT_PAGE_VIRTUAL=y\n        void *shadow;                            // if CONFIG_KMEMCHECK=y && kernel < 4.14\n        int _last_cpuid;                         // if CONFIG_LAST_CPUPID_NOT_IN_PAGE_FLAGS=y\n    };\n\n    struct page {                                // if 4.18 <= kernel < 5.17\n        unsigned long flags;\n        struct page *next;\n        int pages;                               // if 64bit else `short pages`\n        int pobjects;                            // if 64bit else `short pobjects`\n        struct kmem_cache *slab_cache;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        union {};                                // unsigned int\n        atomic_t _refcount;\n        unsigned long memcg_data;                // if CONFIG_MEMCG=y && 5.10 <= kernel\n        struct mem_cgroup *mem_cgroup;           // if CONFIG_MEMCG=y && kernel < 5.10\n        void *virtual;                           // if CONFIG_WANT_PAGE_VIRTUAL=y\n        int _last_cpuid;                         // if CONFIG_LAST_CPUPID_NOT_IN_PAGE_FLAGS=y\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=n && 5.17 <= kernel < 6.2\n        unsigned long __page_flags;\n        struct slab *next;\n        int slabs;\n        struct kmem_cache *slab_cache;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        unsigned int __unused;\n        atomic_t __page_refcount;\n        unsigned long memcg_data;                // if CONFIG_MEMCG=y\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=n && 6.2 <= kernel < 6.10\n        unsigned long __page_flags;\n        struct kmem_cache *slab_cache;\n        struct slab *next;\n        int slabs;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        unsigned int __unused;\n        atomic_t __page_refcount;\n        unsigned long memcg_data;                // if CONFIG_MEMCG=y\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=n && 6.10 <= kernel\n        unsigned long __page_flags;              // if kernel < 6.18\n        memdesc_flags_t flags;                   // if 6.18 <= kernel\n        struct kmem_cache *slab_cache;\n        struct slab *next;\n        int slabs;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        unsigned int __page_type;\n        atomic_t __page_refcount;\n        unsigned long obj_exts;                  // if CONFIG_SLAB_OBJ_EXT=y\n    };\n\n    struct kmem_cache_node {\n        spinlock_t list_lock;\n        unsigned long nr_partial;\n        struct list_head partial;\n        atomic_long_t nr_slabs;                  // if CONFIG_SLUB_DEBUG=y\n        atomic_long_t total_objects;             // if CONFIG_SLUB_DEBUG=y\n        struct list_head full;                   // if CONFIG_SLUB_DEBUG=y\n        struct node_barn *barn;                  // 6.18 <= kernel\n    };\n    \"\"\"\n\n    # CONFIG_SLAB_VIRTUAL=y\n    \"\"\"\n    struct kmem_cache {                          // if CONFIG_SLAB_VIRTUAL=y\n        ...\n        struct kmem_cache_order_objects min;     // [ANNOTATION]\n        struct kmem_cache_order_objects oo;      //    In kernel < 6.1.56, `min` and `oo` are swapped.\n        unsigned long nr_freed_pages;            // if CONFIG_SLAB_VIRTUAL=y && kernel < 6.1.56\n        struct list_head freed_slabs_normal;     // if CONFIG_SLAB_VIRTUAL=y && kernel < 6.1.56\n        struct list_head freed_slabs_min;        // if CONFIG_SLAB_VIRTUAL=y && kernel < 6.1.56\n        spinlock_t freed_slabs_lock;             // if CONFIG_SLAB_VIRTUAL=y && kernel < 6.1.56\n        struct kmem_cache_virtual {              // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n            spinlock_t freed_slabs_lock;         // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n            struct list_head freed_slabs;        // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n            struct list_head freed_slabs_min;    // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n            unsigned long nr_freed_pages;        // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n        } virtual;                               // if CONFIG_SLAB_VIRTUAL=y && 6.1.56 <= kernel\n        gfp_t allocflags;\n        ...\n        const char * name;\n        struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n        ...\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=y && kernel < 6.6\n        struct slab *compound_slab_head;\n        struct folio *backing_folio;\n        struct kmem_cache_order_objects oo;\n        spinlock_t slab_lists_lock;\n        struct list_head flush_list_elem;\n        unsigned long align_mask;\n        atomic_t pinstate;\n        struct slab *next;\n        int slabs;\n        struct kmem_cache *slab_cache;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        unsigned int __unused;\n        unsigned long memcg_data;                // if CONFIG_MEMCG=y\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=y && 6.6 <= kernel < 6.12\n        struct folio *backing_folio;\n        struct kmem_cache *slab_cache;\n        struct slab *next;\n        int slabs;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        struct kmem_cache_order_objects oo;\n        spinlock_t slab_lock;\n        unsigned long memcg_data;                // if CONFIG_MEMCG=y\n    }\n\n    struct virtual_slab {                        // if CONFIG_SLAB_VIRTUAL=y && 6.6 <= kernel < 6.12\n        struct slab slab;\n        struct virtual_slab *compound_slab_head;\n        unsigned long align_mask;\n    };\n\n    struct slab {                                // if CONFIG_SLAB_VIRTUAL=y && 6.12 <= kernel\n        struct slab *compound_slab_head;\n        struct folio *backing_folio;\n        struct kmem_cache_order_objects oo;\n        struct list_head flush_list_elem;\n        unsigned long align_mask;\n        spinlock_t slab_lock;\n        struct kmem_cache *slab_cache;\n        struct slab *next;\n        int slabs;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        unsigned long obj_exts                   // if CONFIG_SLAB_OBJ_EXT=y\n    };\n    \"\"\"\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            if not self.args.meta and not self.args.rescan:\n                return True\n\n        kversion = Kernel.kernel_version()\n        if not kversion:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        # resolve slab_caches\n        self.slab_caches = KernelAddressHeuristicFinder.get_slab_caches()\n        if self.slab_caches is None:\n            self.quiet_err(\"Failed to resolve `slab_caches`\")\n            return False\n        else:\n            self.quiet_info(\"slab_caches: {:#x}\".format(self.slab_caches))\n\n        # resolve __per_cpu_offset\n        __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n        if __per_cpu_offset is None:\n            self.quiet_info(\"__per_cpu_offset: Not found\")\n            self.cpu_offset = []\n            self.ncpus = 1\n        else:\n            self.quiet_info(\"__per_cpu_offset: {:#x}\".format(__per_cpu_offset))\n            self.cpu_offset = KernelCurrentCommand.get_each_cpu_offset(__per_cpu_offset)\n            self.ncpus = len(self.cpu_offset)\n\n        # offsetof(kmem_cache, list)\n        self.resolve_kmem_cache_offset_list()\n        if self.kmem_cache_offset_list is None:\n            self.quiet_info(\"offsetof(kmem_cache, list): Not found\")\n            return False\n        self.quiet_info(\"offsetof(kmem_cache, list): {:#x}\".format(self.kmem_cache_offset_list))\n\n        # offsetof(kmem_cache, name)\n        self.kmem_cache_offset_name = self.kmem_cache_offset_list - current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, name): {:#x}\".format(self.kmem_cache_offset_name))\n\n        # for CONFIG_SLAB_VIRTUAL\n        self.resolve_for_CONFIG_SLAB_VIRTUAL()\n\n        # offsetof(kmem_cache, cpu_slab)\n        self.kmem_cache_offset_cpu_slab = 0\n        self.quiet_info(\"offsetof(kmem_cache, cpu_slab): {:#x}\".format(self.kmem_cache_offset_cpu_slab))\n\n        # offsetof(kmem_cache, flags)\n        if kversion < \"6.18\":\n            self.kmem_cache_offset_flags = current_arch.ptrsize\n        else:\n            CONFIG_LOCKDEP = Symbol.get_ksymaddr(\"fs_reclaim_acquire\")\n            if CONFIG_LOCKDEP:\n                self.kmem_cache_offset_flags = current_arch.ptrsize * 4\n            else:\n                self.kmem_cache_offset_flags = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache, flags): {:#x}\".format(self.kmem_cache_offset_flags))\n\n        # offsetof(kmem_cache, cpu_sheaves)\n        if kversion < \"6.18\":\n            self.kmem_cache_offset_cpu_sheaves = None\n        else:\n            self.kmem_cache_offset_cpu_sheaves = self.kmem_cache_offset_flags - current_arch.ptrsize\n            self.quiet_info(\"offsetof(kmem_cache, cpu_sheaves): {:#x}\".format(self.kmem_cache_offset_cpu_sheaves))\n\n        # offsetof(kmem_cache, size)\n        self.kmem_cache_offset_size = self.kmem_cache_offset_flags + current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache, size): {:#x}\".format(self.kmem_cache_offset_size))\n\n        # offsetof(kmem_cache, object_size)\n        self.kmem_cache_offset_object_size = self.kmem_cache_offset_size + 4\n        self.quiet_info(\"offsetof(kmem_cache, object_size): {:#x}\".format(self.kmem_cache_offset_object_size))\n\n        # offsetof(kmem_cache, offset)\n        if kversion < \"5.9\":\n            self.kmem_cache_offset_offset = self.kmem_cache_offset_object_size + 4\n        else:\n            self.kmem_cache_offset_offset = self.kmem_cache_offset_object_size + 4 + 8\n        self.quiet_info(\"offsetof(kmem_cache, offset): {:#x}\".format(self.kmem_cache_offset_offset))\n\n        # offsetof(kmem_cache, red_left_pad)\n        self.kmem_cache_offset_red_left_pad = self.kmem_cache_offset_name - current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, red_left_pad): {:#x}\".format(self.kmem_cache_offset_red_left_pad))\n\n        # offsetof(kmem_cache, random)\n        self.resolve_kmem_cache_offset_random()\n        if self.kmem_cache_offset_random is None:\n            self.quiet_info(\"offsetof(kmem_cache, random): Not found\")\n        else:\n            self.quiet_info(\"offsetof(kmem_cache, random): {:#x}\".format(self.kmem_cache_offset_random))\n\n        # offsetof(kmem_cache, node)\n        self.resolve_kmem_cache_offset_node()\n        if self.kmem_cache_offset_node is None:\n            self.quiet_info(\"offsetof(kmem_cache, node): Not found\")\n        else:\n            self.quiet_info(\"offsetof(kmem_cache, node): {:#x}\".format(self.kmem_cache_offset_node))\n\n        # offsetof(kmem_cache_cpu, freelist)\n        self.kmem_cache_cpu_offset_freelist = 0\n        self.quiet_info(\"offsetof(kmem_cache_cpu, freelist): {:#x}\".format(self.kmem_cache_cpu_offset_freelist))\n\n        # offsetof(kmem_cache_cpu, page or slab)\n        self.kmem_cache_cpu_offset_page = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache_cpu, {:s}): {:#x}\".format(\n            Kernel.slab_page_str(), self.kmem_cache_cpu_offset_page,\n        ))\n\n        # offsetof(kmem_cache_cpu, partial)\n        self.kmem_cache_cpu_offset_partial = current_arch.ptrsize * 3\n        self.quiet_info(\"offsetof(kmem_cache_cpu, partial): {:#x}\".format(self.kmem_cache_cpu_offset_partial))\n\n        # offsetof(page, next) / offsetof(slab, next)\n        if self.slab_virtual_enabled:\n            if kversion < \"6.6\":\n                self.page_offset_next = current_arch.ptrsize * 7\n            elif kversion < \"6.12\":\n                self.page_offset_next = current_arch.ptrsize * 2\n            else: # 6.12\n                self.page_offset_next = current_arch.ptrsize * 8\n        else:\n            if kversion < \"4.16\" and is_32bit():\n                self.page_offset_next = current_arch.ptrsize * 5\n            elif kversion < \"4.18\":\n                self.page_offset_next = current_arch.ptrsize * 4\n            elif kversion < \"5.17\":\n                self.page_offset_next = current_arch.ptrsize\n            elif kversion < \"6.2\":\n                self.page_offset_next = current_arch.ptrsize\n            else:\n                self.page_offset_next = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof({:s}, next): {:#x}\".format(\n            Kernel.slab_page_str(), self.page_offset_next,\n        ))\n\n        # offsetof(page, freelist) / offsetof(slab, freelist)\n        if self.slab_virtual_enabled:\n            if kversion < \"6.6\":\n                self.page_offset_freelist = current_arch.ptrsize * 10\n            elif kversion < \"6.12\":\n                self.page_offset_freelist = current_arch.ptrsize * 4\n            else: # 6.12\n                self.page_offset_freelist = current_arch.ptrsize * 10\n        else:\n            if kversion < \"4.18\":\n                self.page_offset_freelist = current_arch.ptrsize * 2\n            elif kversion < \"5.17\":\n                self.page_offset_freelist = current_arch.ptrsize * 4\n            elif kversion < \"6.2\":\n                self.page_offset_freelist = current_arch.ptrsize * 4\n            else:\n                self.page_offset_freelist = current_arch.ptrsize * 4\n        self.quiet_info(\"offsetof({:s}, freelist): {:#x}\".format(\n            Kernel.slab_page_str(), self.page_offset_freelist,\n        ))\n\n        # offsetof(page, slab_cache) / offsetof(slab, slab_cache)\n        if self.slab_virtual_enabled:\n            if kversion < \"6.6\":\n                self.page_offset_slab_cache = current_arch.ptrsize * 9\n            elif kversion < \"6.12\":\n                self.page_offset_slab_cache = current_arch.ptrsize\n            else: # 6.12\n                self.page_offset_slab_cache = current_arch.ptrsize * 7\n        else:\n            if kversion < \"4.16\" and is_32bit():\n                self.page_offset_slab_cache = current_arch.ptrsize * 7\n            elif kversion < \"4.18\":\n                self.page_offset_slab_cache = current_arch.ptrsize * 6\n            elif kversion < \"5.17\":\n                self.page_offset_slab_cache = current_arch.ptrsize * 3\n            elif kversion < \"6.2\":\n                self.page_offset_slab_cache = current_arch.ptrsize * 3\n            else:\n                self.page_offset_slab_cache = current_arch.ptrsize\n        self.quiet_info(\"offsetof({:s}, slab_cache): {:#x}\".format(\n            Kernel.slab_page_str(), self.page_offset_slab_cache,\n        ))\n\n        # offsetof(page, inuse_objects_frozen) / offsetof(slab, inuse_objects_frozen)\n        self.page_offset_inuse_objects_frozen = self.page_offset_freelist + current_arch.ptrsize\n        self.quiet_info(\"offsetof({:s}, inuse_objects_frozen): {:#x}\".format(\n            Kernel.slab_page_str(), self.page_offset_inuse_objects_frozen,\n        ))\n\n        # parse extra members of `struct slab` for CONFIG_SLAB_VIRTUAL=y\n        if self.slab_virtual_enabled:\n            # offsetof(slab, flush_list_elem)\n            # [ANNOTATION]\n            #   In 6.6-based implementation, the member `flush_list_elem` has been removed from `struct slab`,\n            #   however, `slub_tlbflush_queue` uses the member `slab_list` or `next` (which?) for the same purpose.\n            #   So, when CONFIG_SLAB_VIRTUAL=y and 6.6 or later, `flush_list_elem` means `next`.\n            if kversion < \"6.6\":\n                self.page_offset_flush_list_elem = current_arch.ptrsize * 3\n            elif kversion < \"6.12\":\n                self.page_offset_flush_list_elem = current_arch.ptrsize * 2\n            else: # 6.12\n                self.page_offset_flush_list_elem = current_arch.ptrsize * 3\n            self.quiet_info(\"offsetof(slab, flush_list_elem): {:#x}\".format(self.page_offset_flush_list_elem))\n\n        # offsetof(kmem_cache_node, partial)\n        self.resolve_kmem_cache_node_offset_partial()\n        if self.kmem_cache_node_offset_partial is None:\n            self.quiet_info(\"offsetof(kmem_cache_node, partial): Not found\")\n        else:\n            self.quiet_info(\"offsetof(kmem_cache_node, partial): {:#x}\".format(self.kmem_cache_node_offset_partial))\n\n        # offsetof(kmem_cache_node, full)\n        if self.kmem_cache_node_offset_partial is None:\n            self.kmem_cache_node_offset_full = None\n        else:\n            self.kmem_cache_node_offset_full = self.kmem_cache_node_offset_partial + current_arch.ptrsize * 4\n\n        # for sheaves / barn\n        self.resolve_sheaves()\n\n        self.initialized = True\n        return True\n\n    @staticmethod\n    def get_flags_str(flags_value):\n        flags_dic = {\n            0x80000000: \"__OBJECT_POISON\",\n            0x40000000: \"__CMPXCHG_DOUBLE\",\n            0x20000000: \"SLAB_SKIP_KFENCE\",\n            0x10000000: \"SLAB_NO_USER_FLAGS\",\n            0x08000000: \"SLAB_KASAN\",\n            0x04000000: \"SLAB_ACCOUNT\",\n            0x02000000: \"SLAB_FAILSLAB\",\n            0x01000000: \"SLAB_NOTRACK\",\n            0x00800000: \"SLAB_NOLEAKTRACE\",\n            0x00400000: \"SLAB_DEBUG_OBJECTS\",\n            0x00200000: \"SLAB_TRACE\",\n            0x00100000: \"SLAB_MEM_SPREAD\",\n            0x00080000: \"SLAB_TYPESAFE_BY_RCU\",\n            0x00040000: \"SLAB_PANIC\",\n            0x00020000: \"SLAB_RECLAIM_ACCOUNT\",\n            0x00010000: \"SLAB_STORE_USER\",\n            0x00008000: \"SLAB_CACHE_DMA32\",\n            0x00004000: \"SLAB_CACHE_DMA\",\n            0x00002000: \"SLAB_HWCACHE_ALIGN\",\n            0x00001000: \"SLAB_KMALLOC\",\n            0x00000800: \"SLAB_POISON\",\n            0x00000400: \"SLAB_RED_ZONE\",\n            0x00000200: \"SLAB_DEBUG_INITIAL\", # kernel < v2.6.22\n            0x00000100: \"SLAB_CONSISTENCY_CHECKS\",\n        }\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n\n        flags_str = \" | \".join(flags)\n        if flags_str == \"\":\n            flags_str = \"none\"\n        return flags_str\n\n    def get_next_kmem_cache(self, addr, point_to_base=True):\n        if point_to_base:\n            addr += self.kmem_cache_offset_list\n        if self.args.reverse_walk:\n            return read_int_from_memory(addr) - self.kmem_cache_offset_list\n        else:\n            return read_int_from_memory(addr + current_arch.ptrsize) - self.kmem_cache_offset_list\n\n    def get_name(self, addr):\n        name_addr = read_int_from_memory(addr + self.kmem_cache_offset_name)\n        return read_cstring_from_memory(name_addr)\n\n    def get_random(self, addr):\n        if self.kmem_cache_offset_random is None:\n            return 0\n        else:\n            return read_int_from_memory(addr + self.kmem_cache_offset_random)\n\n    def get_kmem_cache_cpu(self, addr, cpu):\n        cpu_slab = read_int_from_memory(addr + self.kmem_cache_offset_cpu_slab)\n        if len(self.cpu_offset) > 0:\n            kmem_cache_cpu = cpu_slab + self.cpu_offset[cpu]\n        else:\n            kmem_cache_cpu = cpu_slab\n        return AddressUtil.align_address(kmem_cache_cpu)\n\n    def page2virt(self, page, kmem_cache, freelist_fastpath=()):\n        if self.slab_virtual_enabled:\n            ret = gdb.execute(\"slab-virtual --quiet to_virt {:#x}\".format(page[\"address\"]), to_string=True)\n            r = re.search(r\"Virt: (\\S+)\", ret)\n            if r:\n                return int(r.group(1), 16)\n            return None\n\n        if not self.args.skip_page2virt:\n            r = Kernel.page2virt(page[\"address\"])\n            if r is not None:\n                return r\n\n        # set up for heuristic search from freelist\n        freelist = list(freelist_fastpath) + page[\"freelist\"]\n        freelist = [x for x in freelist if isinstance(x, int) and x != 0] # ignore str and last 0\n        if not freelist:\n            return None\n\n        # heuristic detection pattern 1\n        # freed chunks are scattered and can be confirmed on each of the pages\n        page_heads = [x & get_pagesize_mask_high() for x in freelist]\n        uniq_page_heads = list(set(page_heads))\n        if page[\"num_pages\"] == len(uniq_page_heads):\n            return min(uniq_page_heads)\n\n        # heuristic detection pattern 2\n        # if there is only one pattern with good alignment, use it\n        # e.g., num_pages = 5\n        # 0xXXXX0000\n        # 0xXXXX1000   <----------------------------------- most_top_page   ^\n        # 0xXXXX2000                                                       ^|\n        # 0xXXXX3000   <-- chunk in freelist (min_page) ^                 ^||\n        # 0xXXXX4000                                    | known_num_pages |||\n        # 0xXXXX5000   <-- chunk in freelist (max_page) v                 ||v pattern 3\n        # 0xXXXX6000                                                      |v pattern 2\n        # 0xXXXX7000                                                      v pattern 1\n        chunk_size = kmem_cache[\"size\"]\n        min_page = min(freelist) & get_pagesize_mask_high()\n        max_page = max(freelist) & get_pagesize_mask_high()\n        known_num_pages = ((max_page - min_page) // get_pagesize()) + 1\n        unknown_num_pages = page[\"num_pages\"] - known_num_pages\n        most_top_page = min_page - (unknown_num_pages * get_pagesize())\n        candidate_top_pages = range(most_top_page, min_page + get_pagesize(), get_pagesize())\n        # alignment check for each candidate_top_pages\n        valid_top_pages = []\n        for cand_top in candidate_top_pages:\n            for chunk in freelist:\n                # divisible?\n                if (chunk - cand_top) % chunk_size != 0:\n                    break\n            else:\n                valid_top_pages.append(cand_top)\n            # fast break if invalid\n            if len(valid_top_pages) >= 2:\n                break\n        # confirm if there is only one valid pattern\n        if len(valid_top_pages) == 1:\n            return valid_top_pages[0]\n\n        # not found\n        return None\n\n    def pointer_xor(self, addr, chunk, cache):\n\n        def pattern1(addr, chunk, cache):\n            return chunk ^ addr ^ cache[\"random\"]\n\n        def pattern2(addr, chunk, cache):\n            return chunk ^ byteswap(addr) ^ cache[\"random\"]\n\n        if is_64bit():\n            shift_bits = 48\n        else:\n            shift_bits = 24\n\n        if self.swap is False:\n            chunk = pattern1(addr, chunk, cache)\n        elif self.swap is True:\n            chunk = pattern2(addr, chunk, cache)\n\n        elif self.swap is None: # swap type is unknown, try heuristic check\n            if pattern1(addr, chunk, cache) == 0:\n                chunk = pattern1(addr, chunk, cache)\n                self.swap = False\n            elif (chunk >> shift_bits) == (cache[\"random\"] >> shift_bits):\n                chunk = pattern1(addr, chunk, cache)\n                self.swap = False\n            else:\n                chunk = pattern2(addr, chunk, cache)\n                self.swap = True\n        return chunk\n\n    def walk_freelist(self, chunk, kmem_cache):\n        if self.args.simple:\n            return [chunk]\n\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        freelist = [chunk]\n        while chunk:\n            try:\n                addr = chunk + kmem_cache[\"offset\"]\n                chunk = read_int_from_memory(addr) # get next chunk\n            except gdb.MemoryError:\n                freelist.append(\"{:s}\".format(\n                    Color.colorify(\"Corrupted (Memory access denied)\", corrupted_msg_color),\n                ))\n                break\n            if self.kmem_cache_offset_random is not None: # fix if randomized\n                chunk = self.pointer_xor(addr, chunk, kmem_cache)\n            if chunk % 8:\n                freelist.append(\"{:#x}: {:s}\".format(\n                    chunk, Color.colorify(\"Corrupted (Not aligned)\", corrupted_msg_color),\n                ))\n                break\n            if chunk in freelist:\n                freelist.append(\"{:#x}: {:s}\".format(\n                    chunk, Color.colorify(\"Corrupted (Loop detected)\", corrupted_msg_color),\n                ))\n                break\n            freelist.append(chunk)\n        return freelist\n\n    def walk_caches_active_page(self, cpu, kmem_cache):\n        active_page = {}\n        active_page[\"address\"] = page = read_int_from_memory(\n            kmem_cache[\"kmem_cache_cpu\"][cpu][\"address\"] + self.kmem_cache_cpu_offset_page,\n        )\n        if is_valid_addr(page):\n            x = read_int_from_memory(page + self.page_offset_inuse_objects_frozen)\n            active_page[\"inuse\"] = x & 0xffff\n            active_page[\"objects\"] = (x >> 16) & 0x7fff\n            active_page[\"frozen\"] = (x >> 31) & 1\n            active_chunk = read_int_from_memory(page + self.page_offset_freelist)\n            active_page[\"freelist\"] = self.walk_freelist(active_chunk, kmem_cache)\n            active_page[\"num_pages\"] = (\n                kmem_cache[\"size\"] * active_page[\"objects\"] + get_pagesize_mask_low()\n            ) // get_pagesize()\n\n            active_page[\"virt_addr\"] = self.page2virt(\n                active_page, kmem_cache, kmem_cache[\"kmem_cache_cpu\"][cpu][\"freelist\"]\n            )\n\n        kmem_cache[\"kmem_cache_cpu\"][cpu][\"active_page\"] = active_page\n        return\n\n    def walk_caches_partial_page(self, cpu, kmem_cache):\n        kmem_cache[\"kmem_cache_cpu\"][cpu][\"partial_pages\"] = []\n        current_partial_page = read_int_from_memory(\n            kmem_cache[\"kmem_cache_cpu\"][cpu][\"address\"] + self.kmem_cache_cpu_offset_partial,\n        )\n        while True:\n            partial_page = {}\n            partial_page[\"address\"] = current_partial_page\n            if not is_valid_addr(current_partial_page):\n                kmem_cache[\"kmem_cache_cpu\"][cpu][\"partial_pages\"].append(partial_page)\n                break\n            x = read_int_from_memory(current_partial_page + self.page_offset_inuse_objects_frozen)\n            partial_page[\"inuse\"] = x & 0xffff\n            partial_page[\"objects\"] = (x >> 16) & 0x7fff\n            if partial_page[\"objects\"] == 0 or partial_page[\"inuse\"] > partial_page[\"objects\"]:\n                break # something is wrong\n            partial_page[\"frozen\"] = (x >> 31) & 1\n            partial_chunk = read_int_from_memory(current_partial_page + self.page_offset_freelist)\n            partial_page[\"freelist\"] = self.walk_freelist(partial_chunk, kmem_cache)\n            partial_page[\"num_pages\"] = (\n                kmem_cache[\"size\"] * partial_page[\"objects\"] + get_pagesize_mask_low()\n            ) // get_pagesize()\n            partial_page[\"virt_addr\"] = self.page2virt(partial_page, kmem_cache)\n            kmem_cache[\"kmem_cache_cpu\"][cpu][\"partial_pages\"].append(partial_page)\n            next_partial_page = read_int_from_memory(current_partial_page + self.page_offset_next)\n            if next_partial_page in [x[\"address\"] for x in kmem_cache[\"kmem_cache_cpu\"][cpu][\"partial_pages\"]]:\n                break\n            current_partial_page = next_partial_page\n        return\n\n    def walk_node_list(self, kmem_cache, kmem_cache_node, offset_list): # use different offsets\n        node_page_list = []\n        node_page_head = kmem_cache_node + offset_list\n        if not is_valid_addr(node_page_head):\n            return node_page_list\n        current_node_page = read_int_from_memory(node_page_head)\n        while current_node_page != node_page_head:\n            node_page = {}\n            node_page[\"address\"] = current_node_page - self.page_offset_next\n            if not is_valid_addr(node_page[\"address\"]):\n                node_page_list.append(node_page)\n                break\n            x = read_int_from_memory(node_page[\"address\"] + self.page_offset_inuse_objects_frozen)\n            node_page[\"inuse\"] = x & 0xffff\n            node_page[\"objects\"] = (x >> 16) & 0x7fff\n            if node_page[\"objects\"] == 0 or node_page[\"inuse\"] > node_page[\"objects\"]:\n                break # something is wrong\n            node_page[\"frozen\"] = (x >> 31) & 1\n            node_chunk = read_int_from_memory(node_page[\"address\"] + self.page_offset_freelist)\n            node_page[\"freelist\"] = self.walk_freelist(node_chunk, kmem_cache)\n            node_page[\"num_pages\"] = (\n                kmem_cache[\"size\"] * node_page[\"objects\"] + get_pagesize_mask_low()\n            ) // get_pagesize()\n            node_page[\"virt_addr\"] = self.page2virt(node_page, kmem_cache)\n            node_page_list.append(node_page)\n            current_node_page = read_int_from_memory(node_page[\"address\"] + self.page_offset_next)\n        return node_page_list\n\n    # for sheaf / barn\n    def walk_node_barn_list(self, kmem_cache, kmem_cache_node):\n        if not self.sheaves_enabled:\n            return\n\n        if self.args.skip_sheaf:\n            return\n\n        if not hasattr(kmem_cache, \"node_barn\"):\n            kmem_cache[\"node_barn\"] = []\n\n        def read_link_list(addr):\n            seen = []\n            while is_valid_addr(addr):\n                if addr in seen:\n                    break\n                seen.append(addr)\n                addr = read_int_from_memory(addr)\n            if len(seen) >= 1:\n                seen = seen[1:] # skip first\n            return seen\n\n        node_barn = {}\n        node_barn[\"address\"] = read_int_from_memory(kmem_cache_node + self.kmem_cache_node_offset_barn)\n        if is_valid_addr(node_barn[\"address\"]):\n            # full\n            node_barn[\"sheaves_full\"] = []\n            sheaves_full = read_link_list(node_barn[\"address\"] + self.node_barn_offset_sheaves_full)\n            for addr in sheaves_full:\n                sheaf = self.walk_sheaf(addr - self.slab_sheaf_offset_barn_list, kmem_cache[\"address\"])\n                node_barn[\"sheaves_full\"].append(sheaf)\n\n            # empty\n            node_barn[\"sheaves_empty\"] = []\n            sheaves_empty = read_link_list(node_barn[\"address\"] + self.node_barn_offset_sheaves_empty)\n            for addr in sheaves_empty:\n                sheaf = self.walk_sheaf(addr - self.slab_sheaf_offset_barn_list, kmem_cache[\"address\"])\n                node_barn[\"sheaves_empty\"].append(sheaf)\n\n        kmem_cache[\"node_barn\"].append(node_barn)\n        return\n\n    def walk_caches_node_page(self, cpu, kmem_cache):\n        if not self.kmem_cache_offset_node:\n            return\n        if not self.kmem_cache_node_offset_partial:\n            return\n\n        kmem_cache[\"nodes_partial\"] = []\n        if self.args.slub_debug_y:\n            kmem_cache[\"nodes_full\"] = []\n\n        kmem_cache_node_array = kmem_cache[\"address\"] + self.kmem_cache_offset_node\n        current_kmem_cache_node_ptr = kmem_cache_node_array\n        while True:\n            current_kmem_cache_node = read_int_from_memory(current_kmem_cache_node_ptr)\n            if current_kmem_cache_node == 0:\n                break\n            if current_kmem_cache_node == current_kmem_cache_node_ptr:\n                break\n            if current_kmem_cache_node & 0b111:\n                break\n\n            # node list (partial)\n            node_page_list_partial = self.walk_node_list(\n                kmem_cache, current_kmem_cache_node, self.kmem_cache_node_offset_partial,\n            )\n            kmem_cache[\"nodes_partial\"].append(node_page_list_partial)\n\n            # node list (full; exists when CONFIG_SLUB_DEBUG=y)\n            if self.args.slub_debug_y and self.kmem_cache_node_offset_full:\n                node_page_list_full = self.walk_node_list(\n                    kmem_cache, current_kmem_cache_node, self.kmem_cache_node_offset_full,\n                )\n                kmem_cache[\"nodes_full\"].append(node_page_list_full)\n\n            # node barn\n            self.walk_node_barn_list(kmem_cache, current_kmem_cache_node)\n\n            # goto next\n            current_kmem_cache_node_ptr += current_arch.ptrsize\n        return\n\n    # for CONFIG_SLAB_VIRTUAL\n    def walk_slab_list(self, list_head, offset_next):\n        slab_list = []\n        current_slab = read_int_from_memory(list_head) - offset_next\n        while is_valid_addr(current_slab) and current_slab + offset_next != list_head:\n            slab = {}\n            slab[\"address\"] = current_slab\n            kmem_cache = read_int_from_memory(current_slab + self.page_offset_slab_cache)\n            slab[\"slab_cache_name\"] = self.get_name(kmem_cache)\n            slab_list.append(slab)\n            # next slab\n            current_slab = read_int_from_memory(current_slab + offset_next) - offset_next\n        return slab_list\n\n    # for sheaf / barn\n    def walk_sheaf(self, addr, kmem_cache_addr):\n        sheaf = {}\n        sheaf[\"address\"] = addr\n        if not is_valid_addr(sheaf[\"address\"]):\n            return sheaf\n        sheaf[\"kmem_cache\"] = read_int_from_memory(sheaf[\"address\"] + self.slab_sheaf_offset_kmem_cache)\n        assert sheaf[\"kmem_cache\"] == kmem_cache_addr\n        sheaf[\"size\"] = read_int32_from_memory(sheaf[\"address\"] + self.slab_sheaf_offset_size)\n        sheaf[\"objects\"] = []\n        for i in range(sheaf[\"size\"]):\n            v = read_int_from_memory(sheaf[\"address\"] + self.slab_sheaf_offset_objects + current_arch.ptrsize * i)\n            sheaf[\"objects\"].append(v)\n        return sheaf\n\n    # for sheaf / barn\n    def walk_cpu_sheaves(self, cpu, kmem_cache):\n        if not self.sheaves_enabled:\n            return\n\n        if self.args.skip_sheaf:\n            return\n\n        if \"cpu_sheaves\" not in kmem_cache:\n            kmem_cache[\"cpu_sheaves\"] = {}\n\n        # cpu_sheaves\n        kmem_cache[\"cpu_sheaves\"][cpu] = {}\n        kmem_cache[\"cpu_sheaves\"][cpu][\"address\"] = self.get_slub_percpu_sheaves(kmem_cache[\"address\"], cpu)\n        if kmem_cache[\"cpu_sheaves\"][cpu][\"address\"] is None:\n            return\n        if self.slub_percpu_sheaves_offset_main is None:\n            return\n\n        # cpu_sheaves->main\n        kmem_cache[\"cpu_sheaves\"][cpu][\"main\"] = self.walk_sheaf(\n            read_int_from_memory(kmem_cache[\"cpu_sheaves\"][cpu][\"address\"] + self.slub_percpu_sheaves_offset_main),\n            kmem_cache[\"address\"],\n        )\n\n        # cpu_sheaves->spare\n        kmem_cache[\"cpu_sheaves\"][cpu][\"spare\"] = self.walk_sheaf(\n            read_int_from_memory(kmem_cache[\"cpu_sheaves\"][cpu][\"address\"] + self.slub_percpu_sheaves_offset_spare),\n            kmem_cache[\"address\"],\n        )\n        return\n\n    def walk_caches(self, target_names, cpus):\n        current_kmem_cache = self.get_next_kmem_cache(self.slab_caches, point_to_base=False)\n        parsed_caches = [{\"name\": \"slab_caches\", \"next\": current_kmem_cache}]\n\n        # first, parse kmem_cache\n        while current_kmem_cache + self.kmem_cache_offset_list != self.slab_caches:\n            kmem_cache = {}\n            # parse member\n            kmem_cache[\"name\"] = self.get_name(current_kmem_cache)\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                current_kmem_cache = self.get_next_kmem_cache(current_kmem_cache)\n                continue\n            kmem_cache[\"address\"] = current_kmem_cache\n            kmem_cache[\"flags\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_flags)\n            kmem_cache[\"flags_str\"] = SlubDumpCommand.get_flags_str(kmem_cache[\"flags\"])\n            kmem_cache[\"size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_size)\n            kmem_cache[\"object_size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_object_size)\n            kmem_cache[\"offset\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_offset)\n            kmem_cache[\"red_left_pad\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_red_left_pad)\n            kmem_cache[\"random\"] = self.get_random(current_kmem_cache)\n            kmem_cache[\"next\"] = self.get_next_kmem_cache(current_kmem_cache)\n            # parse extra members for feat. CONFIG_SLAB_VIRTUAL\n            if self.slab_virtual_enabled:\n                kmem_cache[\"nr_freed_pages\"] = read_int_from_memory(current_kmem_cache + self.kmem_cache_offset_nr_freed_pages)\n                kmem_cache[\"freed_slabs_normal\"] = self.walk_slab_list(\n                    current_kmem_cache + self.kmem_cache_offset_freed_slabs_normal, self.page_offset_next,\n                )\n                kmem_cache[\"freed_slabs_min\"] = self.walk_slab_list(\n                    current_kmem_cache + self.kmem_cache_offset_freed_slabs_min, self.page_offset_next,\n                )\n            parsed_caches.append(kmem_cache)\n\n            # goto next\n            current_kmem_cache = kmem_cache[\"next\"]\n\n            # fast break\n            if target_names != [] and not (self.args.list or self.args.list_no_sort):\n                parsed_names = [x[\"name\"] for x in parsed_caches]\n                if all(t in parsed_names for t in target_names):\n                    break\n\n        if self.args.list or self.args.list_no_sort:\n            return parsed_caches # fast return\n\n        # second, parse kmem_cache_cpu\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for kmem_cache in tqdm(parsed_caches[1:], leave=False): # parsed_caches[0] is slab_caches, so skip\n            # parse kmem_cache_cpu\n            kmem_cache[\"kmem_cache_cpu\"] = {}\n            for cpu in cpus:\n                kmem_cache[\"kmem_cache_cpu\"][cpu] = {}\n                kmem_cache[\"kmem_cache_cpu\"][cpu][\"address\"] = self.get_kmem_cache_cpu(kmem_cache[\"address\"], cpu)\n                active_chunk_fast = read_int_from_memory(\n                    kmem_cache[\"kmem_cache_cpu\"][cpu][\"address\"] + self.kmem_cache_cpu_offset_freelist,\n                )\n                kmem_cache[\"kmem_cache_cpu\"][cpu][\"freelist\"] = self.walk_freelist(active_chunk_fast, kmem_cache)\n                # parse active\n                if self.dump_target_active:\n                    self.walk_caches_active_page(cpu, kmem_cache)\n                    # parse cpu_sheaves\n                    self.walk_cpu_sheaves(cpu, kmem_cache)\n                # parse partial\n                if self.dump_target_partial:\n                    self.walk_caches_partial_page(cpu, kmem_cache)\n            # parse node\n            if self.dump_target_node:\n                self.walk_caches_node_page(cpu, kmem_cache)\n        return parsed_caches\n\n    def dump_page_print_layout(self, tag, kmem_cache, page, freelist, freelist_fastpath):\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        if page[\"virt_addr\"] is None:\n            self.out.append(\"        layout: Failed to the get first page\")\n            return\n\n        end_virt = page[\"virt_addr\"] + page[\"num_pages\"] * get_pagesize()\n        start_addr = page[\"virt_addr\"] + kmem_cache[\"red_left_pad\"]\n\n        if kmem_cache[\"red_left_pad\"]:\n            chunk_s = Color.colorify_hex(page[\"virt_addr\"], used_address_color)\n            self.out.append(\"        {:7s}   {:#05x} {:s} ({:s})\".format(\"layout:\", 0, chunk_s, \"never-used\"))\n            start_idx = 1\n        else:\n            start_idx = 0\n\n        for idx, chunk in enumerate(range(start_addr, end_virt, kmem_cache[\"size\"]), start=start_idx):\n            if chunk in freelist_fastpath[:-1]:\n                next_chunk = freelist_fastpath[freelist_fastpath.index(chunk) + 1]\n                if isinstance(next_chunk, str):\n                    next_msg = \"next: {:s}\".format(next_chunk)\n                else:\n                    next_msg = \"next: {:#x}\".format(next_chunk)\n                chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            elif chunk in freelist[:-1]:\n                next_chunk = freelist[freelist.index(chunk) + 1]\n                if isinstance(next_chunk, str):\n                    next_msg = \"next: {:s}\".format(next_chunk)\n                else:\n                    next_msg = \"next: {:#x}\".format(next_chunk)\n                if tag == \"active\":\n                    next_msg += \" (slow path)\"\n                chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            else:\n                if page[\"objects\"] <= idx:\n                    next_msg = \"never-used\"\n                else:\n                    next_msg = \"in-use\"\n                chunk_s = Color.colorify_hex(chunk, used_address_color)\n            self.out.append(\"        {:7s}   {:#05x} {:s} ({:s})\".format(\n                \"layout:\" if idx == 0 else \"\", idx, chunk_s, next_msg,\n            ))\n\n            # dump chunks\n            if self.args.hexdump_used and next_msg == \"in-use\":\n                peeked_data = read_memory(chunk, self.args.hexdump_used)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.hexdump_freed and next_msg.startswith(\"next: \"):\n                peeked_data = read_memory(chunk, self.args.hexdump_freed)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.telescope_used and next_msg == \"in-use\":\n                n = self.args.telescope_used // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n\n            if self.args.telescope_freed and next_msg.startswith(\"next: \"):\n                n = self.args.telescope_freed // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n        return\n\n    def dump_page_print_freelist(self, tag, kmem_cache, page, freelist, freelist_fastpath):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        def print_freelist(freelist):\n            for chunk_addr in freelist:\n                if page[\"virt_addr\"] is not None:\n                    if chunk_addr == 0:\n                        continue\n                    if isinstance(chunk_addr, str):\n                        chunk_idx = \"\"\n                        msg = chunk_addr\n                    else:\n                        chunk_idx = (chunk_addr - page[\"virt_addr\"]) // kmem_cache[\"size\"]\n                        if chunk_idx < 0 or page[\"objects\"] <= chunk_idx:\n                            chunk_idx = \"\"\n                        else:\n                            chunk_idx = \"{:#05x}\".format(chunk_idx)\n                        msg = Color.colorify_hex(chunk_addr, freed_address_color)\n                    self.out.append(\"                  {:5s} {:s}\".format(chunk_idx, msg))\n                else:\n                    if isinstance(chunk_addr, str):\n                        msg = chunk_addr\n                    else:\n                        msg = Color.colorify_hex(chunk_addr, freed_address_color)\n                    self.out.append(\"                        {:s}\".format(msg))\n            return\n\n        if tag == \"active\":\n            if freelist_fastpath == [] or freelist_fastpath == [0]:\n                self.out.append(\"        freelist (fast path): (none)\")\n            else:\n                self.out.append(\"        freelist (fast path):\")\n                print_freelist(freelist_fastpath)\n            if freelist == [] or freelist == [0]:\n                self.out.append(\"        freelist (slow path): (none)\")\n            else:\n                self.out.append(\"        freelist (slow path):\")\n                print_freelist(freelist)\n        else:\n            if freelist == [] or freelist == [0]:\n                self.out.append(\"        freelist: (none)\")\n            else:\n                self.out.append(\"        freelist:\")\n                print_freelist(freelist)\n        return\n\n    def dump_page(self, page, kmem_cache, tag, freelist_fastpath=()):\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n        heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        freelist_fastpath = list(freelist_fastpath)\n\n        # page address\n        if tag == \"active\":\n            tag_s = Color.colorify(\"{:s} page\".format(tag), label_active_color)\n        else:\n            tag_s = Color.colorify(\"{:s} page\".format(tag), label_inactive_color)\n        self.out.append(\"      {:s}: {:#x}\".format(tag_s, page[\"address\"]))\n\n        # fast return if invalid\n        if not is_valid_addr(page[\"address\"]):\n            return\n\n        # print virtual address\n        if page[\"virt_addr\"] is None:\n            self.out.append(\"        virtual address: ???\")\n        else:\n            colored_virt_addr = Color.colorify_hex(page[\"virt_addr\"], heap_page_color)\n            self.out.append(\"        virtual address: {:s}\".format(colored_virt_addr))\n\n        # print info\n        self.out.append(\"        num pages: {:d}\".format(page[\"num_pages\"]))\n\n        if self.args.simple:\n            return\n\n        freelist = page[\"freelist\"]\n        if tag == \"active\":\n            freelist_len = len(set(freelist + freelist_fastpath)) - 1 # ignore last 0\n            inuse = page[\"objects\"] - freelist_len\n        else:\n            inuse = page[\"inuse\"]\n        self.out.append(\"        in-use: {:d}/{:d}\".format(inuse, page[\"objects\"]))\n        self.out.append(\"        frozen: {:d}\".format(page[\"frozen\"]))\n\n        # print layout\n        self.dump_page_print_layout(tag, kmem_cache, page, freelist, freelist_fastpath)\n\n        # print freelist\n        self.dump_page_print_freelist(tag, kmem_cache, page, freelist, freelist_fastpath)\n        return\n\n    # for CONFIG_SLAB_VIRTUAL\n    def dump_slub_tlbflush_queue(self, parsed_slabs):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        not_mapped_virt = Config.get_gef_setting(\"theme.address_valid_but_none\")\n        # dump\n        self.out.append(\"slub_tlbflush_queue @ {:#x}\".format(self.slub_tlbflush_queue))\n        for slab in parsed_slabs:\n            slab_addr = slab[\"address\"]\n            self.out.append(\"\")\n            self.out.append(\"  slab: {:#x}\".format(slab_addr))\n            self.out.append(\"    kmem_cache: {:s}\".format(Color.colorify(slab[\"slab_cache_name\"], chunk_label_color)))\n            # virtual address is not mapped here\n            virt = \"{:#x}\".format(self.page2virt_for_slab_virtual(slab_addr))\n            self.out.append(\"    virt: {:s}\".format(Color.colorify(virt, not_mapped_virt)))\n        return\n\n    # for sheaf / barn\n    def dump_sheaf(self, sheaf, tag):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        self.out.append(\"      {:s}: {:#x}\".format(tag, sheaf[\"address\"]))\n        self.out.append(\"        size: {:d}\".format(sheaf[\"size\"]))\n\n        if self.args.simple:\n            return\n\n        for i, chunk in enumerate(sheaf[\"objects\"]):\n            chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            if i == 0:\n                self.out.append(\"        objects:  {:#05x} {:s}\".format(i, chunk_s))\n            elif i == len(sheaf[\"objects\"]) - 1:\n                self.out.append(\"                  {:#05x} {:s} <- top\".format(i, chunk_s))\n            else:\n                self.out.append(\"                  {:#05x} {:s}\".format(i, chunk_s))\n\n            if self.args.hexdump_freed:\n                peeked_data = read_memory(chunk, self.args.hexdump_freed)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n            if self.args.telescope_freed:\n                n = self.args.telescope_freed // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n        return\n\n    # for sheaf / barn\n    def dump_sheaves(self, cpu_sheaves, kmem_cache):\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n\n        # main\n        if \"main\" in cpu_sheaves:\n            if cpu_sheaves[\"main\"][\"address\"]:\n                tag = Color.colorify(\"main sheaf\", label_active_color) + \" (fastest path)\"\n                self.dump_sheaf(cpu_sheaves[\"main\"], tag)\n\n        # spare\n        if \"spare\" in cpu_sheaves:\n            if cpu_sheaves[\"spare\"][\"address\"]:\n                tag = Color.colorify(\"spare sheaf\", label_inactive_color)\n                self.dump_sheaf(cpu_sheaves[\"spare\"], tag)\n        return\n\n    def dump_caches(self, target_names, cpus, parsed_caches):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n\n        self.out.append(\"slab_caches @ {:#x}\".format(self.slab_caches))\n        for kmem_cache in parsed_caches[1:]:\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                continue\n\n            # dump kmem_cache metadata\n            self.out.append(\"\")\n            self.out.append(\"  kmem_cache: {:#x}\".format(kmem_cache[\"address\"]))\n            self.out.append(\"    name: {:s}\".format(Color.colorify(kmem_cache[\"name\"], chunk_label_color)))\n            self.out.append(\"    flags: {:#x} ({:s})\".format(kmem_cache[\"flags\"], kmem_cache[\"flags_str\"]))\n            object_size_s = Color.colorify_hex(kmem_cache[\"object_size\"], chunk_size_color)\n            self.out.append(\"    object size: {:s} (chunk size: {:#x})\".format(object_size_s, kmem_cache[\"size\"]))\n            self.out.append(\"    offset (next pointer in chunk): {:#x}\".format(kmem_cache[\"offset\"]))\n            if self.kmem_cache_offset_random is not None:\n                if self.args.no_xor is False:\n                    if self.swap is True:\n                        fmt = \"    random (xor key): {:#x} ^ byteswap(&chunk->next)\"\n                        self.out.append(fmt.format(kmem_cache[\"random\"]))\n                    else:\n                        fmt = \"    random (xor key): {:#x} ^ &chunk->next\"\n                        self.out.append(fmt.format(kmem_cache[\"random\"]))\n            self.out.append(\"    red_left_pad: {:#x}\".format(kmem_cache[\"red_left_pad\"]))\n\n            # dump freelist in kmem_cache only if CONFIG_SLAB_VIRTUAL=y\n            if self.slab_virtual_enabled:\n                nr_freed_pages = kmem_cache[\"nr_freed_pages\"]\n                self.out.append(\"    nr_freed_pages: {:#d}\".format(nr_freed_pages))\n\n                # freed_slabs_normal/freed_slabs\n                self.out.append(\"    freed_slabs_normal: {:#d}/{:#d}\".format(\n                    len(kmem_cache[\"freed_slabs_normal\"]), nr_freed_pages,\n                ))\n                for idx, slab in enumerate(kmem_cache[\"freed_slabs_normal\"]):\n                    self.out.append(\"             {:#05x} {:#x}\".format(idx, slab[\"address\"]))\n\n                # freed_slabs_min\n                self.out.append(\"    freed_slabs_min: {:#d}/{:#d}\".format(\n                    len(kmem_cache[\"freed_slabs_min\"]), nr_freed_pages,\n                ))\n                for idx, slab in enumerate(kmem_cache[\"freed_slabs_min\"]):\n                    self.out.append(\"             {:#05x} {:#x}\".format(idx, slab[\"address\"]))\n\n            # dump each kmem_cache_cpu\n            for cpu in cpus:\n                self.out.append(\"    kmem_cache_cpu (cpu{:d}): {:#x}\".format(\n                    cpu, kmem_cache[\"kmem_cache_cpu\"][cpu][\"address\"],\n                ))\n\n                # dump active\n                if self.dump_target_active:\n                    active_page = kmem_cache[\"kmem_cache_cpu\"][cpu][\"active_page\"]\n                    freelist_fastpath = kmem_cache[\"kmem_cache_cpu\"][cpu][\"freelist\"]\n                    self.dump_page(active_page, kmem_cache, \"active\", freelist_fastpath)\n                    # dump sheaves\n                    if \"cpu_sheaves\" in kmem_cache:\n                        cpu_sheaves = kmem_cache[\"cpu_sheaves\"][cpu]\n                        self.dump_sheaves(cpu_sheaves, kmem_cache)\n\n                # dump partial\n                if self.dump_target_partial:\n                    printed_count = 0\n                    for partial_page in kmem_cache[\"kmem_cache_cpu\"][cpu][\"partial_pages\"]:\n                        self.dump_page(partial_page, kmem_cache, \"partial\")\n                        printed_count += 1\n                    if printed_count > 1 : # included address == 0\n                        self.out.append(\"        (end of the list)\")\n\n            # dump nodes\n            if self.dump_target_node and \"nodes_partial\" in kmem_cache:\n                for node_index, node_page_list_partial in enumerate(kmem_cache[\"nodes_partial\"]):\n                    node_addr = read_int_from_memory(\n                        kmem_cache[\"address\"] + self.kmem_cache_offset_node + current_arch.ptrsize * node_index,\n                    )\n                    self.out.append(\"    kmem_cache_node[{:d}]: {:#x}\".format(node_index, node_addr))\n\n                    # node list (partial)\n                    printed_count = 0\n                    for node_page in node_page_list_partial:\n                        self.dump_page(node_page, kmem_cache, \"node\")\n                        printed_count += 1\n                    if printed_count == 0:\n                        self.out.append(\"      {:s}: (none)\".format(\n                            Color.colorify(\"node pages\", label_inactive_color),\n                        ))\n\n                    # node list (full; exists when CONFIG_SLUB_DEBUG=y)\n                    if \"nodes_full\" in kmem_cache:\n                        node_page_list_full = kmem_cache[\"nodes_full\"][node_index]\n                        printed_count = 0\n                        for node_page in node_page_list_full:\n                            self.dump_page(node_page, kmem_cache, \"node (full)\")\n                            printed_count += 1\n                        if printed_count == 0:\n                            self.out.append(\"      {:s}: (none)\".format(\n                                Color.colorify(\"node (full) pages\", label_inactive_color),\n                            ))\n\n                    # barn list (6.18~)\n                    if \"node_barn\" in kmem_cache:\n                        for node_barn in kmem_cache[\"node_barn\"]:\n                            if \"shaves_full\" in node_barn:\n                                for sheaves_full in node_barn[\"sheaves_full\"]:\n                                    self.dump_sheaf(sheaves_full, Color.colorify(\"node full sheaf\", \"underline\"))\n                            if \"shaves_empty\" in node_barn:\n                                for sheaves_empty in node_barn[\"sheaves_empty\"]:\n                                    self.dump_sheaf(sheaves_empty, Color.colorify(\"node empty sheaf\", \"underline\"))\n\n            self.out.append(\"    next: {:#x}\".format(kmem_cache[\"next\"]))\n        return\n\n    def dump_names(self, parsed_caches):\n        name_width = max(len(k[\"name\"]) for k in parsed_caches[1:])\n\n        if not self.args.quiet:\n            fmt = \"{:<18s} {:<18s} {:\" + str(name_width) + \"s} {:20s}\"\n            legend = [\"Object Size\", \"Chunk Size\", \"Name\", \"kmem_cache\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if self.args.list_no_sort:\n            target_caches = parsed_caches[1:]\n        else:\n            target_caches = sorted(parsed_caches[1:], key=lambda x: (x[\"object_size\"], x[\"size\"], x[\"name\"]))\n\n        for kmem_cache in target_caches:\n            objsz = \"{0:d} ({0:#x})\".format(kmem_cache[\"object_size\"])\n            chunksz = \"{0:d} ({0:#x})\".format(kmem_cache[\"size\"])\n            chunk_name = kmem_cache[\"name\"]\n            address = kmem_cache[\"address\"]\n            self.out.append(\"{:18s} {:18s} {:{:d}s} {:#x}\".format(objsz, chunksz, chunk_name, name_width, address))\n        return\n\n    def slubwalk(self, target_names, cpu):\n        if self.initialize() is False:\n            self.quiet_err(\"Initialization failed\")\n            return\n\n        if self.args.meta:\n            return\n\n        if self.args.list or self.args.list_no_sort:\n            parsed_caches = self.walk_caches(target_names, cpus=None)\n            self.dump_names(parsed_caches)\n            return\n\n        if cpu is None:\n            target_cpus = list(range(self.ncpus))\n        else:\n            if self.ncpus <= cpu:\n                self.quiet_err(\"CPU number is invalid (valid range: {:d}-{:d})\".format(0, self.ncpus - 1))\n                return\n            target_cpus = [cpu]\n\n        if self.args.tlbflush_queue:\n            if self.slab_virtual_enabled:\n                parsed_queue = self.walk_slab_list(self.slub_tlbflush_queue, self.page_offset_flush_list_elem)\n                self.dump_slub_tlbflush_queue(parsed_queue)\n            else:\n                self.quiet_warn(\"CONFIG_SLAB_VIRTUAL is disabled. option `--tlbflush-queue` is ignored\")\n            return\n\n        parsed_caches = self.walk_caches(target_names, target_cpus)\n        self.dump_caches(target_names, target_cpus, parsed_caches)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if args.help_for_slab_virtual:\n            gef_print(self._note2_.strip())\n            return\n\n        self.quiet_info(\"Wait for memory scan\")\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            pass\n        elif allocator == \"SLUB_TINY\":\n            self.quiet_err(\"Unsupported; You should use `slub-tiny-dump`\")\n            return\n        elif allocator == \"SLAB\":\n            self.quiet_err(\"Unsupported; You should use `slab-dump`\")\n            return\n        elif allocator == \"SLOB\":\n            self.quiet_err(\"Unsupported; You should use `slob-dump`\")\n            return\n        else:\n            self.quiet_err(\"Unsupported: Unknown allocator\")\n            return\n\n        # The slub-dump command is used by page2virt and kmagic to find vmemmap and sizeof(struct page).\n        # Therefore, slub-dump itself may be called recursively (up to once) from slub-dump.\n        # If a recursive call is made, various parameters held by self will be destroyed.\n        # It's very tricky, but if we make sure to call page2virt first,\n        # no further calls will be made and it will work without any problems.\n        if not hasattr(self, \"initialized\"):\n            if is_x86() or is_arm32():\n                if not args.skip_page2virt:\n                    args = self.args # backup\n                    gdb.execute(\"page2virt 0\", to_string=True)\n                    # self.args will be overwritten. this is workaround.\n                    self.args = args # revert\n\n        if args.no_byte_swap is None:\n            self.swap = None\n        else:\n            self.swap = not args.no_byte_swap\n\n        if args.no_xor or args.no_byte_swap:\n            args.rescan = True\n        if args.offset_random is not None or args.offset_node is not None:\n            args.rescan = True\n\n        # dump target\n        self.dump_target_active = True\n        self.dump_target_partial = args.verbose or args.vverbose\n        self.dump_target_node = args.vverbose\n        if args.only_partial:\n            self.dump_target_active = False\n            self.dump_target_partial = True\n            self.dump_target_node = False\n        elif args.only_node:\n            self.dump_target_active = False\n            self.dump_target_partial = False\n            self.dump_target_node = True\n\n        self.maps = None\n        self.out = []\n        self.slubwalk(args.cache_name, args.cpu)\n        self.print_output()\n        return\n\n\n@register_command\nclass SlubTinyDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump SLUB-TINY free-list.\"\"\"\n\n    _cmdline_ = \"slub-tiny-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"cache_name\", metavar=\"SLUB_CACHE_NAME\", nargs=\"*\", help=\"filter by specific slub cache name.\")\n    parser.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"list all slub cache names.\")\n    parser.add_argument(\"-L\", \"--list-no-sort\", action=\"store_true\", help=\"list all slub cache names without sort.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"-R\", \"--reverse-walk\", action=\"store_true\", help=\"reverse order walk for slab_caches->list_head.\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"skip displaying layout and freelist.\")\n    parser.add_argument(\"--hexdump-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--hexdump-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cached offset.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    parser.add_argument(\"--skip-page2virt\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] used internally in gef, please don't use it.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} kmalloc-256  # dump kmalloc-256 from all cpus\",\n        \"{0:s} --list       # list slub cache names\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified SLUB-TINY structure:\",\n        \"\",\n        \"                         +-kmem_cache--+     +-kmem_cache--+   +-kmem_cache--+\",\n        \"                         | flags       |     | flags       |   | flags       |\",\n        \"                         | size        |     | size        |   | size        |\",\n        \"                         | object_size |     | object_size |   | object_size |\",\n        \"                         | offset      |     | offset      |   | offset      |\",\n        \"       +-slab_caches-+   | name        |     | name        |   | name        |\",\n        \" ...<->| list_head   |<->| list_head   |<--->| list_head   |<->| list_head   |<-> ...\",\n        \"       +-------------+   | node[]      |--+  | node[]      |   | node[]      |\",\n        \"                         +-------------+  |  +-------------+   +-------------+\",\n        \"                                          |\",\n        \"    +-------------------------------------+\",\n        \"    |                                               [numa node partial page freelist]\",\n        \"    v                     +-slab-----------+          +-chunk---+  +-chunk---+\",\n        \"  +-kmem_cache_node-+     | freelist       |----+     | ^       |  | ^       |\",\n        \"  | partial         |---->| next           |--+ |     | |offset |  | |offset |\",\n        \"  +-----------------+     +----------------+  | |     | v       |  | v       |\",\n        \"  | ...             |                         | +---->| next    |->| next    |->NULL\",\n        \"  +-----------------+  +----------------------+       +---------+  +---------+\",\n        \"                       |\",\n        \"                       |                            [numa node partial page freelist]\",\n        \"                       |  +-slab-----------+          +-chunk---+  +-chunk---+\",\n        \"                       |  | freelist       |----+     | ^       |  | ^       |\",\n        \"                       +->| next           |--+ |     | |offset |  | |offset |\",\n        \"                          +----------------+  | |     | v       |  | v       |\",\n        \"                                              | +---->| next    |->| next    |->NULL\",\n        \"                       +----------------------+       +---------+  +---------+\",\n        \"                       |\",\n        \"                       v\",\n        \"                      ...\",\n        \"* SLUB-TINY was introduced in kernel 6.2.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @Cache.cache_until_next\n    def parse_kmem_caches_for_initialize(self):\n        seen = [self.slab_caches]\n        current = self.slab_caches\n        while True:\n            current = read_int_from_memory(current)\n            if current in seen:\n                break\n            seen.append(current)\n        kmem_caches = seen[1:] # skip slab_caches itself\n        return kmem_caches\n\n    def resolve_kmem_cache_offset_list(self):\n        # fast path\n        try:\n            self.kmem_cache_offset_list = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).list\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        candidate = (0, -1) # (count, candidate_offset)\n        for candidate_offset in range(current_arch.ptrsize * 2, 0x70, current_arch.ptrsize):\n            # backward search for the start of `struct kmem_cache`\n            count = 0\n            for kmem_cache in kmem_caches:\n                val = read_int_from_memory(kmem_cache - candidate_offset)\n                if val & 0x4000_0000: # __CMPXCHG_DOUBLE\n                    count += 1\n            if candidate[0] < count:\n                candidate = (count, candidate_offset)\n\n        self.kmem_cache_offset_list = candidate[1]\n        return\n\n    def resolve_kmem_cache_offset_node(self):\n        # fast path\n        try:\n            self.kmem_cache_offset_node = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).node\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        self.kmem_cache_offset_node = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        start_offset = self.kmem_cache_offset_list + current_arch.ptrsize * 2 # sizeof(kmem_cache.list)\n        for candidate_offset in range(start_offset, start_offset + 0x100, current_arch.ptrsize):\n            # walk from list for heuristic search\n            found = True\n            for kmem_cache in kmem_caches:\n                top = kmem_cache - self.kmem_cache_offset_list\n                maybe_node = read_int_from_memory(top + candidate_offset)\n                if not is_valid_addr(maybe_node):\n                    found = False\n                    break\n                # skip node[0].{list_lock,nr_partial} and check node[0].partial.next\n                if not is_valid_addr(maybe_node + current_arch.ptrsize * 2):\n                    found = False\n                    break\n                # node[0].partial.next is slab\n                # maybe_slab actually points to &slab.next, not to the beginning of the structure\n                maybe_slab = read_int_from_memory(maybe_node + current_arch.ptrsize * 2)\n                if not is_valid_addr(maybe_slab):\n                    found = False\n                    break\n                # slab.next (it's actually the list_head)\n                a = read_int_from_memory(maybe_slab)\n                if not is_valid_addr(a):\n                    found = False\n                    break\n                b = read_int_from_memory(maybe_slab + current_arch.ptrsize)\n                if not is_valid_addr(b):\n                    found = False\n                    break\n                # something is in linklist\n                if a != maybe_node + current_arch.ptrsize * 2:\n                    # check slab->slab_cache\n                    c = read_int_from_memory(maybe_slab - current_arch.ptrsize)\n                    if c != top:\n                        found = False\n                        break\n\n            if found:\n                self.kmem_cache_offset_node = candidate_offset\n                return\n        return\n\n    def resolve_kmem_cache_node_offset_partial(self):\n        # fast path\n        try:\n            self.kmem_cache_node_offset_partial = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache_node*)0).partial\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        self.kmem_cache_node_offset_partial = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        node = read_int_from_memory(kmem_caches[0] - self.kmem_cache_offset_list + self.kmem_cache_offset_node)\n        for i in range(2, 16):\n            offset_partial = current_arch.ptrsize * i\n            if is_double_link_list(node + offset_partial):\n                self.kmem_cache_node_offset_partial = offset_partial\n                return\n        return\n\n    \"\"\"\n    struct kmem_cache {\n        struct slub_percpu_sheaves __percpu *cpu_sheaves; // 6.18 <= kernel\n        slab_flags_t flags;                      // unsigned int (+ padding 4 byte)\n        unsigned long min_partial;\n        unsigned int size;\n        unsigned int object_size;\n        struct reciprocal_value {                //\n            u32 m;                               //\n            u8 sh1, sh2;                         // (+ padding 2 byte)\n        } reciprocal_size;                       //\n        unsigned int offset;\n        unsigned int cpu_partial;                // if CONFIG_SLUB_CPU_PARTIAL=y\n        unsigned int cpu_partial_slabs;          // if CONFIG_SLUB_CPU_PARTIAL=y\n        struct kmem_cache_order_objects oo;\n        struct kmem_cache_order_objects min;\n        gfp_t allocflags;                        // unsigned int\n        int refcount;\n        void (*ctor)(void *);\n        unsigned int inuse;\n        unsigned int align;\n        unsigned int red_left_pad;\n        const char *name;\n        struct list_head list; <-----> struct list_head <-----> struct list_head <-----> ...\n        struct kobject {\n            const char *name;\n            struct list_head entry;\n            struct kobject *parent;\n            struct kset *kset;\n            const struct kobj_type *ktype;\n            struct kernfs_node *sd;\n            struct kref kref;\n            struct delayed_work release;         // if CONFIG_DEBUG_KOBJECT_RELEASE=y\n            unsigned int state_initialized:1;\n            unsigned int state_in_sysfs:1;\n            unsigned int state_add_uevent_sent:1;\n            unsigned int state_remove_uevent_sent:1;\n            unsigned int uevent_suppress:1;\n        } kobj;                                  // if CONFIG_SYSFS=y\n        unsigned int remote_node_defrag_ratio;   // if CONFIG_NUMA=y\n        struct kasan_cache {\n            int alloc_meta_offset;\n            int free_meta_offset;\n            bool is_kmalloc;\n        } kasan_info;                            // if CONFIG_KASAN=y\n        unsigned int useroffset;                 // if CONFIG_HARDENED_USERCOPY=y\n        unsigned int usersize;                   // if CONFIG_HARDENED_USERCOPY=y\n        struct kmem_cache_node *node[MAX_NUMNODES];\n    };\n\n    struct slab {\n        unsigned long __page_flags;\n        struct kmem_cache *slab_cache;\n        struct slab *next;\n        int slabs;\n        void *freelist;\n        unsigned inuse:16, objects:15, frozen:1;\n        ...\n    };\n\n    struct kmem_cache_node {\n        spinlock_t list_lock;\n        unsigned long nr_partial;\n        struct list_head partial;\n        atomic_long_t nr_slabs;                  // if CONFIG_SLUB_DEBUG=y\n        atomic_long_t total_objects;             // if CONFIG_SLUB_DEBUG=y\n        struct list_head full;                   // if CONFIG_SLUB_DEBUG=y\n    };\n    \"\"\"\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            if not self.args.meta and not self.args.rescan:\n                return True\n\n        kversion = Kernel.kernel_version()\n        if not kversion:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        # resolve slab_caches\n        self.slab_caches = KernelAddressHeuristicFinder.get_slab_caches()\n        if self.slab_caches is None:\n            self.quiet_err(\"Failed to resolve `slab_caches`\")\n            return False\n        else:\n            self.quiet_info(\"slab_caches: {:#x}\".format(self.slab_caches))\n\n        # offsetof(kmem_cache, list)\n        self.resolve_kmem_cache_offset_list()\n        self.quiet_info(\"offsetof(kmem_cache, list): {:#x}\".format(self.kmem_cache_offset_list))\n\n        # offsetof(kmem_cache, name)\n        self.kmem_cache_offset_name = self.kmem_cache_offset_list - current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, name): {:#x}\".format(self.kmem_cache_offset_name))\n\n        # offsetof(kmem_cache, flags)\n        if kversion < \"6.18\":\n            self.kmem_cache_offset_flags = 0\n        else:\n            self.kmem_cache_offset_flags = current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, flags): {:#x}\".format(self.kmem_cache_offset_flags))\n\n        # offsetof(kmem_cache, size)\n        self.kmem_cache_offset_size = self.kmem_cache_offset_flags + current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache, size): {:#x}\".format(self.kmem_cache_offset_size))\n\n        # offsetof(kmem_cache, object_size)\n        self.kmem_cache_offset_object_size = self.kmem_cache_offset_size + 4\n        self.quiet_info(\"offsetof(kmem_cache, object_size): {:#x}\".format(self.kmem_cache_offset_object_size))\n\n        # offsetof(kmem_cache, offset)\n        self.kmem_cache_offset_offset = self.kmem_cache_offset_object_size + 4 + 8\n        self.quiet_info(\"offsetof(kmem_cache, offset): {:#x}\".format(self.kmem_cache_offset_offset))\n\n        # offsetof(kmem_cache, red_left_pad)\n        self.kmem_cache_offset_red_left_pad = self.kmem_cache_offset_name - current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, red_left_pad): {:#x}\".format(self.kmem_cache_offset_red_left_pad))\n\n        # offsetof(kmem_cache, node)\n        self.resolve_kmem_cache_offset_node()\n        if self.kmem_cache_offset_node is None:\n            self.quiet_info(\"offsetof(kmem_cache, node): Not found\")\n        else:\n            self.quiet_info(\"offsetof(kmem_cache, node): {:#x}\".format(self.kmem_cache_offset_node))\n\n        # offsetof(slab, next)\n        self.slab_offset_next = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(slab, next): {:#x}\".format(self.slab_offset_next))\n\n        # offsetof(slab, freelist)\n        self.slab_offset_freelist = current_arch.ptrsize * 4\n        self.quiet_info(\"offsetof(slab, freelist): {:#x}\".format(self.slab_offset_freelist))\n\n        # offsetof(slab, slab_cache)\n        self.slab_offset_slab_cache = current_arch.ptrsize\n        self.quiet_info(\"offsetof(slab, slab_cache): {:#x}\".format(self.slab_offset_slab_cache))\n\n        # offsetof(slab, inuse_objects_frozen)\n        self.slab_offset_inuse_objects_frozen = self.slab_offset_freelist + current_arch.ptrsize\n        self.quiet_info(\"offsetof(slab, inuse_objects_frozen): {:#x}\".format(self.slab_offset_inuse_objects_frozen))\n\n        # offsetof(kmem_cache_node, partial)\n        self.resolve_kmem_cache_node_offset_partial()\n        if self.kmem_cache_node_offset_partial is None:\n            self.quiet_info(\"offsetof(kmem_cache_node, partial): Not found\")\n            return False\n        else:\n            self.quiet_info(\"offsetof(kmem_cache_node, partial): {:#x}\".format(self.kmem_cache_node_offset_partial))\n\n        self.initialized = True\n        return True\n\n    def get_next_kmem_cache(self, addr, point_to_base=True):\n        if point_to_base:\n            addr += self.kmem_cache_offset_list\n        if self.args.reverse_walk:\n            return read_int_from_memory(addr) - self.kmem_cache_offset_list\n        else:\n            return read_int_from_memory(addr + current_arch.ptrsize) - self.kmem_cache_offset_list\n\n    def get_name(self, addr):\n        name_addr = read_int_from_memory(addr + self.kmem_cache_offset_name)\n        return read_cstring_from_memory(name_addr)\n\n    def page2virt(self, page, kmem_cache):\n        if not self.args.skip_page2virt:\n            ret = gdb.execute(\"page2virt {:#x}\".format(page[\"address\"]), to_string=True)\n            r = re.search(r\"Virt: (\\S+)\", ret)\n            if r:\n                return int(r.group(1), 16)\n\n        # set up for heuristic search from freelist\n        freelist = page[\"freelist\"]\n        freelist = [x for x in freelist if isinstance(x, int) and x != 0] # ignore str and last 0\n        if not freelist:\n            return None\n\n        # heuristic detection pattern 1\n        # freed chunks are scattered and can be confirmed on each of the pages\n        page_heads = [x & get_pagesize_mask_high() for x in freelist]\n        uniq_page_heads = list(set(page_heads))\n        if page[\"num_pages\"] == len(uniq_page_heads):\n            return min(uniq_page_heads)\n\n        # heuristic detection pattern 2\n        # if there is only one pattern with good alignment, use it\n        # e.g., num_pages = 5\n        # 0xXXXX0000\n        # 0xXXXX1000   <----------------------------------- most_top_page   ^\n        # 0xXXXX2000                                                       ^|\n        # 0xXXXX3000   <-- chunk in freelist (min_page) ^                 ^||\n        # 0xXXXX4000                                    | known_num_pages |||\n        # 0xXXXX5000   <-- chunk in freelist (max_page) v                 ||v pattern 3\n        # 0xXXXX6000                                                      |v pattern 2\n        # 0xXXXX7000                                                      v pattern 1\n        chunk_size = kmem_cache[\"size\"]\n        min_page = min(freelist) & get_pagesize_mask_high()\n        max_page = max(freelist) & get_pagesize_mask_high()\n        known_num_pages = ((max_page - min_page) // get_pagesize()) + 1\n        unknown_num_pages = page[\"num_pages\"] - known_num_pages\n        most_top_page = min_page - (unknown_num_pages * get_pagesize())\n        candidate_top_pages = range(most_top_page, min_page + get_pagesize(), get_pagesize())\n        # alignment check for each candidate_top_pages\n        valid_top_pages = []\n        for cand_top in candidate_top_pages:\n            for chunk in freelist:\n                # divisible?\n                if (chunk - cand_top) % chunk_size != 0:\n                    break\n            else:\n                valid_top_pages.append(cand_top)\n            # fast break if invalid\n            if len(valid_top_pages) >= 2:\n                break\n        # confirm if there is only one valid pattern\n        if len(valid_top_pages) == 1:\n            return valid_top_pages[0]\n\n        # not found\n        return None\n\n    def walk_freelist(self, chunk, kmem_cache):\n        if self.args.simple:\n            return [chunk]\n\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        freelist = [chunk]\n        while chunk:\n            try:\n                addr = chunk + kmem_cache[\"offset\"]\n                chunk = read_int_from_memory(addr) # get next chunk\n            except gdb.MemoryError:\n                freelist.append(\"{:s}\".format(\n                    Color.colorify(\"Corrupted (Memory access denied)\", corrupted_msg_color),\n                ))\n                break\n            if chunk % 8:\n                freelist.append(\"{:#x}: {:s}\".format(\n                    chunk, Color.colorify(\"Corrupted (Not aligned)\", corrupted_msg_color),\n                ))\n                break\n            if chunk in freelist:\n                freelist.append(\"{:#x}: {:s}\".format(\n                    chunk, Color.colorify(\"Corrupted (Loop detected)\", corrupted_msg_color),\n                ))\n                break\n            freelist.append(chunk)\n        return freelist\n\n    def walk_caches_node_page(self, kmem_cache):\n        kmem_cache[\"nodes\"] = []\n        kmem_cache_node_array = kmem_cache[\"address\"] + self.kmem_cache_offset_node\n        current_kmem_cache_node_ptr = kmem_cache_node_array\n        while True:\n            current_kmem_cache_node = read_int_from_memory(current_kmem_cache_node_ptr)\n            if current_kmem_cache_node == 0:\n                break\n            if current_kmem_cache_node == current_kmem_cache_node_ptr:\n                break\n            if current_kmem_cache_node & 0b111:\n                break\n\n            # node list\n            node_page_list = []\n            node_page_head = current_kmem_cache_node + self.kmem_cache_node_offset_partial\n            if not is_valid_addr(node_page_head):\n                break\n            current_node_page = read_int_from_memory(node_page_head)\n            while current_node_page != node_page_head:\n                node_page = {}\n                node_page[\"address\"] = current_node_page - self.slab_offset_next\n                if not is_valid_addr(node_page[\"address\"]):\n                    node_page_list.append(node_page)\n                    break\n                x = read_int_from_memory(node_page[\"address\"] + self.slab_offset_inuse_objects_frozen)\n                node_page[\"inuse\"] = x & 0xffff\n                node_page[\"objects\"] = (x >> 16) & 0x7fff\n                if node_page[\"objects\"] == 0 or node_page[\"inuse\"] > node_page[\"objects\"]:\n                    break # something is wrong\n                node_page[\"frozen\"] = (x >> 31) & 1\n                node_chunk = read_int_from_memory(node_page[\"address\"] + self.slab_offset_freelist)\n                node_page[\"freelist\"] = self.walk_freelist(node_chunk, kmem_cache)\n                node_page[\"num_pages\"] = (\n                    kmem_cache[\"size\"] * node_page[\"objects\"] + get_pagesize_mask_low()\n                ) // get_pagesize()\n                node_page[\"virt_addr\"] = self.page2virt(node_page, kmem_cache)\n                node_page_list.append(node_page)\n                current_node_page = read_int_from_memory(node_page[\"address\"] + self.slab_offset_next)\n            kmem_cache[\"nodes\"].append(node_page_list)\n\n            # goto next\n            current_kmem_cache_node_ptr += current_arch.ptrsize\n        return\n\n    def walk_caches(self, target_names):\n        current_kmem_cache = self.get_next_kmem_cache(self.slab_caches, point_to_base=False)\n        parsed_caches = [{\"name\": \"slab_caches\", \"next\": current_kmem_cache}]\n\n        # first, parse kmem_cache\n        while current_kmem_cache + self.kmem_cache_offset_list != self.slab_caches:\n            kmem_cache = {}\n            # parse member\n            kmem_cache[\"name\"] = self.get_name(current_kmem_cache)\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                current_kmem_cache = self.get_next_kmem_cache(current_kmem_cache)\n                continue\n            kmem_cache[\"address\"] = current_kmem_cache\n            kmem_cache[\"flags\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_flags)\n            kmem_cache[\"flags_str\"] = SlubDumpCommand.get_flags_str(kmem_cache[\"flags\"])\n            kmem_cache[\"size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_size)\n            kmem_cache[\"object_size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_object_size)\n            kmem_cache[\"offset\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_offset)\n            kmem_cache[\"red_left_pad\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_red_left_pad)\n            kmem_cache[\"next\"] = self.get_next_kmem_cache(current_kmem_cache)\n            parsed_caches.append(kmem_cache)\n            # goto next\n            current_kmem_cache = kmem_cache[\"next\"]\n            # fast break\n            if target_names != [] and not (self.args.list or self.args.list_no_sort):\n                parsed_names = [x[\"name\"] for x in parsed_caches]\n                if all(t in parsed_names for t in target_names):\n                    break\n\n        if self.args.list or self.args.list_no_sort:\n            return parsed_caches # fast return\n\n        # second, parse node then update\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for kmem_cache in tqdm(parsed_caches[1:], leave=False): # parsed_caches[0] is slab_caches, so skip\n            # parse node\n            self.walk_caches_node_page(kmem_cache)\n\n        return parsed_caches\n\n    def dump_page_print_layout(self, kmem_cache, page, freelist):\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        if page[\"virt_addr\"] is None:\n            self.out.append(\"        layout: Failed to the get first page\")\n            return\n\n        end_virt = page[\"virt_addr\"] + page[\"num_pages\"] * get_pagesize()\n        start_addr = page[\"virt_addr\"] + kmem_cache[\"red_left_pad\"]\n\n        if kmem_cache[\"red_left_pad\"]:\n            chunk_s = Color.colorify_hex(page[\"virt_addr\"], used_address_color)\n            self.out.append(\"        {:7s}   {:#05x} {:s} ({:s})\".format(\"layout:\", 0, chunk_s, \"never-used\"))\n            start_idx = 1\n        else:\n            start_idx = 0\n\n        for idx, chunk in enumerate(range(start_addr, end_virt, kmem_cache[\"size\"]), start=start_idx):\n            if chunk in freelist[:-1]:\n                next_chunk = freelist[freelist.index(chunk) + 1]\n                if isinstance(next_chunk, str):\n                    next_msg = \"next: {:s}\".format(next_chunk)\n                else:\n                    next_msg = \"next: {:#x}\".format(next_chunk)\n                chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            else:\n                if page[\"objects\"] <= idx:\n                    next_msg = \"never-used\"\n                else:\n                    next_msg = \"in-use\"\n                chunk_s = Color.colorify_hex(chunk, used_address_color)\n            layout_msg = \"layout:\" if idx == 0 else \"\"\n            self.out.append(\"        {:7s}   {:#05x} {:s} ({:s})\".format(layout_msg, idx, chunk_s, next_msg))\n\n            # dump chunks\n            if self.args.hexdump_used and next_msg == \"in-use\":\n                peeked_data = read_memory(chunk, self.args.hexdump_used)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.hexdump_freed and next_msg.startswith(\"next: \"):\n                peeked_data = read_memory(chunk, self.args.hexdump_freed)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.telescope_used and next_msg == \"in-use\":\n                n = self.args.telescope_used // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n\n            if self.args.telescope_freed and next_msg.startswith(\"next: \"):\n                n = self.args.telescope_freed // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n        return\n\n    def dump_page_print_freelist(self, kmem_cache, page, freelist):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        if freelist == [] or freelist == [0]:\n            self.out.append(\"        freelist: (none)\")\n            return\n\n        for idx, chunk_addr in enumerate(freelist):\n            if page[\"virt_addr\"] is not None:\n                if chunk_addr == 0:\n                    continue\n                if isinstance(chunk_addr, str):\n                    chunk_idx = \"\"\n                    msg = chunk_addr\n                else:\n                    chunk_idx = (chunk_addr - page[\"virt_addr\"]) // kmem_cache[\"size\"]\n                    if chunk_idx < 0 or page[\"objects\"] <= chunk_idx:\n                        chunk_idx = \"\"\n                    else:\n                        chunk_idx = \"{:#05x}\".format(chunk_idx)\n                    msg = Color.colorify_hex(chunk_addr, freed_address_color)\n                freelist_msg = \"freelist:\" if idx == 0 else \"\"\n                self.out.append(\"        {:9s} {:5s} {:s}\".format(freelist_msg, chunk_idx, msg))\n            else:\n                if isinstance(chunk_addr, str):\n                    msg = chunk_addr\n                else:\n                    msg = Color.colorify_hex(chunk_addr, freed_address_color)\n                freelist_msg = \"freelist:\" if idx == 0 else \"\"\n                self.out.append(\"        {:9s}       {:s}\".format(freelist_msg, msg))\n        return\n\n    def dump_page(self, page, kmem_cache, tag, freelist=None):\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n\n        # page address\n        tag_s = Color.colorify(\"{:s} page\".format(tag), label_active_color)\n        self.out.append(\"      {:s}: {:#x}\".format(tag_s, page[\"address\"]))\n\n        # fast return if invalid\n        if not is_valid_addr(page[\"address\"]):\n            return\n\n        # for partial or node page\n        if freelist is None:\n            freelist = page[\"freelist\"]\n\n        # print virtual address\n        if page[\"virt_addr\"] is None:\n            self.out.append(\"        virtual address: ???\")\n        else:\n            colored_virt_addr = Color.colorify_hex(page[\"virt_addr\"], heap_page_color)\n            self.out.append(\"        virtual address: {:s}\".format(colored_virt_addr))\n\n        # print info\n        self.out.append(\"        num pages: {:d}\".format(page[\"num_pages\"]))\n\n        if self.args.simple:\n            return\n\n        if tag == \"active\":\n            freelist_len = len(freelist) - 1 # ignore last 0\n            inuse = page[\"objects\"] - freelist_len\n        else:\n            inuse = page[\"inuse\"]\n        self.out.append(\"        in-use: {:d}/{:d}\".format(inuse, page[\"objects\"]))\n        self.out.append(\"        frozen: {:d}\".format(page[\"frozen\"]))\n\n        # print layout\n        self.dump_page_print_layout(kmem_cache, page, freelist)\n\n        # print freelist\n        self.dump_page_print_freelist(kmem_cache, page, freelist)\n        return\n\n    def dump_caches(self, target_names, parsed_caches):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n\n        self.out.append(\"slab_caches @ {:#x}\".format(self.slab_caches))\n        for kmem_cache in parsed_caches[1:]:\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                continue\n\n            # dump kmem_cache metadata\n            self.out.append(\"\")\n            self.out.append(\"  kmem_cache: {:#x}\".format(kmem_cache[\"address\"]))\n            self.out.append(\"    name: {:s}\".format(Color.colorify(kmem_cache[\"name\"], chunk_label_color)))\n            self.out.append(\"    flags: {:#x} ({:s})\".format(kmem_cache[\"flags\"], kmem_cache[\"flags_str\"]))\n            object_size_s = Color.colorify_hex(kmem_cache[\"object_size\"], chunk_size_color)\n            self.out.append(\"    object size: {:s} (chunk size: {:#x})\".format(object_size_s, kmem_cache[\"size\"]))\n            self.out.append(\"    offset (next pointer in chunk): {:#x}\".format(kmem_cache[\"offset\"]))\n            self.out.append(\"    red_left_pad: {:#x}\".format(kmem_cache[\"red_left_pad\"]))\n\n            # dump nodes\n            for node_index, node_page_list in enumerate(kmem_cache[\"nodes\"]):\n                node_addr = read_int_from_memory(\n                    kmem_cache[\"address\"] + self.kmem_cache_offset_node + current_arch.ptrsize * node_index,\n                )\n                self.out.append(\"    kmem_cache_node[{:d}]: {:#x}\".format(node_index, node_addr))\n                printed_count = 0\n                for node_page in node_page_list:\n                    self.dump_page(node_page, kmem_cache, \"node\")\n                    printed_count += 1\n                if printed_count == 0:\n                    tag = Color.colorify(\"node pages\", label_inactive_color)\n                    self.out.append(\"      {:s}: (none)\".format(tag))\n\n            self.out.append(\"    next: {:#x}\".format(kmem_cache[\"next\"]))\n        return\n\n    def dump_names(self, parsed_caches):\n        name_width = max(len(k[\"name\"]) for k in parsed_caches[1:])\n\n        if not self.args.quiet:\n            fmt = \"{:<18s} {:<18s} {:\" + str(name_width) + \"s} {:20s}\"\n            legend = [\"Object Size\", \"Chunk Size\", \"Name\", \"kmem_cache\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if self.args.list_no_sort:\n            target_caches = parsed_caches[1:]\n        else:\n            target_caches = sorted(parsed_caches[1:], key=lambda x: (x[\"object_size\"], x[\"size\"], x[\"name\"]))\n\n        for kmem_cache in target_caches:\n            objsz = \"{0:d} ({0:#x})\".format(kmem_cache[\"object_size\"])\n            chunksz = \"{0:d} ({0:#x})\".format(kmem_cache[\"size\"])\n            chunk_name = kmem_cache[\"name\"]\n            address = kmem_cache[\"address\"]\n            self.out.append(\"{:18s} {:18s} {:{:d}s} {:#x}\".format(objsz, chunksz, chunk_name, name_width, address))\n        return\n\n    def slub_tiny_walk(self, target_names):\n        if self.initialize() is False:\n            self.quiet_err(\"Initialization failed\")\n            return\n\n        if self.args.meta:\n            return\n\n        if self.args.list or self.args.list_no_sort:\n            parsed_caches = self.walk_caches(target_names)\n            self.dump_names(parsed_caches)\n            return\n\n        parsed_caches = self.walk_caches(target_names)\n        self.dump_caches(target_names, parsed_caches)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            self.quiet_err(\"Unsupported; You should use `slub-dump`\")\n            return\n        elif allocator == \"SLUB_TINY\":\n            pass\n        elif allocator == \"SLAB\":\n            self.quiet_err(\"Unsupported; You should use `slab-dump`\")\n            return\n        elif allocator == \"SLOB\":\n            self.quiet_err(\"Unsupported; You should use `slob-dump`\")\n            return\n        else:\n            self.quiet_err(\"Unsupported: Unknown allocator\")\n            return\n\n        # The slub-tiny-dump command is used by page2virt and kmagic to find vmemmap and sizeof(struct page).\n        # Therefore, slub-tiny-dump itself may be called recursively (up to once) from slub-tiny-dump.\n        # If a recursive call is made, various parameters held by self will be destroyed.\n        # It's very tricky, but if we make sure to call page2virt first,\n        # no further calls will be made and it will work without any problems.\n        if not hasattr(self, \"initialized\"):\n            if is_x86() or is_arm32():\n                if not args.skip_page2virt:\n                    args = self.args # backup\n                    gdb.execute(\"page2virt 0\", to_string=True)\n                    # self.args will be overwritten. this is workaround.\n                    self.args = args # revert\n\n        self.maps = None\n        self.out = []\n        self.slub_tiny_walk(args.cache_name)\n        self.print_output()\n        return\n\n\n@register_command\nclass SlabDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump SLAB free-list.\"\"\"\n\n    _cmdline_ = \"slab-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"cache_name\", metavar=\"SLAB_CACHE_NAME\", nargs=\"*\", help=\"filter by specific slab cache name.\")\n    parser.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"list all slab cache names.\")\n    parser.add_argument(\"-L\", \"--list-no-sort\", action=\"store_true\", help=\"list all slab cache names without sort.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"--cpu\", type=int, help=\"filter by specific cpu.\")\n    parser.add_argument(\"-R\", \"--reverse-walk\", action=\"store_true\", help=\"reverse order walk for slab_caches->list_head.\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"skip displaying layout and freelist.\")\n    parser.add_argument(\"--skip-partial\", action=\"store_true\", help=\"skip displaying slabs_partial.\")\n    parser.add_argument(\"--skip-full\", action=\"store_true\", help=\"skip displaying slabs_full.\")\n    parser.add_argument(\"--skip-free\", action=\"store_true\", help=\"skip displaying slabs_free.\")\n    parser.add_argument(\"--hexdump-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--hexdump-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-freed\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `unused (freed) chunks` if layout is resolved.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cached offset.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} kmalloc-256          # dump kmalloc-256 from all cpus\",\n        \"{0:s} kmalloc-256 --cpu 1  # dump kmalloc-256 from cpu 1\",\n        \"{0:s} --list               # list slab cache names\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified SLAB structure:\",\n        \"\\n\"\n        \"                         +-kmem_cache--+         +-kmem_cache--+   +-kmem_cache--+\",\n        \"                         | cpu_cache   |---+     | cpu_cache   |   | cpu_cache   |\",\n        \"                         | limit       |   |     | limit       |   | limit       |\",\n        \"                         | size        |   |     | size        |   | size        |\",\n        \"                         | flags       |   |     | flags       |   | flags       |\",\n        \"                         | num         |   |     | num         |   | num         |\",\n        \"                         | gfporder    |   |     | gfporder    |   | gfporder    |\",\n        \"       +-slab_caches-+   | name        |   |     | name        |   | name        |\",\n        \" ...<->| list_head   |<->| list_head   |<------->| list_head   |<->| list_head   |<-> ...\",\n        \"       +-------------+   | object_size |   |     | object_size |   | object_size |\",\n        \"                         | node[]      |------+  | node[]      |   | node[]      |\",\n        \"                         +-------------+   |  |  +-------------+   +-------------+\",\n        \"    +-__per_cpu_offset-+                   |  |\",\n        \"    | cpu0_offset      |--+----------------+  |\",\n        \"    | cpu1_offset      |  |                   |\",\n        \"    | cpu2_offset      |  |                   v                  +-page/slab-+    +-page/slab-+\",\n        \"    | ...              |  |       +-kmem_cache_node-+      +---->| slab_list |--->| slab_list |-->...\",\n        \"    +------------------+  |       | slabs_partial   |------+     | freelist  |    | freelist  |\",\n        \"                          |       | slabs_full      |----->...   | s_mem     |-+  | s_mem     |-+\",\n        \"      +-------------------+       | slabs_free      |----->...   | active    | |  | active    | |\",\n        \"      |                           +-----------------+            +-----------+ |  +-----------+ |\",\n        \"      v                                                                        |                |\",\n        \"    +-array_cache--------+                                         +-----------+    +-----------+\",\n        \"    | avail              |                                         |                |\",\n        \"    | limit              |                                         v                v\",\n        \"    | entry[]            |                                       +-chunk--+       +-chunk--+\",\n        \"    |   freed_chunk_ptr  |-------------------------------------->|        |       |        |\",\n        \"    |   freed_chunk_ptr  |----------------------------+          +-chunk--+       +-chunk--+\",\n        \"    |   freed_chunk_ptr  |                            |          |        |       |        |\",\n        \"    |   freed_chunk_ptr  |                            |          +-chunk--+       +-chunk--+\",\n        \"    |   freed_chunk_ptr  |                            +--------->|        |       |        |\",\n        \"    |   ...              |                                       +-...----+       +-...----+\",\n        \"    +--------------------+\",\n        \"* `struct page` has been split into `struct page` and `struct slab` since kernel 5.17.\",\n        \"  The structure name used for SLAB has been changed to `struct slab`.\",\n        \"* Chunks in array_cache are marked as in-use, even though they are actually reusable.\",\n        \"* SLAB was removed in kernel 6.8.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    \"\"\"\n    struct kmem_cache {\n        struct array_cache __percpu *cpu_cache;  // In fact, the offset value, not the pointer. if 3.18 <= kernel\n        unsigned int batchcount;\n        unsigned int limit;\n        unsigned int shared;\n        unsigned int size;\n        struct reciprocal_value {\n            u32 m;\n            u8 sh1, sh2;\n        } reciprocal_buffer_size;\n        slab_flags_t flags;                      // unsigned int\n        unsigned int num;\n        unsigned int gfporder;\n        gfp_t allocflags;                        // unsigned int\n        size_t colour;\n        unsigned int colour_off;\n        struct kmem_cache *freelist_cache;       // if kernel < 6.1\n        unsigned int freelist_size;\n        void (*ctor)(void *obj);\n        const char *name;\n        struct list_head list;  <-----> struct list_head <-----> struct list_head <-----> ...\n        int refcount;\n        int object_size;\n        int align;\n        unsigned long num_active;                // if CONFIG_DEBUG_SLAB=y\n        unsigned long num_allocations;           // if CONFIG_DEBUG_SLAB=y\n        unsigned long high_mark;                 // if CONFIG_DEBUG_SLAB=y\n        unsigned long grown;                     // if CONFIG_DEBUG_SLAB=y\n        unsigned long reaped;                    // if CONFIG_DEBUG_SLAB=y\n        unsigned long errors;                    // if CONFIG_DEBUG_SLAB=y\n        unsigned long max_freeable;              // if CONFIG_DEBUG_SLAB=y\n        unsigned long node_allocs;               // if CONFIG_DEBUG_SLAB=y\n        unsigned long node_frees;                // if CONFIG_DEBUG_SLAB=y\n        unsigned long node_overflow;             // if CONFIG_DEBUG_SLAB=y\n        atomic_t allochit;                       // if CONFIG_DEBUG_SLAB=y\n        atomic_t allocmiss;                      // if CONFIG_DEBUG_SLAB=y\n        atomic_t freehit;                        // if CONFIG_DEBUG_SLAB=y\n        atomic_t freemiss;                       // if CONFIG_DEBUG_SLAB=y\n        atomic_t store_user_clean;               // if CONFIG_DEBUG_SLAB=y && CONFIG_DEBUG_SLAB_LEAK=y && 4.6 <= kernel < 5.2\n        int obj_offset;                          // if CONFIG_DEBUG_SLAB=y\n        struct memcg_cache_params memcg_params;  // if CONFIG_MEMCG=y && kernel < 5.9\n        struct kasan_cache kasan_info;           // if CONFIG_KASAN=y && 4.6 <= kernel\n        unsigned int *random_seq;                // if CONFIG_SLAB_FREELIST_RANDOM=y && 4.7 <= kernel\n        unsigned int useroffset;                 // if 4.16 <= kernel\n        unsigned int usersize;                   // if 4.16 <= kernel\n        struct kmem_cache_node *node[MAX_NUMNODES]; // if 3.18 <= kernel\n        struct kmem_cache_node **node;           // if kernel < 3.18\n        struct array_cache *array[NR_CPUS + MAX_NUMNODES];  // if kernel < 3.18\n    };\n\n    struct array_cache {\n        unsigned int avail;\n        unsigned int limit;\n        unsigned int batchcount;\n        unsigned int touched;\n        spinlock_t lock;                         // if kernel < 3.17\n        void *entry[];\n    };\n\n    struct kmem_cache_node {\n        raw_spinlock_t list_lock;\n        struct list_head slabs_partial;\n        struct list_head slabs_full;\n        struct list_head slabs_free;\n        unsigned long total_slabs;               // if 4.10 <= kernel\n        unsigned long free_slabs;                // if 4.10 <= kernel\n        unsigned long num_slabs;                 // if 4.9 <= kernel < 4.10\n        unsigned long free_objects;\n        unsigned int free_limit;\n        unsigned int colour_next;\n        struct array_cache *shared;\n        struct alien_cache **alien;\n        unsigned long next_reap;\n        int free_touched;\n    };\n\n    struct page {                                // if kernel < 4.18\n        unsigned long flags;\n        void *s_mem;\n        void *freelist;\n        unsigned int active;\n        atomic_t refcount;                       // if kernel < 4.16\n        struct rcu_head rcu_head;\n        struct kmem_cache *slab_cache;\n        ...\n    };\n\n    struct page {                                // if 4.18 <= kernel < 5.17\n        unsigned long flags;\n        struct list_head slab_list;\n        struct kmem_cache *slab_cache;\n        void *freelist;\n        void *s_mem;\n        unsigned int active;\n        ...\n    };\n\n    struct slab {                                // if 5.17 <= kernel\n        unsigned long __page_flags;\n        struct kmem_cache *slab_cache;           // if 6.2 <= kernel\n        struct list_head slab_list;\n        struct kmem_cache *slab_cache;           // if kernel < 6.2\n        void *freelist;\n        void *s_mem;\n        unsigned int active;\n        ...\n    };\n    \"\"\"\n\n    @Cache.cache_until_next\n    def parse_kmem_caches_for_initialize(self):\n        seen = [self.slab_caches]\n        current = self.slab_caches\n        while True:\n            current = read_int_from_memory(current)\n            if current in seen:\n                break\n            seen.append(current)\n        kmem_caches = seen[1:] # skip slab_caches itself\n        return kmem_caches\n\n    def resolve_kmem_cache_offset_node(self):\n        # fast path\n        try:\n            self.kmem_cache_offset_node = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache*)0).node\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.16\":\n            self.kmem_cache_offset_node = self.kmem_cache_offset_object_size + 4 * 2 # heuristic could not use, so hard-coded\n            return\n\n        self.kmem_cache_offset_node = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        # Search heuristically using useroffset and usersize as markers\n        start_offset = self.kmem_cache_offset_list + current_arch.ptrsize * 2\n        for candidate_offset in range(start_offset, start_offset + 0x100, 4):\n            found = True\n            for kmem_cache in kmem_caches:\n                kmem_cache_top = kmem_cache - self.kmem_cache_offset_list\n                user_offset = read_int32_from_memory(kmem_cache_top + candidate_offset)\n                user_size = read_int32_from_memory(kmem_cache_top + candidate_offset + 4)\n                object_size = read_int32_from_memory(kmem_cache_top + self.kmem_cache_offset_object_size)\n                if user_offset == user_size == 0:\n                    continue\n                if user_offset != 0 and user_size == 0:\n                    found = False\n                    break\n                if object_size < user_size:\n                    found = False\n                    break\n                node_addr_ptr = kmem_cache_top + candidate_offset + 4 + 4\n                node_addr_ptr = align_to_ptrsize(node_addr_ptr)\n                node_addr = read_int_from_memory(node_addr_ptr)\n                if not is_valid_addr(node_addr):\n                    found = False\n                    break\n\n            if found:\n                self.kmem_cache_offset_node = align_to_ptrsize(candidate_offset + 4 * 2)\n                return\n        return\n\n    def resolve_kmem_cache_node_offset_slabs_partial(self):\n        # fast path\n        try:\n            self.kmem_cache_node_offset_slabs_partial = to_unsigned_long(\n                gdb.parse_and_eval(\"&((struct kmem_cache_node*)0).slabs_partial\")\n            )\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        self.kmem_cache_node_offset_slabs_partial = None\n        kmem_caches = self.parse_kmem_caches_for_initialize()\n        # sizeof(raw_spinlock_t) can take many different values and must be determined heuristically.\n        for candidate_offset in range(0, 0x80, current_arch.ptrsize):\n            found = True\n            for _kmem_cache in kmem_caches:\n                kmem_cache = _kmem_cache - self.kmem_cache_offset_list\n                if \"3.18\" <= kversion:\n                    kmem_cache_node_array = kmem_cache + self.kmem_cache_offset_node\n                else:\n                    kmem_cache_node_array = read_int_from_memory(kmem_cache + self.kmem_cache_offset_node)\n                kmem_cache_node_0 = read_int_from_memory(kmem_cache_node_array)\n\n                # slabs_partial\n                if not is_double_link_list(kmem_cache_node_0 + candidate_offset + current_arch.ptrsize * 0):\n                    found = False\n                    break\n                # slabs_full\n                if not is_double_link_list(kmem_cache_node_0 + candidate_offset + current_arch.ptrsize * 2):\n                    found = False\n                    break\n                # slabs_free\n                if not is_double_link_list(kmem_cache_node_0 + candidate_offset + current_arch.ptrsize * 4):\n                    found = False\n                    break\n\n            if found:\n                self.kmem_cache_node_offset_slabs_partial = candidate_offset\n                return\n        return\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            if not self.args.meta and not self.args.rescan:\n                return True\n\n        kversion = Kernel.kernel_version()\n        if not kversion:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        # resolve slab_caches\n        self.slab_caches = KernelAddressHeuristicFinder.get_slab_caches()\n        if self.slab_caches is None:\n            self.quiet_err(\"Failed to resolve `slab_caches`\")\n            return False\n        else:\n            self.quiet_info(\"slab_caches: {:#x}\".format(self.slab_caches))\n\n        # resolve __per_cpu_offset\n        __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n        if __per_cpu_offset is None:\n            self.quiet_info(\"__per_cpu_offset: Not found\")\n            self.cpu_offset = []\n            self.ncpus = 1\n        else:\n            self.quiet_info(\"__per_cpu_offset: {:#x}\".format(__per_cpu_offset))\n            self.cpu_offset = KernelCurrentCommand.get_each_cpu_offset(__per_cpu_offset)\n            self.ncpus = len(self.cpu_offset)\n\n        # offsetof(kmem_cache, list)\n        if kversion < \"3.18\":\n            self.kmem_cache_offset_list = current_arch.ptrsize * 6 + 4 * 10\n        elif kversion < \"6.1\":\n            self.kmem_cache_offset_list = current_arch.ptrsize * 7 + 4 * 10\n        else:\n            self.kmem_cache_offset_list = current_arch.ptrsize * 4 + 4 * 12\n        self.quiet_info(\"offsetof(kmem_cache, list): {:#x}\".format(self.kmem_cache_offset_list))\n\n        # offsetof(kmem_cache, name)\n        self.kmem_cache_offset_name = self.kmem_cache_offset_list - current_arch.ptrsize\n        self.quiet_info(\"offsetof(kmem_cache, name): {:#x}\".format(self.kmem_cache_offset_name))\n\n        # offsetof(kmem_cache, size)\n        if \"3.18\" <= kversion:\n            self.kmem_cache_offset_size = current_arch.ptrsize + 4 * 3\n        else:\n            self.kmem_cache_offset_size = 4 * 3\n        self.quiet_info(\"offsetof(kmem_cache, size): {:#x}\".format(self.kmem_cache_offset_size))\n\n        # offsetof(kmem_cache, flags)\n        self.kmem_cache_offset_flags = self.kmem_cache_offset_size + 4 * 3\n        self.quiet_info(\"offsetof(kmem_cache, flags): {:#x}\".format(self.kmem_cache_offset_flags))\n\n        # offsetof(kmem_cache, num)\n        self.kmem_cache_offset_num = self.kmem_cache_offset_flags + 4\n        self.quiet_info(\"offsetof(kmem_cache, num): {:#x}\".format(self.kmem_cache_offset_num))\n\n        # offsetof(kmem_cache, gfporder)\n        self.kmem_cache_offset_gfporder = self.kmem_cache_offset_num + 4\n        self.quiet_info(\"offsetof(kmem_cache, gfporder): {:#x}\".format(self.kmem_cache_offset_gfporder))\n\n        # offsetof(kmem_cache, object_size)\n        self.kmem_cache_offset_object_size = self.kmem_cache_offset_list + current_arch.ptrsize * 2 + 4\n        self.quiet_info(\"offsetof(kmem_cache, object_size): {:#x}\".format(self.kmem_cache_offset_object_size))\n\n        # offsetof(kmem_cache, node)\n        self.resolve_kmem_cache_offset_node()\n        if self.kmem_cache_offset_node is None:\n            self.quiet_info(\"offsetof(kmem_cache, node): Not found\")\n            return False\n        else:\n            self.quiet_info(\"offsetof(kmem_cache, node): {:#x}\".format(self.kmem_cache_offset_node))\n\n        # offsetof(kmem_cache, cpu_cache) / offsetof(kmem_cache, array)\n        if \"3.18\" <= kversion:\n            self.kmem_cache_offset_cpu_cache = 0\n            self.quiet_info(\"offsetof(kmem_cache, cpu_cache): {:#x}\".format(self.kmem_cache_offset_cpu_cache))\n        else:\n            self.kmem_cache_offset_array = self.kmem_cache_offset_node + current_arch.ptrsize\n            self.quiet_info(\"offsetof(kmem_cache, array): {:#x}\".format(self.kmem_cache_offset_array))\n\n        # offsetof(page, next) / offsetof(slab, next)\n        if kversion < \"4.16\":\n            self.page_offset_next = current_arch.ptrsize * 3 + 4 * 2\n        elif kversion < \"4.18\":\n            self.page_offset_next = current_arch.ptrsize * 3 + 4\n        elif kversion < \"5.17\":\n            self.page_offset_next = current_arch.ptrsize\n        elif kversion < \"6.2\":\n            self.page_offset_next = current_arch.ptrsize\n        else:\n            self.page_offset_next = current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof({:s}, next): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_next))\n\n        # offsetof(page, freelist) / offsetof(slab, freelist)\n        if kversion < \"4.18\":\n            self.page_offset_freelist = current_arch.ptrsize * 2\n        elif kversion < \"5.17\":\n            self.page_offset_freelist = current_arch.ptrsize * 4\n        elif kversion < \"6.2\":\n            self.page_offset_freelist = current_arch.ptrsize * 4\n        else:\n            self.page_offset_freelist = current_arch.ptrsize * 4\n        self.quiet_info(\"offsetof({:s}, freelist): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_freelist))\n\n        # offsetof(page, slab_cache) / offsetof(slab, slab_cache)\n        if kversion < \"4.16\" and is_32bit():\n            self.page_offset_slab_cache = current_arch.ptrsize * 7\n        elif kversion < \"4.18\":\n            self.page_offset_slab_cache = current_arch.ptrsize * 6\n        elif kversion < \"5.17\":\n            self.page_offset_slab_cache = current_arch.ptrsize * 3\n        elif kversion < \"6.2\":\n            self.page_offset_slab_cache = current_arch.ptrsize * 3\n        else:\n            self.page_offset_slab_cache = current_arch.ptrsize\n        self.quiet_info(\"offsetof({:s}, slab_cache): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_slab_cache))\n\n        # offsetof(page, s_mem) / offsetof(slab, s_mem)\n        if kversion < \"4.18\":\n            self.page_offset_s_mem = current_arch.ptrsize\n        elif kversion < \"5.17\":\n            self.page_offset_s_mem = current_arch.ptrsize * 5\n        elif kversion < \"6.2\":\n            self.page_offset_s_mem = 8 + current_arch.ptrsize * 5\n        else:\n            self.page_offset_s_mem = 8 + current_arch.ptrsize * 5\n        self.quiet_info(\"offsetof({:s}, s_mem): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_s_mem))\n\n        # offsetof(page, active) / offsetof(slab, active)\n        if kversion < \"4.18\":\n            self.page_offset_active = current_arch.ptrsize * 3\n        elif kversion < \"5.17\":\n            self.page_offset_active = current_arch.ptrsize * 6\n        elif kversion < \"6.2\":\n            self.page_offset_active = current_arch.ptrsize * 6\n        else:\n            self.page_offset_active = current_arch.ptrsize * 6\n        self.quiet_info(\"offsetof({:s}, active): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_active))\n\n        # offsetof(kmem_cache_node, slabs_partial)\n        self.resolve_kmem_cache_node_offset_slabs_partial()\n        if self.kmem_cache_node_offset_slabs_partial is None:\n            self.quiet_info(\"offsetof(kmem_cache_node, slabs_partial): Not found\")\n            return False\n        else:\n            self.quiet_info(\"offsetof(kmem_cache_node, slabs_partial): {:#x}\".format(self.kmem_cache_node_offset_slabs_partial))\n\n        # offsetof(kmem_cache_node, slabs_full)\n        self.kmem_cache_node_offset_slabs_full = self.kmem_cache_node_offset_slabs_partial + current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache_node, slabs_full): {:#x}\".format(self.kmem_cache_node_offset_slabs_full))\n\n        # offsetof(kmem_cache_node, slabs_free)\n        self.kmem_cache_node_offset_slabs_free = self.kmem_cache_node_offset_slabs_full + current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(kmem_cache_node, slabs_free): {:#x}\".format(self.kmem_cache_node_offset_slabs_free))\n\n        # offsetof(array_cache, avail)\n        self.array_cache_offset_avail = 0\n        self.quiet_info(\"offsetof(array_cache, avail): {:#x}\".format(self.array_cache_offset_avail))\n\n        # offsetof(array_cache, limit)\n        self.array_cache_offset_limit = 4\n        self.quiet_info(\"offsetof(array_cache, limit): {:#x}\".format(self.array_cache_offset_limit))\n\n        # offsetof(array_cache, entry)\n        if \"3.17\" <= kversion:\n            self.array_cache_offset_entry = 4 * 4\n        else:\n            sizeof_raw_spinlock_t = self.kmem_cache_node_offset_slabs_partial\n            self.array_cache_offset_entry = 4 * 4 + sizeof_raw_spinlock_t\n        self.quiet_info(\"offsetof(array_cache, entry): {:#x}\".format(self.array_cache_offset_entry))\n\n        self.initialized = True\n        return True\n\n    def get_next_kmem_cache(self, addr, point_to_base=True):\n        if point_to_base:\n            addr += self.kmem_cache_offset_list\n        if self.args.reverse_walk:\n            return read_int_from_memory(addr) - self.kmem_cache_offset_list\n        else:\n            return read_int_from_memory(addr + current_arch.ptrsize) - self.kmem_cache_offset_list\n\n    def get_name(self, addr):\n        name_addr = read_int_from_memory(addr + self.kmem_cache_offset_name)\n        return read_cstring_from_memory(name_addr)\n\n    def get_array_cache_cpu(self, addr, cpu):\n        kversion = Kernel.kernel_version()\n        if \"3.18\" <= kversion:\n            cpu_cache = read_int_from_memory(addr + self.kmem_cache_offset_cpu_cache)\n            if len(self.cpu_offset) > 0:\n                # __percpu\n                return AddressUtil.align_address(cpu_cache + self.cpu_offset[cpu])\n            else:\n                # not __percpu\n                return cpu_cache\n        else:\n            return read_int_from_memory(addr + self.kmem_cache_offset_array + current_arch.ptrsize * cpu)\n\n    def walk_array_cache(self, array_cache, cpu, kmem_cache):\n        if self.args.simple:\n            return []\n\n        freelist = []\n        entry = array_cache + self.array_cache_offset_entry\n        end = entry + kmem_cache[\"array_cache\"][cpu][\"avail\"] * current_arch.ptrsize\n        for current in range(entry, end, current_arch.ptrsize):\n            chunk = read_int_from_memory(current)\n            freelist.append(chunk)\n        return freelist\n\n    def walk_node_list(self, node_page_head, current_node_page, kmem_cache):\n        kversion = Kernel.kernel_version()\n        node_page_list = []\n        seen = [] # avoid infinity loop\n        while current_node_page != node_page_head:\n            if current_node_page in seen:\n                break\n            seen.append(current_node_page)\n            node_page = {}\n            node_page[\"address\"] = current_node_page - self.page_offset_next\n            if not is_valid_addr(node_page[\"address\"]):\n                node_page_list.append(node_page)\n                break\n            node_page[\"s_mem\"] = read_int_from_memory(node_page[\"address\"] + self.page_offset_s_mem)\n            node_page[\"s_mem_base\"] = node_page[\"s_mem\"] & get_pagesize_mask_high()\n\n            if not self.args.simple:\n                freelist_addr = read_int_from_memory(node_page[\"address\"] + self.page_offset_freelist)\n                if is_valid_addr(freelist_addr):\n                    active = read_int32_from_memory(node_page[\"address\"] + self.page_offset_active)\n                    if \"3.15\" <= kversion:\n                        freelist_byteseq = read_memory(freelist_addr, kmem_cache[\"objperslab\"])\n                        node_page[\"freelist\"] = list(freelist_byteseq[active:])\n                    else:\n                        freelist_intseq = read_memory(freelist_addr, kmem_cache[\"objperslab\"] * 4)\n                        node_page[\"freelist\"] = slice_unpack(freelist_intseq, current_arch.ptrsize)[active:]\n                else:\n                    node_page[\"freelist\"] = []\n\n            node_page_list.append(node_page)\n            current_node_page = read_int_from_memory(node_page[\"address\"] + self.page_offset_next)\n        return node_page_list\n\n    def walk_caches(self, target_names, cpus):\n        kversion = Kernel.kernel_version()\n        current_kmem_cache = self.get_next_kmem_cache(self.slab_caches, point_to_base=False)\n        parsed_caches = [{\"name\": \"slab_caches\", \"next\": current_kmem_cache}]\n\n        # first, parse kmem_cache\n        while current_kmem_cache + self.kmem_cache_offset_list != self.slab_caches:\n            kmem_cache = {}\n            # parse member\n            kmem_cache[\"name\"] = self.get_name(current_kmem_cache)\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                current_kmem_cache = self.get_next_kmem_cache(current_kmem_cache)\n                continue\n            kmem_cache[\"address\"] = current_kmem_cache\n            kmem_cache[\"flags\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_flags)\n            kmem_cache[\"flags_str\"] = SlubDumpCommand.get_flags_str(kmem_cache[\"flags\"])\n            kmem_cache[\"size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_size)\n            kmem_cache[\"object_size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_object_size)\n            kmem_cache[\"objperslab\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_num)\n            gfporder = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_gfporder)\n            kmem_cache[\"pagesperslab\"] = 1 << gfporder\n            kmem_cache[\"next\"] = self.get_next_kmem_cache(current_kmem_cache)\n            parsed_caches.append(kmem_cache)\n            # goto next\n            current_kmem_cache = kmem_cache[\"next\"]\n            # fast break\n            if target_names != [] and not (self.args.list or self.args.list_no_sort):\n                parsed_names = [x[\"name\"] for x in parsed_caches]\n                if all(t in parsed_names for t in target_names):\n                    break\n\n        if self.args.list or self.args.list_no_sort:\n            return parsed_caches\n\n        # second, parse array_cache and node\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for kmem_cache in tqdm(parsed_caches[1:], leave=False): # parsed_caches[0] is slab_caches, so skip\n            # parse array_cache\n            kmem_cache[\"array_cache\"] = {}\n            kmem_cache[\"array_cache\"][\"freelist_all\"] = []\n            for cpu in cpus:\n                kmem_cache[\"array_cache\"][cpu] = {}\n                if not is_valid_addr(self.get_array_cache_cpu(kmem_cache[\"address\"], cpu)):\n                    continue\n                kmem_cache[\"array_cache\"][cpu][\"address\"] = array_cache = self.get_array_cache_cpu(kmem_cache[\"address\"], cpu)\n                kmem_cache[\"array_cache\"][cpu][\"avail\"] = read_int32_from_memory(array_cache + self.array_cache_offset_avail)\n                kmem_cache[\"array_cache\"][cpu][\"limit\"] = read_int32_from_memory(array_cache + self.array_cache_offset_limit)\n                kmem_cache[\"array_cache\"][cpu][\"freelist\"] = self.walk_array_cache(array_cache, cpu, kmem_cache)\n                kmem_cache[\"array_cache\"][\"freelist_all\"].extend(kmem_cache[\"array_cache\"][cpu][\"freelist\"])\n\n            # parse node\n            kmem_cache[\"nodes\"] = []\n            if \"3.18\" <= kversion:\n                kmem_cache_node_array = kmem_cache[\"address\"] + self.kmem_cache_offset_node\n            else:\n                kmem_cache_node_array = read_int_from_memory(kmem_cache[\"address\"] + self.kmem_cache_offset_node)\n            current_kmem_cache_node_ptr = kmem_cache_node_array\n            while True:\n                # 3.18 or after: node is array (node[MAX_NUMNODES]), so need loop until invalid address\n                current_kmem_cache_node = read_int_from_memory(current_kmem_cache_node_ptr)\n                if not is_valid_addr(current_kmem_cache_node):\n                    break\n                slabs_list = {}\n\n                node_page_head = current_kmem_cache_node + self.kmem_cache_node_offset_slabs_partial\n                if is_valid_addr(node_page_head):\n                    current_node_page = read_int_from_memory(node_page_head)\n                    slabs_list[\"slabs_partial\"] = self.walk_node_list(node_page_head, current_node_page, kmem_cache)\n\n                node_page_head = current_kmem_cache_node + self.kmem_cache_node_offset_slabs_full\n                if is_valid_addr(node_page_head):\n                    current_node_page = read_int_from_memory(node_page_head)\n                    slabs_list[\"slabs_full\"] = self.walk_node_list(node_page_head, current_node_page, kmem_cache)\n\n                node_page_head = current_kmem_cache_node + self.kmem_cache_node_offset_slabs_free\n                if is_valid_addr(node_page_head):\n                    current_node_page = read_int_from_memory(node_page_head)\n                    slabs_list[\"slabs_free\"] = self.walk_node_list(node_page_head, current_node_page, kmem_cache)\n\n                kmem_cache[\"nodes\"].append(slabs_list)\n\n                if kversion < \"3.18\":\n                    # 3.17 or before: node is single element (**node), so skip loop\n                    break\n                current_kmem_cache_node_ptr += current_arch.ptrsize\n        return parsed_caches\n\n    def dump_page(self, page, kmem_cache, tag):\n        heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        # page address\n        tag_s = Color.colorify(tag, label_inactive_color)\n        self.out.append(\"      {:s}: {:#x}\".format(tag_s, page[\"address\"]))\n\n        # fast return if invalid\n        if not is_valid_addr(page[\"address\"]):\n            return\n\n        # print virtual address\n        colored_s_mem_base = Color.colorify_hex(page[\"s_mem_base\"], heap_page_color)\n        self.out.append(\"        virtual address (s_mem & ~0xfff): {:s}\".format(colored_s_mem_base))\n\n        # print info\n        self.out.append(\"        num pages: {:d}\".format(kmem_cache[\"pagesperslab\"]))\n\n        colour_off = page[\"s_mem\"] - page[\"s_mem_base\"]\n        self.out.append(\"        colour offset: {:#x}\".format(colour_off))\n\n        if self.args.simple:\n            return\n\n        # print layout\n        freelist = page[\"freelist\"]\n        end_virt = page[\"s_mem_base\"] + kmem_cache[\"pagesperslab\"] * get_pagesize()\n\n        if colour_off:\n            chunk_s = Color.colorify_hex(page[\"s_mem_base\"], used_address_color)\n            self.out.append(\"        {:7s}   ---- {:s} ({:s})\".format(\"layout:\", chunk_s, \"never-used\"))\n\n        for idx, chunk in enumerate(range(page[\"s_mem\"], end_virt, kmem_cache[\"size\"])):\n            if idx in freelist:\n                idxidx = freelist.index(idx)\n                if idxidx == len(freelist) - 1:\n                    next_msg = \"next: None\"\n                else:\n                    next_idx = freelist[idxidx + 1]\n                    next_msg = \"next: {:#x}\".format(next_idx)\n                chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            elif \"array_cache\" in kmem_cache and chunk in kmem_cache[\"array_cache\"][\"freelist_all\"]:\n                next_msg = \"in-use (array_cache)\"\n                chunk_s = Color.colorify_hex(chunk, freed_address_color)\n            else:\n                if kmem_cache[\"objperslab\"] <= idx:\n                    next_msg = \"never-used\"\n                else:\n                    next_msg = \"in-use\"\n                chunk_s = Color.colorify_hex(chunk, used_address_color)\n            self.out.append(\"        {:7s}   {:#04x} {:s} ({:s})\".format(\n                \"layout:\" if idx == 0 else \"\", idx, chunk_s, next_msg,\n            ))\n\n            # dump chunks\n            if self.args.hexdump_used and next_msg == \"in-use\":\n                peeked_data = read_memory(chunk, self.args.hexdump_used)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.hexdump_freed and next_msg.startswith((\"next: \", \"in-use (array_cache)\")):\n                peeked_data = read_memory(chunk, self.args.hexdump_freed)\n                h = hexdump(peeked_data, 0x10, base=chunk, unit=current_arch.ptrsize)\n                self.out.append(h)\n\n            if self.args.telescope_used and next_msg == \"in-use\":\n                n = self.args.telescope_used // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n\n            if self.args.telescope_freed and next_msg.startswith((\"next: \", \"in-use (array_cache)\")):\n                n = self.args.telescope_freed // current_arch.ptrsize\n                for i in range(n):\n                    line = DereferenceCommand.pprint_dereferenced(chunk, i)\n                    self.out.append(line)\n\n        # print freelist\n        if freelist == []:\n            self.out.append(\"        freelist: (none)\")\n        else:\n            for i, idx in enumerate(freelist):\n                chunk = page[\"s_mem\"] + kmem_cache[\"size\"] * idx\n                msg = Color.colorify_hex(chunk, freed_address_color)\n                self.out.append(\"        {:9s} {:#04x} {:s}\".format(\"freelist:\" if i == 0 else \"\", idx, msg))\n        return\n\n    def dump_array_cache(self, cpu, kmem_cache):\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        tag_s = Color.colorify(\"array_cache (cpu{:d})\".format(cpu), label_active_color)\n        if \"array_cache\" not in kmem_cache:\n            self.out.append(\"      {:s}: (none)\".format(tag_s))\n            return\n        if \"address\" not in kmem_cache[\"array_cache\"][cpu]:\n            self.out.append(\"      {:s}: (none)\".format(tag_s))\n            return\n        self.out.append(\"      {:s}: {:#x}\".format(tag_s, kmem_cache[\"array_cache\"][cpu][\"address\"]))\n\n        self.out.append(\"        avail: {:d}\".format(kmem_cache[\"array_cache\"][cpu][\"avail\"]))\n        self.out.append(\"        limit: {:d}\".format(kmem_cache[\"array_cache\"][cpu][\"limit\"]))\n\n        if self.args.simple:\n            return\n\n        freelist = kmem_cache[\"array_cache\"][cpu][\"freelist\"]\n        if freelist == []:\n            self.out.append(\"        entry: (none)\")\n        else:\n            for idx, f in enumerate(freelist):\n                if not is_valid_addr(f):\n                    break\n                msg = Color.colorify_hex(f, freed_address_color)\n                self.out.append(\"        {:6s} {:s}\".format(\"entry:\" if idx == 0 else \"\", msg))\n        return\n\n    def dump_caches(self, target_names, cpus, parsed_caches):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n\n        self.out.append(\"slab_caches @ {:#x}\".format(self.slab_caches))\n        for kmem_cache in parsed_caches[1:]:\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                continue\n\n            # dump kmem_cache metadata\n            self.out.append(\"\")\n            self.out.append(\"  kmem_cache: {:#x}\".format(kmem_cache[\"address\"]))\n            self.out.append(\"    name: {:s}\".format(Color.colorify(kmem_cache[\"name\"], chunk_label_color)))\n            self.out.append(\"    flags: {:#x} ({:s})\".format(kmem_cache[\"flags\"], kmem_cache[\"flags_str\"]))\n            object_size_s = Color.colorify_hex(kmem_cache[\"object_size\"], chunk_size_color)\n            self.out.append(\"    object size: {:s} (chunk size: {:#x})\".format(object_size_s, kmem_cache[\"size\"]))\n            self.out.append(\"    object per slab: {:#x}\".format(kmem_cache[\"objperslab\"]))\n            self.out.append(\"    pages per slab: {:#x}\".format(kmem_cache[\"pagesperslab\"]))\n\n            # dump array_cache\n            for cpu in cpus:\n                self.dump_array_cache(cpu, kmem_cache)\n\n            # dump nodes\n            if len(kmem_cache[\"nodes\"]) == 0:\n                self.out.append(\"      {:s}: (none)\".format(Color.colorify(\"node pages\", label_inactive_color)))\n            else:\n                for node_index, slabs_list in enumerate(kmem_cache[\"nodes\"]):\n                    node_addr = read_int_from_memory(\n                        kmem_cache[\"address\"] + self.kmem_cache_offset_node + current_arch.ptrsize * node_index,\n                    )\n                    self.out.append(\"    kmem_cache_node[{:d}]: {:#x}\".format(node_index, node_addr))\n\n                    if not self.args.skip_partial and \"slabs_partial\" in slabs_list:\n                        if len(slabs_list[\"slabs_partial\"]) == 0:\n                            tag = Color.colorify(\"node[{:d}].slabs_partial\".format(node_index), label_inactive_color)\n                            self.out.append(\"      {:s}: (none)\".format(tag))\n                        else:\n                            for node_page in slabs_list[\"slabs_partial\"]:\n                                self.dump_page(node_page, kmem_cache, tag=\"node[{:d}].slabs_partial\".format(node_index))\n\n                    if not self.args.skip_full and \"slabs_full\" in slabs_list:\n                        if len(slabs_list[\"slabs_full\"]) == 0:\n                            tag = Color.colorify(\"node[{:d}].slabs_full\".format(node_index), label_inactive_color)\n                            self.out.append(\"      {:s}: (none)\".format(tag))\n                        else:\n                            for node_page in slabs_list[\"slabs_full\"]:\n                                self.dump_page(node_page, kmem_cache, tag=\"node[{:d}].slabs_full\".format(node_index))\n\n                    if not self.args.skip_free and \"slabs_free\" in slabs_list:\n                        if len(slabs_list[\"slabs_free\"]) == 0:\n                            tag = Color.colorify(\"node[{:d}].slabs_free\".format(node_index), label_inactive_color)\n                            self.out.append(\"      {:s}: (none)\".format(tag))\n                        else:\n                            for node_page in slabs_list[\"slabs_free\"]:\n                                self.dump_page(node_page, kmem_cache, tag=\"node[{:d}].slabs_free\".format(node_index))\n\n            self.out.append(\"    next: {:#x}\".format(kmem_cache[\"next\"]))\n        return\n\n    def dump_names(self, parsed_caches):\n        name_width = max(len(k[\"name\"]) for k in parsed_caches[1:])\n\n        if not self.args.quiet:\n            fmt = \"{:<18s} {:<18s} {:\" + str(name_width) + \"s} {:20s}\"\n            legend = [\"Object Size\", \"Chunk Size\", \"Name\", \"kmem_cache\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if self.args.list_no_sort:\n            target_caches = parsed_caches[1:]\n        else:\n            target_caches = sorted(parsed_caches[1:], key=lambda x: (x[\"object_size\"], x[\"size\"], x[\"name\"]))\n\n        for kmem_cache in target_caches:\n            objsz = \"{0:d} ({0:#x})\".format(kmem_cache[\"object_size\"])\n            chunksz = \"{0:d} ({0:#x})\".format(kmem_cache[\"size\"])\n            chunk_name = kmem_cache[\"name\"]\n            address = kmem_cache[\"address\"]\n            self.out.append(\"{:18s} {:18s} {:{:d}s} {:#x}\".format(objsz, chunksz, chunk_name, name_width, address))\n        return\n\n    def slabwalk(self, target_names, cpu):\n        if self.initialize() is False:\n            self.quiet_err(\"Initialization failed\")\n            return\n\n        if self.args.meta:\n            return\n\n        if self.args.list or self.args.list_no_sort:\n            parsed_caches = self.walk_caches(target_names, cpus=None)\n            self.dump_names(parsed_caches)\n            return\n\n        if cpu is None:\n            target_cpus = list(range(self.ncpus))\n        else:\n            if self.ncpus <= cpu:\n                self.quiet_err(\"CPU number is invalid (valid range: {:d}-{:d})\".format(0, self.ncpus - 1))\n                return\n            target_cpus = [cpu]\n\n        parsed_caches = self.walk_caches(target_names, target_cpus)\n        self.dump_caches(target_names, target_cpus, parsed_caches)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            self.quiet_err(\"Unsupported; You should use `slub-dump`\")\n            return\n        elif allocator == \"SLUB_TINY\":\n            self.quiet_err(\"Unsupported; You should use `slub-tiny-dump`\")\n            return\n        elif allocator == \"SLAB\":\n            pass\n        elif allocator == \"SLOB\":\n            self.quiet_err(\"Unsupported; You should use `slob-dump`\")\n            return\n        else:\n            self.quiet_err(\"Unsupported: Unknown allocator\")\n            return\n\n        self.maps = None\n        self.out = []\n        self.slabwalk(args.cache_name, args.cpu)\n        self.print_output()\n        return\n\n\n@register_command\nclass SlobDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump SLOB free-list.\"\"\"\n\n    _cmdline_ = \"slob-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"cache_name\", metavar=\"SLOB_CACHE_NAME\", nargs=\"*\",\n                        help=\"filter by specific slob cache name (need -v option).\")\n    parser.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"list all slob cache names.\")\n    parser.add_argument(\"-L\", \"--list-no-sort\", action=\"store_true\", help=\"list all slob cache names without sort.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"-R\", \"--reverse-walk\", action=\"store_true\", help=\"reverse order walk for slab_caches->list_head.\")\n    parser.add_argument(\"-s\", \"--simple\", action=\"store_true\", help=\"skip showing freelist.\")\n    parser.add_argument(\"--large\", action=\"store_true\", help=\"display only free_slob_large.\")\n    parser.add_argument(\"--medium\", action=\"store_true\", help=\"display only free_slob_medium.\")\n    parser.add_argument(\"--small\", action=\"store_true\", help=\"display only free_slob_small.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cached offset.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode (print kmem_cache).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} kmalloc-256  # dump kmalloc-256 kmem_cache and all freelists\",\n        \"{0:s} --list       # list slob cache names\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified SLOB structure:\",\n        \"\",\n        \"                         +-kmem_cache--+   +-kmem_cache--+   +-kmem_cache--+\",\n        \"                         | object_size |   | object_size |   | object_size |\",\n        \"                         | size        |   | size        |   | size        |\",\n        \"                         | flags       |   | flags       |   | flags       |\",\n        \"       +-slab_caches-+   | name        |   | name        |   | name        |\",\n        \" ...<->| list_head   |<->| list_head   |<->| list_head   |<->| list_head   |<-> ...\",\n        \"       +-------------+   +-------------+   +-------------+   +-------------+\",\n        \"* slab_caches is not used when traversing the freelist\",\n        \"\",\n        \"   +-free_slob_large--+              +-page/slab-----+           +-page/slab-----+\",\n        \"   | list_head        |<---------+   | freelist      |-----+     | freelist      |\",\n        \"   +-free_slob_medium-+          |   | units (total) |     |     | units (total) |\",\n        \"   | list_head        |-->...    +-->| list_head     |<----|---->| list_head     |<->...\",\n        \"   +-free_slob_small--+              +---------------+     |     +---------------+\",\n        \"   | list_head        |-->...                              |\",\n        \"   +------------------+                      +-------------+\",\n        \"   small : size < 0x100                      |\",\n        \"   medium: 0x100 <= size < 0x400             |   +-chunk-----+   +-chunk-----+\",\n        \"   large : 0x400 <= size < 0x1000            +-->| units     |-->| -offset   |-->...\",\n        \"* size is only judged when first inserted,       | offset    |   +-----------+\",\n        \"  so divided remainder is stay on.               +-----------+   (when units=1, stored negative offset)\",\n        \"\",\n        \"* `struct page` has been split into `struct page` and `struct slab` since kernel 5.17.\",\n        \"  The structure name used for SLOB has been changed to `struct slab`.\",\n        \"* SLOB was removed in kernel 6.4.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    \"\"\"\n    struct kmem_cache {\n        unsigned int object_size;\n        unsigned int size;\n        unsigned int align;\n        slab_flags_t flags;                      // unsigned int\n        unsigned int useroffset;                 // if 4.16 <= kernel\n        unsigned int usersize;                   // if 4.16 <= kernel\n        const char *name;\n        int refcount;\n        void (*ctor)(void *);\n        struct list_head list;\n    };\n\n    struct page {                                // if kernel < 4.18\n        unsigned long flags;\n        void *__unused_1;\n        void *freelist;\n        int units;\n        atomic_t refcount;                       // if kernel < 4.16\n        struct list_head lru;\n        ...\n    };\n\n    struct page {                                // if 4.18 <= kernel < 5.17\n        unsigned long flags;\n        struct list_head lru;\n        struct kmem_cache *__unused_1;\n        void *freelist;\n        void *__unused_2;\n        int units;\n        ...\n    };\n\n    struct slab {                                // if 5.17 <= kernel\n        unsigned long __page_flags;\n        struct list_head slab_list;\n        void *__unused_1;\n        void *freelist\n        long units;\n        unsigned int __unused_2;\n    };\n    \"\"\"\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            if not self.args.meta and not self.args.rescan:\n                return True\n\n        kversion = Kernel.kernel_version()\n        if not kversion:\n            self.quiet_err(\"Failed to resolve kernel version\")\n            return False\n\n        # resolve slab_caches\n        self.slab_caches = KernelAddressHeuristicFinder.get_slab_caches()\n        if self.slab_caches is None:\n            self.quiet_err(\"Failed to resolve `slab_caches`\")\n            return False\n        else:\n            self.quiet_info(\"slab_caches: {:#x}\".format(self.slab_caches))\n\n        # resolve global freelists\n        self.free_slob_large = Symbol.get_ksymaddr(\"free_slob_large\")\n        if self.free_slob_large is None:\n            self.quiet_err(\"Failed to resolve `free_slob_large`\")\n            return False\n        else:\n            self.quiet_info(\"free_slob_large: {:#x}\".format(self.free_slob_large))\n\n        self.free_slob_medium = Symbol.get_ksymaddr(\"free_slob_medium\")\n        if self.free_slob_medium is None:\n            self.quiet_err(\"Failed to resolve `free_slob_medium`\")\n            return False\n        else:\n            self.quiet_info(\"free_slob_medium: {:#x}\".format(self.free_slob_medium))\n\n        self.free_slob_small = Symbol.get_ksymaddr(\"free_slob_small\")\n        if self.free_slob_small is None:\n            self.quiet_err(\"Failed to resolve `free_slob_small`\")\n            return False\n        else:\n            self.quiet_info(\"free_slob_small: {:#x}\".format(self.free_slob_small))\n\n        # offsetof(kmem_cache, list)\n        if kversion < \"4.16\":\n            self.kmem_cache_offset_list = current_arch.ptrsize * 3 + 4 * 4\n        else:\n            self.kmem_cache_offset_list = current_arch.ptrsize * 3 + 4 * 6\n        self.quiet_info(\"offsetof(kmem_cache, list): {:#x}\".format(self.kmem_cache_offset_list))\n\n        # offsetof(kmem_cache, name)\n        self.kmem_cache_offset_name = self.kmem_cache_offset_list - current_arch.ptrsize * 3\n        self.quiet_info(\"offsetof(kmem_cache, name): {:#x}\".format(self.kmem_cache_offset_name))\n\n        # offsetof(kmem_cache, object_size)\n        self.kmem_cache_offset_object_size = 0\n        self.quiet_info(\"offsetof(kmem_cache, object_size): {:#x}\".format(self.kmem_cache_offset_object_size))\n\n        # offsetof(kmem_cache, size)\n        self.kmem_cache_offset_size = 4\n        self.quiet_info(\"offsetof(kmem_cache, size): {:#x}\".format(self.kmem_cache_offset_size))\n\n        # offsetof(kmem_cache, flags)\n        self.kmem_cache_offset_flags = 4 * 3\n        self.quiet_info(\"offsetof(kmem_cache, flags): {:#x}\".format(self.kmem_cache_offset_flags))\n\n        # offsetof(page, next) / offsetof(slab, next)\n        if kversion < \"4.16\":\n            self.page_offset_next = current_arch.ptrsize * 3 + 4 * 2\n        elif kversion < \"4.18\":\n            self.page_offset_next = current_arch.ptrsize * 4\n        elif kversion < \"5.17\":\n            self.page_offset_next = current_arch.ptrsize\n        else:\n            self.page_offset_next = current_arch.ptrsize\n        self.quiet_info(\"offsetof({:s}, next): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_next))\n\n        # offsetof(page, freelist) / offsetof(slab, freelist)\n        if kversion < \"4.18\":\n            self.page_offset_freelist = current_arch.ptrsize * 2\n        elif kversion < \"5.17\":\n            self.page_offset_freelist = current_arch.ptrsize * 4\n        else:\n            self.page_offset_freelist = current_arch.ptrsize * 4\n        self.quiet_info(\"offsetof({:s}, freelist): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_freelist))\n\n        # offsetof(page, units) / offsetof(slab, units)\n        if kversion < \"4.18\":\n            self.page_offset_units = current_arch.ptrsize * 3\n        elif kversion < \"5.17\":\n            self.page_offset_freelist = current_arch.ptrsize * 6\n        else:\n            self.page_offset_freelist = current_arch.ptrsize * 5\n        self.quiet_info(\"offsetof({:s}, units): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_units))\n\n        self.initialized = True\n        return True\n\n    def get_next_kmem_cache(self, addr, point_to_base=True):\n        if point_to_base:\n            addr += self.kmem_cache_offset_list\n        if self.args.reverse_walk:\n            return read_int_from_memory(addr) - self.kmem_cache_offset_list\n        else:\n            return read_int_from_memory(addr + current_arch.ptrsize) - self.kmem_cache_offset_list\n\n    def get_name(self, addr):\n        name_addr = read_int_from_memory(addr + self.kmem_cache_offset_name)\n        return read_cstring_from_memory(name_addr)\n\n    def walk_freelist(self, head, page):\n        if self.args.simple:\n            return []\n\n        freelist = []\n        current = head\n        while True:\n            base = current & get_pagesize_mask_high()\n            units = struct.unpack(\"<h\", read_memory(current, 2))[0]\n            if units < 0:\n                next = -units\n                units = 1\n            else:\n                next = struct.unpack(\"<h\", read_memory(current + 2, 2))[0]\n            freelist.append([current, units])\n            current = base + next * 2\n            if (current & 0xfff) == 0:\n                break\n        return freelist\n\n    def walk_page_freelist(self, head):\n        seen = [head]\n        page_freelist = []\n        current = read_int_from_memory(head)\n        while True:\n            seen.append(current)\n            page = {}\n            page[\"address\"] = current - self.page_offset_next\n            page[\"units\"] = read_int32_from_memory(page[\"address\"] + self.page_offset_units)\n            freelist_head = read_int_from_memory(page[\"address\"] + self.page_offset_freelist)\n            page[\"virt_addr\"] = freelist_head & get_pagesize_mask_high()\n            page[\"num_pages\"] = 1\n            page[\"freelist\"] = self.walk_freelist(freelist_head, page)\n            page[\"next\"] = next = read_int_from_memory(current)\n            page_freelist.append(page)\n            if next in seen:\n                break\n            current = next\n        return page_freelist\n\n    def walk_caches(self, target_names):\n        current_kmem_cache = self.get_next_kmem_cache(self.slab_caches, point_to_base=False)\n        parsed_caches = [{\"name\": \"slab_caches\", \"next\": current_kmem_cache}]\n\n        while current_kmem_cache + self.kmem_cache_offset_list != self.slab_caches:\n            kmem_cache = {}\n            # parse member\n            kmem_cache[\"name\"] = self.get_name(current_kmem_cache)\n            if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                current_kmem_cache = self.get_next_kmem_cache(current_kmem_cache)\n                continue\n            kmem_cache[\"address\"] = current_kmem_cache\n            kmem_cache[\"flags\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_flags)\n            kmem_cache[\"flags_str\"] = SlubDumpCommand.get_flags_str(kmem_cache[\"flags\"])\n            kmem_cache[\"size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_size)\n            kmem_cache[\"object_size\"] = read_int32_from_memory(current_kmem_cache + self.kmem_cache_offset_object_size)\n            kmem_cache[\"next\"] = self.get_next_kmem_cache(current_kmem_cache)\n            parsed_caches.append(kmem_cache)\n            # goto next\n            current_kmem_cache = kmem_cache[\"next\"]\n            # fast break\n            if target_names != [] and not (self.args.list or self.args.list_no_sort):\n                parsed_names = [x[\"name\"] for x in parsed_caches]\n                if all(t in parsed_names for t in target_names):\n                    break\n\n        if self.args.list or self.args.list_no_sort:\n            return parsed_caches, None\n\n        parsed_freelist = {}\n        if self.args.large:\n            parsed_freelist[\"large\"] = self.walk_page_freelist(self.free_slob_large)\n        if self.args.medium:\n            parsed_freelist[\"medium\"] = self.walk_page_freelist(self.free_slob_medium)\n        if self.args.small:\n            parsed_freelist[\"small\"] = self.walk_page_freelist(self.free_slob_small)\n\n        return parsed_caches, parsed_freelist\n\n    def dump_freelist(self, tag, page_freelist):\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        self.out.append(titlify(\"{:s} @ {:#x}\".format(tag, getattr(self, tag))))\n\n        for page in page_freelist:\n            self.out.append(\"  {:s}: {:#x}\".format(Color.colorify(\"page\", label_active_color), page[\"address\"]))\n            colored_virt_addr = Color.colorify_hex(page[\"virt_addr\"], heap_page_color)\n            self.out.append(\"    virtual address: {:s}\".format(colored_virt_addr))\n            self.out.append(\"    num pages: {:d}\".format(page[\"num_pages\"]))\n            self.out.append(\"    total units: {:#x}\".format(page[\"units\"]))\n            for i, (chunk, units) in enumerate(page[\"freelist\"]):\n                self.out.append(\"    {:9s} {:s} (units: {:#x}, size: {:s})\".format(\n                    \"freelist:\" if i == 0 else \"\",\n                    Color.colorify_hex(chunk, freed_address_color),\n                    units,\n                    Color.colorify_hex(units * 2, chunk_size_color),\n                ))\n            self.out.append(\"    next: {:#x}\".format(page[\"next\"]))\n            self.out.append(\"\")\n        return\n\n    def dump_caches(self, target_names, parsed_caches, parsed_freelist):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        if self.args.verbose:\n            self.out.append(titlify(\"{:s} @ {:#x}\".format(\"slab_caches\", self.slab_caches)))\n            for kmem_cache in parsed_caches[1:]:\n                if target_names != [] and kmem_cache[\"name\"] not in target_names:\n                    continue\n                self.out.append(\"  kmem_cache: {:#x}\".format(kmem_cache[\"address\"]))\n                colored_name = Color.colorify(kmem_cache[\"name\"], chunk_label_color)\n                self.out.append(\"    name: {:s}\".format(colored_name))\n                self.out.append(\"    flags: {:#x} ({:s})\".format(kmem_cache[\"flags\"], kmem_cache[\"flags_str\"]))\n                object_size_s = Color.colorify_hex(kmem_cache[\"object_size\"], chunk_size_color)\n                self.out.append(\"    object size: {:s} (chunk size: {:#x})\".format(object_size_s, kmem_cache[\"size\"]))\n                self.out.append(\"    next: {:#x}\".format(kmem_cache[\"next\"]))\n                self.out.append(\"\")\n\n        if self.args.large:\n            self.dump_freelist(\"free_slob_large\", parsed_freelist[\"large\"])\n        if self.args.medium:\n            self.dump_freelist(\"free_slob_medium\", parsed_freelist[\"medium\"])\n        if self.args.small:\n            self.dump_freelist(\"free_slob_small\", parsed_freelist[\"small\"])\n        return\n\n    def dump_names(self, parsed_caches):\n        name_width = max(len(k[\"name\"]) for k in parsed_caches[1:])\n\n        if not self.args.quiet:\n            fmt = \"{:<18s} {:<18s} {:\" + str(name_width) + \"s} {:20s}\"\n            legend = [\"Object Size\", \"Chunk Size\", \"Name\", \"kmem_cache\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        if self.args.list_no_sort:\n            target_caches = parsed_caches[1:]\n        else:\n            target_caches = sorted(parsed_caches[1:], key=lambda x: (x[\"object_size\"], x[\"size\"], x[\"name\"]))\n\n        for kmem_cache in target_caches:\n            objsz = \"{0:d} ({0:#x})\".format(kmem_cache[\"object_size\"])\n            chunksz = \"{0:d} ({0:#x})\".format(kmem_cache[\"size\"])\n            chunk_name = kmem_cache[\"name\"]\n            address = kmem_cache[\"address\"]\n            self.out.append(\"{:18s} {:18s} {:{:d}s} {:#x}\".format(objsz, chunksz, chunk_name, name_width, address))\n        return\n\n    def slobwalk(self, target_names):\n        if self.initialize() is False:\n            self.quiet_err(\"Initialization failed\")\n            return\n\n        if self.args.meta:\n            return\n\n        if self.args.list or self.args.list_no_sort:\n            parsed_caches, _ = self.walk_caches(target_names)\n            self.dump_names(parsed_caches)\n            return\n\n        parsed_caches, parsed_freelist = self.walk_caches(target_names)\n        self.dump_caches(target_names, parsed_caches, parsed_freelist)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            self.quiet_err(\"Unsupported; You should use `slub-dump`\")\n            return\n        elif allocator == \"SLUB_TINY\":\n            self.quiet_err(\"Unsupported; You should use `slub-tiny-dump`\")\n            return\n        elif allocator == \"SLAB\":\n            self.quiet_err(\"Unsupported; You should use `slab-dump`\")\n            return\n        elif allocator == \"SLOB\":\n            pass\n        else:\n            self.quiet_err(\"Unsupported: Unknown allocator\")\n            return\n\n        if (args.large, args.medium, args.small) == (False, False, False):\n            self.args.large = True\n            self.args.medium = True\n            self.args.small = True\n\n        self.maps = None\n        self.out = []\n        self.slobwalk(args.cache_name)\n        self.print_output()\n        return\n\n\n@register_command\nclass SlabContainsCommand(GenericCommand):\n    \"\"\"Resolve the slab cache (kmem_cache) that an object belongs to (for slab/slub/slub-tiny).\"\"\"\n\n    _cmdline_ = \"slab-contains\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n    _aliases_ = [\"xslab\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"target address.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified page/slab structure:\",\n        \"\",\n        \"+-kmem_cache-+\",\n        \"| cpu_slab   |--->+-kmem_cache_cpu-+\",\n        \"| ...        |    | page/slab      |--+\",\n        \"+------------+    | freelist       |  |\",\n        \"      ^           +----------------+  |   <---virt/page translate--->\",\n        \"      |                               v\",\n        \"      |                         +-page/slab---+               +-0x1000-page-+ <--base (named by GEF)\",\n        \"      +-------------------------|  slab_cache |               | chunk       |\",\n        \"      |                         +-page/slab---+               | ...         |\",\n        \"      +-------------------------|  slab_cache |               +-0x1000-page-+\",\n        \"      |                         +-page/slab---+               | chunk       |\",\n        \"      +-------------------------|  slab_cache |               | chunk       | <--user specified address\",\n        \"                                +-------------+               | ...         |\",\n        \"                                                              +-0x1000-page-+\",\n        \"                                                              | chunk       |\",\n        \"                                                              | ...         |\",\n        \"                                                              +-------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        cmd = {\"SLUB\": \"slub-dump\", \"SLAB\": \"slab-dump\", \"SLUB_TINY\": \"slub-tiny-dump\"}[self.allocator]\n        res = gdb.execute(\"{:s} --meta\".format(cmd), to_string=True)\n\n        r = re.search(r\"offsetof\\((?:page|slab), slab_cache\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        self.page_offset_slab_cache = int(r.group(1), 16)\n        if self.args.verbose:\n            info(\"offsetof({:s}, slab_cache): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_slab_cache))\n\n        r = re.search(r\"offsetof\\((?:page|slab), next\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        self.page_offset_next = int(r.group(1), 16)\n        if self.args.verbose:\n            info(\"offsetof({:s}, next): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_next))\n\n        r = re.search(r\"offsetof\\(kmem_cache, name\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        self.kmem_cache_offset_name = int(r.group(1), 16)\n        if self.args.verbose:\n            info(\"offsetof(kmem_cache, name): {:#x}\".format(self.kmem_cache_offset_name))\n\n        r = re.search(r\"offsetof\\(kmem_cache, size\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        self.kmem_cache_offset_size = int(r.group(1), 16)\n        if self.args.verbose:\n            info(\"offsetof(kmem_cache, size): {:#x}\".format(self.kmem_cache_offset_size))\n\n        r = re.search(r\"offsetof\\(kmem_cache, object_size\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        self.kmem_cache_offset_object_size = int(r.group(1), 16)\n        if self.args.verbose:\n            info(\"offsetof(kmem_cache, object_size): {:#x}\".format(self.kmem_cache_offset_object_size))\n\n        # for aligned check\n        if self.allocator in [\"SLUB\", \"SLUB_TINY\"]:\n            r = re.search(r\"offsetof\\(kmem_cache, red_left_pad\\): (0x\\S+)\", res)\n            if not r:\n                return False\n            self.kmem_cache_offset_red_left_pad = int(r.group(1), 16)\n            if self.args.verbose:\n                info(\"offsetof(kmem_cache, red_left_pad): {:#x}\".format(self.kmem_cache_offset_red_left_pad))\n\n        if self.allocator == \"SLAB\":\n            r = re.search(r\"offsetof\\((?:page|slab), s_mem\\): (0x\\S+)\", res)\n            if not r:\n                return False\n            self.page_offset_s_mem = int(r.group(1), 16)\n            if self.args.verbose:\n                info(\"offsetof({:s}, s_mem): {:#x}\".format(Kernel.slab_page_str(), self.page_offset_s_mem))\n\n        # for slab-virtual\n        if is_x86_64():\n            r = re.search(r\"offsetof\\(kmem_cache, freed_slabs_min\\): (0x\\S+)\", res)\n            if r:\n                self.slab_virtual_enabled = True\n                if self.args.verbose:\n                    info(\"offsetof(kmem_cache, freed_slabs_min): {:#x}\".format(int(r.group(1), 16)))\n            else:\n                self.slab_virtual_enabled = False\n        else:\n            self.slab_virtual_enabled = False\n\n        # for num of pages\n        if self.allocator in [\"SLUB\", \"SLUB_TINY\"]:\n            r = re.search(r\"offsetof\\((?:page|slab), inuse_objects_frozen\\): (0x\\S+)\", res)\n            if not r:\n                return False\n            self.page_offset_inuse_objects_frozen = int(r.group(1), 16)\n            if self.args.verbose:\n                info(\"offsetof({:s}, inuse_objects_frozen): {:#x}\".format(\n                    Kernel.slab_page_str(), self.page_offset_inuse_objects_frozen,\n                ))\n\n        elif self.allocator == \"SLAB\":\n            r = re.search(r\"offsetof\\(kmem_cache, gfporder\\): (0x\\S+)\", res)\n            if not r:\n                return False\n            self.kmem_cache_offset_gfporder = int(r.group(1), 16)\n            if self.args.verbose:\n                info(\"offsetof(kmem_cache, gfporder): {:#x}\".format(self.kmem_cache_offset_gfporder))\n\n        self.initialized = True\n        return True\n\n    def virt2page_wrapper(self, vaddr):\n        if self.slab_virtual_enabled:\n            ret = gdb.execute(\"slab-virtual --quiet from_virt {:#x}\".format(vaddr), to_string=True)\n            r = re.search(r\"Slab: (\\S+)\", ret)\n        else:\n            ret = gdb.execute(\"virt2page {:#x}\".format(vaddr), to_string=True)\n            r = re.search(r\"Page: (\\S+)\", ret)\n\n        if r:\n            return int(r.group(1), 16)\n        return None\n\n    def check_slab_dump(self, target_addr, slab_cache_name):\n\n        def get_freed_addresses(res):\n            freed_addresses = []\n            res = Color.remove_color(res)\n            in_freelist_section = 0\n            for line in res.splitlines():\n                line = line.rstrip()\n                if not in_freelist_section:\n                    if re.match(r\"^        (freelist|objects:)\", line):\n                        in_freelist_section = 1\n                    elif re.match(r\"^        entry:\", line):\n                        in_freelist_section = 2\n                elif in_freelist_section == 1:\n                    if not line.startswith(\"                  0x\"):\n                        in_freelist_section = 0\n                elif in_freelist_section == 2:\n                    if not line.startswith(\"               0x\"):\n                        in_freelist_section = 0\n                if in_freelist_section == 1:\n                    r = re.search(r\"0x\\S+ (0x\\S+)\", line)\n                    if r:\n                        freed_chunk = int(r.group(1), 16)\n                        freed_addresses.append(freed_chunk)\n                elif in_freelist_section == 2:\n                    r = re.search(r\"(0x\\S+)\", line)\n                    if r:\n                        freed_chunk = int(r.group(1), 16)\n                        freed_addresses.append(freed_chunk)\n            return freed_addresses\n\n        if self.allocator == \"SLUB\":\n            res = gdb.execute(\"slub-dump --node --no-pager --quiet {:s}\".format(slab_cache_name), to_string=True)\n        elif self.allocator == \"SLUB_TINY\":\n            res = gdb.execute(\"slub-tiny-dump --no-pager --quiet {:s}\".format(slab_cache_name), to_string=True)\n        elif self.allocator == \"SLAB\":\n            res = gdb.execute(\"slab-dump --no-pager --quiet {:s}\".format(slab_cache_name), to_string=True)\n        else:\n            return\n\n        freed_addresses = get_freed_addresses(res)\n\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        if target_addr in freed_addresses:\n            gef_print(\"status: {:s} (found in freelist)\".format(Color.colorify(\"freed\", freed_address_color)))\n        else:\n            gef_print(\"status: {:s} (not found in freelist)\".format(Color.colorify(\"in-use\", used_address_color)))\n        return\n\n    def slab_contains(self):\n        current = self.args.address & get_pagesize_mask_high()\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        try:\n            while True:\n                page = self.virt2page_wrapper(current)\n                if page is None:\n                    self.quiet_err(\"Invalid address\")\n                    return\n\n                self.quiet_print(\"{:s}: {:#x}\".format(Kernel.slab_page_str(), page))\n\n                page_next = read_int_from_memory(page + self.page_offset_next)\n                if page_next & 1:\n                    current -= get_pagesize()\n                    self.quiet_warn(\"Detected invalid value, continue exploring...\")\n                    continue\n\n                kmem_cache = read_int_from_memory(page + self.page_offset_slab_cache)\n                if kmem_cache == 0:\n                    self.quiet_err(\"This address is not managed by slab (kmem_cache=0)\")\n                    return\n\n                self.quiet_print(\"kmem_cache: {:#x}\".format(kmem_cache))\n\n                if (kmem_cache & get_pagesize_mask_high()) == 0xdead_0000_0000_0000:\n                    current -= get_pagesize()\n                    self.quiet_warn(\"Detected invalid value, continue exploring...\")\n                    continue\n\n                if kmem_cache & 1:\n                    current -= get_pagesize()\n                    self.quiet_warn(\"Detected invalid value, continue exploring...\")\n                    continue\n\n                self.quiet_print(\"base: {:#x}\".format(current))\n                break\n        except (gdb.MemoryError, ZeroDivisionError):\n            self.quiet_err(\"Memory read error\")\n            return\n\n        try:\n            slab_cache_name_ptr = read_int_from_memory(kmem_cache + self.kmem_cache_offset_name)\n            slab_cache_name = read_cstring_from_memory(slab_cache_name_ptr)\n            if slab_cache_name is None:\n                self.quiet_err(\"This address is not managed by slab (slab_cache_name=\\\"\\\")\")\n                return\n\n            slab_cache_size = read_int32_from_memory(kmem_cache + self.kmem_cache_offset_size)\n            slab_cache_object_size = read_int32_from_memory(kmem_cache + self.kmem_cache_offset_object_size)\n\n            if self.allocator in [\"SLUB\", \"SLUB_TINY\"]:\n                red_left_pad = read_int_from_memory(kmem_cache + self.kmem_cache_offset_red_left_pad)\n                color_offset = 0\n                x = read_int_from_memory(page + self.page_offset_inuse_objects_frozen)\n                objects = (x >> 16) & 0x7fff\n                num_pages = (slab_cache_size * objects + get_pagesize_mask_low()) // get_pagesize()\n            else:\n                red_left_pad = 0\n                s_mem = read_int_from_memory(page + self.page_offset_s_mem)\n                color_offset = s_mem & 0xfff\n                gfporder = read_int32_from_memory(kmem_cache + self.kmem_cache_offset_gfporder)\n                num_pages = 1 << gfporder\n\n            # `inuse` is not displayed because it is not a reliable reference value.\n            # The value of `slab->inuse` also includes the number of chunks registered in `kmem_cache_cpu->freelist` etc.\n            # However, what the user actually wants is the number of chunks that are truly in use,\n            # excluding those accounted for by `kmem_cache_cpu->freelist`.\n            # Accurately deriving that value is non-trivial.\n            msg = (\"name: {:s}  object_size: {:s} (chunk_size: {:#x})  num_pages: {:#x}\".format(\n                Color.colorify(slab_cache_name, chunk_label_color),\n                Color.colorify_hex(slab_cache_object_size, chunk_size_color),\n                slab_cache_size,\n                num_pages,\n            ))\n            aligned = True\n            if (self.args.address - (red_left_pad + color_offset) - current) % slab_cache_size != 0:\n                msg += \" \" + Color.redify(\"(unaligned?)\")\n                aligned = False\n            gef_print(msg)\n\n            # resolve freelist and print chunk status (in-use or freed)\n            if aligned:\n                self.check_slab_dump(self.args.address, slab_cache_name)\n        except (gdb.MemoryError, ZeroDivisionError):\n            self.quiet_err(\"Memory read error\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        if not hasattr(self, \"initialized\"):\n            self.initialized = False\n\n        if args.rescan:\n            self.initialized = False\n\n        if not hasattr(self, \"allocator\"):\n            self.allocator = Kernel.get_slab_type()\n\n        if self.allocator not in [\"SLUB\", \"SLUB_TINY\", \"SLAB\"]:\n            self.quiet_err(\"Unsupported: SLOB, Unknown allocator\")\n            return\n\n        ret = self.initialize()\n        if not ret:\n            self.quiet_err(\"Failed to initialize\")\n            return\n\n        self.slab_contains()\n        return\n\n\n@register_command\nclass KmemCacheAliasCommand(GenericCommand, BufferingOutput):\n    \"\"\"Resolve the slab cache (kmem_cache) alias.\"\"\"\n\n    _cmdline_ = \"kmem-cache-alias\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"names\", nargs=\"*\", help=\"filter by specific cache name(s) (substring match).\")\n    parser.add_argument(\"-s\", \"--sort-by-size\", action=\"store_true\", help=\"sort by object size.\")\n    parser.add_argument(\"-m\", \"--merged-only\", action=\"store_true\",\n                        help=\"show only merged caches grouped by physical cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command requires CONFIG_SYSFS=y.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def parse_rb_node(self, rb_node):\n        if not rb_node or not is_valid_addr(rb_node):\n            return []\n\n        right = read_int_from_memory(rb_node + current_arch.ptrsize * 1) & ~1 # remove RB_BLACK\n        left = read_int_from_memory(rb_node + current_arch.ptrsize * 2) & ~1 # remove RB_BLACK\n\n        ret = [rb_node]\n        if right:\n            ret += self.parse_rb_node(right)\n        if left:\n            ret += self.parse_rb_node(left)\n        return ret\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        self.slab_kset = KernelAddressHeuristicFinder.get_slab_kset()\n        if self.slab_kset is None:\n            self.quiet_err(\"Could not find slab_kset\")\n            return False\n        self.quiet_info(\"slab_kset: {:#x}\".format(self.slab_kset))\n\n        \"\"\"\n        struct kset {\n            struct list_head list;\n            spinlock_t list_lock;\n            struct kobject {\n                const char *name; // -> \"slab\"\n                struct list_head entry;\n                struct kobject *parent;\n                struct kset *kset;\n                const struct kobj_type *ktype;\n                struct kernfs_node *sd;\n                ...\n            } kobj;\n            const struct kset_uevent_ops *uevent_ops;\n        } __randomize_layout;\n        \"\"\"\n        kset = read_int_from_memory(self.slab_kset)\n        for i in range(0x10):\n            if not is_valid_addr(kset + current_arch.ptrsize * i):\n                continue\n            name_ptr = read_int_from_memory(kset + current_arch.ptrsize * i)\n            name = read_cstring_from_memory(name_ptr)\n            if name != \"slab\":\n                continue\n            if not is_double_link_list(kset + current_arch.ptrsize * (i + 1)):\n                continue\n            # found\n            self.offset_kobj_sd = current_arch.ptrsize * (i + 6)\n            self.quiet_info(\"offsetof(kset, kobj.sd): {:#x}\".format(self.offset_kobj_sd))\n            break\n        else:\n            self.quiet_err(\"Could not find offsetof(kset, kobj.sd)\")\n            return False\n\n        \"\"\"\n        struct kernfs_node {\n            atomic_t count;\n            atomic_t active;\n        #ifdef CONFIG_DEBUG_LOCK_ALLOC\n            struct lockdep_map dep_map;\n        #endif\n            struct kernfs_node __rcu *__parent;\n            const char __rcu *name;\n            struct rb_node {\n                unsigned long __rb_parent_color;\n                struct rb_node *rb_right;\n                struct rb_node *rb_left;\n            } __attribute__((aligned(sizeof(long)))) rb;\n            const void *ns;\n            unsigned int hash;\n            unsigned short flags; // v6.9~\n            umode_t mode; // unsigned short, v6.9~\n            union {\n                struct kernfs_elem_dir {\n                    unsigned long subdirs;\n                    struct rb_root children;\n                    struct kernfs_root *root;\n                } dir;\n                struct kernfs_elem_symlink {\n                    struct kernfs_node *target_kn;\n                } symlink;\n                struct kernfs_elem_attr attr;\n            };\n            u64 id;\n            void *priv;\n            struct kernfs_iattrs *iattr;\n            struct rcu_head rcu;\n        };\n        \"\"\"\n\n        sd = read_int_from_memory(kset + self.offset_kobj_sd)\n        for i in range(0x20):\n            if not is_valid_addr(sd + current_arch.ptrsize * i):\n                continue\n            name_ptr = read_int_from_memory(sd + current_arch.ptrsize * i)\n            name = read_cstring_from_memory(name_ptr)\n            if name != \"slab\":\n                continue\n            # found\n            self.offset_name = current_arch.ptrsize * i\n            self.offset_rb = self.offset_name + current_arch.ptrsize\n            self.offset_union = self.offset_rb + current_arch.ptrsize * 5\n            subdirs = read_int_from_memory(sd + self.offset_union)\n            if subdirs == 0 or subdirs > 0x1000:\n                # subdirs should be small positive number (~0x200), at most, it should not be 0x1000.\n                # so there exists padding or flags||mode if not.\n                self.offset_union += current_arch.ptrsize\n            self.offset_dir_children = self.offset_union + current_arch.ptrsize\n            self.offset_symlink_target_kn = self.offset_union\n            self.quiet_info(\"offsetof(kernfs_node, name): {:#x}\".format(self.offset_name))\n            self.quiet_info(\"offsetof(kernfs_node, rb): {:#x}\".format(self.offset_rb))\n            self.quiet_info(\"offsetof(kernfs_node, dir.children): {:#x}\".format(self.offset_dir_children))\n            self.quiet_info(\"offsetof(kernfs_node, symlink.target_kn): {:#x}\".format(self.offset_symlink_target_kn))\n            break\n        else:\n            self.quiet_err(\"Could not find offsetof(kernfs_node, name)\")\n            return False\n\n        self.initialized = True\n        return True\n\n    def parse_kmem_cache_alias(self):\n        # get children_root\n        kset = read_int_from_memory(self.slab_kset)\n        sd = read_int_from_memory(kset + self.offset_kobj_sd)\n        children_root = read_int_from_memory(sd + self.offset_dir_children)\n\n        # parse\n        alias_groups = {}\n        nodes = self.parse_rb_node(children_root)\n        for node in nodes:\n            node = node - self.offset_rb\n            name_ptr = read_int_from_memory(node + self.offset_name)\n            name = read_cstring_from_memory(name_ptr)\n\n            target_kn = read_int_from_memory(node + self.offset_symlink_target_kn)\n            alias = \"-\"\n            if is_valid_addr(target_kn):\n                alias_ptr = read_int_from_memory(target_kn + self.offset_name)\n                alias = read_cstring_from_memory(alias_ptr)\n            # rare case: L2TP!IPv6 -> L2TP/IPv6\n            if \"!\" in name:\n                name = name.replace(\"!\", \"/\")\n            alias_groups[name] = {\n                \"alias\": alias,\n                \"slab_cache_name\": None,\n                \"name\": name,\n                \"object_size\": 0,\n                \"chunk_size\": 0,\n            }\n\n        # parse slub-dump\n        cmd = {\"SLUB\": \"slub-dump\", \"SLUB_TINY\": \"slub-tiny-dump\"}[self.allocator]\n        res = gdb.execute(\"{:s} --list --no-pager --quiet\".format(cmd), to_string=True)\n        used_names = []\n        for line in res.splitlines():\n            r = re.search(r\"(\\d+)\\s+\\(0x\\S+\\)\\s+(\\d+)\\s+\\(0x\\S+\\)\\s+(\\S+)\\s+0x\\S+$\", line)\n            object_size = int(r.group(1))\n            chunk_size = int(r.group(2))\n            name = r.group(3)\n            used_names.append([object_size, chunk_size, name])\n\n        # identify the actual slab_cache name in use\n        for object_size, chunk_size, slab_cache_name in used_names:\n            original_slab_cache_name = slab_cache_name\n\n            # In older kernels, the slab_cache name may include the process name,\n            # such as \"kmalloc-512(342:serial-getty@ttyAMA0.service)\".\n            # To support this, anything after the parentheses is ignored.\n            if slab_cache_name not in alias_groups:\n                if \"(\" in slab_cache_name:\n                    slab_cache_name = slab_cache_name[:slab_cache_name.find(\"(\")]\n\n            # skip if not found\n            if slab_cache_name not in alias_groups:\n                self.quiet_err(\"Could not find key: {:s}\".format(original_slab_cache_name))\n                continue\n\n            for k in alias_groups.keys():\n                # already resolved\n                if alias_groups[k][\"slab_cache_name\"]:\n                    continue\n\n                if alias_groups[k][\"alias\"] == \"-\":\n                    if k == alias_groups[slab_cache_name][\"alias\"]:\n                        # k: \":0000256\" -> \"-\"\n                        # slab_cache_name: \"key_jar\" -> \":0000256\"\n                        alias_groups[k][\"slab_cache_name\"] = slab_cache_name\n                        alias_groups[k][\"object_size\"] = object_size\n                        alias_groups[k][\"chunk_size\"] = chunk_size\n                    elif k == slab_cache_name:\n                        # k: \"kmalloc-256\" -> \"-\"\n                        # slab_cache_name: \"kmalloc-256\" -> \"-\"\n                        alias_groups[k][\"slab_cache_name\"] = slab_cache_name\n                        alias_groups[k][\"object_size\"] = object_size\n                        alias_groups[k][\"chunk_size\"] = chunk_size\n                else:\n                    if alias_groups[k][\"alias\"] == alias_groups[slab_cache_name][\"alias\"]:\n                        # k: \"key_jar\" -> \":0000256\"\n                        # slab_cache_name: \"key_jar\" -> \":0000256\"\n                        alias_groups[k][\"slab_cache_name\"] = slab_cache_name\n                        alias_groups[k][\"object_size\"] = object_size\n                        alias_groups[k][\"chunk_size\"] = chunk_size\n        return alias_groups\n\n    def make_output_merged(self, alias_groups):\n        chunk_label_color = Config.get_gef_setting(\"theme.heap_chunk_label\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        # group entries by their Physical Cache Name\n        merged_groups = {}\n        for name, info in alias_groups.items():\n            if not info[\"slab_cache_name\"]:\n                continue\n\n            phys_name = info[\"slab_cache_name\"]\n            if phys_name not in merged_groups:\n                merged_groups[phys_name] = []\n\n            entry = info.copy()\n            entry[\"logical_name\"] = name\n            merged_groups[phys_name].append(entry)\n\n        # list keys\n        if self.args.names:\n            target_phys_groups = set()\n\n            # Check every physical group\n            for phys_name, children in merged_groups.items():\n                matched_group = False\n                for child in children:\n                    child_name = child[\"logical_name\"]\n                    for filter_name in self.args.names:\n                        if filter_name in child_name:\n                            target_phys_groups.add(phys_name)\n                            matched_group = True\n                            break\n\n                    if matched_group:\n                        break # found a match in this group, move to next one\n            if not target_phys_groups:\n                self.out.append(\"No caches found matching filter '{}'.\".format(\", \".join(self.args.names)))\n                return\n\n            # Only process the unique set of matching groups\n            keys_to_process = [k for k in merged_groups.keys() if k in target_phys_groups]\n        else:\n            keys_to_process = list(merged_groups.keys())\n\n        # sort by keys\n        if self.args.sort_by_size:\n            sorted_phys_names = sorted(keys_to_process,\n                key=lambda k: (merged_groups[k][0][\"object_size\"] if merged_groups[k] else 0))\n        else:\n            sorted_phys_names = sorted(keys_to_process)\n\n        # print\n        self.out.append(titlify(\"Merged Slab Caches\"))\n        found_merge = False\n        for phys_name in sorted_phys_names:\n            children = merged_groups[phys_name]\n\n            # MERGE-ONLY LOGIC:\n            # We want to hide groups that are just [PhysicalOwner, SysfsID]\n            # We count how many \"real\" aliases exist.\n            # A \"real\" alias is one that is NOT the physical owner AND NOT the sysfs group ID (alias == \"-\")\n            real_aliases = 0\n            keep_this_group = False\n            for child in children:\n                # If alias is \"-\" it's the sysfs group ID (e.g. :0000064)\n                # If logical_name == phys_name, it's the physical owner\n                if child[\"alias\"] != \"-\" and child[\"logical_name\"] != phys_name:\n                    real_aliases += 1\n\n                # filtering by name\n                if self.args.names:\n                    for filter_name in self.args.names:\n                        if child[\"logical_name\"] in filter_name:\n                            keep_this_group = True\n                            break\n            if real_aliases == 0 and not keep_this_group:\n                continue\n            found_merge = True\n\n            # print header\n            header = \"{:s} (Object size: {:s}, Chunk size: {:#x})\".format(\n                Color.colorify(phys_name, chunk_label_color),\n                Color.colorify_hex(children[0][\"object_size\"], chunk_size_color),\n                children[0][\"chunk_size\"],\n            )\n            self.out.append(header)\n\n            # print as tree\n            children.sort(key=lambda x: x[\"logical_name\"])\n            for i, child in enumerate(children):\n                # If non-ASCII characters are included, they will affect\n                # the processing of dev/update-syscalls/update-syscalls.py and\n                # other programs for developing, so they should be written in hexadecimal.\n                if i == len(children) - 1:\n                    tree_char = b\"\\xe2\\x94\\x94\\xe2\\x94\\x80\\xe2\\x94\\x80 \".decode()\n                else:\n                    tree_char = b\"\\xe2\\x94\\x9c\\xe2\\x94\\x80\\xe2\\x94\\x80 \".decode()\n\n                # coloring\n                name_str = child[\"logical_name\"]\n                already_colored = False\n                # Highlight the specific match if filtering is active\n                if self.args.names:\n                    for filter_name in self.args.names:\n                        if filter_name in name_str:\n                            name_str = Color.colorify(name_str, \"bold underline orange\")\n                            already_colored = True\n                            break\n\n                if name_str == phys_name:\n                    if not already_colored:\n                        name_str = Color.colorify(name_str, \"green\")\n                    line = tree_char + name_str + \" (Physical Owner)\"\n                elif child[\"alias\"] == \"-\":\n                    line = tree_char + Color.colorify(name_str, \"gray\") + \" (Sysfs Group)\"\n                else:\n                    line = tree_char + name_str\n                self.out.append(line)\n            self.out.append(\"\")\n\n        if not found_merge:\n            self.out.append(\"No interesting merges found (1:1 mappings only).\")\n        return\n\n    def make_output(self, alias_groups):\n        fmt = \"{:16s} {:16s} {:30s} {:12s} {:s}\"\n        legend = [\"Object Size\", \"Chunk Size\", \"Name\", \"Alias\", \"slab_cache name\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # sort by keys\n        if self.args.sort_by_size:\n            sorted_alias_groups = sorted(alias_groups.items(),\n                key=lambda x: (x[1][\"object_size\"], x[1][\"chunk_size\"], x[1][\"name\"]))\n        else:\n            sorted_alias_groups = sorted(alias_groups.items())\n\n        found = False\n        # print\n        for name, v in sorted_alias_groups:\n            # filtering by name\n            if self.args.names:\n                for filter_name in self.args.names:\n                    if filter_name in name:\n                        break\n                    if filter_name in v[\"alias\"]:\n                        break\n                    if filter_name in v[\"slab_cache_name\"]:\n                        break\n                else:\n                    continue\n\n            # print flat\n            found = True\n            if v[\"object_size\"] == 0:\n                self.out.append(\"{:16s} {:16s} {:30s} {:12s} {:s}\".format(\n                    \"-\", \"-\", name, v[\"alias\"], \"<UNUSED>\",\n                ))\n            else:\n                object_size = \"{0:d} ({0:#x})\".format(v[\"object_size\"])\n                chunk_size = \"{0:d} ({0:#x})\".format(v[\"chunk_size\"])\n                self.out.append(\"{:16s} {:16s} {:30s} {:12s} {:s}\".format(\n                    object_size, chunk_size, name, v[\"alias\"], v[\"slab_cache_name\"],\n                ))\n\n        if self.args.names and not found:\n            self.out.append(\"No caches found matching filters\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"3.14\":\n            self.quiet_err(\"Unsupported before v3.14\")\n            return\n\n        if not hasattr(self, \"allocator\"):\n            self.allocator = Kernel.get_slab_type()\n\n        if self.allocator not in [\"SLUB\", \"SLUB_TINY\"]:\n            self.quiet_err(\"Unsupported: SLAB, SLOB, Unknown allocator\")\n            return\n\n        ret = self.initialize()\n        if not ret:\n            self.quiet_err(\"Failed to initialize\")\n            return\n\n        self.out = []\n        alias_groups = self.parse_kmem_cache_alias()\n        if self.args.merged_only:\n            self.make_output_merged(alias_groups)\n        else:\n            self.make_output(alias_groups)\n        self.print_output()\n        return\n\n\n@register_command\nclass BuddyDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the zone of the page allocator (buddy allocator) free-list.\"\"\"\n\n    _cmdline_ = \"buddy-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n    _aliases_ = [\"zone-dump\", \"pcplist\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-z\", \"--zone\", dest=\"zone_filter\", action=\"append\",\n                        choices=[\"DMA\", \"DMA32\", \"Normal\", \"HighMem\", \"Movable\", \"Device\"],\n                        help=\"filter by specified zone name.\")\n    parser.add_argument(\"-o\", \"--order\", dest=\"order_filter\", action=\"append\", type=int,\n                        help=\"filter by specified order.\")\n    parser.add_argument(\"-m\", \"--mtype\", dest=\"mtype_filter\", action=\"append\", type=int,\n                        help=\"filter by specified mtype.\")\n    parser.add_argument(\"-p\", \"--pcp-index\", dest=\"pcp_index_filter\", action=\"append\", type=int,\n                        help=\"filter by specified per-cpu index.\")\n    parser.add_argument(\"-P\", \"--only-pcp\", action=\"store_true\", help=\"dump only per-cpu pages.\")\n    parser.add_argument(\"-F\", \"--skip-pcp\", action=\"store_true\", help=\"skip dumping per-cpu pages (dump only free_area).\")\n    parser.add_argument(\"--cpu\", action=\"append\", type=int, help=\"filter by specific cpu for per-cpu pages.\")\n    parser.add_argument(\"-s\", \"--sort\", action=\"store_true\",\n                        help=\"sort by page address instead of link list order of each size. overrides -c to 0.\")\n    parser.add_argument(\"-S\", \"--sort-verbose\", action=\"store_true\",\n                        help=\"enable --sort and add used area. filtered areas are treated as used. overrides -c to 0.\")\n    parser.add_argument(\"-Q\", \"--skip-phys\", action=\"store_true\", help=\"skip virt -> phys translation.\")\n    parser.add_argument(\"-M\", \"--use-physmap\", action=\"store_true\",\n                        help=\"use physmap for virt -> phys translation to speed up (when KGDB mode, x64/arm64 only).\")\n    parser.add_argument(\"--MIGRATE_PCPTYPES\", type=int, choices=[3, 4], default=3,\n                        help=\"use specify value; linux: 3, android: 4 (2023~).\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-c\", \"--count\", metavar=\"N\", type=AddressUtil.parse_address, default=5,\n                        help=\"max entries to read per list (default: %(default)s, 0=unlimited). -s/-S/-v/-vv override this to 0.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"show all entries for non-sort mode. equivalent to -c 0.\")\n    parser.add_argument(\"-vv\", \"--vverbose\", action=\"store_true\",\n                        help=\"show empty entries too for non-sort mode. overrides -c to 0.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -z DMA32\",\n        \"{0:s} -o 1 -o 2\",\n        \"{0:s} --only-pcp --pcp-index 0 --cpu 0\",\n        \"{0:s} --sort-verbose\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified buddy allocator structure:\",\n        \"\",\n        \"  +-node_data[MAX_NUMNODES]-+\",\n        \"  | *pglist_data (node 0)   |--+\",\n        \"  | *pglist_data (node 1)   |  |\",\n        \"  | *pglist_data (node 2)   |  |\",\n        \"  | ...                     |  |\",\n        \"  +-------------------------+  |\",\n        \"                               |\",\n        \"    +--------------------------+\",\n        \"    |\",\n        \"    v\",\n        \"  +-pglist_data------------------------------+\",\n        \"  | node_zones[MAX_NR_ZONES]                 |\",\n        \"  |   +-node_zones[0]----------------------+ |   +--->+-per_cpu_pages--------+\",\n        \"  |   |  ...                               | |   |    | ...                  |\",\n        \"  |   |  per_cpu_pageset                   |-----+    | lists[NR_PCP_LISTS]  |    +-page-----+\",\n        \"  |   |  ...                               | |        |   +-lists[0]-------+ |    | flags    |\",\n        \"  |   |  name                              | |        |   | next           |----->| lru.next |->...\",\n        \"  |   |  ...                               | |        |   | prev           | |    | lru.prev |\",\n        \"  |   |  free_area[MAX_ORDER]              | |        |   +-lists[1]-------+ |    | ...      |\",\n        \"  |   |    +-free_area[0]----------------+ | |        |   | ...            | |    +----------+\",\n        \"  |   |    | free_list[MIGRATE_TYPES]    | | |        |   +----------------+ |\",\n        \"  |   |    |   +-free_list[0]----------+ | | |        +----------------------+\",\n        \"  |   |    |   | next                  |---------+\",\n        \"  |   |    |   | prev                  | | | |   |\",\n        \"  |   |    |   +-free_list[1]----------+ | | |   |    +-page-----+    +-page-----+    +-page-----+\",\n        \"  |   |    |   | ...                   | | | |   |    | flags    |    | flags    |    | flags    |\",\n        \"  |   |    |   +-----------------------+ | | |   +--->| lru.next |--->| lru.next |--->| lru.next |->...\",\n        \"  |   |    | nr_free                     | | |        | lru.prev |    | lru.prev |    | lru.prev |\",\n        \"  |   |    +-free_area[1]----------------+ | |        | ...      |    | ...      |    | ...      |\",\n        \"  |   |    | ...                         | | |        +----------+    +----------+    +----------+\",\n        \"  |   |    +-----------------------------+ | |\",\n        \"  |   +-node_zones[1]----------------------+ |\",\n        \"  |   |  ...                               | |\",\n        \"  |   +------------------------------------+ |\",\n        \"  | ...                                      |\",\n        \"  +------------------------------------------+\",\n        \"\",\n        \"You can combine this result with information of in-use space. Try using `kvmmap` command.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def resolve_zone_offset_name(self):\n        # fast path\n        try:\n            self.offset_name = to_unsigned_long(gdb.parse_and_eval(\"&((struct zone*)0).name\"))\n            self.sizeof_zone = to_unsigned_long(gdb.parse_and_eval(\"sizeof(struct zone)\"))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        current = self.nodes[0]\n        name_offsets = []\n        while len(name_offsets) < 2:\n            val = read_int_from_memory(current)\n            name = read_cstring_from_memory(val)\n            if name in [\"DMA\", \"DMA32\", \"Normal\", \"HighMem\", \"Movable\", \"Device\"]:\n                offset = current - self.nodes[0]\n                name_offsets.append(offset)\n            current += current_arch.ptrsize\n        self.offset_name = name_offsets[0]\n        self.sizeof_zone = name_offsets[1] - name_offsets[0]\n        return\n\n    def resolve_zone_offset_per_cpu_pageset(self):\n        # fast path\n        kversion = Kernel.kernel_version()\n        try:\n            if kversion < \"5.14\":\n                self.offset_per_cpu_pageset = to_unsigned_long(gdb.parse_and_eval(\"&((struct zone*)0).pageset\"))\n            else:\n                self.offset_per_cpu_pageset = to_unsigned_long(gdb.parse_and_eval(\"&((struct zone*)0).per_cpu_pageset\"))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        if \"3.12\" <= kversion:\n            current = self.nodes[0]\n            while current < self.nodes[0] + self.offset_name:\n                val = read_int_from_memory(current)\n                if is_valid_addr(val):\n                    offset_zone_pgdat = current - self.nodes[0]\n                    self.offset_per_cpu_pageset = offset_zone_pgdat + current_arch.ptrsize\n                    return\n                current += current_arch.ptrsize\n            self.offset_per_cpu_pageset = None\n            return\n\n        for i in range(1, 100):\n            candidate_offset = current_arch.ptrsize * i\n            val = read_int_from_memory(self.nodes[0] + candidate_offset)\n\n            if val == 0 or val < 0x100:\n                continue\n\n            if self.cpu_offset is None:\n                if not is_valid_addr(val):\n                    continue\n                # found\n                self.offset_per_cpu_pageset = candidate_offset\n                return\n            else:\n                if not is_valid_addr(self.cpu_offset[0] + val):\n                    continue\n                x = read_memory(self.cpu_offset[0] + val, 0x40)\n                if set(x) == {0}:\n                    continue\n                # found\n                self.offset_per_cpu_pageset = candidate_offset\n                return\n\n        self.offset_per_cpu_pageset = None\n        return\n\n    def resolve_per_cpu_pages_offset_lists(self, per_cpu_pageset):\n        \"\"\"\n        struct per_cpu_pageset { // ~v5.13\n            struct per_cpu_pages pcp;\n            ...\n        }\n\n        struct per_cpu_pages {\n            spinlock_t lock; // v5.14~\n            int count;\n            int high;\n            int batch;\n            short free_factor; // v5.14~\n        #ifdef CONFIG_NUMA\n            short expire; // v5.14~\n        #endif\n            struct list_head lists[NR_PCP_LISTS]; // v5.14~\n            struct list_head lists[MIGRATE_PCPTYPES]; // ~v5.13\n        } ____cacheline_aligned_in_smp;\n        \"\"\"\n\n        # fast path\n        try:\n            self.offset_lists = to_unsigned_long(gdb.parse_and_eval(\"&((struct per_cpu_pages*)0).lists\"))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        current = align_to_ptrsize(per_cpu_pageset + 4 * 3) # count, high, batch\n        while not is_double_link_list(current): # search for list_head\n            current += current_arch.ptrsize\n        self.offset_lists = current - per_cpu_pageset\n        return\n\n    def resolve_NR_PCP_LISTS(self, per_cpu_pageset):\n        # GEF detects MIGRATE_PCPTYPES and NR_PCP_LISTS using the same logic.\n        # It will retain them as NR_PCP_LISTS regardless of version.\n\n        # fast path\n        try:\n            self.NR_PCP_LISTS = to_unsigned_long(gdb.parse_and_eval(\n                \"sizeof(((struct per_cpu_pages*)0).lists) / sizeof(((struct per_cpu_pages*)0).lists[0])\",\n            ))\n            return\n        except gdb.error:\n            # In some environments, the size of list_head is not saved, resulting in division by 0.\n            try:\n                t = gdb.lookup_type(\"struct per_cpu_pages\")\n                f = next(x for x in t.fields() if x.name == \"lists\")\n                lo, hi = f.type.range()\n                self.NR_PCP_LISTS = hi - lo\n                return\n            except gdb.error:\n                pass\n\n        # slow path\n        current = per_cpu_pageset + self.offset_lists\n        while is_double_link_list(current): # search for not list_head\n            current += current_arch.ptrsize * 2\n        self.NR_PCP_LISTS = ((current - per_cpu_pageset) - self.offset_lists) // (current_arch.ptrsize * 2)\n        return\n\n    def resolve_MAX_NR_ZONES(self):\n        # fast path\n        try:\n            self.MAX_NR_ZONES = to_unsigned_long(gdb.parse_and_eval(\n                \"sizeof(((struct zone*)0).lowmem_reserve) / sizeof(((struct zone*)0).lowmem_reserve[0])\",\n            ))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        self.MAX_NR_ZONES = 0\n        for i in range(6):\n            zone = self.nodes[0] + self.sizeof_zone * i\n            name_ptr = read_int_from_memory(zone + self.offset_name)\n            name = read_cstring_from_memory(name_ptr)\n            if not name:\n                break\n            self.MAX_NR_ZONES += 1\n        return\n\n    def resolve_zone_offset_free_area(self):\n        \"\"\"\n        struct free_area {\n            struct list_head free_list[MIGRATE_TYPES];\n            unsigned long nr_free;\n        };\n        \"\"\"\n        # fast path\n        try:\n            self.offset_free_area = to_unsigned_long(gdb.parse_and_eval(\"&((struct zone*)0).free_area\"))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        kversion = Kernel.kernel_version()\n        if \"3.12\" <= kversion:\n            current = self.nodes[0] + self.offset_name + current_arch.ptrsize\n        else:\n            current = self.nodes[0]\n        while True:\n            # search for list_head\n            if is_double_link_list(current):\n                break\n            current += current_arch.ptrsize\n        self.offset_free_area = current - self.nodes[0]\n        return\n\n    def resolve_MIGRATE_TYPES(self):\n        # fast path\n        try:\n            self.MIGRATE_TYPES = to_unsigned_long(gdb.parse_and_eval(\n                \"sizeof(((struct free_area*)0).free_list) / sizeof(((struct free_area*)0).free_list[0])\",\n            ))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        current = free_area = self.nodes[0] + self.offset_free_area\n        while True:\n            val = read_int_from_memory(current)\n            if not is_valid_addr(val):\n                break\n            current += current_arch.ptrsize\n        offset_nr_free = current - free_area\n        sizeof_list_head = current_arch.ptrsize * 2\n        self.MIGRATE_TYPES = offset_nr_free // sizeof_list_head\n        return\n\n    def resolve_migratetype_names(self):\n        if self.args.MIGRATE_PCPTYPES == 3:\n            \"\"\"\n            const char * const migratetype_names[MIGRATE_TYPES] = {\n                \"Unmovable\",\n                \"Movable\",\n                \"Reclaimable\",\n                \"HighAtomic\",\n            #ifdef CONFIG_CMA\n                \"CMA\",\n            #endif\n            #ifdef CONFIG_MEMORY_ISOLATION\n                \"Isolate\",\n            #endif\n            };\n            \"\"\"\n            kversion = Kernel.kernel_version()\n            if self.MIGRATE_TYPES == 4:\n                if \"4.4\" <= kversion:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Movable\",\n                        \"Reclaimable\",\n                        \"HighAtomic\",\n                    ]\n                else:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Reclaimable\",\n                        \"Movable\",\n                        \"Reserve\",\n                    ]\n            elif self.MIGRATE_TYPES == 5:\n                if \"4.4\" <= kversion:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Movable\",\n                        \"Reclaimable\",\n                        \"HighAtomic\",\n                        \"Isolate\",\n                    ]\n                else:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Reclaimable\",\n                        \"Movable\",\n                        \"Reserve\",\n                        \"Isolate\",\n                    ]\n            elif self.MIGRATE_TYPES == 6:\n                if \"4.4\" <= kversion:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Movable\",\n                        \"Reclaimable\",\n                        \"HighAtomic\",\n                        \"Contiguous\", # CONFIG_CMA needs CONFIG_MEMORY_ISOLATION, so there is only this pattern\n                        \"Isolate\",\n                    ]\n                else:\n                    self.migrate_types = [\n                        \"Unmovable\",\n                        \"Reclaimable\",\n                        \"Movable\",\n                        \"Reserve\",\n                        \"Contiguous\", # CONFIG_CMA needs CONFIG_MEMORY_ISOLATION, so there is only this pattern\n                        \"Isolate\",\n                    ]\n            else:\n                err(\"MIGRATE_TYPES: {:#x}\".format(self.MIGRATE_TYPES))\n                raise\n\n            self.MIGRATE_PCPTYPES = 3\n\n        elif self.args.MIGRATE_PCPTYPES == 4:\n            # https://android.googlesource.com/kernel/common/+/433445e9a160%5E%21/#F1\n            \"\"\"\n            const char * const migratetype_names[MIGRATE_TYPES] = {\n                \"Unmovable\",\n                \"Movable\",\n                \"Reclaimable\",\n            #ifdef CONFIG_CMA\n                \"CMA\",\n            #endif\n                \"HighAtomic\",\n            #ifdef CONFIG_MEMORY_ISOLATION\n                \"Isolate\",\n            #endif\n            };\n            \"\"\"\n\n            if self.MIGRATE_TYPES == 4:\n                self.migrate_types = [\n                    \"Unmovable\",\n                    \"Movable\",\n                    \"Reclaimable\",\n                    \"HighAtomic\",\n                ]\n            elif self.MIGRATE_TYPES == 5:\n                self.migrate_types = [\n                    \"Unmovable\",\n                    \"Movable\",\n                    \"Reclaimable\",\n                    \"HighAtomic\",\n                    \"Isolate\",\n                ]\n            elif self.MIGRATE_TYPES == 6:\n                self.migrate_types = [\n                    \"Unmovable\",\n                    \"Movable\",\n                    \"Reclaimable\",\n                    \"Contiguous\", # CONFIG_CMA needs CONFIG_MEMORY_ISOLATION, so there is only this pattern\n                    \"HighAtomic\",\n                    \"Isolate\",\n                ]\n            else:\n                err(\"MIGRATE_TYPES: {:#x}\".format(self.MIGRATE_TYPES))\n                raise\n            self.MIGRATE_PCPTYPES = 4\n        return\n\n    def resolve_MAX_ORDER(self):\n        # fast path\n        try:\n            self.MAX_ORDER = to_unsigned_long(gdb.parse_and_eval(\n                \"sizeof(((struct zone*)0).free_area) / sizeof(((struct zone*)0).free_area[0])\",\n            ))\n            return\n        except gdb.error:\n            pass\n\n        # slow path\n        current = free_area = self.nodes[0] + self.offset_free_area\n        while True:\n            ok = True\n            for i in range(self.MIGRATE_TYPES):\n                if not is_double_link_list(current + current_arch.ptrsize * (i * 2)):\n                    ok = False\n                    break\n            if not ok:\n                break\n            current += self.sizeof_free_area\n        self.MAX_ORDER = (current - free_area) // self.sizeof_free_area\n        return\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # per_cpu_offset\n        __per_cpu_offset = KernelAddressHeuristicFinder.get_per_cpu_offset()\n        if __per_cpu_offset is None:\n            self.cpu_offset = None\n        else:\n            self.cpu_offset = KernelCurrentCommand.get_each_cpu_offset(__per_cpu_offset)\n\n        # search for node_data\n        node_data = KernelAddressHeuristicFinder.get_node_data()\n        if node_data:\n            self.quiet_info(\"node_data: {:#x}\".format(node_data))\n            # parse each node (*pglist_data)\n            self.nodes = []\n            current = node_data\n            while True:\n                node = read_int_from_memory(current)\n                if not is_valid_addr(node):\n                    break\n                self.nodes.append(node)\n                current += current_arch.ptrsize\n\n        else:\n            first_node = KernelAddressHeuristicFinder.get_node_data0()\n            if first_node:\n                self.quiet_info(\"first_node: {:#x}\".format(first_node))\n                self.nodes = [first_node]\n            else:\n                self.quiet_err(\"Failed to resolve node_data or first_node\")\n                return False\n\n        self.quiet_info(\"num of nodes: {:d}\".format(len(self.nodes)))\n        assert len(self.nodes) > 0\n\n        \"\"\"\n        typedef struct pglist_data {\n            struct zone node_zones[MAX_NR_ZONES];\n            ...\n        };\n\n        struct zone { // v3.12, v3.14~\n            unsigned long _watermark[NR_WMARK]; // v5.0~\n            unsigned long watermark_boost; // v5.0~\n            unsigned long watermark[NR_WMARK]; // ~v4.20\n            unsigned long nr_reserved_highatomic; // v4.4~\n            unsigned long nr_free_highatomic; // v6.12~\n            long lowmem_reserve[MAX_NR_ZONES];\n        #ifdef CONFIG_NEED_MULTIPLE_NODES // v5.10\n        #ifdef CONFIG_NUMA // ~v5.9, v5.11~\n            int node;\n        #endif\n            unsigned int inactive_ratio; // ~v4.7\n            struct pglist_data *zone_pgdat;\n            struct per_cpu_pageset __percpu *pageset; // ~v5.13\n            struct per_cpu_pages __percpu *per_cpu_pageset; // v5.14~\n            struct per_cpu_zonestat __percpu *per_cpu_zonestats; // v5.14~\n            ...\n            const char *name;\n        #ifdef CONFIG_MEMORY_ISOLATION\n            unsigned long nr_isolate_pageblock;\n        #endif\n        #ifdef CONFIG_MEMORY_HOTPLUG\n            seqlock_t span_seqlock;\n        #endif\n            int initialized; // v4.9~\n            wait_queue_head_t *wait_table; // ~v4.8\n            unsigned long wait_table_hash_nr_entries; // ~v4.8\n            unsigned long wait_table_bits; // ~v4.8\n            ZONE_PADDING(_pad1_)\n            spinlock_t lock; // ~v3.19\n            struct free_area free_area[MAX_ORDER];\n            ...\n        };\n\n        struct zone { // ~v3.11, v3.13\n            unsigned long watermark[NR_WMARK];\n            unsigned long percpu_drift_mark;\n            unsigned long lowmem_reserve[MAX_NR_ZONES];\n            unsigned long dirty_balance_reserve; // v3.3~\n        #ifdef CONFIG_NUMA\n            int node;\n            unsigned long min_unmapped_pages;\n            unsigned long min_slab_pages;\n        #endif\n            struct per_cpu_pageset __percpu *pageset;\n            spinlock_t lock;\n            int all_unreclaimable;\n        #if defined CONFIG_COMPACTION || defined CONFIG_CMA\n            bool compact_blockskip_flush; // v3.7~\n            unsigned long compact_cached_free_pfn; // v3.6~\n            unsigned long compact_cached_migrate_pfn; // v3.7~\n        #endif\n        #ifdef CONFIG_MEMORY_HOTPLUG\n            seqlock_t span_seqlock;\n        #endif\n        #ifdef CONFIG_CMA\n            unsigned long min_cma_pages; // v3.4~v3.7\n        #endif\n            struct free_area free_area[MAX_ORDER];\n            ...\n            const char *name;\n        };\n\n        static char * const zone_names[MAX_NR_ZONES] = {\n        #ifdef CONFIG_ZONE_DMA\n             \"DMA\",\n        #endif\n        #ifdef CONFIG_ZONE_DMA32\n             \"DMA32\",\n        #endif\n             \"Normal\",\n        #ifdef CONFIG_HIGHMEM\n             \"HighMem\",\n        #endif\n             \"Movable\",\n        #ifdef CONFIG_ZONE_DEVICE\n             \"Device\", // v4.3~\n        #endif\n        };\n        \"\"\"\n\n        # zone->name, sizeof(struct zone)\n        self.resolve_zone_offset_name()\n        self.quiet_info(\"offsetof(zone, name): {:#x}\".format(self.offset_name))\n        self.quiet_info(\"sizeof(zone): {:#x}\".format(self.sizeof_zone))\n\n        # zone->per_cpu_pageset\n        self.resolve_zone_offset_per_cpu_pageset()\n        if self.offset_per_cpu_pageset is None:\n            self.quiet_err(\"Failed to resolve per_cpu_pageset\")\n            return False\n        else:\n            self.quiet_info(\"offsetof(zone, per_cpu_pageset): {:#x}\".format(self.offset_per_cpu_pageset))\n\n        # per_cpu_pageset->lists\n        if __per_cpu_offset is None:\n            per_cpu_pageset = read_int_from_memory(self.nodes[0] + self.offset_per_cpu_pageset)\n        else:\n            per_cpu_pageset = read_int_from_memory(self.nodes[0] + self.offset_per_cpu_pageset) + self.cpu_offset[0]\n            per_cpu_pageset = AddressUtil.align_address(per_cpu_pageset)\n        self.resolve_per_cpu_pages_offset_lists(per_cpu_pageset)\n        self.quiet_info(\"offsetof(per_cpu_pages, lists): {:#x}\".format(self.offset_lists))\n\n        # NR_PCP_LISTS\n        self.resolve_NR_PCP_LISTS(per_cpu_pageset)\n        self.quiet_info(\"NR_PCP_LISTS: {:d}\".format(self.NR_PCP_LISTS))\n\n        # MAX_NR_ZONES\n        self.resolve_MAX_NR_ZONES()\n        self.quiet_info(\"MAX_NR_ZONES: {:d}\".format(self.MAX_NR_ZONES))\n\n        # zone->free_area\n        self.resolve_zone_offset_free_area()\n        self.quiet_info(\"offsetof(zone, free_area): {:#x}\".format(self.offset_free_area))\n\n        # MIGRATE_TYPES\n        self.resolve_MIGRATE_TYPES()\n        self.quiet_info(\"MIGRATE_TYPES: {:d}\".format(self.MIGRATE_TYPES))\n\n        # migratetype_names\n        self.resolve_migratetype_names()\n\n        # sizeof(free_area)\n        sizeof_list_head =  current_arch.ptrsize * 2\n        self.sizeof_free_area = sizeof_list_head * self.MIGRATE_TYPES + current_arch.ptrsize\n        self.quiet_info(\"sizeof(free_area): {:#x}\".format(self.sizeof_free_area))\n\n        # MAX_ORDER\n        self.resolve_MAX_ORDER()\n        self.quiet_info(\"MAX_ORDER: {:d}\".format(self.MAX_ORDER))\n\n        \"\"\"\n        struct page { // v5.18~\n            unsigned long flags;\n            union {\n                struct {\n                    union {\n                        struct list_head lru;\n                        ...\n        };\n\n        struct page { // v4.18~v5.17\n            unsigned long flags;\n            union {\n                struct {\n                    struct list_head lru;\n                    ...\n        };\n\n        struct page { // v3.1~v4.17\n            unsigned long flags;\n            union { }; // ptrsize\n            union { }; // ptrsize\n            union { }; // 8 bytes\n            union {\n                struct list_head lru;\n                ...\n        };\n        \"\"\"\n        # page->lru\n        kversion = Kernel.kernel_version()\n        if \"4.18\" <= kversion:\n            self.offset_lru = current_arch.ptrsize\n        else:\n            self.offset_lru = current_arch.ptrsize * 3 + 8\n\n        self.initialized = True\n        return True\n\n    class Entry:\n        def __init__(self, page, size, is_highmem, args, cpu_num=None):\n            self.page = page\n            self.size = size\n            self.is_highmem = is_highmem\n            self.args = args\n            self.cpu_num = cpu_num\n            return\n\n        def get_virt_phys_str(self):\n            virt_str = \"???\"\n            phys_str = \"???\"\n\n            if self.is_highmem:\n                return virt_str, phys_str\n\n            heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n            align = AddressUtil.get_format_address_width()\n\n            virt = Kernel.page2virt(self.page)\n            phys = None\n\n            if virt:\n                if self.args.skip_phys:\n                    pass\n                elif self.args.use_physmap:\n                    if is_x86_64():\n                        physmap = KernelAddressHeuristicFinder.get_PAGE_OFFSET()\n                    elif is_arm64():\n                        physmap = KernelAddressHeuristicFinder.consts().physmap_base\n                    if physmap is not None:\n                        phys = virt - physmap\n                else:\n                    phys = PageMap.v2p_from_map(virt, BuddyDumpCommand.maps)\n\n            if virt is not None:\n                virt_str = \"{:#0{:d}x}-{:#0{:d}x}\".format(virt, align, virt + self.size, align)\n                virt_str = Color.colorify(virt_str, heap_page_color)\n\n            if phys is not None:\n                phys_str = \"{:#0{:d}x}-{:#0{:d}x}\".format(phys, align, phys + self.size, align)\n            return virt_str, phys_str\n\n        def __str__(self):\n            chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n            freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n            align = AddressUtil.get_format_address_width()\n\n            page_str = Color.colorify(\"{:#0{:d}x}\".format(self.page, align), freed_address_color)\n            size_str = Color.colorify(\"{:#08x}\".format(self.size), chunk_size_color)\n            virt_str, phys_str = self.get_virt_phys_str()\n\n            if self.cpu_num is not None:\n                msg = \"    page:{:s}  size:{:s}  virt:{:s}  phys:{:s} (pcp, cpu={:d})\".format(\n                    page_str, size_str, virt_str, phys_str, self.cpu_num,\n                )\n            else:\n                msg = \"    page:{:s}  size:{:s}  virt:{:s}  phys:{:s}\".format(\n                    page_str, size_str, virt_str, phys_str,\n                )\n            return msg\n\n    @Cache.cache_this_session\n    def get_pageblock_order(self): # for 5.14 ~ 6.10\n        kversion = Kernel.kernel_version()\n        if not (\"5.14\" <= kversion < \"6.10\"):\n            return None\n\n        PMD_SHIFT = KernelAddressHeuristicFinder.consts().PMD_SHIFT\n        PAGE_SHIFT = KernelAddressHeuristicFinder.consts().PAGE_SHIFT\n        HPAGE_SHIFT = PMD_SHIFT\n        HUGETLB_PAGE_ORDER = HPAGE_SHIFT - PAGE_SHIFT\n\n        CONFIG_HUGETLB_PAGE = bool(\n            Symbol.get_ksymaddr(\"hugetlb_fault\") or Symbol.get_ksymaddr(\"hugetlbfs_read_iter\")\n        )\n        # CONFIG_HUGETLB_PAGE_SIZE_VARIABLE is ia64 or ppc only, so ignored\n\n        if \"5.14\" <= kversion < \"5.18\":\n            if CONFIG_HUGETLB_PAGE:\n                return HUGETLB_PAGE_ORDER\n            else:\n                return self.MAX_ORDER - 1\n        elif \"5.18\" <= kversion < \"6.8\":\n            if CONFIG_HUGETLB_PAGE:\n                return min(HUGETLB_PAGE_ORDER, self.MAX_ORDER - 1)\n            else:\n                return self.MAX_ORDER - 1\n        else: # 6.8 <= kversion < \"6.10\"\n            MAX_PAGE_ORDER = self.MAX_ORDER - 1\n            if CONFIG_HUGETLB_PAGE:\n                return min(HUGETLB_PAGE_ORDER, MAX_PAGE_ORDER)\n            else:\n                return MAX_PAGE_ORDER\n\n    def dump_pcp_entry(self, list_i, i, cpu_num, is_highmem):\n        PAGE_ALLOC_COSTLY_ORDER = 3\n        NR_LOWORDER_PCP_LISTS = (self.MIGRATE_PCPTYPES * (PAGE_ALLOC_COSTLY_ORDER + 1))\n\n        if i < NR_LOWORDER_PCP_LISTS:\n            # for normal case\n            order = i // self.MIGRATE_PCPTYPES\n            mtype = i % self.MIGRATE_PCPTYPES\n            mtype_str = self.migrate_types[mtype]\n        else:\n            # for CONFIG_TRANSPARENT_HUGEPAGE\n            kversion = Kernel.kernel_version()\n\n            if kversion < \"5.14\":\n                raise\n            elif \"5.14\" <= kversion < \"6.0\":\n                # indices 12..14 are \"base=4 + migratetype\"\n                base = PAGE_ALLOC_COSTLY_ORDER + 1\n                mtype = i - self.MIGRATE_PCPTYPES * base # 0,1,2\n                if 0 <= mtype < self.MIGRATE_PCPTYPES:\n                    mtype_str = self.migrate_types[mtype]\n                else:\n                    mtype_str = \"THP_UNKNOWN\"\n                order = self.get_pageblock_order()\n            elif (\"6.0\" <= kversion < \"6.1\") or (\"6.2\" <= kversion < \"6.6.37\") or (\"6.7\" <= kversion < \"6.9\"):\n                # 1 slot\n                mtype = i - NR_LOWORDER_PCP_LISTS\n                if i == NR_LOWORDER_PCP_LISTS:\n                    mtype_str = \"THP\"\n                else:\n                    mtype_str = \"THP_UNKNOWN\"\n                order = self.get_pageblock_order()\n            elif (\"6.1\" <= kversion < \"6.2\") or (\"6.6.37\" <= kversion < \"6.7\") or (\"6.9\" <= kversion < \"6.10\"):\n                # 2 slots\n                thp_i = i - NR_LOWORDER_PCP_LISTS\n                mtype = thp_i\n                if 0 <= thp_i < 2:\n                    mtype_str = \"THP_MOVABLE\" if thp_i == 1 else \"THP_OTHER\"\n                else:\n                    mtype_str = \"THP_UNKNOWN\"\n                order = self.get_pageblock_order()\n            else: # 6.10~\n                # 2 slots\n                thp_i = i - NR_LOWORDER_PCP_LISTS\n                mtype = thp_i\n                if 0 <= thp_i < 2:\n                    mtype_str = \"THP_MOVABLE\" if thp_i == 1 else \"THP_OTHER\"\n                else:\n                    mtype_str = \"THP_UNKNOWN\"\n\n                HPAGE_PMD_SHIFT = KernelAddressHeuristicFinder.consts().PMD_SHIFT\n                PAGE_SHIFT = KernelAddressHeuristicFinder.consts().PAGE_SHIFT\n                HPAGE_PMD_ORDER = HPAGE_PMD_SHIFT - PAGE_SHIFT\n                order = HPAGE_PMD_ORDER\n\n        # size info\n        PAGE_SIZE = KernelAddressHeuristicFinder.consts().PAGE_SIZE\n        size = PAGE_SIZE * (2 ** order)\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        size_str = Color.colorify(\"{:#08x}\".format(size), chunk_size_color)\n\n        # make title\n        pcp_title = \"  pcp_index: {:d}, order: {:d} ({:s} bytes), mtype: {:d} (={:s})\".format(\n            i, order, size_str, mtype, mtype_str,\n        )\n        entries = []\n\n        # filtering\n        if self.args.mtype_filter and mtype not in self.args.mtype_filter:\n            return pcp_title, entries, bool(len(entries))\n        if self.args.order_filter and order not in self.args.order_filter:\n            return pcp_title, entries, bool(len(entries))\n\n        # fast check\n        current = read_int_from_memory(list_i)\n        if not is_valid_addr(current):\n            return pcp_title, entries, bool(len(entries))\n\n        # parse pcp entries\n        MAX_ENTRIES = self.args.count\n        while current != list_i:\n            page = current - self.offset_lru\n            entry = self.Entry(page, size, is_highmem, self.args, cpu_num=cpu_num)\n            entries.append(entry)\n            if MAX_ENTRIES and len(entries) >= MAX_ENTRIES:\n                entries.append(None)  # sentinel for \"...\"\n                break\n            current = read_int_from_memory(current)\n        return pcp_title, entries, bool(len(entries))\n\n    def dump_pcp(self, zone, is_highmem):\n        # list pageset\n        per_cpu_pageset = read_int_from_memory(zone + self.offset_per_cpu_pageset)\n        if self.cpu_offset is None:\n            per_cpu_pageset = [per_cpu_pageset]\n        else:\n            per_cpu_pageset = [AddressUtil.align_address(cpuoff + per_cpu_pageset) for cpuoff in self.cpu_offset]\n\n        # parse each cpu\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        sizeof_list_head = current_arch.ptrsize * 2\n        pcp_all_entries = {}\n        for cpu_num, pcp in tqdm(enumerate(per_cpu_pageset), leave=False, desc=\"cpu\", total=len(per_cpu_pageset)):\n            if self.args.cpu and cpu_num not in self.args.cpu:\n                continue\n            # parse each pcp list\n            pcp_entries = []\n            for i in tqdm(range(self.NR_PCP_LISTS), leave=False, desc=\"pcplist\"):\n                if self.args.pcp_index_filter and i not in self.args.pcp_index_filter:\n                    continue\n                lists_i = pcp + self.offset_lists + sizeof_list_head * i\n                res = self.dump_pcp_entry(lists_i, i, cpu_num, is_highmem)\n                pcp_entries.append(res)\n            pcp_all_entries[cpu_num] = pcp_entries\n        return pcp_all_entries\n\n    def dump_free_list(self, free_list, mtype, size, is_highmem):\n        # make title\n        mtype_title = \"  mtype: {:d} (={:s})\".format(mtype, self.migrate_types[mtype])\n        entries = []\n\n        # fast check\n        current = read_int_from_memory(free_list)\n        if not is_valid_addr(current):\n            return mtype_title, entries, bool(len(entries))\n\n        # parse free list\n        MAX_ENTRIES = self.args.count\n        while current != free_list:\n            page = current - self.offset_lru\n            entry = self.Entry(page, size, is_highmem, self.args)\n            entries.append(entry)\n            if MAX_ENTRIES and len(entries) >= MAX_ENTRIES:\n                entries.append(None)  # sentinel for \"...\"\n                break\n            current = read_int_from_memory(current)\n        return mtype_title, entries, bool(len(entries))\n\n    def dump_free_area(self, free_area, order, is_highmem):\n        # size info\n        PAGE_SIZE = KernelAddressHeuristicFinder.consts().PAGE_SIZE\n        size = PAGE_SIZE * (2 ** order)\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        size_str = Color.colorify_hex(size, chunk_size_color)\n        order_title = \"order: {:d} ({:s} bytes)\".format(order, size_str)\n\n        # prase free area\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        sizeof_list_head = current_arch.ptrsize * 2\n        free_lists = []\n        has_any = False\n        for mtype in tqdm(range(self.MIGRATE_TYPES), leave=False, desc=\"mtype\"):\n            if self.args.mtype_filter and mtype not in self.args.mtype_filter:\n                continue\n            free_list = free_area + sizeof_list_head * mtype\n            res = self.dump_free_list(free_list, mtype, size, is_highmem)\n            has_any |= res[2]\n            free_lists.append(res)\n        return order_title, free_lists, has_any\n\n    def dump_zone(self, zone, is_highmem=False):\n        zone_entry = {}\n\n        # parse pcp\n        if not self.args.skip_pcp:\n            zone_entry[\"per_cpu_pageset\"] = self.dump_pcp(zone, is_highmem)\n\n        # parse free_area\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        if not self.args.only_pcp:\n            free_area_entries = []\n            for order in tqdm(range(self.MAX_ORDER), leave=False, desc=\"order\"):\n                if self.args.order_filter and order not in self.args.order_filter:\n                    continue\n                free_area_i = zone + self.offset_free_area + self.sizeof_free_area * order\n                res = self.dump_free_area(free_area_i, order, is_highmem)\n                free_area_entries.append(res)\n            zone_entry[\"free_area\"] = free_area_entries\n        return zone_entry\n\n    def dump_node(self, node):\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        zone_entries = []\n        for i in tqdm(range(self.MAX_NR_ZONES), leave=False, desc=\"zone\"):\n            zone = node + self.sizeof_zone * i\n            name_ptr = read_int_from_memory(zone + self.offset_name)\n            name = read_cstring_from_memory(name_ptr)\n            if self.args.zone_filter and name not in self.args.zone_filter:\n                continue\n            title = \"zone[{:d}] @ {:#x} ({:s})\".format(i, zone, name)\n            is_highmem = name == \"HighMem\"\n            res = self.dump_zone(zone, is_highmem=is_highmem)\n            zone_entries.append([title, res])\n        return zone_entries\n\n    def make_output_for_sort(self, node_entries):\n        # get all etnries\n        all_entries = []\n        for _, zone_entries in node_entries:\n            for _, zone_entry in zone_entries:\n                if \"per_cpu_pageset\" in zone_entry:\n                    for _, pcp_all_entries in zone_entry[\"per_cpu_pageset\"].items():\n                        for _, pcp_entries, has_any in pcp_all_entries:\n                            if not has_any:\n                                continue\n                            for entry in pcp_entries:\n                                all_entries.append(entry)\n\n                if \"free_area\" in zone_entry:\n                    for _, free_lists, has_any in zone_entry[\"free_area\"]:\n                        if not has_any:\n                            continue\n                        for _, free_list, has_any2 in free_lists:\n                            if not has_any2:\n                                continue\n                            for entry in free_list:\n                                all_entries.append(entry)\n\n        # sort\n        all_entries = sorted(all_entries, key=lambda e: e.page)\n\n        # make output\n        prev_virt = None\n        prev_size = None\n        first = True\n        align = AddressUtil.get_format_address_width()\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for entry in tqdm(all_entries, leave=False):\n            # for simple sort\n            if not self.args.sort_verbose:\n                self.out.append(str(entry))\n                continue\n\n            # for verbose sort (filling the gap)\n\n            # add used area if calculable\n            virt = Kernel.page2virt(entry.page)\n            if first:\n                if virt is not None:\n                    phys = None\n                    if self.args.skip_phys:\n                        pass\n                    elif self.args.use_physmap:\n                        if is_x86_64():\n                            physmap = KernelAddressHeuristicFinder.get_PAGE_OFFSET()\n                        elif is_arm64():\n                            physmap = KernelAddressHeuristicFinder.consts().physmap_base\n                        if physmap is not None:\n                            phys = virt - physmap\n                    else:\n                        phys = PageMap.v2p_from_map(virt, BuddyDumpCommand.maps)\n\n                    if phys is not None:\n                        self.out.append(\"    used:{:{:d}s}  size:{:#08x}\".format(\"\", align, phys))\n\n                first = False\n            else:\n                if isinstance(virt, int) and isinstance(prev_virt, int):\n                    if prev_virt + prev_size != virt:\n                        diff = virt - (prev_virt + prev_size)\n                        self.out.append(\"    used:{:{:d}s}  size:{:#08x}\".format(\"\", align, diff))\n\n            # add free area\n            self.out.append(str(entry))\n\n            prev_virt = virt\n            prev_size = entry.size\n        return\n\n    def make_output(self, node_entries):\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n\n        for node_title, zone_entries in tqdm(node_entries, leave=False, desc=\"node\"):\n            self.out.append(titlify(node_title))\n\n            for zone_title, zone_entry in tqdm(zone_entries, leave=False, desc=\"zone\"):\n                self.out.append(titlify(zone_title))\n\n                if \"per_cpu_pageset\" in zone_entry:\n                    self.out.append(titlify(\"per_cpu_pageset\"))\n                    for cpu_num, pcp_all_entries in tqdm(zone_entry[\"per_cpu_pageset\"].items(), leave=False, desc=\"cpu\"):\n                        self.out.append(\"cpu: {:d}\".format(cpu_num))\n                        for pcp_title, pcp_entries, has_any in tqdm(pcp_all_entries, leave=False, desc=\"pcplist\"):\n                            if not has_any and not self.args.vverbose:\n                                continue\n                            self.out.append(pcp_title)\n                            for i, entry in enumerate(pcp_entries):\n                                if self.args.count and i >= self.args.count:\n                                    self.out.append(\"    ...\")\n                                    break\n                                self.out.append(str(entry))\n\n                if \"free_area\" in zone_entry:\n                    self.out.append(titlify(\"free_area\"))\n                    for order_title, free_lists, has_any in tqdm(zone_entry[\"free_area\"], leave=False, desc=\"order\"):\n                        if not has_any and not self.args.vverbose:\n                            continue\n                        self.out.append(order_title)\n                        for mtype_title, free_list, has_any2 in tqdm(free_lists, leave=False, desc=\"mtype\"):\n                            if not has_any2 and not self.args.vverbose:\n                                continue\n                            self.out.append(mtype_title)\n                            for i, entry in enumerate(free_list):\n                                if self.args.count and i >= self.args.count:\n                                    self.out.append(\"    ...\")\n                                    break\n                                self.out.append(str(entry))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.1\":\n            self.quiet_err(\"Unsupported before v3.1\")\n            return\n\n        if self.args.use_physmap:\n            if not (is_x86_64() or is_arm64()):\n                self.quiet_err(\"Unsupported architecture\")\n                return\n\n        # parse args\n        if args.rescan:\n            self.initialized = False\n        self.args.sort = args.sort_verbose or args.sort\n        self.args.verbose = args.vverbose or args.verbose\n        if self.args.sort or self.args.verbose:\n            self.args.count = 0\n\n        # initialize\n        self.quiet_info(\"Wait for memory scan\")\n        if not self.initialize():\n            return\n\n        # do not use cache\n        if not self.args.skip_phys and not self.args.use_physmap:\n            BuddyDumpCommand.maps = PageMap.get_page_maps(None)\n            if BuddyDumpCommand.maps is None:\n                self.quiet_err(\"Failed to resolve maps\")\n                return\n\n        # dump\n        node_entries = []\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for i, node in tqdm(enumerate(self.nodes), leave=False, total=len(self.nodes), desc=\"node\"):\n            title = \"node[{:d}] @ {:#x}\".format(i, node)\n            res = self.dump_node(node)\n            node_entries.append([title, res])\n        self.quiet_info(\"Parse OK, making output...\")\n\n        # print\n        self.out = []\n        if self.args.sort:\n            self.make_output_for_sort(node_entries)\n        else:\n            self.make_output(node_entries)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelPipeCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump pipe information.\"\"\"\n\n    _cmdline_ = \"kpipe\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-i\", \"--inode-filter\", type=AddressUtil.parse_address, default=[], action=\"append\",\n                        help=\"filter by specific struct inode.\")\n    parser.add_argument(\"-f\", \"--file-filter\", type=AddressUtil.parse_address, default=[], action=\"append\",\n                        help=\"filter by specific struct file.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified pipe structure:\",\n        \"\",\n        \"+-task_struct-+  +->+-files_struct-+  +->+-fdtable---+  +->+-files*[]----+  +->+-file------+\",\n        \"| ...         |  |  | ...          |  |  | max_fds   |  |  | [0]         |--+  | ...       |\",\n        \"| files       |--+  | fdt          |--+  | fd        |--+  | ...         |     | f_path    |\",\n        \"| ...         |     | ...          |     | ...       |     | [max_fds-1] |     |   dentry  |---+\",\n        \"+-------------+     +--------------+     +-----------+     +-------------+     | ...       |   |\",\n        \"                                                                               +-----------+   |\",\n        \"                                                                                               |\",\n        \"+----------------------------------------------------------------------------------------------+\",\n        \"|\",\n        \"|  +-dentry---+  +->+-inode-----+  +->+-pipe_inode_info--------+  +->+-pipe_buffer-+\",\n        \"|  | ...      |  |  | ...       |  |  | ...                    |  |  | page        |--->page\",\n        \"+->| d_inode  |--+  | i_pipe    |--+  | head, tail, (v5.5~)    |  |  | offset      |\",\n        \"   | ...      |     | ...       |     | max_usage, (v5.5~)     |  |  | len         |\",\n        \"   +----------+     +-----------+     | ring_size, (v5.5~)     |  |  | ...         |\",\n        \"                                      | nrbuf, curbuf, (~v5.4) |  |  +-------------+\",\n        \"                                      | buffers (~v5.4)        |  |  | page        |--->page\",\n        \"                                      | ...                    |  |  | offset      |\",\n        \"                                      | bufs                   |--+  | len         |\",\n        \"                                      | ...                    |     | ...         |\",\n        \"                                      +------------------------+     +-------------+\",\n        \"                                                                     | ...         |\",\n        \"                                                                     +-------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self, pipe_files):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # inode->i_pipe\n        offset_i_pipe = self.get_offset_i_pipe(pipe_files)\n        if not offset_i_pipe:\n            self.quiet_err(\"Could not find inode->i_pipe\")\n            return False\n        self.offset_i_pipe = offset_i_pipe\n        self.quiet_info(\"offsetof(inode, i_pipe): {:#x}\".format(self.offset_i_pipe))\n\n        # pipe_inode_info->bufs\n        offset_bufs = self.get_offset_bufs(pipe_files)\n        if not offset_bufs:\n            self.quiet_err(\"Could not find pipe_inode_info->bufs\")\n            return False\n        self.offset_bufs = offset_bufs\n        self.quiet_info(\"offsetof(pipe_inode_info, bufs): {:#x}\".format(self.offset_bufs))\n\n        kversion = Kernel.kernel_version()\n        if \"5.5\" <= kversion:\n            # pipe_inode_info->{head,tail,max_usage,ring_size}\n            ret = self.get_offset_head_or_nrbuf(pipe_files)\n            if ret is None:\n                self.quiet_err(\"Could not find pipe_inode_info->head\")\n                return False\n            self.offset_head = ret\n            self.quiet_info(\"offsetof(pipe_inode_info, head): {:#x}\".format(self.offset_head))\n            self.offset_tail = self.offset_head + 4\n            self.quiet_info(\"offsetof(pipe_inode_info, tail): {:#x}\".format(self.offset_tail))\n            self.offset_max_usage = self.offset_tail + 4\n            self.quiet_info(\"offsetof(pipe_inode_info, max_usage): {:#x}\".format(self.offset_max_usage))\n            self.offset_ring_size = self.offset_max_usage + 4\n            self.quiet_info(\"offsetof(pipe_inode_info, ring_size): {:#x}\".format(self.offset_ring_size))\n        else:\n            # pipe_inode_info->{nrbuf,curbuf,buffers}\n            ret = self.get_offset_head_or_nrbuf(pipe_files)\n            if ret is None:\n                self.quiet_err(\"Could not find pipe_inode_info->nrbuf\")\n                return False\n            self.offset_nrbuf = ret\n            self.quiet_info(\"offsetof(pipe_inode_info, nrbuf): {:#x}\".format(self.offset_nrbuf))\n            self.offset_curbuf = self.offset_nrbuf + 4\n            self.quiet_info(\"offsetof(pipe_inode_info, curbuf): {:#x}\".format(self.offset_curbuf))\n            self.offset_buffers = self.offset_curbuf + 4\n            self.quiet_info(\"offsetof(pipe_inode_info, buffers): {:#x}\".format(self.offset_buffers))\n\n        # pipe_buffer->{page, offset, len, flags}\n        \"\"\"\n        struct pipe_buffer {\n            struct page *page;\n            unsigned int offset, len;\n            const struct pipe_buf_operations *ops;\n            unsigned int flags;\n            unsigned long private;\n        };\n        \"\"\"\n        self.offset_page = 0\n        self.quiet_info(\"offsetof(pipe_buffer, page): {:#x}\".format(self.offset_page))\n        self.offset_offset = current_arch.ptrsize\n        self.quiet_info(\"offsetof(pipe_buffer, offset): {:#x}\".format(self.offset_offset))\n        self.offset_len = self.offset_offset + 4\n        self.quiet_info(\"offsetof(pipe_buffer, len): {:#x}\".format(self.offset_len))\n        self.offset_flags = self.offset_len + 4 + current_arch.ptrsize\n        self.quiet_info(\"offsetof(pipe_buffer, flags): {:#x}\".format(self.offset_flags))\n        self.sizeof_pipe_buffer = align_to_ptrsize(self.offset_flags + 4) + current_arch.ptrsize\n        self.quiet_info(\"sizeof(pipe_buffer): {:#x}\".format(self.sizeof_pipe_buffer))\n\n        self.initialized = True\n        return True\n\n    def get_offset_i_pipe(self, pipe_files):\n        \"\"\"\n        struct inode {\n            ...\n            struct list_head i_lru;\n            struct list_head i_sb_list;\n            struct list_head i_wb_list;\n            ...\n        #if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING)\n            atomic_t i_readcount;\n        #endif\n            const struct file_operations *i_fop;     // ~v5.1\n            union {                                  // v5.2~\n                const struct file_operations *i_fop; // v5.2~\n                void (*free_inode)(struct inode *);  // v5.2~\n            };                                       // v5.2~\n            struct file_lock_context *i_flctx;\n            struct address_space i_data;\n        #ifdef CONFIG_QUOTA                   // ~v3.18\n            struct dquot *i_dquot[MAXQUOTAS]; // ~v3.18 // MAXQUOTAS=2\n        #endif                                // ~v3.18\n            struct list_head i_devices;       // ~v6.13\n            union {                           // v6.14~\n                struct list_head i_devices;   // v6.14~\n                int i_linklen;                // v6.14~\n            };                                // v6.14~\n            union {\n                struct pipe_inode_info *i_pipe;  <-- here\n                struct block_device *i_bdev;\n                struct cdev *i_cdev;\n                char *i_link;\n                unsigned i_dir_seq;\n            };\n            ...\n        };\n        \"\"\"\n\n        # plan 1\n        inode = pipe_files[0][1]\n        for i in range(0x100):\n            # search three list_head\n            if not is_double_link_list(inode + current_arch.ptrsize * (i + 0)):\n                continue\n            if not is_double_link_list(inode + current_arch.ptrsize * (i + 2)):\n                continue\n            if not is_double_link_list(inode + current_arch.ptrsize * (i + 4)):\n                continue\n            # search i_pipe\n            for j in range(i + 6, 0x100):\n                if not is_double_link_list(inode + current_arch.ptrsize * (j + 0)): # i_devices\n                    continue\n                if not is_valid_addr_addr(inode + current_arch.ptrsize * (j + 2)): # i_pipe\n                    continue\n                if is_double_link_list(inode + current_arch.ptrsize * (j + 2)): # i_pipe\n                    continue\n                i_pipe = read_int_from_memory(inode + current_arch.ptrsize * (j + 2))\n                # count 0x10 and 0x01 value\n                count_0x10 = 0\n                count_0x01 = 0\n                for k in range(0x20):\n                    v = read_int32_from_memory(i_pipe + 4 * k)\n                    if v == 0x01:\n                        count_0x01 += 1\n                    if v == 0x10:\n                        count_0x10 += 1\n                    if count_0x10 > 1 or count_0x01 > 3:\n                        return current_arch.ptrsize * (j + 2)\n\n        # plan 2\n        for i in range(0x100):\n            v = read_int_from_memory(inode + current_arch.ptrsize * i)\n            # i_pipe is valid addr\n            if v < 0x10000 or not is_valid_addr(v):\n                continue\n            # skip invalid chunk\n            ret = Kernel.get_slab_contains(v)\n            if ret is None:\n                continue\n            # pipe_inode_info is allocated from kmalloc-192 (x64) or kmalloc-256 (arm64).\n            # sometimes it is allocated from kmalloc-512, kmalloc-128, kmalloc-96 and kmalloc-64.\n            # Other candidates found are kmalloc-2k, kmalloc-1024 and inode_cache (these are false positives),\n            # so these should be excluded.\n            if re.search(r\"kmalloc(-cg)?-(64|96|128|192|256|512)\", ret):\n                return current_arch.ptrsize * i\n\n        return None\n\n    def get_offset_bufs(self, pipe_files):\n        \"\"\"\n        [v5.5~]\n        struct pipe_inode_info {\n            struct mutex mutex;\n            wait_queue_head_t rd_wait, wr_wait; // v5.6~\n            wait_queue_head_t wait; // ~v5.5\n            unsigned int head;\n            unsigned int tail;\n            unsigned int max_usage;\n            unsigned int ring_size;\n        #ifdef CONFIG_WATCH_QUEUE // v5.8~\n            bool note_loss;       // v5.8~\n        #endif                    // v5.8~\n            unsigned int nr_accounted; // v5.8~\n            unsigned int readers;\n            unsigned int writers;\n            unsigned int files;\n            unsigned int r_counter;\n            unsigned int w_counter;\n            bool poll_usage; // v5.10~\n            struct page *tmp_page;\n            struct fasync_struct *fasync_readers;\n            struct fasync_struct *fasync_writers;\n            struct pipe_buffer *bufs;  <-- here\n            struct user_struct *user;\n        #ifdef CONFIG_WATCH_QUEUE            // v5.8~\n            struct watch_queue *watch_queue; // v5.8~\n        #endif                               // v5.8~\n        };\n\n        [~v5.4]\n        struct pipe_inode_info {\n            struct mutex mutex; // v3.10~\n            wait_queue_head_t wait;\n            unsigned int nrbufs, curbuf, buffers;\n            unsigned int readers;\n            unsigned int writers;\n            unsigned int files; // v3.10~\n            unsigned int waiting_writers;\n            unsigned int r_counter;\n            unsigned int w_counter;\n            struct page *tmp_page;\n            struct fasync_struct *fasync_readers;\n            struct fasync_struct *fasync_writers;\n            struct inode *inode; // ~v3.9\n            struct pipe_buffer *bufs; <-- here\n            struct user_struct *user; // v3.10, v3.12, v3.14, v3.16, v3.18, v4.1, v4.4~\n        };\n\n        struct pipe_buffer {\n            struct page *page;\n            unsigned int offset, len;\n            const struct pipe_buf_operations *ops; // allow NULL\n            unsigned int flags;\n            unsigned long private;\n        };\n        \"\"\"\n\n        # plan 1\n        seen = []\n        for _file, inode in pipe_files:\n            if inode in seen:\n                continue\n            seen.append(inode)\n            pipe_inode_info = read_int_from_memory(inode + self.offset_i_pipe)\n            for i in range(0x40):\n                offset_bufs = current_arch.ptrsize * i\n                if not is_valid_addr_addr(pipe_inode_info + offset_bufs):\n                    continue\n                if is_double_link_list(pipe_inode_info + offset_bufs):\n                    continue\n                if is_double_link_list(pipe_inode_info + offset_bufs - current_arch.ptrsize):\n                    continue\n                # bufs\n                bufs = read_int_from_memory(pipe_inode_info + offset_bufs)\n                if is_64bit():\n                    if not is_valid_addr_addr(bufs + current_arch.ptrsize * 0): # page\n                        continue\n                    len_ = read_int32_from_memory(bufs + current_arch.ptrsize * 1 + 4) # len\n                    if len_ == 0 or is_valid_addr_addr(bufs + current_arch.ptrsize * 1): # offset||len\n                        continue\n                    ops = read_int_from_memory(bufs + current_arch.ptrsize * 2) # ops\n                    if ops != 0 and not is_valid_addr(ops):\n                        continue\n                    if is_valid_addr_addr(bufs + current_arch.ptrsize * 3): # flags\n                        continue\n                    if is_valid_addr_addr(bufs + current_arch.ptrsize * 4): # private\n                        continue\n                else:\n                    if not is_valid_addr_addr(bufs + current_arch.ptrsize * 0): # page\n                        continue\n                    if is_valid_addr_addr(bufs + current_arch.ptrsize * 1): # offset\n                        continue\n                    len_ = read_int_from_memory(bufs + current_arch.ptrsize * 2) # len\n                    if len_ == 0 or is_valid_addr_addr(len_):\n                        continue\n                    ops = read_int_from_memory(bufs + current_arch.ptrsize * 3) # ops\n                    if ops != 0 and not is_valid_addr(ops):\n                        continue\n                    if is_valid_addr_addr(bufs + current_arch.ptrsize * 4): # flags\n                        continue\n                    if is_valid_addr_addr(bufs + current_arch.ptrsize * 5): # private\n                        continue\n                # found\n                self.quiet_info(\"offset of bufs is found by heuristic way1\")\n                return offset_bufs\n\n        # plan 2\n        kversion = Kernel.kernel_version()\n        inode = pipe_files[0][1]\n        pipe_inode_info = read_int_from_memory(inode + self.offset_i_pipe)\n        for i in range(0x80):\n            if not is_valid_addr(pipe_inode_info + current_arch.ptrsize * i):\n                break\n            v = read_int_from_memory(pipe_inode_info + current_arch.ptrsize * i)\n            # bufs is valid addr\n            if v < 0x10000 or not is_valid_addr(v):\n                continue\n            # bufs is not self\n            if v == pipe_inode_info:\n                continue\n            # skip invalid chunk\n            ret = Kernel.get_slab_contains(v)\n            if ret is None:\n                continue\n            # pipe_inode_info is allocated from kmalloc-1k (x64) or kmalloc-512 (x86)\n            if re.search(r\"kmalloc(-cg)?-(1k|1024|512)\", ret):\n                self.quiet_info(\"offset of bufs is found by heuristic way2-1\")\n                return current_arch.ptrsize * i\n            # before v5.5, pipe_buffer is allocated not from slub, but `user` is allocated from slub.\n            if kversion < \"5.5\" and \"uid_cache\" in ret:\n                self.quiet_info(\"offset of bufs is found by heuristic way2-2\")\n                return current_arch.ptrsize * (i - 1)\n        return None\n\n    def get_offset_head_or_nrbuf(self, pipe_files):\n        inode = pipe_files[0][1]\n        pipe_inode_info = read_int_from_memory(inode + self.offset_i_pipe)\n\n        for i in range(3, 0x40):\n            if is_64bit():\n                # head||tail/nrbuf||curbuf is not address\n                v1 = read_int_from_memory(pipe_inode_info + current_arch.ptrsize * i)\n                if is_valid_addr(v1):\n                    continue\n                # head/nrbuf is too large\n                v1_32 = read_int32_from_memory(pipe_inode_info + current_arch.ptrsize * i)\n                if v1_32 > 0x100:\n                    continue\n                # max_usage||ring_size/buffers||readers is not address\n                v2 = read_int_from_memory(pipe_inode_info + current_arch.ptrsize * (i + 1))\n                if is_valid_addr(v2):\n                    continue\n                # max_usage/buffers is too large or zero\n                v2_32 = read_int32_from_memory(pipe_inode_info + current_arch.ptrsize * (i + 1))\n                if v2_32 > 0x100 or v2_32 == 0:\n                    continue\n                return current_arch.ptrsize * i\n            else:\n                # head/nrbuf is not address\n                v1 = read_int_from_memory(pipe_inode_info + current_arch.ptrsize * i)\n                if is_valid_addr(v1):\n                    continue\n                # head/nrbuf is too large\n                v1_32 = read_int32_from_memory(pipe_inode_info + current_arch.ptrsize * i)\n                if v1_32 > 0x100:\n                    continue\n                # max_usage/buffers is not address\n                v2 = read_int_from_memory(pipe_inode_info + current_arch.ptrsize * (i + 2))\n                if is_valid_addr(v2):\n                    continue\n                # max_usage/buffers is too large or zero\n                v2_32 = read_int32_from_memory(pipe_inode_info + current_arch.ptrsize * (i + 2))\n                if v2_32 > 0x100 or v2_32 == 0:\n                    continue\n                return current_arch.ptrsize * i\n        return None\n\n    def get_pipe_files(self):\n        # struct file of pipe\n        ret = gdb.execute(\"ktask --quiet --no-pager --user-process-only --print-fd\", to_string=True)\n        pipe_files = []\n        for line in ret.splitlines():\n            m = re.search(r\"\\d+\\s+(0x\\S+) 0x\\S+ (0x\\S+) pipe:\\[\\d+\\]\", line)\n            if not m:\n                continue\n            file = int(m.group(1), 16)\n            inode = int(m.group(2), 16)\n            pipe_files.append((file, inode))\n        if pipe_files:\n            self.quiet_info(\"Num of pipe: {:d}\".format(len({x[1] for x in pipe_files})))\n        return pipe_files\n\n    def get_flags_str(self, flags_value):\n        flags_dic = {\n            0x01: \"PIPE_BUF_FLAG_LRU\",\n            0x02: \"PIPE_BUF_FLAG_ATOMIC\",\n            0x04: \"PIPE_BUF_FLAG_GIFT\",\n            0x08: \"PIPE_BUF_FLAG_PACKET\",\n            0x10: \"PIPE_BUF_FLAG_CAN_MERGE\",\n            0x20: \"PIPE_BUF_FLAG_WHOLE\",\n            0x40: \"PIPE_BUF_FLAG_LOSS\",\n        }\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n\n        flags_str = \" | \".join(flags)\n        if flags_str == \"\":\n            flags_str = \"none\"\n        return flags_str\n\n    def dump_pipe(self, pipe_files):\n        heap_page_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        kversion = Kernel.kernel_version()\n\n        inodes = {}\n        for file, inode in pipe_files:\n            inodes[inode] = inodes.get(inode, []) + [file]\n\n        for inode, files in inodes.items():\n            if self.args.inode_filter and inode not in self.args.inode_filter:\n                continue\n\n            if self.args.file_filter and not (set(self.args.file_filter) & set(files)):\n                continue\n\n            related_files = \", \".join([\"{:#x}\".format(x) for x in files])\n            self.out.append(\"inode: {:#x} (related struct file: {:s})\".format(inode, related_files))\n\n            pipe_inode_info = read_int_from_memory(inode + self.offset_i_pipe)\n            self.out.append(\"  pipe_inode_info: {:#x}\".format(pipe_inode_info))\n\n            pipe_buffer = read_int_from_memory(pipe_inode_info + self.offset_bufs)\n            self.out.append(\"    pipe_buffer: {:#x}\".format(pipe_buffer))\n\n            if \"5.5\" <= kversion:\n                head = read_int32_from_memory(pipe_inode_info + self.offset_head)\n                tail = read_int32_from_memory(pipe_inode_info + self.offset_tail)\n                max_usage = read_int32_from_memory(pipe_inode_info + self.offset_max_usage)\n                ring_size = read_int32_from_memory(pipe_inode_info + self.offset_ring_size)\n                self.out.append(\"    head: {:d}, tail: {:d}, max: {:d}, ring_size: {:d}\".format(\n                    head, tail, max_usage, ring_size,\n                ))\n            else:\n                nrbuf = read_int32_from_memory(pipe_inode_info + self.offset_nrbuf)\n                curbuf = read_int32_from_memory(pipe_inode_info + self.offset_curbuf)\n                buffers = read_int32_from_memory(pipe_inode_info + self.offset_buffers)\n                self.out.append(\"    nrbuf: {:d}, curbuf: {:d}, buffers: {:d}\".format(\n                    nrbuf, curbuf, buffers,\n                ))\n                head = curbuf + nrbuf\n                tail = curbuf\n                max_usage = buffers\n\n            used_range = [x % max_usage for x in range(tail, head)]\n            for idx in range(max_usage):\n                base = pipe_buffer + self.sizeof_pipe_buffer * idx\n                page = read_int_from_memory(base + self.offset_page)\n                offset = read_int32_from_memory(base + self.offset_offset)\n                len_ = read_int32_from_memory(base + self.offset_len)\n                flags = read_int32_from_memory(base + self.offset_flags)\n                virt = Kernel.page2virt(page)\n\n                if idx in used_range:\n                    status = Color.colorify(\"used\", used_address_color)\n                else:\n                    status = Color.colorify(\"free\", freed_address_color)\n\n                if head % max_usage == idx:\n                    head_marker = \"head\"\n                else:\n                    head_marker = \"    \"\n\n                if tail % max_usage == idx:\n                    tail_marker = \"tail\"\n                else:\n                    tail_marker = \"    \"\n\n                out = \"    {:s} {:s} {:s} [{:02d}] page: {:#x}, \".format(\n                    head_marker, tail_marker, status, idx, page,\n                )\n                if virt:\n                    colored_virt = Color.colorify_hex(virt, heap_page_color)\n                    out += \"(virt: {:s}), \".format(colored_virt)\n                out += \"offset: {:#x}, len: {:#x}, flags: {:#x} ({:s})\".format(\n                    offset, len_, flags, self.get_flags_str(flags),\n                )\n                self.out.append(out)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        allocator = Kernel.get_slab_type()\n        if allocator not in [\"SLUB\", \"SLUB_TINY\", \"SLAB\"]:\n            err(\"Unsupported: SLOB, Unknown allocator\")\n            return\n\n        # init\n        kinfo = Kernel.get_kernel_layout()\n        if kinfo.has_none:\n            self.quiet_err(\"The kernel .text area could not be determined correctly\")\n            return\n\n        pipe_files = self.get_pipe_files()\n        if not pipe_files:\n            self.quiet_info(\"Nothing to dump\")\n            return\n\n        ret = self.initialize(pipe_files)\n        if ret is False:\n            return\n\n        # dump\n        self.out = []\n        self.dump_pipe(pipe_files)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelBpfCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the BPF information.\"\"\"\n\n    _cmdline_ = \"kbpf\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-p\", \"--only-progs\", action=\"store_true\", help=\"print progs only.\")\n    parser.add_argument(\"-m\", \"--only-maps\", action=\"store_true\", help=\"print maps only.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified bpf structure:\",\n        \"\",\n        \"+-prog_idr----+   +--->+-xa_node----------+   +--------->+-bpf_prog-------------+\",\n        \"| idr_rt      |   |    | shift            |   |          | ...                  |\",\n        \"|   xa_lock   |   |    | ...              |   |          | type                 |\",\n        \"|   xa_flags  |   |    | count            |   |          | expected_attach_type |\",\n        \"|   xa_head   |---+    | ...              |   |          | len                  |\",\n        \"| idr_base    |        | slots[0]         |---+          | jited_len            |\",\n        \"| idr_next    |        | slots[1]         |--->xa_node   | tag[8]               |\",\n        \"+-------------+        | ...              |    or        | ...                  |\",\n        \"                       | slots[15 or 63]  |    bpf_prog  | bpf_func             |---> BPF-code\",\n        \"                       | ...              |              | ...                  |\",\n        \"                       +------------------+              | aux                  |\",\n        \"                                                         | ...                  |\",\n        \"                                                         +----------------------+\",\n        \"\",\n        \"+-map_idr-----+   +--->+-xa_node----------+   +--------->+-bpf_array------------+\",\n        \"| idr_rt      |   |    | shift            |   |          | map                  |\",\n        \"|   xa_lock   |   |    | ...              |   |          |   ...                |\",\n        \"|   xa_flags  |   |    | count            |   |          |   map_type           |\",\n        \"|   xa_head   |---+    | ...              |   |          |   key_size           |\",\n        \"| idr_base    |        | slots[0]         |---+          |   value_size         |\",\n        \"| idr_next    |        | slots[1]         |--->xa_node   |   max_entries        |\",\n        \"+-------------+        | ...              |    or        |   ...                |\",\n        \"                       | slots[15 or 63]  |    bpf_array | elem_size            |\",\n        \"                       | ...              |              | index_mask           |\",\n        \"                       +------------------+              | ...                  |\",\n        \"                                                         +----------------------+\",\n        \"                                                         | value[0]             |\",\n        \"                                                         | value[1]             |\",\n        \"                                                         | ...                  |\",\n        \"                                                         | value[max_entries-1] |\",\n        \"                                                         +----------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def parse_xarray(self, ptr, root=False):\n        if ptr == 0:\n            return []\n\n        ptr &= ~3 # untagged\n\n        if root:\n            node = read_int_from_memory(ptr + self.offset_xa_head)\n            return self.parse_xarray(node)\n\n        shift = read_int8_from_memory(ptr + self.offset_shift)\n        count = read_int8_from_memory(ptr + self.offset_count)\n        slots = ptr + self.offset_slots\n        elems = []\n        for i in range(64): # 16 or 64\n            x = read_int_from_memory(slots + current_arch.ptrsize * i)\n            if x == 0:\n                continue\n            if shift:\n                elems += self.parse_xarray(x)\n            else:\n                elems.append(x)\n            count -= 1\n            if count == 0:\n                break\n        return elems\n\n    def initialize(self):\n        # get global address\n        prog_idr = KernelAddressHeuristicFinder.get_prog_idr()\n        if not prog_idr:\n            return False\n        self.quiet_info(\"prog_idr: {:#x}\".format(prog_idr))\n\n        map_idr = KernelAddressHeuristicFinder.get_map_idr()\n        if not map_idr:\n            return False\n        self.quiet_info(\"map_idr: {:#x}\".format(map_idr))\n\n        kversion = Kernel.kernel_version()\n\n        \"\"\"\n        struct xarray {\n            spinlock_t xa_lock;\n            gfp_t xa_flags;\n            void __rcu *xa_head;\n        };\n        \"\"\"\n        # idr->idr_rt->xa_head\n        base = prog_idr + 4 * 2\n        max_sizeof_idr = abs(prog_idr - map_idr)\n        for i in range(20):\n            pos = base + current_arch.ptrsize * i\n            if (pos - prog_idr) >= max_sizeof_idr:\n                continue\n            x = read_int_from_memory(pos)\n            if not is_valid_addr(x):\n                continue\n            if (x & 2) != 2: # tag\n                continue\n            y = read_cstring_from_memory(x)\n            if y and len(y) > 8 or y == \"bpf\":\n                continue\n            z = read_int_from_memory(x)\n            if is_valid_addr(z):\n                continue\n            self.offset_xa_head = pos - prog_idr\n            self.quiet_info(\"offsetof(xarray, xa_head): {:#x}\".format(self.offset_xa_head))\n            break\n        else:\n            err(\"Could not find xa_head. (maybe uninitialized?)\")\n            return False\n\n        \"\"\"\n        struct xa_node {\n            unsigned char shift;\n            unsigned char offset;\n            unsigned char count;\n            unsigned char nr_values;\n            struct xa_node __rcu *parent;\n            struct xarray *array;\n            union {\n                struct list_head private_list;\n                struct rcu_head rcu_head;\n            };\n            void __rcu *slots[XA_CHUNK_SIZE];\n            union {\n                unsigned long tags[XA_MAX_MARKS][XA_MARK_LONGS];\n                unsigned long marks[XA_MAX_MARKS][XA_MARK_LONGS];\n            };\n        };\n        \"\"\"\n        # xa_node->{shift,count,slots}\n        self.offset_shift = 0\n        self.offset_count = 2\n        self.offset_slots = current_arch.ptrsize * 5\n        self.quiet_info(\"offsetof(xa_node, shift): {:#x}\".format(self.offset_shift))\n        self.quiet_info(\"offsetof(xa_node, count): {:#x}\".format(self.offset_count))\n        self.quiet_info(\"offsetof(xa_node, slots): {:#x}\".format(self.offset_slots))\n\n        # parse progs, maps\n        try:\n            progs = self.parse_xarray(prog_idr, root=True)\n            self.quiet_info(\"Num of progs: {:#x}\".format(len(progs)))\n            maps = self.parse_xarray(map_idr, root=True)\n            self.quiet_info(\"Num of maps: {:#x}\".format(len(maps)))\n        except gdb.MemoryError:\n            self.quiet_err(\"Not found\")\n            return False\n\n        \"\"\"\n        struct bpf_prog {\n            u16 pages;\n            u16 jited:1,\n                jit_requested:1,\n                gpl_compatible:1,\n                cb_access:1,\n                dst_needed:1,\n                blinded:1,\n                is_func:1,\n                kprobe_override:1,\n                has_callchain_buf:1,\n                enforce_expected_attach_type:1,\n                call_get_stack:1;\n            enum bpf_prog_type type;\n            enum bpf_attach_type expected_attach_type;\n            u32 len;\n            u32 jited_len;\n            u8 tag[BPF_TAG_SIZE]; // 8 byte\n            struct bpf_prog_stats __percpu *stats; // v5.12~\n            int __percpu *active;                  // v5.12~\n            unsigned int (*bpf_func)(const void *ctx, const struct bpf_insn *insn); // v5.12~\n            struct bpf_prog_aux *aux;\n            struct sock_fprog_kern *orig_prog;\n            unsigned int (*bpf_func)(const void *ctx, const struct bpf_insn *insn); // ~v5.11\n            const struct bpf_insn *insn);\n            struct sock_filter insns[0];\n            struct bpf_insn insnsi[];\n        };\n        \"\"\"\n        # bpf_prog->{type,expected_attach_type,len,jited_len,tag,aux}\n        self.offset_prog_type = 4\n        self.offset_expected_attach_type = self.offset_prog_type + 4\n        self.offset_len = self.offset_expected_attach_type + 4\n        self.offset_jited_len = self.offset_len + 4\n        self.offset_tag = self.offset_jited_len + 4\n        if \"5.12\" <= kversion:\n            self.offset_aux = align_to_ptrsize(self.offset_tag + 8) + current_arch.ptrsize * 3\n            self.offset_bpf_func = self.offset_aux - current_arch.ptrsize\n        else:\n            self.offset_aux = align_to_ptrsize(self.offset_tag + 8)\n            self.offset_bpf_func = self.offset_aux + current_arch.ptrsize * 2\n        self.offset_orig_prog = self.offset_aux + current_arch.ptrsize\n        self.quiet_info(\"offsetof(bpf_prog, type): {:#x}\".format(self.offset_prog_type))\n        self.quiet_info(\"offsetof(bpf_prog, expected_attach_type): {:#x}\".format(self.offset_expected_attach_type))\n        self.quiet_info(\"offsetof(bpf_prog, len): {:#x}\".format(self.offset_len))\n        self.quiet_info(\"offsetof(bpf_prog, jited_len): {:#x}\".format(self.offset_jited_len))\n        self.quiet_info(\"offsetof(bpf_prog, tag): {:#x}\".format(self.offset_tag))\n        self.quiet_info(\"offsetof(bpf_prog, aux): {:#x}\".format(self.offset_aux))\n        self.quiet_info(\"offsetof(bpf_prog, bpf_func): {:#x}\".format(self.offset_bpf_func))\n        self.quiet_info(\"offsetof(bpf_prog, orig_prog): {:#x}\".format(self.offset_orig_prog))\n\n        try:\n            self.seccomp_tools_command = [GefUtil.which(\"ceccomp\"), \"disasm\", \"-c\", \"always\"]\n            self.quiet_info(\"ceccomp is found\")\n        except FileNotFoundError:\n            try:\n                self.seccomp_tools_command = [GefUtil.which(\"seccomp-tools\"), \"disasm\"]\n                self.quiet_info(\"seccomp-tools is found\")\n                if is_arm32():\n                    self.quiet_warn(\"`seccomp-tools` is not supported on ARM32. \"\n                                    \"Consider using `ceccomp` instead, as it supports ARM32.\")\n                    self.quiet_info(\"GEF uses `capstone-disassemble bpf_func`\")\n                    self.seccomp_tools_command = None\n            except FileNotFoundError:\n                self.quiet_info(\"Could not find ceccomp or seccomp-tools, GEF uses `capstone-disassemble bpf_func`\")\n                self.seccomp_tools_command = None\n\n        if maps:\n            \"\"\"\n            struct bpf_map {\n                const struct bpf_map_ops *ops ____cacheline_aligned;\n                struct bpf_map *inner_map_meta;\n            #ifdef CONFIG_SECURITY\n                void *security;\n            #endif\n                enum bpf_map_type map_type;\n                u32 key_size;\n                u32 value_size;\n                u32 max_entries;\n                ...\n            };\n            \"\"\"\n            # bpf_map->{map_type,key_size,value_size,max_entries}\n            cand = read_int_from_memory(maps[0] + current_arch.ptrsize * 2)\n            if cand == 0 or is_valid_addr(cand):\n                self.offset_map_type = current_arch.ptrsize * 3\n            else:\n                self.offset_map_type = current_arch.ptrsize * 2\n            self.offset_key_size = self.offset_map_type + 4\n            self.offset_value_size = self.offset_key_size + 4\n            self.offset_max_entries = self.offset_value_size + 4\n            self.quiet_info(\"offsetof(bpf_map, map_type): {:#x}\".format(self.offset_map_type))\n            self.quiet_info(\"offsetof(bpf_map, key_size): {:#x}\".format(self.offset_key_size))\n            self.quiet_info(\"offsetof(bpf_map, value_size): {:#x}\".format(self.offset_value_size))\n            self.quiet_info(\"offsetof(bpf_map, max_entries): {:#x}\".format(self.offset_max_entries))\n\n            \"\"\"\n            struct bpf_array {\n                struct bpf_map map;\n                u32 elem_size;\n                u32 index_mask;\n                struct bpf_array_aux *aux;\n                union {\n                    char value[0] __aligned(8);\n                    void *ptrs[0] __aligned(8);\n                    void __percpu *pptrs[0] __aligned(8);\n                };\n            };\n            \"\"\"\n            # bpf_array->union_array\n            value_size = read_int32_from_memory(maps[0] + self.offset_value_size)\n            value_size_aligned_8 = align(value_size, 8)\n            max_entries = read_int32_from_memory(maps[0] + self.offset_max_entries)\n            k = 1\n            while k < max_entries:\n                k <<= 1\n            index_mask = k - 1\n\n            sizeof_cache_line = 0x40 # ?\n            base = maps[0] + sizeof_cache_line * 3\n            for i in range(100):\n                pos = base + current_arch.ptrsize * i\n                x = read_int32_from_memory(pos)\n                y = read_int32_from_memory(pos + 4)\n                if x == value_size_aligned_8 and y == index_mask:\n                    self.offset_union_array = (pos - maps[0]) + 4 * 2 + current_arch.ptrsize\n                    self.quiet_info(\"offsetof(bpf_array, union_array): {:#x}\".format(self.offset_union_array))\n                    break\n            else:\n                return False\n        return progs, maps\n\n    def dump_bpf_progs(self, progs):\n        self.out.append(titlify(\"prog_idr\"))\n        fmt = \"{:3s} {:18s} {:23s} {:24s} {:18s} {:18s} {:18s} {:9s} {:18s}\"\n        legend = [\"#\", \"bpf_prog\", \"bpf_prog_type\", \"bpf_attach_type\", \"tag\", \"bpf_prog_aux\", \"bpf_func\", \"jited_len\", \"orig_prog\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        defined_prog_types = [\n            \"UNSPEC\",\n            \"SOCKET_FILTER\",\n            \"KPROBE\",\n            \"SCHED_CLS\",\n            \"SCHED_ACT\",\n            \"TRACEPOINT\",\n            \"XDP\",\n            \"PERF_EVENT\",\n            \"CGROUP_SKB\",\n            \"CGROUP_SOCK\",\n            \"LWT_IN\",\n            \"LWT_OUT\",\n            \"LWT_XMIT\",\n            \"SOCK_OPS\",\n            \"SK_SKB\",\n            \"CGROUP_DEVICE\",\n            \"SK_MSG\",\n            \"RAW_TRACEPOINT\",\n            \"CGROUP_SOCK_ADDR\",\n            \"LWT_SEG6LOCAL\",\n            \"LIRC_MODE2\",\n            \"SK_REUSEPORT\",\n            \"FLOW_DISSECTOR\",\n            \"CGROUP_SYSCTL\",\n            \"RAW_TRACEPOINT_WRITABLE\",\n            \"CGROUP_SOCKOPT\",\n            \"TRACING\",\n            \"STRUCT_OPS\",\n            \"EXT\",\n            \"LSM\",\n            \"SK_LOOKUP\",\n        ]\n\n        defined_attach_types = [\n            \"CGROUP_INET_INGRESS\",\n            \"CGROUP_INET_EGRESS\",\n            \"CGROUP_INET_SOCK_CREATE\",\n            \"CGROUP_SOCK_OPS\",\n            \"SK_SKB_STREAM_PARSER\",\n            \"SK_SKB_STREAM_VERDICT\",\n            \"CGROUP_DEVICE\",\n            \"SK_MSG_VERDICT\",\n            \"CGROUP_INET4_BIND\",\n            \"CGROUP_INET6_BIND\",\n            \"CGROUP_INET4_CONNECT\",\n            \"CGROUP_INET6_CONNECT\",\n            \"CGROUP_INET4_POST_BIND\",\n            \"CGROUP_INET6_POST_BIND\",\n            \"CGROUP_UDP4_SENDMSG\",\n            \"CGROUP_UDP6_SENDMSG\",\n            \"LIRC_MODE2\",\n            \"FLOW_DISSECTOR\",\n            \"CGROUP_SYSCTL\",\n            \"CGROUP_UDP4_RECVMSG\",\n            \"CGROUP_UDP6_RECVMSG\",\n            \"CGROUP_GETSOCKOPT\",\n            \"CGROUP_SETSOCKOPT\",\n            \"TRACE_RAW_TP\",\n            \"TRACE_FENTRY\",\n            \"TRACE_FEXIT\",\n            \"MODIFY_RETURN\",\n            \"LSM_MAC\",\n            \"TRACE_ITER\",\n            \"CGROUP_INET4_GETPEERNAME\",\n            \"CGROUP_INET6_GETPEERNAME\",\n            \"CGROUP_INET4_GETSOCKNAME\",\n            \"CGROUP_INET6_GETSOCKNAME\",\n            \"XDP_DEVMAP\",\n            \"CGROUP_INET_SOCK_RELEASE\",\n            \"XDP_CPUMAP\",\n            \"SK_LOOKUP\",\n            \"XDP\",\n        ]\n\n        fmt = \"{:<3d} {:#018x} {:23s} {:24s} {:#018x} {:#018x} {:#018x} {:<#9x} {:#018x}\"\n        for i, prog in enumerate(progs):\n            bpf_type = read_int32_from_memory(prog + self.offset_prog_type)\n            bpf_attach_type = read_int32_from_memory(prog + self.offset_expected_attach_type)\n            jited_len = read_int32_from_memory(prog + self.offset_jited_len)\n            orig_prog = read_int_from_memory(prog + self.offset_orig_prog)\n            t1 = defined_prog_types[bpf_type]\n            t2 = defined_attach_types[bpf_attach_type]\n            tag = read_int64_from_memory(prog + self.offset_tag)\n            aux = read_int_from_memory(prog + self.offset_aux)\n            bpf_func = read_int_from_memory(prog + self.offset_bpf_func)\n            self.out.append(fmt.format(i, prog, t1, t2, tag, aux, bpf_func, jited_len, orig_prog))\n\n            if self.args.verbose:\n                # dump func\n                if self.seccomp_tools_command and is_valid_addr(orig_prog):\n                    # use seccomp-tools or ceccomp\n                    cnt = read_int16_from_memory(orig_prog)\n                    prog = read_int_from_memory(orig_prog + current_arch.ptrsize)\n                    data = read_memory(prog, cnt * 8)\n                    tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"kbpf\")\n                    os.fdopen(tmp_fd, \"wb\").write(data)\n                    ret = GefUtil.gef_execute_external(\n                        self.seccomp_tools_command + [tmp_path], as_list=True,\n                    )\n                    self.out.extend(ret)\n                    os.unlink(tmp_path)\n                elif is_valid_addr(bpf_func):\n                    try:\n                        __import__(\"capstone\")\n                        # use capstone\n                        data = read_memory(bpf_func, jited_len)\n                        dump_count = 0\n                        for insn in Disasm.capstone_disassemble(bpf_func, jited_len, code=data.hex()):\n                            msg = insn.colored_text(10)\n                            self.out.append(msg)\n                            dump_count += insn.size\n                            if dump_count >= jited_len:\n                                break\n                    except ImportError:\n                        ret = gdb.execute(\"x/40i {:#x}\".format(bpf_func), to_string=True).rstrip()\n                        self.out.append(ret)\n                        self.out.append(\"...\")\n                else:\n                    self.err_add_out(\"Memory read error\")\n                self.out.append(titlify(\"\"))\n        return\n\n    def dump_bpf_maps(self, maps):\n        self.out.append(titlify(\"map_idr\"))\n        fmt = \"{:3s} {:18s} {:21s} {:10s} {:10s} {:10s} {:18s}\"\n        legend = [\"#\", \"bpf_map\", \"bpf_map_type\", \"key_size\", \"value_size\", \"max_ents\", \"array\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        defined_map_types = [\n            \"UNSPEC\",\n            \"HASH\",\n            \"ARRAY\",\n            \"PROG_ARRAY\",\n            \"PERF_EVENT_ARRAY\",\n            \"PERCPU_HASH\",\n            \"PERCPU_ARRAY\",\n            \"STACK_TRACE\",\n            \"CGROUP_ARRAY\",\n            \"LRU_HASH\",\n            \"LRU_PERCPU_HASH\",\n            \"LPM_TRIE\",\n            \"ARRAY_OF_MAPS\",\n            \"HASH_OF_MAPS\",\n            \"DEVMAP\",\n            \"SOCKMAP\",\n            \"CPUMAP\",\n            \"XSKMAP\",\n            \"SOCKHASH\",\n            \"CGROUP_STORAGE\",\n            \"REUSEPORT_SOCKARRAY\",\n            \"PERCPU_CGROUP_STORAGE\",\n            \"QUEUE\",\n            \"STACK\",\n            \"SK_STORAGE\",\n            \"DEVMAP_HASH\",\n            \"STRUCT_OPS\",\n            \"RINGBUF\",\n            \"INODE_STORAGE\",\n        ]\n\n        fmt = \"{:<3d} {:#018x} {:21s} {:#010x} {:#010x} {:#010x} {:#018x}\"\n        for i, m in enumerate(maps):\n            map_type = read_int32_from_memory(m + self.offset_map_type)\n            t1 = defined_map_types[map_type]\n            key_size = read_int32_from_memory(m + self.offset_key_size)\n            val_size = read_int32_from_memory(m + self.offset_value_size)\n            max_ents = read_int32_from_memory(m + self.offset_max_entries)\n            union_array = m + self.offset_union_array\n            self.out.append(fmt.format(i, m, t1, key_size, val_size, max_ents, union_array))\n\n            if self.verbose:\n                if map_type == 2: # ARRAY\n                    res = gdb.execute(\"dereference -n {:#x} {:#x}\".format(union_array, max_ents), to_string=True)\n                    self.out.append(res.rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"4.20\":\n            # xarray is introduced from 4.20\n            self.quiet_err(\"Unsupported before v4.20\")\n            return\n\n        stv_bpf_ret = gdb.execute(\"syscall-table-view -f bpf --quiet --no-pager\", to_string=True)\n        if \"bpf\" not in stv_bpf_ret:\n            self.quiet_err(\"bpf syscall is unimplemented\")\n            return\n        elif \"invalid bpf\" in stv_bpf_ret:\n            self.quiet_err(\"bpf syscall is disabled\")\n            return\n\n        # init\n        ret = self.initialize()\n        if ret is False:\n            self.quiet_err(\"Failed to initialize\")\n            return\n        progs, maps = ret\n\n        # dump\n        self.out = []\n        if not args.only_maps:\n            self.dump_bpf_progs(progs)\n        if not args.only_progs:\n            self.dump_bpf_maps(maps)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelIpcsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump IPCs information (System V semaphore, message queue and shared memory).\"\"\"\n\n    _cmdline_ = \"kipcs\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"dump the beginning of msg_msg.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n        \"\",\n        \"Simplified ipc structure:\",\n        \"\",\n        \"+-task_struct-+  +-->+-nsproxy--+  +-->+-ipc_namespace-+\",\n        \"| ...         |  |   | ...      |  |   | ...           |\",\n        \"| nsproxy     |--+   | ipc_ns   |--+   | ids[0] (sem)  |\",\n        \"| ...         |      | ...      |      |   ...         |\",\n        \"+-------------+      +----------+      |   ipcs_idr    |\",\n        \"                                       |     xa_head   |-->xarray-->+-sem_array-+\",\n        \"                                       |     ...       |            | ...       |\",\n        \"                                       | ids[1] (msg)  |            +-----------+\",\n        \"                                       |   ...         |\",\n        \"                                       |   ipcs_idr    |\",\n        \"                                       |     xa_head   |-->xarray-->+-msg_queue-+\",\n        \"                                       |     ...       |            | ...       |\",\n        \"                                       | ids[2] (shm)  |            +-----------+\",\n        \"                                       |   ...         |\",\n        \"                                       |   ipcs_idr    |\",\n        \"                                       |     xa_head   |-->xarray-->+-shmid_kernel-+\",\n        \"                                       |     ...       |            | ...          |\",\n        \"                                       | ...           |            +--------------+\",\n        \"                                       +---------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_all_ipc_ns(self):\n        res = gdb.execute(\"ktask --print-namespace --user-process-only --no-pager --quiet\", to_string=True)\n        r = re.findall(r\"nsproxy->ipc_ns\\s+(0x\\S+)\", res)\n\n        ipc_ns_list = []\n        # do not use `set()` because the order is important.\n        for x in r:\n            x = int(x, 16)\n            if x not in ipc_ns_list:\n                ipc_ns_list.append(x)\n        return ipc_ns_list\n\n    def initialize(self, ipc_ns_list):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        if ipc_ns_list == []:\n            return False\n\n        if ipc_ns_list == [0]:\n            err(\"Could not find valid ipc_ns (maybe CONFIG_SYSVIPC=n)\")\n            return False\n\n        # ipc_namespace\n        \"\"\"\n        struct ipc_namespace {\n            refcount_t count; // ~5.10\n            struct ipc_ids {\n                int in_use;\n                unsigned short seq;\n                struct rw_semaphore {\n                    atomic_long_t count;\n                    atomic_long_t owner;\n                #ifdef CONFIG_RWSEM_SPIN_ON_OWNER\n                    struct optimistic_spin_queue osq;\n                #endif\n                    raw_spinlock_t wait_lock;\n                    struct list_head wait_list;\n                #ifdef CONFIG_DEBUG_RWSEMS\n                    void *magic;\n                #endif\n                #ifdef CONFIG_DEBUG_LOCK_ALLOC\n                    struct lockdep_map dep_map;\n                #endif\n                } rwsem;\n                struct idr {\n                    struct radix_tree_root { // =struct xarray\n                        spinlock_t xa_lock;\n                        gfp_t xa_flags;\n                        void __rcu *xa_head;\n                    } idr_rt;\n                    unsigned int idr_base;\n                    unsigned int idr_next;\n                } ipcs_idr;\n                int max_idx;\n                int last_idx;\n            #ifdef CONFIG_CHECKPOINT_RESTORE\n                int next_id;\n            #endif\n                struct rhashtable key_ht;\n            } ids[3];\n            ...\n        \"\"\"\n        kversion = Kernel.kernel_version()\n        if \"5.11\" <= kversion:\n            self.offset_ids = 0\n        else:\n            self.offset_ids = current_arch.ptrsize\n        self.quiet_info(\"offsetof(ipc_namespace, ids): {:#x}\".format(self.offset_ids))\n\n        # offsetof(ipc_ids, ipcs_idr.idr_rt.xa_head): tagged valid pointer is `xa_head`.\n        # sizeof(ids[0]): find two `xa_head` and calculate the distance.\n        init_ipc_ns = ipc_ns_list[0]\n        found = []\n        first_xa_flags = None\n        for i in range(6, 120):\n            base = self.offset_ids + current_arch.ptrsize * i\n            \"\"\"\n            [x64 before using IPC]\n            0xffffffff8b1841f8|+0x0038|+007: 0x0080000400000000 <- xa_lock, xa_flags\n            0xffffffff8b184200|+0x0040|+008: 0x0000000000000000 <- xa_head\n            0xffffffff8b184208|+0x0048|+009: 0x0000000000000000 <- idr_base, idr_next\n            [x64 after using IPC]\n            0xffffffff8b1841f8|+0x0038|+007: 0x0080000400000000\n            0xffffffff8b184200|+0x0040|+008: 0xffff9250c7dc2002 ->  0x0000000000000001\n            0xffffffff8b184208|+0x0048|+009: 0x0000000100000000\n            [x64 after deleting IPC]\n            0xffffffff8b1841f8|+0x0038|+007: 0x0080000400000000\n            0xffffffff8b184200|+0x0040|+008: 0x0000000000000000\n            0xffffffff8b184208|+0x0048|+009: 0x0000000100000000\n\n            [x86 before using IPC]\n            0xc1b4e104|+0x0024|+009: 0x00000000 <- xa_lock\n            0xc1b4e108|+0x0028|+010: 0x00800004 <- xa_flags\n            0xc1b4e10c|+0x002c|+011: 0x00000000 <- xa_head\n            0xc1b4e110|+0x0030|+012: 0x00000000 <- idr_base\n            0xc1b4e114|+0x0034|+013: 0x00000000 <- idr_next\n            [x86 after using IPC]\n            0xc1b4e104|+0x0024|+009: 0x00000000\n            0xc1b4e108|+0x0028|+010: 0x00800004\n            0xc1b4e10c|+0x002c|+011: 0xc2c67392  ->  0x00000001\n            0xc1b4e110|+0x0030|+012: 0x00000000\n            0xc1b4e114|+0x0034|+013: 0x00000001\n            [x86 after deleting IPC]\n            0xc1b4e104|+0x0024|+009: 0x00000000\n            0xc1b4e108|+0x0028|+010: 0x00800004\n            0xc1b4e10c|+0x002c|+011: 0x00000000\n            0xc1b4e110|+0x0030|+012: 0x00000000\n            0xc1b4e114|+0x0034|+013: 0x00000001\n            \"\"\"\n\n            # xa_flags\n            x = read_int_from_memory(init_ipc_ns + base - current_arch.ptrsize)\n            if x == 0 or is_valid_addr(x):\n                continue\n            if first_xa_flags is not None and first_xa_flags != x:\n                continue\n\n            # xa_head\n            y = read_int_from_memory(init_ipc_ns + base)\n            if y:\n                if not is_valid_addr(y):\n                    continue\n                if y & 0x2 != 0x2: # xa_head is NULL or tagged address\n                    continue\n\n            # idr_base, idr_next\n            if is_32bit():\n                z1 = read_int_from_memory(init_ipc_ns + base + current_arch.ptrsize) # idr_base\n                z2 = read_int_from_memory(init_ipc_ns + base + current_arch.ptrsize * 2) # idr_next\n                if is_valid_addr(z1) or is_valid_addr(z2):\n                    continue\n                if y and z1 == 0 and z2 == 0:\n                    continue\n            else:\n                z = read_int_from_memory(init_ipc_ns + base + current_arch.ptrsize) # idr_base, idr_next\n                if is_valid_addr(z): # idr_base, idr_next\n                    continue\n                if y and z == 0:\n                    continue\n\n            # first found\n            if not hasattr(self, \"offset_xa_head\"):\n                self.offset_xa_head = base - self.offset_ids\n                first_xa_flags = x\n\n            # found\n            found.append(base - self.offset_ids)\n\n            # exit loop?\n            if len(found) >= 2:\n                self.sizeof_ipc_ids = found[1] - found[0]\n                break\n        else:\n            self.quiet_err(\"Could not find ipc_namespace->ids[0].ipcs_idr.idr_rt.xa_head\")\n            self.quiet_err(\"Not recognized sizeof(struct ipc_ids)\")\n            self.quiet_err(\"Maybe CONFIG_SYSVIPC=n\")\n            return False\n        self.quiet_info(\"offsetof(ipc_ids, ipcs_idr.idr_rt.xa_head): {:#x}\".format(self.offset_xa_head))\n        self.quiet_info(\"sizeof(struct ipc_ids): {:#x}\".format(self.sizeof_ipc_ids))\n\n        # xa_node\n        \"\"\"\n        struct xa_node {\n            unsigned char shift;\n            unsigned char offset;\n            unsigned char count;\n            unsigned char nr_values;\n            struct xa_node __rcu *parent;\n            struct xarray *array;\n            union {\n                struct list_head private_list;\n                struct rcu_head rcu_head;\n            };\n            void __rcu *slots[XA_CHUNK_SIZE];\n            union {\n                unsigned long tags[XA_MAX_MARKS][XA_MARK_LONGS];\n                unsigned long marks[XA_MAX_MARKS][XA_MARK_LONGS];\n            };\n        };\n        \"\"\"\n        # xa_node->{shift,count,slots}\n        self.offset_shift = 0\n        self.offset_count = 2\n        self.offset_slots = current_arch.ptrsize * 5\n\n        # kern_ipc_perm\n        \"\"\"\n        struct kern_ipc_perm {\n            spinlock_t lock;\n            bool deleted;\n            int id;\n            key_t key;\n            kuid_t uid;\n            kgid_t gid;\n            kuid_t cuid;\n            kgid_t cgid;\n            umode_t mode;\n            unsigned long seq;\n            void *security;\n            struct rhash_head khtnode;\n            struct rcu_head rcu;\n            refcount_t refcount;\n        } ____cacheline_aligned_in_smp __randomize_layout;\n        \"\"\"\n        self.offset_id = 4 + 4\n        self.offset_key = self.offset_id + 4\n        self.offset_uid = self.offset_key + 4\n        self.offset_gid = self.offset_uid + 4\n        self.offset_mode = self.offset_gid + 4 + 4 + 4\n\n        self.initialized = True\n        return True\n\n    def parse_xarray(self, ptr, root=False):\n        if ptr == 0:\n            return []\n\n        ptr &= ~3 # untagged\n\n        if root:\n            # ptr is &ipc_ids[i]\n            node = read_int_from_memory(ptr + self.offset_xa_head)\n            return self.parse_xarray(node)\n\n        shift = read_int8_from_memory(ptr + self.offset_shift)\n        count = read_int8_from_memory(ptr + self.offset_count)\n        slots = ptr + self.offset_slots\n        elems = []\n        for i in range(64): # 16 or 64\n            x = read_int_from_memory(slots + current_arch.ptrsize * i)\n            if x == 0:\n                continue\n            if shift:\n                elems += self.parse_xarray(x)\n            else:\n                elems.append(x)\n            count -= 1\n            if count == 0:\n                break\n        return elems\n\n    def dump_ipc_sem_ids(self, ipc_ids_ptr):\n        \"\"\"\n        struct sem_array {\n            struct kern_ipc_perm sem_perm;\n            time64_t sem_ctime;\n            struct list_head pending_alter;\n            struct list_head pending_const;\n            struct list_head list_id;\n            int sem_nsems;\n            ...\n        } __randomize_layout;\n        \"\"\"\n        self.out.append(titlify(\"Semaphore Arrays\"))\n        fmt = \"{:18s} {:5s} {:10s} {:4s} {:4s} {:5s} {:s}\"\n        legend = [\"sem_array\", \"semid\", \"key\", \"uid\", \"gid\", \"perms\", \"nsems\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        elems = self.parse_xarray(ipc_ids_ptr, root=True)\n        for e in elems:\n            semid = read_int32_from_memory(e + self.offset_id)\n            key = read_int32_from_memory(e + self.offset_key)\n            uid = read_int32_from_memory(e + self.offset_uid)\n            gid = read_int32_from_memory(e + self.offset_gid)\n            mode = read_int16_from_memory(e + self.offset_mode)\n\n            if not hasattr(self, \"offset_sem_nsems\"):\n                for i in range(1, 64):\n                    # search pending_alter, pending_const, list_id\n                    base = self.offset_mode + current_arch.ptrsize * i\n                    addrs = [read_int_from_memory(e + base + current_arch.ptrsize * j) for j in range(6)]\n                    if all(is_valid_addr(x) for x in addrs):\n                        # found\n                        self.offset_sem_nsems = base + current_arch.ptrsize * 6\n                        break\n            if hasattr(self, \"offset_sem_nsems\"):\n                nsems = read_int_from_memory(e + self.offset_sem_nsems)\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:d}\".format(\n                    e, semid, key, uid, gid, mode, nsems,\n                ))\n            else:\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:s}\".format(\n                    e, semid, key, uid, gid, mode, \"?\",\n                ))\n\n        return\n\n    def dump_ipc_msg_ids(self, ipc_ids_ptr):\n        \"\"\"\n        struct msg_queue {\n            struct kern_ipc_perm q_perm;\n            time64_t q_stime;\n            time64_t q_rtime;\n            time64_t q_ctime;\n            unsigned long q_cbytes;\n            unsigned long q_qnum;\n            unsigned long q_qbytes;\n            struct pid *q_lspid;\n            struct pid *q_lrpid;\n            struct list_head q_messages; <--> msg_msg.m_list\n            struct list_head q_receivers;\n            struct list_head q_senders;\n        } __randomize_layout;\n\n        struct msg_msg {\n            struct list_head m_list;\n            long m_type;\n            size_t m_ts; /* message text size */\n            struct msg_msgseg *next;\n            void *security;\n        };\n        \"\"\"\n        self.out.append(titlify(\"Message Queues\"))\n        fmt = \"{:18s} {:5s} {:10s} {:4s} {:4s} {:5s} {:10s} {:s}\"\n        legend = [\"msg_queue\", \"msqid\", \"key\", \"uid\", \"gid\", \"perms\", \"used-bytes\", \"messages\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        elems = self.parse_xarray(ipc_ids_ptr, root=True)\n        for e in elems:\n            msqid = read_int32_from_memory(e + self.offset_id)\n            key = read_int32_from_memory(e + self.offset_key)\n            uid = read_int32_from_memory(e + self.offset_uid)\n            gid = read_int32_from_memory(e + self.offset_gid)\n            mode = read_int16_from_memory(e + self.offset_mode)\n\n            if not hasattr(self, \"offset_q_cbytes\"):\n                for i in range(1, 64):\n                    # search q_messages, q_receivers, q_senders\n                    base = self.offset_mode + current_arch.ptrsize * i\n                    addrs = [read_int_from_memory(e + base + current_arch.ptrsize * j) for j in range(6)]\n                    if all(is_valid_addr(x) for x in addrs):\n                        x = read_int_from_memory(e + base + current_arch.ptrsize * 6)\n                        if not is_valid_addr(x):\n                            # found\n                            self.offset_q_cbytes = base - current_arch.ptrsize * 5\n                            self.offset_q_qnum = base - current_arch.ptrsize * 4\n                            self.offset_q_messages = base\n                            break\n            if hasattr(self, \"offset_q_cbytes\"):\n                q_cbytes = read_int_from_memory(e + self.offset_q_cbytes)\n                q_qnum = read_int_from_memory(e + self.offset_q_qnum)\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:<#10x} {:<d}\".format(\n                    e, msqid, key, uid, gid, mode, q_cbytes, q_qnum,\n                ))\n            else:\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:10s} {:s}\".format(\n                    e, msqid, key, uid, gid, mode, \"?\", \"?\",\n                ))\n\n            if self.args.verbose:\n                if hasattr(self, \"offset_q_messages\"):\n                    current = e + self.offset_q_messages\n                    seen = [current]\n                    while is_valid_addr(current):\n                        current = read_int_from_memory(current)\n                        if current in seen:\n                            break\n                        seen.append(current)\n                        self.out.append(\"msg_msg: {:#x}\".format(current))\n                        res = gdb.execute(\"dereference -n {:#x} 8\".format(current), to_string=True)\n                        self.out.append(res.rstrip())\n        return\n\n    def dump_ipc_shm_ids(self, ipc_ids_ptr):\n        \"\"\"\n        struct shmid_kernel {\n            struct kern_ipc_perm shm_perm;\n            struct file *shm_file;\n            unsigned long shm_nattch;\n            unsigned long shm_segsz;\n            ...\n        } __randomize_layout;\n        \"\"\"\n        self.out.append(titlify(\"Shared Memory Segments\"))\n        fmt = \"{:18s} {:5s} {:10s} {:4s} {:4s} {:5s} {:10s} {:s}\"\n        legend = [\"shmid_kernel\", \"shmid\", \"key\", \"uid\", \"gid\", \"perms\", \"bytes\", \"nattch\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        elems = self.parse_xarray(ipc_ids_ptr, root=True)\n        for e in elems:\n            shmid = read_int32_from_memory(e + self.offset_id)\n            key = read_int32_from_memory(e + self.offset_key)\n            uid = read_int32_from_memory(e + self.offset_uid)\n            gid = read_int32_from_memory(e + self.offset_gid)\n            mode = read_int16_from_memory(e + self.offset_mode)\n\n            if not hasattr(self, \"offset_shm_nattch\"):\n                for i in range(1, 64):\n                    # search shm_file and shm_segsz\n                    base = self.offset_mode + current_arch.ptrsize * i\n                    x = read_int_from_memory(e + base)\n                    y = read_int_from_memory(e + base + current_arch.ptrsize * 2)\n                    if is_valid_addr(x) and y != 0 and y % 0x1000 == 0:\n                        # found\n                        self.offset_shm_nattch = base + current_arch.ptrsize\n                        self.offset_shm_segsz = base + current_arch.ptrsize * 2\n                        break\n            if hasattr(self, \"offset_shm_nattch\"):\n                nattch = read_int_from_memory(e + self.offset_shm_nattch)\n                segsz = read_int_from_memory(e + self.offset_shm_segsz)\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:<#10x} {:<d}\".format(\n                    e, shmid, key, uid, gid, mode, segsz, nattch,\n                ))\n            else:\n                self.out.append(\"{:#018x} {:<5d} {:#010x} {:<4d} {:<4d} {:#5o} {:10s} {:s}\".format(\n                    e, shmid, key, uid, gid, mode, \"?\", \"?\",\n                ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"4.20\":\n            # xarray is introduced from 4.20\n            self.quiet_err(\"Unsupported before v4.20\")\n            return\n\n        ipc_ns_list = self.get_all_ipc_ns()\n        if not ipc_ns_list:\n            self.quiet_info(\"Nothing to dump\")\n            return\n\n        ret = self.initialize(ipc_ns_list)\n        if not ret:\n            self.quiet_err(\"Failed to initialize\")\n            return\n\n        self.out = []\n        for i, ipc_ns in enumerate(ipc_ns_list):\n            if i == 0:\n                self.out.append(titlify(\"init_ipc_ns: {:#x}\".format(ipc_ns)))\n            else:\n                self.out.append(titlify(\"ipc_ns: {:#x}\".format(ipc_ns)))\n            self.dump_ipc_sem_ids(ipc_ns + self.offset_ids + self.sizeof_ipc_ids * 0)\n            self.dump_ipc_msg_ids(ipc_ns + self.offset_ids + self.sizeof_ipc_ids * 1)\n            self.dump_ipc_shm_ids(ipc_ns + self.offset_ids + self.sizeof_ipc_ids * 2)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelDeviceIOCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump I/O-port and I/O-memory information.\"\"\"\n\n    _cmdline_ = \"kdevio\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified ioport structure:\",\n        \"\",\n        \"+-ioport_resource-+       +-------->+-resource--------+\",\n        \"| start           |       |         | start           |\",\n        \"| end             |       |         | end             |\",\n        \"| name            |       |         | name            |\",\n        \"| flags           |       |         | flags           |\",\n        \"| desc            |       |         | desc            |\",\n        \"| parent          |-------+         | parent          |\",\n        \"| sibling         |--> resource     | sibling         |\",\n        \"| child           |--> resource     | child           |\",\n        \"+-----------------+                 +-----------------+\",\n        \"\",\n        \"Simplified iomem structure:\",\n        \"\",\n        \"+-iomem_resource--+       +-------->+-resource--------+\",\n        \"| start           |       |         | start           |\",\n        \"| end             |       |         | end             |\",\n        \"| name            |       |         | name            |\",\n        \"| flags           |       |         | flags           |\",\n        \"| desc            |       |         | desc            |\",\n        \"| parent          |-------+         | parent          |\",\n        \"| sibling         |--> resource     | sibling         |\",\n        \"| child           |--> resource     | child           |\",\n        \"+-----------------+                 +-----------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def dump_resource(self, addr):\n        if not is_valid_addr(addr):\n            return []\n        if addr in self.seen:\n            return []\n        self.seen.append(addr)\n\n        if not hasattr(self, \"sizeof_resource_size_t\"):\n            name_ptr = read_int_from_memory(addr + 0x8 * 2) # sizeof(resource_size_t) == 8\n            if name_ptr and is_valid_addr(name_ptr):\n                name = read_cstring_from_memory(name_ptr)\n                if name in [\"PCI IO\", \"PCI mem\"]:\n                    self.sizeof_resource_size_t = 0x8\n\n        if not hasattr(self, \"sizeof_resource_size_t\"):\n            name_ptr = read_int_from_memory(addr + 0x4 * 2) # sizeof(resource_size_t) == 4\n            if name_ptr and is_valid_addr(name_ptr):\n                name = read_cstring_from_memory(name_ptr)\n                if name in [\"PCI IO\", \"PCI mem\"]:\n                    self.sizeof_resource_size_t = 0x4\n\n        if not hasattr(self, \"sizeof_resource_size_t\"):\n            err(\"Not recognized sizeof(resource_size_t)\")\n            return []\n\n        \"\"\"\n        struct resource {\n            resource_size_t start; // 4 or 8\n            resource_size_t end; // 4 or 8\n            const char *name;\n            unsigned long flags;\n            unsigned long desc; // v4.5~\n            struct resource *parent, *sibling, *child;\n        };\n        \"\"\"\n        if self.sizeof_resource_size_t == 8:\n            start = read_int64_from_memory(addr)\n            end = read_int64_from_memory(addr + 8)\n        elif self.sizeof_resource_size_t == 4:\n            start = read_int32_from_memory(addr)\n            end = read_int32_from_memory(addr + 4)\n        name = read_cstring_from_memory(read_int_from_memory(addr + self.sizeof_resource_size_t * 2))\n        flags = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize)\n\n        ret = [(addr, start, end, name, flags)]\n\n        kversion = Kernel.kernel_version()\n        if \"4.5\" <= kversion:\n            parent = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 3)\n            ret += self.dump_resource(parent)\n            sibling = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 4)\n            ret += self.dump_resource(sibling)\n            child = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 5)\n            ret += self.dump_resource(child)\n        else:\n            parent = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 2)\n            ret += self.dump_resource(parent)\n            sibling = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 3)\n            ret += self.dump_resource(sibling)\n            child = read_int_from_memory(addr + self.sizeof_resource_size_t * 2 + current_arch.ptrsize * 4)\n            ret += self.dump_resource(child)\n        return ret\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        self.out = []\n\n        # ioport\n        ioport_resource = KernelAddressHeuristicFinder.get_ioport_resource()\n        if not ioport_resource:\n            err(\"Could not find ioport_resource\")\n        else:\n            info(\"ioport_resource: {:#x}\".format(ioport_resource))\n\n            self.seen = []\n            resources = self.dump_resource(ioport_resource)\n            if resources:\n                name_width = max(len(res[3]) for res in resources)\n            else:\n                name_width = 4\n\n            self.out.append(titlify(\"I/O-port\"))\n            fmt = \"{:18s} {:17s} {:{:d}s} {:s}\"\n            legend = [\"resource\", \"I/O address\", \"name\", name_width, \"flags\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            for addr, start, end, name, flags in sorted(resources, key=lambda x: x[1]):\n                self.out.append(\"{:#018x} {:#08x}-{:#08x} {:{:d}s} {:#010x} ({:s})\".format(\n                    addr, start, end, name, name_width, flags, KernelPciDeviceCommand.get_flags_str(flags),\n                ))\n\n        # iomem\n        iomem_resource = KernelAddressHeuristicFinder.get_iomem_resource()\n        if not iomem_resource:\n            err(\"Could not find iomem_resource\")\n        else:\n            info(\"iomem_resource: {:#x}\".format(iomem_resource))\n\n            self.seen = []\n            resources = self.dump_resource(iomem_resource)\n            if resources:\n                name_width = max(len(res[3]) for res in resources)\n            else:\n                name_width = 4\n\n            self.out.append(titlify(\"I/O-memory\"))\n            fmt = \"{:18s} {:37s} {:{:d}s} {:s}\"\n            legend = [\"resource\", \"Physical address\", \"name\", name_width, \"flags\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            for addr, start, end, name, flags in sorted(resources, key=lambda x: x[1]):\n                self.out.append(\"{:#018x} {:#018x}-{:#018x} {:{:d}s} {:#010x} ({:s})\".format(\n                    addr, start, end, name, name_width, flags, KernelPciDeviceCommand.get_flags_str(flags),\n                ))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelDmaBufCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump DMA-BUF information.\"\"\"\n\n    _cmdline_ = \"kdmabuf\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified DMA-BUF structure:\",\n        \"\",\n        \"                 +-dma_buf-----+      +-dma_buf-----+\",\n        \"                 | size        |      | size        |\",\n        \"                 | file        |      | file        |\",\n        \"                 | ...         |      | ...         |\",\n        \"                 | exp_name    |      | exp_name    |\",\n        \"                 | name        |      | name        |\",\n        \"+---------+      | ...         |      | ...         |\",\n        \"| db_list |----->| list_node   |----->| list_node   |-->...\",\n        \"+---------+      | priv        |--+   | priv        |\",\n        \"                 | ...         |  |   | ...         |\",\n        \"                 +-------------+  |   +-------------+\",\n        \"                                  |\",\n        \"     +----------------------------+\",\n        \"     |\",\n        \"     +--->+-system_heap_buffer-+  +-->+-scatterlist--+\",\n        \"          | ...                |  |   | page_link    |----->+------+\",\n        \"          | len                |  |   | offset       |      | page |\",\n        \"          | sg_table           |  |   | length       |      +------+\",\n        \"          |   sgl              |--+   | ...          |\",\n        \"          |   ...              |      +--------------+\",\n        \"          | ...                |      | page_link    |-->page\",\n        \"          +--------------------+      | offset       |   or\",\n        \"                                      | length       |   scatterlist\",\n        \"                                      | ...          |\",\n        \"                                      +--------------+\",\n        \"                                      | ...          |\",\n        \"                                      +--------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        self.db_list = KernelAddressHeuristicFinder.get_db_list()\n        if self.db_list is None:\n            err(\"Could not find db_list (maybe DMA_SHARED_BUFFER=n)\")\n            return False\n        self.quiet_info(\"db_list: {:#x}\".format(self.db_list))\n\n        first_dma_buf = read_int_from_memory(self.db_list)\n        if first_dma_buf == self.db_list:\n            warn(\"Nothing to dump\")\n            return False\n\n        \"\"\"\n        struct dma_buf {\n            size_t size;\n            struct file *file;\n            struct list_head attachments;\n            const struct dma_buf_ops *ops;\n            struct mutex lock; // ~v6.2\n            unsigned vmapping_counter;\n            struct iosys_map {\n                union {\n                    void __iomem *vaddr_iomem;\n                    void *vaddr;\n                };\n                bool is_iomem;\n            } vmap_ptr;\n            const char *exp_name;\n            const char *name;\n            spinlock_t name_lock;\n            struct module *owner;\n            struct list_head list_node;\n            void *priv; <-- struct system_heap_buffer*\n            struct dma_resv *resv;\n            wait_queue_head_t poll;\n            ...\n        }\n\n        [v6.4 x64 example]\n        0xffff8880135f8a00|+0x0000|+000: 0x0000000000001000  // size\n        0xffff8880135f8a08|+0x0008|+001: 0xffff888000f85800  ->  0x0000000000000000 // file\n        0xffff8880135f8a10|+0x0010|+002: 0xffff8880135f8a10  ->  [loop detected] // attachments\n        0xffff8880135f8a18|+0x0018|+003: 0xffff8880135f8a10  ->  [loop detected]\n        0xffff8880135f8a20|+0x0020|+004: 0xffffffff83e79d00 <system_heap_buf_ops>  ->  0x0000000000000000 // ops\n        0xffff8880135f8a28|+0x0028|+005: 0x0000000000000000  // vmapping_counter\n        0xffff8880135f8a30|+0x0030|+006: 0x0000000000000000  // vmap_ptr.vaddr_iomem\n        0xffff8880135f8a38|+0x0038|+007: 0x0000000000000000  // vmap_ptr.is_iomem\n        0xffff8880135f8a40|+0x0040|+008: 0xffffffff8482754e <linux_banner+0x6d70ae>  ->  0x6e006d6574737973 ('system'?) // exp_name\n        0xffff8880135f8a48|+0x0048|+009: 0x0000000000000000  // name\n        0xffff8880135f8a50|+0x0050|+010: 0xdead4ead00000000  // name_lock\n        0xffff8880135f8a58|+0x0058|+011: 0x00000000ffffffff\n        0xffff8880135f8a60|+0x0060|+012: 0xffffffffffffffff\n        0xffff8880135f8a68|+0x0068|+013: 0xffffffff883cc330 <__key.7>  ->  0x0000000000000000\n        0xffff8880135f8a70|+0x0070|+014: 0x0000000000000000\n        0xffff8880135f8a78|+0x0078|+015: 0x0000000000000000\n        0xffff8880135f8a80|+0x0080|+016: 0xffffffff847790c3 <linux_banner+0x628c23>  ->  '&dmabuf->name_lock'\n        0xffff8880135f8a88|+0x0088|+017: 0x0000000000000200\n        0xffff8880135f8a90|+0x0090|+018: 0x0000000000000000  // owner\n        0xffff8880135f8a98|+0x0098|+019: 0xffff8880135f8c98  ->  0xffffffff883cc360 <db_list>  ->  [loop detected] // list_node\n        0xffff8880135f8aa0|+0x00a0|+020: 0xffffffff883cc360 <db_list>  ->  0xffff8880135f8a98  ->  0xffff8880135f8c98  ->  ...\n        0xffff8880135f8aa8|+0x00a8|+021: 0xffff88800f978600  ->  ... // priv\n        0xffff8880135f8ab0|+0x00b0|+022: 0xffff8880135f8b58  ->  0x0000000000000000\n        0xffff8880135f8ab8|+0x00b8|+023: 0xdead4ead00000000\n        0xffff8880135f8ac0|+0x00c0|+024: 0x00000000ffffffff\n        0xffff8880135f8ac8|+0x00c8|+025: 0xffffffffffffffff\n        \"\"\"\n        for i in range(1, 50):\n            a = read_int_from_memory(first_dma_buf - current_arch.ptrsize * (i + 4)) # size\n            b = read_int_from_memory(first_dma_buf - current_arch.ptrsize * (i + 3)) # file\n            c = read_int_from_memory(first_dma_buf - current_arch.ptrsize * (i + 2)) # attachments\n            e = read_int_from_memory(first_dma_buf - current_arch.ptrsize * (i + 0)) # ops\n\n            # size check\n            if a == 0 or (is_valid_addr(a) and AddressUtil.is_msb_on(a)):\n                continue\n            # file check\n            if not is_valid_addr(b):\n                continue\n            # attachments check\n            if not is_double_link_list(c):\n                continue\n            # ops check\n            if not is_valid_addr(e):\n                continue\n\n            self.offset_list_node = current_arch.ptrsize * (i + 4)\n            self.quiet_info(\"offsetof(dma_buf, list_node): {:#x}\".format(self.offset_list_node))\n            break\n        else:\n            err(\"Could not find dma_buf->list_node\")\n            return False\n\n        # dma_buf->{size,file,priv}\n        self.offset_size = 0\n        self.offset_file = current_arch.ptrsize\n        self.offset_priv = self.offset_list_node + current_arch.ptrsize * 2\n        self.quiet_info(\"offsetof(dma_buf, size): {:#x}\".format(self.offset_size))\n        self.quiet_info(\"offsetof(dma_buf, file): {:#x}\".format(self.offset_file))\n        self.quiet_info(\"offsetof(dma_buf, priv): {:#x}\".format(self.offset_priv))\n\n        # dma_buf->{exp_name,name}\n        for i in range(1, 50):\n            top = first_dma_buf - self.offset_list_node\n            x = read_int_from_memory(top + current_arch.ptrsize * i)\n            s = read_cstring_from_memory(x)\n            if s and len(s) >= 3:\n                self.offset_exp_name = current_arch.ptrsize * i\n                self.offset_name = current_arch.ptrsize * (i + 1)\n                self.quiet_info(\"offsetof(dma_buf, exp_name): {:#x}\".format(self.offset_exp_name))\n                self.quiet_info(\"offsetof(dma_buf, name): {:#x}\".format(self.offset_name))\n                break\n        else:\n            err(\"Could not find dma_buf->{exp_name,name}\")\n            return False\n\n        \"\"\"\n        struct system_heap_buffer {\n            struct dma_heap *heap;\n            struct list_head attachments;\n            struct mutex lock;\n            unsigned long len;\n            struct sg_table {\n                struct scatterlist *sgl;\n                unsigned int nents;\n                unsigned int orig_nents;\n            } sg_table;\n            int vmap_cnt;\n            void *vaddr;\n        };\n        \"\"\"\n        # system_heap_buffer->sg_table\n        size = read_int_from_memory(first_dma_buf - self.offset_list_node + self.offset_size)\n        priv = read_int_from_memory(first_dma_buf - self.offset_list_node + self.offset_priv)\n        for i in range(50):\n            x = read_int_from_memory(priv + current_arch.ptrsize * i)\n            if x == size:\n                self.offset_sg_table = current_arch.ptrsize * (i + 1)\n                break\n        else:\n            err(\"Could not find system_heap_buffer->sg_table\")\n            return False\n        self.quiet_info(\"offsetof(system_heap_buffer, sg_table): {:#x}\".format(self.offset_sg_table))\n        return True\n\n    def dump_sgl(self, sg):\n        while True:\n            page_link = read_int_from_memory(sg)\n\n            # check if chain\n            if page_link & 1: # SG_CHAIN\n                sg = page_link & ~3\n                continue\n\n            # output page, phys, virt\n            page = page_link & ~3\n\n            phys = None\n            phys_str = \"???\"\n            ret = gdb.execute(\"page2phys {:#x}\".format(page), to_string=True)\n            r = re.search(r\"Page: \\S+ -> Phys: (\\S+)\", ret)\n            if r:\n                phys = int(r.group(1), 16)\n                phys_str = \"{:#018x}\".format(phys)\n\n            virt_str = \"???\"\n            if phys:\n                r = Kernel.p2v(phys)\n                if r:\n                    r = [hex(x) for x in r if AddressUtil.is_msb_on(x)]\n                    virt_str = \",\".join(r)\n\n            offset = read_int32_from_memory(sg + current_arch.ptrsize)\n            length = read_int32_from_memory(sg + current_arch.ptrsize + 4)\n\n            self.out.append(\"  page: {:#018x}  offset: {:#010x}  length: {:#010x}  phys: {:18s}  virt: {:s}\".format(\n                page, offset, length, phys_str, virt_str,\n            ))\n\n            # check if end\n            if page_link & 2: # SG_END:\n                break\n\n            # calc sizeof(scatterlist) then go to next\n            \"\"\"\n            struct scatterlist {\n                unsigned long page_link;\n                unsigned int offset;\n                unsigned int length;\n                dma_addr_t dma_address;\n            #ifdef CONFIG_NEED_SG_DMA_LENGTH\n                unsigned int dma_length;\n            #endif\n            #ifdef CONFIG_PCI_P2PDMA\n                unsigned int dma_flags;\n            #endif\n            };\n            \"\"\"\n            sg += current_arch.ptrsize + 4 * 2 + current_arch.ptrsize\n            if not is_valid_addr(read_int_from_memory(sg)):\n                sg += current_arch.ptrsize\n            if not is_valid_addr(read_int_from_memory(sg)):\n                sg += current_arch.ptrsize\n        return\n\n    def dump_db_list(self):\n        fmt = \"{:18s} {:18s} {:16s} {:16s} {:18s} {:18s}\"\n        legend = [\"dma_buf\", \"size\", \"exp_name\", \"name\", \"file\", \"priv\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        seen = [self.db_list]\n        current = read_int_from_memory(self.db_list)\n        while True:\n            if not is_valid_addr(current):\n                break\n            if current in seen:\n                break\n            seen.append(current)\n\n            # calc top\n            dma_buf = current - self.offset_list_node\n\n            # size, file, priv\n            size = read_int_from_memory(dma_buf + self.offset_size)\n            file = read_int_from_memory(dma_buf + self.offset_file)\n            priv = read_int_from_memory(dma_buf + self.offset_priv)\n\n            # exp_name\n            exp_name_p = read_int_from_memory(dma_buf + self.offset_exp_name)\n            exp_name = read_cstring_from_memory(exp_name_p)\n\n            # name\n            name_p = read_int_from_memory(dma_buf + self.offset_name)\n            if is_valid_addr(name_p):\n                name = read_cstring_from_memory(name_p)\n            else:\n                name = \"<none>\"\n\n            # dump\n            self.out.append(\"{:#018x} {:#018x} {:16s} {:16s} {:#018x} {:#018x}\".format(\n                dma_buf, size, exp_name, name, file, priv,\n            ))\n\n            # dump sgl\n            sgl = read_int_from_memory(priv + self.offset_sg_table)\n            self.dump_sgl(sgl)\n\n            # go to next\n            current = read_int_from_memory(current)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"5.11\":\n            err(\"Unsupported before v5.11\")\n            return\n\n        ret = gdb.execute(\"ksymaddr-remote --quiet --no-pager dma_heap\", to_string=True)\n        if not ret:\n            err(\"This kernel does not support DMA-BUF\")\n            return\n\n        ret = self.initialize()\n        if ret is False:\n            return\n\n        self.out = []\n        self.dump_db_list()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelIrqCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump IRQ (interrupt request) information.\"\"\"\n\n    _cmdline_ = \"kirq\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified irq structure:\",\n        \"\",\n        \"+-irq_desc_tree(~6.5)-+   +--->+-xa_node---------+   +--->+-irq_desc----+\",\n        \"| xa_lock             |   |    | shift           |   |    | ...         |\",\n        \"| xa_flags            |   |    | ...             |   |    | irq_data    |\",\n        \"| xa_head             |---+    | count           |   |    |   ...       |\",\n        \"+---------------------+        | ...             |   |    |   irq       |\",\n        \"                               | slots[0]        |---+    |   ...       |\",\n        \"                               | slots[1]        |   ^    | ...         |\",\n        \"                               | ...             |   |    | action      |\",\n        \"                               | slots[15 or 63] |   |    |   handler   |\",\n        \"                               | ...             |   |    |   ...       |\",\n        \"                               +-----------------+   |    |   name      |\",\n        \"                                                     |    |   ...       |\",\n        \"+-sparce_irq(6.5~)-+   +-->+-maple_node------+       |    | ...         |\",\n        \"| ...              |   |   | ...             |       |    +-------------+\",\n        \"| ma_root          |---+   | mr64|ma64|alloc |       |\",\n        \"| ...              |       |   ...           |       |\",\n        \"+------------------+       |   slot[]        |-------+\",\n        \"                           +-----------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def parse_xarray(self, ptr, root=False):\n        if ptr == 0:\n            return []\n\n        ptr &= ~3 # untagged\n\n        if root:\n            node = read_int_from_memory(ptr + self.offset_xa_head)\n            return self.parse_xarray(node)\n\n        shift = read_int8_from_memory(ptr + self.offset_shift)\n        count = read_int8_from_memory(ptr + self.offset_count)\n        slots = ptr + self.offset_slots\n        elems = []\n        for i in range(64): # 16 or 64\n            x = read_int_from_memory(slots + current_arch.ptrsize * i)\n            if x == 0:\n                continue\n            if shift:\n                elems += self.parse_xarray(x)\n            else:\n                elems.append(x)\n            count -= 1\n            if count == 0:\n                break\n        return elems\n\n    class MapleTree:\n        \"\"\"Linux v6.5 introduces maple_tree to irq. This is a simple parser.\"\"\"\n        MT_FLAGS_HEIGHT_MASK = 0x7c\n        MT_FLAGS_HEIGHT_OFFSET = 0x02\n        MAPLE_NODE_TYPE_SHIFT = 0x03\n        MAPLE_NODE_TYPE_MASK = 0x0f\n        MAPLE_NODE_POINTER_MASK = 0xff\n        MAPLE_DENSE = 0\n        MAPLE_LEAF_64 = 1\n        MAPLE_RANGE_64 = 2\n        MAPLE_ARANGE_64 = 3\n\n        def __init__(self, ptr):\n            kversion = Kernel.kernel_version()\n\n            # ____cacheline_aligned_in_smp attribute, spinlock_t and lockdep_map_p can be different size\n            # in each environment or situation, so search heuristically.\n            for i in range(0x10):\n                x = read_int_from_memory(ptr + current_arch.ptrsize * i)\n                \"\"\"\n                [x64 v6.4.2]\n                0xffff8bedc104db00|+0x0000|+000: 0x0000000000000000   // union\n                0xffff8bedc104db08|+0x0008|+001: 0xffff8bedc1a6601e   // ma_root\n                0xffff8bedc104db10|+0x0010|+002: 0x000000000000030b   // ma_flags\n\n                [x64 v6.6.1]\n                0xffff972801b78a38|+0x0040|+008: 0x0000000000000000   // (the end of cacheline?)\n                0xffff972801b78a40|+0x0040|+008: 0x0000030b00000000   // ma_flags || union\n                0xffff972801b78a48|+0x0048|+009: 0xffff972801b0cc1e   // ma_root\n                \"\"\"\n                if is_valid_addr(x) and (x & 0xff) in [0x1e, 0x0e]:\n                    offset_ma_root = current_arch.ptrsize * i\n                    if kversion < \"6.6\":\n                        offset_ma_flags = offset_ma_root + current_arch.ptrsize\n                    else:\n                        offset_ma_flags = offset_ma_root - 4\n                        if is_64bit() and read_int32_from_memory(ptr + offset_ma_flags) == 0:\n                            offset_ma_flags = offset_ma_root - 8\n                    break\n            else:\n                raise\n\n            self.ma_root_raw = read_int_from_memory(ptr + offset_ma_root)\n            self.ma_flags = read_int_from_memory(ptr + offset_ma_flags)\n            self.max_depth = (self.ma_flags & self.MT_FLAGS_HEIGHT_MASK) >> self.MT_FLAGS_HEIGHT_OFFSET\n\n            if is_64bit():\n                self.MAPLE_NODE_SLOTS = 31\n                self.MAPLE_RANGE64_SLOTS = 16\n                self.MAPLE_ARANGE64_SLOTS = 10\n                self.MAPLE_ALLOC_SLOTS = self.MAPLE_NODE_SLOTS - 1\n                self.maple_range_64_offset_slot = current_arch.ptrsize * self.MAPLE_RANGE64_SLOTS\n                self.maple_arange_64_offset_slot = current_arch.ptrsize * self.MAPLE_ARANGE64_SLOTS\n                self.maple_alloc_offset_slot = current_arch.ptrsize * 2\n            else:\n                self.MAPLE_NODE_SLOTS = 63\n                self.MAPLE_RANGE64_SLOTS = 32\n                self.MAPLE_ARANGE64_SLOTS = 21\n                self.MAPLE_ALLOC_SLOTS = self.MAPLE_NODE_SLOTS - 2\n                self.maple_range_64_offset_slot = current_arch.ptrsize * self.MAPLE_RANGE64_SLOTS\n                self.maple_arange_64_offset_slot = current_arch.ptrsize * self.MAPLE_ARANGE64_SLOTS\n                self.maple_alloc_offset_slot = current_arch.ptrsize * 3\n\n            self.seen = set()\n            self.iters = self.parse_node(self.ma_root_raw, 1)\n            return\n\n        def parse_node(self, entry, depth):\n            if entry in self.seen:\n                return\n            self.seen.add(entry)\n\n            if self.max_depth < depth:\n                return\n\n            pointer = entry & ~(self.MAPLE_NODE_POINTER_MASK)\n            node_type = (entry >> self.MAPLE_NODE_TYPE_SHIFT) & self.MAPLE_NODE_TYPE_MASK\n\n            if node_type == self.MAPLE_DENSE:\n                slot_top = pointer + self.maple_alloc_offset_slot\n                for i in range(self.MAPLE_ALLOC_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        if is_valid_addr(slot):\n                            yield slot\n            elif node_type == self.MAPLE_LEAF_64:\n                slot_top = pointer + self.maple_range_64_offset_slot\n                for i in range(self.MAPLE_RANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        if is_valid_addr(slot):\n                            yield slot\n            elif node_type == self.MAPLE_RANGE_64:\n                slot_top = pointer + self.maple_range_64_offset_slot\n                for i in range(self.MAPLE_RANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        yield from self.parse_node(slot, depth + 1)\n            elif node_type == self.MAPLE_ARANGE_64:\n                slot_top = pointer + self.maple_arange_64_offset_slot\n                for i in range(self.MAPLE_ARANGE64_SLOTS):\n                    slot = read_int_from_memory(slot_top + current_arch.ptrsize * i)\n                    if (slot & ~(self.MAPLE_NODE_TYPE_MASK)) != 0:\n                        yield from self.parse_node(slot, depth + 1)\n            return\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        kversion = Kernel.kernel_version()\n\n        if kversion < \"6.5\":\n            self.irq_desc_tree = KernelAddressHeuristicFinder.get_irq_desc_tree()\n            if self.irq_desc_tree is None:\n                self.quiet_err(\"Could not find irq_desc_tree\")\n                return False\n\n            for i in range(0, 10):\n                # xa_head\n                x = read_int_from_memory(self.irq_desc_tree + current_arch.ptrsize * i)\n                if not x:\n                    continue\n                if not is_valid_addr(x):\n                    continue\n                if x & 0x2 != 0x2: # xa_head is NULL or tagged address\n                    continue\n                self.offset_xa_head = current_arch.ptrsize * i\n                self.quiet_info(\"offsetof(xarray, xa_head): {:#x}\".format(self.offset_xa_head))\n                break\n            else:\n                self.quiet_err(\"Could not find xa_head. (maybe uninitialized?)\")\n                return False\n\n            # xa_node\n            \"\"\"\n            struct xa_node {\n                unsigned char shift;\n                unsigned char offset;\n                unsigned char count;\n                unsigned char nr_values;\n                struct xa_node __rcu *parent;\n                struct xarray *array;\n                union {\n                    struct list_head private_list;\n                    struct rcu_head rcu_head;\n                };\n                void __rcu *slots[XA_CHUNK_SIZE];\n                union {\n                    unsigned long tags[XA_MAX_MARKS][XA_MARK_LONGS];\n                    unsigned long marks[XA_MAX_MARKS][XA_MARK_LONGS];\n                };\n            };\n            \"\"\"\n            # xa_node->{shift,count,slots}\n            self.offset_shift = 0\n            self.offset_count = 2\n            self.offset_slots = current_arch.ptrsize * 5\n\n            descs = self.parse_xarray(self.irq_desc_tree, root=True)\n\n        else:\n            # \"6.5\" <= kversion\n            self.sparse_irqs = KernelAddressHeuristicFinder.get_sparse_irqs()\n            if self.sparse_irqs is None:\n                self.quiet_err(\"Could not find sparse_irqs\")\n                return False\n\n            descs = list(self.MapleTree(self.sparse_irqs).iters)\n\n        if not descs:\n            self.quiet_err(\"Could not find any valid irq_desc\")\n            return False\n\n        # irq_desc->{irq,action}\n        \"\"\"\n        struct irq_desc {\n            struct irq_common_data {\n                unsigned int __private state_use_accessors;\n            #ifdef CONFIG_NUMA\n                unsigned int node;\n            #endif\n                void *handler_data;\n                struct msi_desc *msi_desc;\n            #ifdef CONFIG_SMP\n                cpumask_var_t affinity;\n            #endif\n            #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK\n                cpumask_var_t effective_affinity;\n            #endif\n            #ifdef CONFIG_GENERIC_IRQ_IPI\n                unsigned int ipi_offset;\n            #endif\n            } irq_common_data;\n            struct irq_data {\n                u32 mask;\n                unsigned int irq;\n                unsigned long hwirq;\n                struct irq_common_data *common;\n                struct irq_chip *chip;\n                struct irq_domain *domain;\n            #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY\n                struct irq_data *parent_data;\n            #endif\n                void *chip_data;\n            } irq_data;\n            unsigned int __percpu *kstat_irqs;\n            irq_flow_handler_t handle_irq;\n            struct irqaction *action;\n            unsigned int status_use_accessors;\n            unsigned int core_internal_state__do_not_mess_with_it;\n            ...\n        };\n        \"\"\"\n\n        if is_x86():\n            desc = descs[0]\n        else:\n            # ARM may have invalid descs[irq=0]\n            desc = descs[-1]\n        self.quiet_info(\"desc: {:#x}\".format(desc))\n\n        for i in range(100):\n            x = read_int_from_memory(desc + current_arch.ptrsize * i)\n            if x == desc:\n                if is_32bit():\n                    self.offset_irq = current_arch.ptrsize * i - 8\n                else:\n                    self.offset_irq = current_arch.ptrsize * i - 12 # for padding\n                self.quiet_info(\"offsetof(irq_desc, irq_data.irq): {:#x}\".format(self.offset_irq))\n                break\n        else:\n            self.quiet_err(\"Could not find irq_desc->irq_data.irq\")\n            return False\n\n        ofs_irq = align_to_ptrsize(self.offset_irq + 4 * 2)\n        for i in range(100):\n            x = read_int_from_memory(desc + ofs_irq + current_arch.ptrsize * i)\n            y = read_int_from_memory(desc + ofs_irq + current_arch.ptrsize * (i + 1))\n            if not is_valid_addr(x) and not is_valid_addr(y):\n                ofs_action_candidate = ofs_irq + current_arch.ptrsize * i - current_arch.ptrsize\n                action_candidate = read_int_from_memory(desc + ofs_action_candidate)\n                if is_valid_addr_addr(action_candidate):\n                    self.offset_action = ofs_action_candidate\n                    self.quiet_info(\"offsetof(irq_desc, action): {:#x}\".format(self.offset_action))\n                    break\n        else:\n            self.quiet_err(\"Could not find irq_desc->action\")\n            return False\n\n        # irqaction->{handler,name}\n        \"\"\"\n        struct irqaction {\n            irq_handler_t handler;\n            void *dev_id;\n            void __percpu *percpu_dev_id;\n            struct irqaction *next;\n            irq_handler_t thread_fn;\n            struct task_struct *thread;\n            struct irqaction *secondary;\n            unsigned int irq;\n            unsigned int flags;\n            unsigned long thread_flags;\n            unsigned long thread_mask;\n            const char *name;\n            struct proc_dir_entry *dir;\n        } ____cacheline_internodealigned_in_smp;\n        \"\"\"\n        self.offset_handler = 0\n        self.quiet_info(\"offsetof(irqaction, handler): {:#x}\".format(self.offset_handler))\n\n        action = read_int_from_memory(desc + self.offset_action)\n        for i in range(100):\n            x = read_int_from_memory(action + current_arch.ptrsize * i)\n            if not is_valid_addr(x):\n                continue\n            s = read_cstring_from_memory(x)\n            if s and len(s) >= 4:\n                self.offset_name = current_arch.ptrsize * i\n                self.quiet_info(\"offsetof(irqaction, name): {:#x}\".format(self.offset_name))\n                break\n        else:\n            self.quiet_err(\"Could not find irqaction->name\")\n            return False\n\n        return True\n\n    def dump_irq(self):\n        kversion = Kernel.kernel_version()\n\n        if kversion < \"6.5\":\n            descs = self.parse_xarray(self.irq_desc_tree, root=True)\n        else:\n            descs = list(self.MapleTree(self.sparse_irqs).iters)\n\n        entries = {}\n        for desc in descs:\n            irq = read_int32_from_memory(desc + self.offset_irq)\n            action = read_int_from_memory(desc + self.offset_action)\n            if action == 0:\n                entries[irq] = [desc, action, None, None]\n            else:\n                handler = read_int_from_memory(action + self.offset_handler)\n                name_ptr = read_int_from_memory(action + self.offset_name)\n                name = read_cstring_from_memory(name_ptr) or \"???\"\n                entries[irq] = [desc, action, handler, name]\n\n        fmt = \"{:3s} {:18s} {:18s} {:24s} {:18s}\"\n        legend = [\"irq\", \"irq_desc\", \"action\", \"name\", \"handler\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for i in range(256):\n            if i in entries:\n                desc, action, handler, name = entries[i]\n                if action:\n                    symbol = Symbol.get_symbol_string(handler, nosymbol_string=\" <NO_SYMBOL>\")\n                    self.out.append(\"{:3d} {:#018x} {:#018x} {:24s} {:#018x}{:s}\".format(\n                        i, desc, action, name, handler, symbol,\n                    ).rstrip())\n                else:\n                    self.out.append(\"{:3d} {:#018x} {:18s} {:24s} {:18s}\".format(\n                        i, desc, \"unused\", \"-\", \"-\",\n                    ).rstrip())\n            else:\n                if self.args.verbose:\n                    self.out.append(\"{:3d} {:18s} {:18s} {:24s} {:18s}\".format(\n                        i, \"unused\", \"unused\", \"-\", \"-\",\n                    ).rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion is None:\n            err(\"Could not find Linux kernel\")\n            return\n        if kversion < \"4.20\":\n            # xarray is introduced from 4.20\n            self.quiet_err(\"Unsupported before v4.20\")\n            return\n\n        ret = self.initialize()\n        if ret is False:\n            return\n\n        self.out = []\n        self.dump_irq()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KernelNetDeviceCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump net device information.\"\"\"\n\n    _cmdline_ = \"knetdev\"\n    _category_ = \"06-g. Qemu-system/KGDB Cooperation - Linux Advanced\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified net_device structure:\",\n        \"\",\n        \"                     +-net_device--------+    +-net_device--------+\",\n        \"                     | ... (v6.8~)       |    | ... (v6.8~)       |\",\n        \"+-init_net------+    | name[]            |    | name[]            |\",\n        \"| ...           |    | ...               |    | ...               |\",\n        \"| dev_base_head |--->| dev_list          |--->| dev_list          |--->...\",\n        \"| ...           |    | ...               |    | ...               |\",\n        \"+---------------+    +-------------------+    +-------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # init_net\n        self.init_net = KernelAddressHeuristicFinder.get_init_net()\n        if self.init_net is None:\n            self.quiet_err(\"Could not find init_net\")\n            return False\n        self.quiet_info(\"init_net: {:#x}\".format(self.init_net))\n\n        \"\"\"\n        struct net {\n            ...\n            struct list_head dev_base_head;\n            ...\n        };\n\n        struct net_device {\n            char name[IFNAMSIZ];\n            ...\n            struct list_head dev_list;  // dev_base_head points here\n            struct list_head napi_list;\n            struct list_head unreg_list;\n            struct list_head close_list;\n            struct list_head ptype_all;\n            struct list_head ptype_specific; // ~v6.7\n            ...\n        };\n        \"\"\"\n        # net->dev_base_head\n        for i in range(0x100):\n            candidate_offset = current_arch.ptrsize * i\n\n            addr = self.init_net + candidate_offset\n            if not is_double_link_list(addr):\n                continue\n\n            cand_netdev = read_int_from_memory(addr)\n            if not is_double_link_list(cand_netdev + current_arch.ptrsize * 2): # napi_list\n                continue\n            if not is_double_link_list(cand_netdev + current_arch.ptrsize * 4): # unreg_list\n                continue\n            if not is_double_link_list(cand_netdev + current_arch.ptrsize * 6): # close_list\n                continue\n            if not is_double_link_list(cand_netdev + current_arch.ptrsize * 8): # ptype_all\n                continue\n            break # found\n        else:\n            self.quiet_err(\"Could not find net->dev_base_head\")\n            return False\n\n        self.offset_dev_base_head = candidate_offset\n        self.quiet_info(\"offsetof(net, dev_base_head): {:#x}\".format(self.offset_dev_base_head))\n\n        # net_device->dev_list\n        netdev_dev_list = read_int_from_memory(self.init_net + self.offset_dev_base_head)\n        for i in range(0x20):\n            candidate_offset = current_arch.ptrsize * i\n            if read_cstring_from_memory(netdev_dev_list - candidate_offset) == \"lo\":\n                break\n        else:\n            self.quiet_err(\"Could not find net_device->dev_list\")\n            return False\n\n        self.offset_dev_list = candidate_offset\n        self.quiet_info(\"offsetof(net_device, dev_list): {:#x}\".format(self.offset_dev_list))\n\n        return True\n\n    def dump_net(self):\n        fmt = \"{:18s} {:s}\"\n        legend = [\"net_device\", \"name\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # `struct net_device` is a very complex struct, and detecting the offset of its members is very difficult.\n        # My best effort is to detect only names and addresses.\n\n        head = current = self.init_net + self.offset_dev_base_head\n        while True:\n            current = read_int_from_memory(current)\n            if current == head:\n                break\n\n            netdev = current - self.offset_dev_list\n            name = read_cstring_from_memory(netdev)\n            self.out.append(\"{:#018x} {:s}\".format(netdev, name))\n\n        kversion = Kernel.kernel_version()\n        if \"6.8\" <= kversion:\n            info(\"In kernel 6.8 and later, the order of the members of `struct net_device` has changed significantly\")\n            info(\"Please note that the address detected as `net_device` is precisely the address of &net_device.name\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        ret = self.initialize()\n        if ret is False:\n            return\n\n        self.out = []\n        self.dump_net()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass VmallocDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump vmalloc used list and freed list.\"\"\"\n\n    _cmdline_ = \"vmalloc-dump\"\n    _category_ = \"06-h. Qemu-system/KGDB Cooperation - Linux Allocator\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"--only-used\", action=\"store_true\", help=\"display only used area.\")\n    parser.add_argument(\"--only-freed\", action=\"store_true\", help=\"display only freed area.\")\n    parser.add_argument(\"--meta\", action=\"store_true\", help=\"display offset information.\")\n    parser.add_argument(\"--hexdump-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"hexdump `used chunks` if layout is resolved.\")\n    parser.add_argument(\"--telescope-used\", metavar=\"SIZE\", type=lambda x: int(x, 16), default=0,\n                        help=\"telescope `used chunks` if layout is resolved.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -q\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified vmalloc structure:\"\n        \"\",\n        \"                           +-vmap_area--+\",\n        \"                           | va_start   |\",\n        \"(~v6.8)                    | va_end     |\",\n        \"+---------------------+    | ...        |\",\n        \"| vmap_area_list      |--->| list       |--->...\",\n        \"+---------------------+    | ...        |\",\n        \"                           | vm         |---->+-vm_struct--+\",\n        \"                           | ...        |     | ...        |\",\n        \"                           +------------+     | flags      |\",\n        \"                                              | ...        |\",\n        \"                                              +------------+\",\n        \"                           +-vmap_area--+\",\n        \"                           | va_start   |\",\n        \"(v5.2~)                    | va_end     |\",\n        \"+---------------------+    | ...        |\",\n        \"| free_vmap_area_list |--->| list       |--->...\",\n        \"+---------------------+    | ...        |\",\n        \"                           +------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            if not self.args.meta and not self.args.rescan:\n                return True\n\n        \"\"\"\n        struct vmap_area {\n            unsigned long va_start;\n            unsigned long va_end;\n            unsigned long subtree_max_size; // v5.2.0~v5.2.21\n            unsigned long flags;            // ~v5.3\n            struct rb_node {\n                unsigned long __rb_parent_color;\n                struct rb_node *rb_right;\n                struct rb_node *rb_left;\n            } rb_node;\n            struct list_head list;\n            union {                             // v5.4~\n                unsigned long subtree_max_size; // v5.4~\n                struct vm_struct *vm;           // v5.4~\n                struct llist_node purge_list;   // v5.4~v5.10\n            };                                  // v5.4~\n            struct llist_node purge_list; // v4.7~v5.3\n            struct list_head purge_list;  // ~v4.7\n            struct vm_struct *vm;         // ~v5.3\n            unsigned long flags; // v6.3~\n        };\n\n        struct vm_struct {\n            struct vm_struct *next;\n            void *addr;\n            unsigned long size;\n            unsigned long flags;\n            struct page **pages;\n        #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC // v5.13~\n            unsigned int page_order;         // v5.13~\n        #endif                               // v5.13~\n            unsigned int nr_pages;\n            phys_addr_t phys_addr;\n            const void *caller;\n            unsigned long requested_size; // v6.12~\n        };\n        \"\"\"\n\n        kversion = Kernel.kernel_version()\n\n        if kversion and kversion < \"6.9\":\n            self.vmap_area_list = KernelAddressHeuristicFinder.get_vmap_area_list()\n            if not self.vmap_area_list:\n                self.quiet_err(\"Could not find vmap_area_list\")\n            else:\n                self.quiet_info(\"vmap_area_list: {:#x}\".format(self.vmap_area_list))\n        else:\n            self.vmap_area_list = None\n\n        if kversion and \"5.2\" <= kversion:\n            self.free_vmap_area_list = KernelAddressHeuristicFinder.get_free_vmap_area_list()\n            if not self.free_vmap_area_list:\n                self.quiet_err(\"Could not find free_vmap_area_list\")\n            else:\n                self.quiet_info(\"free_vmap_area_list: {:#x}\".format(self.free_vmap_area_list))\n        else:\n            self.free_vmap_area_list = None\n\n        if not self.vmap_area_list and not self.free_vmap_area_list:\n            return False\n\n        # vmap_area->list\n        if kversion and \"5.4\" <= kversion:\n            self.offset_list = current_arch.ptrsize * 5\n        elif kversion and \"5.2\" <= kversion:\n            self.offset_list = current_arch.ptrsize * 7\n        else:\n            self.offset_list = current_arch.ptrsize * 6\n        self.quiet_info(\"offsetof(vmap_area, list): {:#x}\".format(self.offset_list))\n\n        # vmap_area->vm\n        if kversion and \"5.4\" <= kversion:\n            self.offset_vm = self.offset_list + current_arch.ptrsize * 2\n        elif kversion and \"4.7\" <= kversion:\n            self.offset_vm = self.offset_list + current_arch.ptrsize * 3\n        else:\n            self.offset_vm = self.offset_list + current_arch.ptrsize * 4\n        self.quiet_info(\"offsetof(vmap_area, vm): {:#x}\".format(self.offset_vm))\n\n        # vm_struct->flags\n        self.offset_flags = current_arch.ptrsize * 3\n        self.quiet_info(\"offsetof(vm_struct, flags): {:#x}\".format(self.offset_flags))\n\n        self.initialized = True\n        return True\n\n    def parse_vmap_area_list(self, head, used):\n        if head is None or not is_valid_addr(head):\n            return []\n\n        seen = [head]\n        current = read_int_from_memory(head)\n        idx = 0\n        areas = []\n        while True:\n            if current in seen:\n                break\n            seen.append(current)\n\n            vmap_area = current - self.offset_list\n            va_start = read_int_from_memory(vmap_area)\n            va_end = read_int_from_memory(vmap_area + current_arch.ptrsize)\n            va_size = va_end - va_start\n\n            flags = None\n            if used:\n                vm = read_int_from_memory(vmap_area + self.offset_vm)\n                if is_valid_addr(vm):\n                    flags = read_int_from_memory(vm + self.offset_flags)\n                else:\n                    flags = 0\n            areas.append([used, va_start, va_end, va_size, flags])\n\n            try:\n                current = read_int_from_memory(current)\n            except gdb.MemoryError:\n                break\n\n            idx += 1\n        return areas\n\n    def get_flags(self, flags_value):\n        flags_dic = {\n            0x00000001: \"VM_IOREMAP\",\n            0x00000002: \"VM_ALLOC\",\n            0x00000004: \"VM_MAP\",\n            0x00000008: \"VM_USERMAP\",\n            0x00000010: \"VM_DMA_COHERENT\",\n            0x00000020: \"VM_UNINITIALIZED\",\n            0x00000040: \"VM_NO_GUARD\",\n            0x00000080: \"VM_KASAN\",\n            0x00000100: \"VM_FLUSH_RESET_PERMS\",\n            0x00000200: \"VM_MAP_PUT_PAGES\",\n        }\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n        return \"|\".join(flags)\n\n    def dump_areas(self, areas):\n        fmt = \"{:4s} {:6s} {:37s} {:18s} {:s}\"\n        legend = [\"#\", \"state\", \"virtual address\", \"size\", \"flags\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        for idx, (used, va_start, va_end, va_size, flags) in enumerate(areas):\n            size_str = \"{:<#18x}\".format(va_size)\n            size_str = Color.colorify(size_str, chunk_size_color)\n            virt_str = \"{:#018x}-{:#018x}\".format(va_start, va_end)\n            if used:\n                virt_str = Color.colorify(virt_str, used_address_color)\n                state = \"in-use\"\n                flags_str = self.get_flags(flags)\n                flags_str = flags_str.rstrip()\n                if not flags_str:\n                    flags_str = \"-\"\n            else:\n                virt_str = Color.colorify(virt_str, freed_address_color)\n                state = \"freed\"\n                flags_str = \"-\"\n            self.out.append(\"{:<4d} {:6s} {:s} {:s} {:s}\".format(idx, state, virt_str, size_str, flags_str))\n\n            # dump chunks\n            if self.args.hexdump_used and used:\n                try:\n                    peeked_data = read_memory(va_start, self.args.hexdump_used)\n                    h = hexdump(peeked_data, 0x10, base=va_start, unit=current_arch.ptrsize)\n                    self.out.append(h)\n                except Exception:\n                    pass\n\n            if self.args.telescope_used and used:\n                n = self.args.telescope_used // current_arch.ptrsize\n                for i in range(n):\n                    try:\n                        line = DereferenceCommand.pprint_dereferenced(va_start, i)\n                        self.out.append(line)\n                    except Exception:\n                        pass\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        ret = self.initialize()\n        if ret is False:\n            return\n\n        if self.args.meta:\n            return\n\n        self.out = []\n        areas = []\n\n        kversion = Kernel.kernel_version()\n\n        # parse used list\n        if not args.only_freed:\n            if kversion and kversion < \"6.9\":\n                areas += self.parse_vmap_area_list(self.vmap_area_list, used=True)\n\n        # parse freed list\n        if not args.only_used:\n            if kversion and \"5.2\" <= kversion:\n                areas += self.parse_vmap_area_list(self.free_vmap_area_list, used=False)\n\n        areas = sorted(areas, key=lambda x:x[1])\n        self.dump_areas(areas)\n\n        self.print_output()\n        return\n\n\n@register_command\nclass KtypesCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display kernel type information from /sys/kernel/btf/vmlinux.\"\"\"\n\n    _cmdline_ = \"ktypes\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command requires CONFIG_DEBUG_INFO_BTF=y.\",\n        \"CONFIG_KALLSYMS_ALL=y is not required.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def check_command(self):\n        try:\n            GefUtil.which(\"bpftool\")\n            if is_x86():\n                GefUtil.which(\"gcc\")\n            elif is_arm64():\n                GefUtil.which(\"aarch64-linux-gnu-gcc\")\n            elif is_arm32():\n                GefUtil.which(\"arm-linux-gnueabihf-gcc\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return False\n        return True\n\n    def get_base_name(self):\n        if not hasattr(__gef_command_instances__[\"ksymaddr-remote\"], \"kernel_version\"):\n            gdb.execute(\"ksymaddr-remote --no-pager GEF_DUMMY_STRING\", to_string=True)\n            if not hasattr(__gef_command_instances__[\"ksymaddr-remote\"], \"kernel_version\"):\n                err(\"Could not find kernel version\")\n                return None\n\n        ks = __gef_command_instances__[\"ksymaddr-remote\"]\n        h = hashlib.sha256(String.str2bytes(ks.version_string)).hexdigest()[-16:]\n        major, minor, patch = ks.kernel_version\n        base_name = os.path.join(GEF_TEMP_DIR, \"ktypes-{:d}.{:d}.{:d}-{:s}\".format(major, minor, patch, h))\n        return base_name\n\n    def get_btf_addr(self):\n        start = Symbol.get_ksymaddr(\"__start_BTF\")\n        if start is None:\n            return None\n        end = Symbol.get_ksymaddr(\"__stop_BTF\")\n        return start, end - start\n\n    def build_header_file(self):\n        base_path = self.get_base_name()\n        if base_path is None:\n            return None\n\n        raw_path = base_path + \".raw\"\n        header_path = base_path + \".h\"\n\n        # use cache\n        if not self.args.rescan:\n            if os.path.exists(header_path) and os.path.getsize(header_path) > 0:\n                return header_path\n\n        # get address of /sys/kernel/btf/vmlinux\n        addr_size = self.get_btf_addr()\n        if addr_size is None:\n            err(\"Could not find /sys/kernel/btf/vmlinux\")\n            return None\n\n        # read /sys/kernel/btf/vmlinux\n        try:\n            content = read_memory(*addr_size)\n        except gdb.MemoryError:\n            err(\"Memory read error\")\n            return None\n\n        # save it\n        open(raw_path, \"wb\").write(content)\n\n        # raw -> vmlinux.h\n        os.system(\"{!r} btf dump file {!r} format c > {!r}\".format(GefUtil.which(\"bpftool\"), raw_path, header_path))\n        return header_path\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if not self.check_command():\n            return\n\n        header_path = self.build_header_file()\n        if header_path is None:\n            warn(\"This kernel may be CONFIG_DEBUG_INFO_BTF=n\")\n            return\n\n        content = open(header_path, \"r\").read()\n\n        self.out = []\n        self.out.extend(content.splitlines())\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass KtypesLoadCommand(KtypesCommand):\n    \"\"\"Load kernel type information from /sys/kernel/btf/vmlinux.\"\"\"\n\n    _cmdline_ = \"ktypes-load\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n    _aliases_ = [\"kt-load\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    _syntax_ = parser.format_help()\n\n    def build_obj_file(self, header_path):\n        source_path = header_path[:-2] + \".c\"\n        obj_path = source_path[:-2]\n\n        # use cache\n        if not self.args.rescan:\n            if os.path.exists(obj_path) and os.path.getsize(obj_path) > 0:\n                return obj_path\n\n        # copy vmlinux.h to vmlinux.c\n        open(source_path, \"wb\").write(open(header_path, \"rb\").read())\n\n        try:\n            if is_x86_64():\n                gcc, opt = GefUtil.which(\"gcc\"), \"\"\n            elif is_x86_32():\n                gcc, opt = GefUtil.which(\"gcc\"), \"-m32\"\n            elif is_arm64():\n                gcc, opt = GefUtil.which(\"aarch64-linux-gnu-gcc\"), \"\"\n            elif is_arm32():\n                gcc, opt = GefUtil.which(\"arm-linux-gnueabihf-gcc\"), \"\"\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return None\n\n        # build with debug types\n        cmd = \"{!r} {:s} -std=c11 -g -O0 -fno-eliminate-unused-debug-types -c {!r} -o {!r}\".format(\n            gcc, opt, source_path, obj_path,\n        )\n        info(cmd)\n        os.system(cmd)\n\n        if not os.path.exists(obj_path):\n            return None\n\n        return obj_path\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if not self.check_command():\n            return\n\n        header_path = self.build_header_file()\n        if header_path is None:\n            warn(\"This kernel may be CONFIG_DEBUG_INFO_BTF=n\")\n            return\n\n        obj_path = self.build_obj_file(header_path)\n        if obj_path is None:\n            err(\"Failed to build\")\n            return\n\n        info(obj_path)\n        gdb.execute(\"file {:s}\".format(obj_path), to_string=True)\n        info(\"Kernel types are loaded successfully\")\n        return\n\n\n@register_command\nclass KsymaddrRemoteCommand(GenericCommand, BufferingOutput):\n    \"\"\"Resolve kernel symbols from kallsyms table.\"\"\"\n    # Thanks to https://github.com/marin-m/vmlinux-to-elf\n\n    _cmdline_ = \"ksymaddr-remote\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n    _aliases_ = [\"ks\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"keyword\", metavar=\"KEYWORD\", nargs=\"*\", help=\"filter by specific symbol name.\")\n    parser.add_argument(\"-t\", \"--type\", action=\"append\", default=[], help=\"filter by symbol type.\")\n    parser.add_argument(\"-e\", \"--exact\", action=\"store_true\", help=\"use exact match.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\", help=\"filter __pfx_*, __ksymtab_*, etc.\")\n    parser.add_argument(\"--vmlinux-file\", help=\"force use your vmlinux file which includes symbols.\")\n    parser.add_argument(\"-I\", \"--ignore-loaded-vmlinux\", action=\"store_true\", help=\"force skip parsing loaded vmlinux.\")\n    parser.add_argument(\"--print-saved-config\", action=\"store_true\", help=\"print saved (cached) config contents.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"enable verbose mode.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} commit_creds prepare_kernel_cred  # OR search\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"GEF caches offset information for parsing kallsyms to speed up this command.\",\n        \"Each cache is used based on kernel version strings.\",\n        \"In other words, in cases where the kernel version is exactly the same and\",\n        \"the CONFIG is slightly different, the offset will be applied incorrectly.\",\n        \"In this case, rescan with `ks -rv` or clear the cache with `gef reset-cache --hard`.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__()\n        \"\"\"\n        # Do not use dict; There are cases where multiple symbols with the same name exist.\n        # cat /proc/kallsyms |grep set_is_seen\n        ffffffff812326e0 t set_is_seen\n        ffffffff81d58900 t set_is_seen\n        ffffffff81d5cab0 t set_is_seen\n        #\n        \"\"\"\n        self.kallsyms = []\n        return\n\n    def get_loaded_vmlinux_path(self):\n        if self.args.ignore_loaded_vmlinux:\n            return None\n\n        # Check `nm` first for later use (in parse_vmlinux)\n        try:\n            GefUtil.which(Config.get_gef_setting(\"gef.nm_command\"))\n        except FileNotFoundError as e:\n            self.quiet_err(\"{}\".format(e))\n            return None\n\n        # check vmlinux\n        for inf in gdb.inferiors():\n            if not hasattr(inf, \"progspace\"):\n                continue\n            if not hasattr(inf.progspace, \"filename\"):\n                continue\n\n            filename = str(inf.progspace.filename)\n            if not os.path.exists(filename):\n                continue\n\n            # Currently, the filename in vmlinux is hard-coded\n            if \"vmlinux\" not in os.path.basename(filename).lower():\n                continue\n\n            # it has symbol?\n            try:\n                elf = Elf(filename)\n                if elf.get_shdr(\".symtab\"):\n                    return filename\n            except Exception:\n                continue\n        return None\n\n    def parse_vmlinux(self, filename):\n        # read symbols\n        try:\n            nm = GefUtil.which(Config.get_gef_setting(\"gef.nm_command\"))\n        except FileNotFoundError as e:\n            self.quiet_err(\"{}\".format(e))\n            return\n        result = GefUtil.gef_execute_external([nm, filename], as_list=True)\n\n        # distinctive addresses to use for rebasing\n        if is_x86():\n            target = [\n                \"asm_exc_divide_error\", # 5.8~\n                \"divide_error\", # 3.0 ~ 5.7\n            ]\n        elif is_arm64() or is_arm32():\n            target = [\n                \"vectors\", # 3.7~\n            ]\n        elif is_riscv64() or is_riscv32():\n            target = [\n                \"handle_exception\", # 4.19~\n            ]\n        else:\n            raise\n\n        # parse symbol\n        tmp_kallsyms = []\n        target_found = {}\n        for line in result:\n            try:\n                addr, typ, name = line.split()\n                addr = int(addr, 16)\n                typ = typ.strip()\n                name = name.strip()\n            except ValueError:\n                continue\n            tmp_kallsyms.append([addr, name, typ])\n\n            if name in target:\n                target_found[\"handler\"] = addr\n\n        # rebase\n        if target_found:\n            text_base_hint = Kernel.get_kernel_base_hint()\n            if text_base_hint:\n                diff = text_base_hint - target_found[\"handler\"]\n                if diff & get_pagesize_mask_low() == 0:\n                    self.kallsyms = []\n                    for addr, name, typ in tmp_kallsyms:\n                        # don't rebase per-cpu offset\n                        if addr >= 0x4000_0000:\n                            # This value is the lowest boundary between ARM32 kernel and userland.\n                            addr += diff\n                        self.kallsyms.append([addr, name, typ])\n                    return\n\n        # fail, use as is\n        self.kallsyms = tmp_kallsyms\n        return\n\n    def get_token_table(self):\n        # Parse symbol name tokens\n        tokens = []\n        position = self.offset_kallsyms_token_table\n        for _ in range(256):\n            token = \"\"\n            while self.kernel_img[position]:\n                token += chr(self.kernel_img[position])\n                position += 1\n            position += 1\n            tokens.append(token)\n        assert len(tokens) == 256\n        return tokens\n\n    def read_kallsyms(self):\n        if self.kallsyms: # resolved already\n            return\n\n        tokens = self.get_token_table()\n        symbol_names = []\n        position = self.offset_kallsyms_names\n        for _ in range(self.num_symbols):\n            # read token length\n            length = self.kernel_img[position]\n            position += 1\n\n            # check if big symbol (6.1~)\n            if self.kernel_version >= (6, 1, 0):\n                if length & 0x80:\n                    low = length & 0x7f\n                    high = self.kernel_img[position]\n                    position += 1\n                    length = (high << 7) | low\n\n            # make symbol_name\n            symbol_name = \"\"\n            for _ in range(length):\n                symbol_token_index = self.kernel_img[position]\n                symbol_token = tokens[symbol_token_index]\n                position += 1\n                symbol_name += symbol_token\n            symbol_names.append(symbol_name)\n\n        for addr, name in zip(self.kernel_addresses, symbol_names):\n            try:\n                self.kallsyms.append([addr, name[1:], name[0]])\n            except IndexError:\n                pass\n        return\n\n    def print_kallsyms(self, keywords, types, smart):\n        if is_32bit():\n            fmt = \"{:#010x} {:s} {:s}\"\n        else:\n            fmt = \"{:#018x} {:s} {:s}\"\n\n        if types:\n            types = [t.lower() for t in types]\n            kallsyms = [entry for entry in self.kallsyms if entry[2].lower() in types]\n        else:\n            kallsyms = self.kallsyms\n\n        if smart:\n            ignore_list = (\n                \"__pfx_\", # prefix symbols for function padding\n                \"__kstrtab_\",\n                \"__ksymtab_\",\n                \"__kcrctab_\",\n                \"__tpstrtab_\", # tracepoint\n                \"__initcall__\",\n                \"__traceiter_\",\n                \"__tracepoint_\",\n                \"__probestub_\",\n                \"__already_done.\",\n                \"__flags.\",\n                \"__func__.\",\n                \"__key.\",\n                \"__mkey.\",\n                \"__msg.\",\n                \"__print_once.\",\n                \"__quirk.\",\n                \"__warned.\",\n                \"__wkey.\",\n                \"___done.\",\n                \"___once_key.\",\n                \"___tp_str.\",\n                \"__compound_literal.\",\n                \"__SCT__tp_func_\",\n                \"__SCK__tp_func_\",\n                \"__TRACE_SYSTEM_\",\n            )\n            kallsyms = [entry for entry in kallsyms if not entry[1].startswith(ignore_list)]\n\n        self.out = []\n        if not keywords:\n            for addr, symbol, typ in kallsyms:\n                self.out.append(fmt.format(addr, typ, symbol))\n\n        elif self.args.exact:\n            for addr, symbol, typ in kallsyms:\n                if symbol in keywords:\n                    self.out.append(fmt.format(addr, typ, symbol))\n\n        else:\n            for addr, symbol, typ in kallsyms:\n                text = fmt.format(addr, typ, symbol)\n                for k in keywords:\n                    if k in text: # not only symbol search, but also address search\n                        self.out.append(text)\n                        break\n        return\n\n    def get_kernel_version_triplet(self, version_number):\n        major = int(version_number.split(\".\")[0])\n        minor = int(version_number.split(\".\")[1])\n        if len(version_number.split(\".\")) == 2:\n            patch = 0\n        else:\n            patch = int(version_number.split(\".\")[2])\n        return (major, minor, patch)\n\n    def get_kernel_version(self):\n        # don't use Kernel.kernel_version, since it refers ksymaddr-remote\n        r = re.search(rb\"Linux version (\\d+\\.[\\d.]*\\d)[ -~]+\", self.kernel_img)\n        if r is None:\n            self.verbose_err(\"Could not find the kernel version\")\n            return False\n        self.version_string = r.group(0)\n        self.version_string_offset = r.span()[0]\n        self.verbose_info(\"linux_banner: {:#x}\".format(self.ro_base + self.version_string_offset))\n        version_number = r.group(1).decode(\"ascii\")\n        self.kernel_version = self.get_kernel_version_triplet(version_number)\n\n        # The important thing for parsing is whether it is 6.1.42 or later.\n        # However, some distributions may have a patch version of 0.\n        # e.g., debian 6.1.119-1 -> 6.1.0-28-amd64\n        # In this case, special processing is required to find a different version string.\n        if self.kernel_version[:2] == (6, 1):\n            # e.g., Linux version 6.1.0-28-amd64 (debian-kernel@lists.debian.org) (gcc-12 (Debian 12.2.0-14) 12.2.0,\n            # GNU ld (GNU Binutils for Debian) 2.40) #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22)\n            r = re.findall(rb\" 6\\.1\\.(\\d+)\", self.version_string)\n            for patch_version in r:\n                patch_version = int(patch_version)\n                if patch_version >= 42:\n                    self.kernel_version = (self.kernel_version[0], self.kernel_version[1], patch_version)\n                    break\n        return True\n\n    def get_cfg_name(self):\n        h = hashlib.sha256(String.str2bytes(self.version_string)).hexdigest()[-16:]\n        major, minor, patch = self.kernel_version\n        cfg_file_name = os.path.join(GEF_TEMP_DIR, \"ksymaddr-remote-{:d}.{:d}.{:d}-{:s}.cfg\".format(major, minor, patch, h))\n        return cfg_file_name\n\n    def save_config(self, param_name):\n        cfg_file_name = self.get_cfg_name()\n        config = configparser.ConfigParser()\n        if os.path.exists(cfg_file_name):\n            config.read(cfg_file_name)\n        else:\n            config[\"parameters\"] = {}\n\n        if param_name in config[\"parameters\"]:\n            return\n\n        config[\"parameters\"][param_name] = str(getattr(self, param_name))\n        with open(cfg_file_name, \"w\") as cfg_file:\n            config.write(cfg_file)\n        return\n\n    def get_saved_config(self, param_names):\n        if self.args.rescan:\n            return False\n\n        cfg_file_name = self.get_cfg_name()\n        if not os.path.exists(cfg_file_name):\n            return False\n\n        config = configparser.ConfigParser()\n        config.read(cfg_file_name)\n        for param_name in param_names:\n            if param_name not in config[\"parameters\"]:\n                return False\n\n        for param_name in param_names:\n            param_value = int(config[\"parameters\"][param_name])\n            setattr(self, param_name, param_value)\n        return True\n\n    def print_saved_config(self):\n        if hasattr(self, \"version_string\"):\n            cfg_file_name = self.get_cfg_name()\n            info(\"path: {:s}\".format(cfg_file_name))\n            if os.path.exists(cfg_file_name):\n                gef_print(titlify(\"content (hexlified)\"))\n                config = configparser.ConfigParser()\n                config.read(cfg_file_name)\n                for param_name in config[\"parameters\"]:\n                    param_value = config[\"parameters\"][param_name]\n                    try:\n                        param_value = int(param_value)\n                        gef_print(\"{:s} = {:#x}\".format(param_name, param_value))\n                    except ValueError:\n                        gef_print(\"{:s} = {:s}\".format(param_name, param_value))\n                return\n\n        err(\"Could not find cached config (Run the `ksymaddr-remote` command at least once)\")\n        return\n\n    def find_kallsyms_token_table(self):\n        ret = self.get_saved_config([\"offset_kallsyms_token_table\"])\n        if ret:\n            self.verbose_info(\"kallsyms_token_table: {:#x}\".format(self.ro_base + self.offset_kallsyms_token_table))\n            return True\n\n        \"\"\"\n        [Search strategy]\n        - kallsyms_token_table has unique sequences like \"30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 00\".\n        - We search for it from .rodata area, then search backwards for invalid characters to get the top.\n\n        [Positional relationship]\n        - ...\n        - kallsyms_token_table\n        - ...\n\n        [Sample values for 64bit]\n        gef> hexdump -n byte kallsyms_token_table\n        0xffffffff8b2b51b0:    65 75 00 77 5f 00 61 64 64 00 64 5f 5f 66 75 6e    |  eu.w_.add.d__fun  |\n        0xffffffff8b2b51c0:    63 5f 5f 00 74 70 5f 66 75 6e 63 00 33 32 00 6e    |  c__.tp_func.32.n  |\n        0xffffffff8b2b51d0:    61 00 66 66 00 69 70 00 78 65 6e 00 70 72 00 73    |  a.ff.ip.xen.pr.s  |\n        0xffffffff8b2b51e0:    65 74 00 63 70 75 00 49 44 00 65 64 00 53 43 00    |  et.cpu.ID.ed.SC.  |\n        0xffffffff8b2b51f0:    66 72 65 00 76 65 5f 00 70 6f 00 78 5f 00 5f 73    |  fre.ve_.po.x_._s  |\n        0xffffffff8b2b5200:    68 00 2e 31 00 62 6c 00 6d 65 6d 00 5f 72 65 67    |  h..1.bl.mem._reg  |\n        0xffffffff8b2b5210:    00 74 5f 5f 00 6c 6f 63 6b 00 62 5f 00 72 5f 5f    |  .t__.lock.b_.r__  |\n        0xffffffff8b2b5220:    6b 73 74 72 74 61 62 6e 73 00 66 75 6e 63 5f 5f    |  kstrtabns.func__  |\n        0xffffffff8b2b5230:    00 69 6e 74 5f 00 72 65 73 00 74 72 61 63 65 00    |  .int_.res.trace.  |\n        0xffffffff8b2b5240:    70 61 72 00 2e 30 00 64 65 76 65 6e 74 5f 00 6d    |  par..0.devent_.m  |\n        0xffffffff8b2b5250:    75 00 61 63 70 69 5f 00 6d 70 00 73 74 61 00 64    |  u.acpi_.mp.sta.d  |\n        0xffffffff8b2b5260:    65 62 75 67 00 5f 5f 5f 00 62 75 67 00 6f 75 00    |  ebug.___.bug.ou.  |\n        0xffffffff8b2b5270:    5f 73 74 61 00 77 72 69 74 00 2e 00 67 72 6f 00    |  _sta.writ...gro.  |\n        0xffffffff8b2b5280:    30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00    |  0.1.2.3.4.5.6.7.  | <- here unique seqs\n        0xffffffff8b2b5290:    38 00 39 00 72 63 00 77 61 00 63 61 6c 00 75 70    |  8.9.rc.wa.cal.up  |\n        0xffffffff8b2b52a0:    5f 00 45 5f 00 67 65 5f 00 6d 61 70 00 41 00 42    |  _.E_.ge_.map.A.B  |\n\n        [Sample values for 32bit]\n        gef> hexdump -n byte kallsyms_token_table\n        0xc6e58efc:    54 52 41 43 45 5f 53 59 53 00 41 43 45 5f 53 59    |  TRACE_SYS.ACE_SY  |\n        0xc6e58f0c:    53 00 5f 53 59 53 00 54 45 4d 00 41 43 45 00 69    |  S._SYS.TEM.ACE.i  |\n        0xc6e58f1c:    67 00 70 6f 69 6e 74 5f 00 62 75 00 75 74 5f 00    |  g.point_.bu.ut_.  | # codespell:ignore\n        0xc6e58f2c:    5f 53 59 00 54 52 00 5f 73 79 00 72 65 61 64 00    |  _SY.TR._sy.read.  |\n        0xc6e58f3c:    66 5f 00 75 6c 00 62 6c 00 61 6c 6c 6f 63 00 74    |  f_.ul.bl.alloc.t  |\n        0xc6e58f4c:    6c 00 63 6c 00 65 79 00 61 74 61 00 70 63 00 5f    |  l.cl.ey.ata.pc._  |\n        0xc6e58f5c:    65 6e 00 76 65 72 00 54 45 00 64 74 72 61 63 65    |  en.ver.TE.dtrace  | # codespell:ignore\n        0xc6e58f6c:    5f 65 76 65 6e 74 5f 00 61 70 00 61 74 65 00 74    |  _event_.ap.ate.t  |\n        0xc6e58f7c:    6e 00 41 43 00 6d 73 00 72 61 77 5f 00 5f 63 6f    |  n.AC.ms.raw_._co  |\n        0xc6e58f8c:    00 73 74 72 00 6d 6f 00 67 69 73 74 65 72 00 69    |  .str.mo.gister.i  |\n        0xc6e58f9c:    70 00 63 6f 6e 00 67 69 73 00 69 6e 69 74 00 66    |  p.con.gis.init.f  |\n        0xc6e58fac:    75 6e 63 00 65 5f 73 00 75 74 00 5f 73 68 00 70    |  unc.e_s.ut._sh.p  |\n        0xc6e58fbc:    6f 00 61 6c 6c 00 2e 00 66 73 5f 00 30 00 31 00    |  o.all...fs_.0.1.  |\n        0xc6e58fcc:    32 00 33 00 34 00 35 00 36 00 37 00 38 00 39 00    |  2.3.4.5.6.7.8.9.  | <- here unique seqs\n        0xc6e58fdc:    6b 5f 00 5f 63 68 00 72 69 74 00 61 63 70 69 00    |  k_._ch.rit.acpi.  |\n        0xc6e58fec:    5f 63 6f 6e 00 65 78 74 34 00 61 6d 00 41 00 42    |  _con.ext4.am.A.B  |\n        \"\"\"\n\n        # first, search for unique bytes\n        seq_to_find = b\"0\\x001\\x002\\x003\\x004\\x005\\x006\\x007\\x008\\x009\\x00\"\n        seq_to_avoid = [b\":\\0\", b\"\\0\\0\", b\"\\0\\1\", b\"\\0\\2\", b\"ASCII\\0\"]\n        target_pattern = seq_to_find + b\"(?!\" + b\"|\".join(seq_to_avoid) + b\")\"\n\n        unique_bytes_offset = []\n        for r in re.finditer(target_pattern, self.kernel_img):\n            unique_bytes_offset.append(r.span()) # (start_pos, end_pos)\n\n        if len(unique_bytes_offset) == 0:\n            self.verbose_err(\"Could not find kallsyms_token_table (0 candidate)\")\n            return False\n\n        if len(unique_bytes_offset) > 1:\n            # strict check\n            for i, offsets in enumerate(unique_bytes_offset.copy()):\n                self.verbose_info(\"unique_bytes {:d}: {:#x}\".format(i, self.ro_base + offsets[0]))\n                follow = self.kernel_img[offsets[1]:offsets[1] + 1]\n                if not follow.isalnum() and follow not in [b\"_\", b\".\"]:\n                    unique_bytes_offset.remove(offsets)\n            # re-check\n            if len(unique_bytes_offset) == 0:\n                self.verbose_err(\"Could not find kallsyms_token_table (0 candidate)\")\n                return False\n            if len(unique_bytes_offset) > 1:\n                self.verbose_err(\"Could not find kallsyms_token_table (multiple candidates)\")\n                return False\n\n        position = unique_bytes_offset[0][0]\n        self.verbose_info(\"unique_bytes: {:#x}\".format(self.ro_base + position))\n\n        # second, backward search for the top\n        position -= 1\n        if position < 0:\n            self.verbose_err(\"Could not find kallsyms_token_table (failed to get top: before '0')\")\n            return False\n        if self.kernel_img[position] != 0:\n            self.verbose_err(\"Unexpected byte before '0' entry in kallsyms_token_table\")\n            return False\n\n        num_tokens_back = ord('0') # 48\n        max_token_len = 50\n\n        # find the beginning of a kallsyms_token_table\n        for _ in range(num_tokens_back):\n            # find the beginning of a token\n            for _ in range(max_token_len):\n                position -= 1\n                if position < 0:\n                    self.verbose_err(\"Could not find kallsyms_token_table (out of range while walking tokens)\")\n                    return False\n\n                b = self.kernel_img[position]\n                if b == 0 or b > ord('z'):\n                    break\n\n            else:\n                # max_token_len exceeded\n                self.verbose_err(\"This structure is not a kallsyms_token_table (token too long)\")\n                return False\n\n        position += 1\n        position += -position % 4\n\n        self.offset_kallsyms_token_table = position\n        self.save_config(\"offset_kallsyms_token_table\")\n        self.verbose_info(\"kallsyms_token_table: {:#x}\".format(self.ro_base + self.offset_kallsyms_token_table))\n        return True\n\n    def find_kallsyms_token_index(self):\n        ret = self.get_saved_config([\"offset_kallsyms_token_index\"])\n        if ret:\n            self.verbose_info(\"kallsyms_token_index: {:#x}\".format(self.ro_base + self.offset_kallsyms_token_index))\n            return True\n\n        \"\"\"\n        [Search strategy]\n        - Find the index where the string appears in kallsyms_token_table.\n        - Find where that index is arranged like a table.\n\n        [Positional relationship]\n        - ...\n        - kallsyms_token_table\n        - kallsyms_token_index\n        - ...\n\n        [Sample values for 64bit]\n        gef> hexdump -n word kallsyms_token_index\n        0xffffffff8b2b5540:    0x0000 0x0003 0x0006 0x000a 0x0014 0x001c 0x001f 0x0022    |  ..............\".  |\n        0xffffffff8b2b5550:    0x0025 0x0028 0x002c 0x002f 0x0033 0x0037 0x003a 0x003d    |  %.(.,./.3.7.:.=.  |\n        0xffffffff8b2b5560:    0x0040 0x0044 0x0048 0x004b 0x004e 0x0052 0x0055 0x0058    |  @.D.H.K.N.R.U.X.  |\n        0xffffffff8b2b5570:    0x005c 0x0061 0x0065 0x006a 0x006d 0x007a 0x0081 0x0086    |  ..a.e.j.m.z.....  |\n        0xffffffff8b2b5580:    0x008a 0x0090 0x0094 0x0097 0x009f 0x00a2 0x00a8 0x00ab    |  ................  |\n        0xffffffff8b2b5590:    0x00af 0x00b5 0x00b9 0x00bd 0x00c0 0x00c5 0x00ca 0x00cc    |  ................  |\n        0xffffffff8b2b55a0:    0x00d0 0x00d2 0x00d4 0x00d6 0x00d8 0x00da 0x00dc 0x00de    |  ................  |\n        0xffffffff8b2b55b0:    0x00e0 0x00e2 0x00e4 0x00e7 0x00ea 0x00ee 0x00f2 0x00f5    |  ................  |\n\n        [Sample values for 32bit]\n        gef> hexdump -n word kallsyms_token_index\n        0xc6e59274:    0x0000 0x000a 0x0012 0x0017 0x001b 0x001f 0x0022 0x0029    |  ............\".).  |\n        0xc6e59284:    0x002c 0x0030 0x0034 0x0037 0x003b 0x0040 0x0043 0x0046    |  ,.0.4.7.;.@.C.F.  |\n        0xc6e59294:    0x0049 0x004f 0x0052 0x0055 0x0058 0x005c 0x005f 0x0063    |  I.O.R.U.X..._.c.  |\n        0xc6e592a4:    0x0067 0x006a 0x0078 0x007b 0x007f 0x0082 0x0085 0x0088    |  g.j.x.{.........  |\n        0xc6e592b4:    0x008d 0x0091 0x0095 0x0098 0x009f 0x00a2 0x00a6 0x00aa    |  ................  |\n        0xc6e592c4:    0x00af 0x00b4 0x00b8 0x00bb 0x00bf 0x00c2 0x00c6 0x00c8    |  ................  |\n        0xc6e592d4:    0x00cc 0x00ce 0x00d0 0x00d2 0x00d4 0x00d6 0x00d8 0x00da    |  ................  |\n        0xc6e592e4:    0x00dc 0x00de 0x00e0 0x00e3 0x00e7 0x00eb 0x00f0 0x00f5    |  ................  |\n        \"\"\"\n\n        # create expected kallsyms_token_index byte sequqence\n        position = self.offset_kallsyms_token_table\n        seq_token_table_head = self.kernel_img[position:position + 256]\n\n        token_offsets = [p16(0)]\n        pos = 0\n        while True:\n            pos = seq_token_table_head.find(b\"\\0\", pos + 1)\n            if pos == -1:\n                break\n            token_offsets.append(p16(pos + 1))\n        seq_to_find = b\"\".join(token_offsets)\n\n        # search for it from memory\n        position = self.kernel_img.find(seq_to_find, self.offset_kallsyms_token_table)\n        if position == -1:\n            self.verbose_err(\"Could not find kallsyms_token_index (0 candidate)\")\n            return False\n\n        self.offset_kallsyms_token_index = position\n        self.save_config(\"offset_kallsyms_token_index\")\n        self.verbose_info(\"kallsyms_token_index: {:#x}\".format(self.ro_base + self.offset_kallsyms_token_index))\n        return True\n\n    def find_kallsyms_markers(self):\n        # determines the size of table elements depended on kernel version.\n        if self.kernel_version < (4, 20, 0):\n            # kallsyms_markers is unsigned long[]\n            self.kallsyms_markers_table_element_size = current_arch.ptrsize\n        else:\n            # kallsyms_markers is unsigned int[]\n            self.kallsyms_markers_table_element_size = 4\n\n        if self.kernel_version >= (6, 1, 42) and self.kernel_version < (6, 9, 0):\n            ret = self.get_saved_config([\n                \"offset_kallsyms_token_markers\",\n                \"offset_kallsyms_seqs_of_names\",\n            ])\n            if ret:\n                self.verbose_info(\"kallsyms_markers: {:#x}\".format(self.ro_base + self.offset_kallsyms_markers))\n                self.verbose_info(\"kallsyms_seqs_of_names: {:#x}\".format(self.ro_base + self.offset_kallsyms_seqs_of_names))\n                return True\n        else:\n            ret = self.get_saved_config([\n                \"offset_kallsyms_token_markers\",\n            ])\n            if ret:\n                self.verbose_info(\"kallsyms_markers: {:#x}\".format(self.ro_base + self.offset_kallsyms_markers))\n                return True\n\n        \"\"\"\n        [Search strategy]\n        - From kallsyms_token_table, search backwards for 0x00000000.\n        - For kernel v6.1.42~v6.8, there is kallsyms_seqs_of_names between kallsyms_markers and kallsyms_token_table,\n          so this should be skipped.\n\n        [Positional relationship]\n        ...\n        - kallsyms_markers\n        - kallsyms_seqs_of_names (v6.1.42~v6.8)\n        - kallsyms_token_table\n        - kallsyms_token_index\n        ...\n        - kallsyms_seqs_of_names (v6.9~)\n        ...\n\n        [Sample values for 64bit ~v6.1.41]\n        gef> hexdump -n dword kallsyms_markers\n        0xffffffff8b2b4b48:    0x00000000 0x00000ab0 0x000016d3 0x00002316    |  .............#..  | <- kallsyms_markers\n        0xffffffff8b2b4b58:    0x00002f38 0x00003cf8 0x00004c4c 0x000059c8    |  8/...<..LL...Y..  |\n        0xffffffff8b2b4b68:    0x0000664b 0x00007316 0x00008119 0x00008f2e    |  Kf...s..........  |\n        0xffffffff8b2b4b78:    0x00009cc6 0x0000a9ff 0x0000b687 0x0000c20f    |  ................  |\n        ...\n        0xffffffff8b2b5180:    0x0013fa80 0x001404c6 0x00140f67 0x00141a29    |  ........g...)...  |\n        0xffffffff8b2b5190:    0x0014240e 0x00142e25 0x00143a5f 0x0014442a    |  .$..%..._:..*D..  |\n        0xffffffff8b2b51a0:    0x00144e55 0x001458d8 0x00146338 0x00000000    |  UN...X..8c......  |\n        0xffffffff8b2b51b0:    0x77007565 0x6461005f 0x5f640064 0x6e75665f    |  eu.w_.add.d__fun  | <- kallsyms_token_table\n\n        [Sample values for 64bit v6.1.42~]\n        gef> hexdump -n dword kallsyms_markers\n        0xffffffff8d5fcde0:    0x00000000 0x00000b55 0x000017bb 0x000024c3    |  ....U........$..  | <- kallsyms_markers\n        0xffffffff8d5fcdf0:    0x000030c1 0x00003dca 0x00004983 0x000058aa    |  .0...=...I...X..  |\n        0xffffffff8d5fce00:    0x00006785 0x0000760e 0x0000828d 0x00009160    |  .g...v......`...  |\n        0xffffffff8d5fce10:    0x00009efa 0x0000ab20 0x0000b73a 0x0000c37d    |  .... ...:...}...  |\n        ...\n        0xffffffff8d5fd790:    0x00212755 0x002131b8 0x00213af8 0x00214558    |  U'!..1!..:!.XE!.  |\n        0xffffffff8d5fd7a0: (*)0x01069d01 0x9d01019d 0x029d0100 0x02039d01    |  ................  | <- kallsyms_seqs_of_names (*)\n        0xffffffff8d5fd7b0:    0xa400291c 0x10a50024 0x0154a500 0xaa0116aa    |  .)..$.....T.....  |\n        0xffffffff8d5fd7c0:    0x87610214 0x01274902 0xb201cbaf 0xbbbc01c9    |  ..a..I'.........  |\n\n        [Sample values for 32bit v6.1.42~]\n        gef> hexdump -n dword kallsyms_markers\n        0xc6e0dc98:    0x00000000 0x00000c61 0x0000188f 0x00002641    |  ....a.......A&..  | <- kallsyms_markers\n        0xc6e0dca8:    0x00003492 0x000041a7 0x00004e6b 0x00005ace    |  .4...A..kN...Z..  |\n        0xc6e0dcb8:    0x0000691b 0x00007703 0x00008411 0x00008fc1    |  .i...w..........  |\n        0xc6e0dcc8:    0x00009c98 0x0000a8ea 0x0000b719 0x0000c4dd    |  ................  |\n        ...\n        0xc6e0e2c8:    0x0014f2fa 0x0014fbeb 0x00150653 0x00634401(*) |  ........S....Dc.  | <- kallsyms_seqs_of_names (*)\n        0xc6e0e2d8:    0xd90030d9 0x8bd30032 0x0189d300 0x6a01e97f    |  .0..2..........j  |\n        0xc6e0e2e8:    0x31d90063 0x0007e100 0xd600b7e1 0xd1d900cb    |  c..1............  |\n        0xc6e0e2f8:    0x0083dd00 0xd90004e9 0x85ef00ab 0x00bfdb00    |  ................  |\n        \"\"\"\n\n        # kallsyms_markers[0] is 0.\n        seq_to_find = b\"\\0\" * self.kallsyms_markers_table_element_size\n\n        # ignore the 0 immediately above kallsyms_token_table.\n        position = self.offset_kallsyms_token_table - 1\n        if len(self.kernel_img) <= position:\n            return False\n        while position > 0 and self.kernel_img[position] == 0:\n            position -= 1\n\n        # aligned search for it from memory\n        while position > 0:\n            needle = self.kernel_img.rfind(seq_to_find, 0, position)\n            if needle == -1:\n                self.verbose_err(\"Could not find kallsyms_markers\")\n                return False\n            # check alignment\n            align_diff = needle % self.kallsyms_markers_table_element_size\n            if align_diff == 0:\n                position = needle\n                break # ok\n            else:\n                position = needle + self.kallsyms_markers_table_element_size - align_diff\n                # not aligned, so retry\n\n        if self.kernel_version >= (6, 1, 42) and self.kernel_version < (6, 9, 0):\n            # kallsyms_seqs_of_names was introduced in kernel 6.1.42\n            # In this case, we may find kallsyms_seqs_of_names instead of kallsyms_markers,\n            # so we should search back through memory again.\n            #\n            # kallsyms_markers        (1) we want to find this\n            # kallsyms_seqs_of_names  (3) this may have been found, try the backward search again\n            # kallsyms_token_table    (2) backward search from here\n            # kallsyms_token_index\n            #\n            while position > 0:\n                # the first some values of kallsyms_markers should be a small number.\n                # if not, detected kallsyms_markers is incorrect and we'll go back further.\n                first_10_elements = self.kernel_img[position + self.kallsyms_markers_table_element_size:]\n                first_10_elements = first_10_elements[:self.kallsyms_markers_table_element_size * 10]\n                first_10_elements = slice_unpack(first_10_elements, self.kallsyms_markers_table_element_size)\n                if all((x & 0xfff_0000) == 0 for x in first_10_elements):\n                    break\n\n                needle = self.kernel_img.rfind(seq_to_find, 0, position)\n                if needle == -1:\n                    self.verbose_err(\"Could not find kallsyms_markers\")\n                    return False\n                # check alignment\n                align_diff = needle % self.kallsyms_markers_table_element_size\n                if align_diff == 0:\n                    position = needle\n                else:\n                    position = needle + self.kallsyms_markers_table_element_size - align_diff\n\n        if position <= 0:\n            self.verbose_err(\"Could not find kallsyms_markers\")\n            return False\n\n        self.offset_kallsyms_markers = position\n        self.save_config(\"offset_kallsyms_markers\")\n        self.verbose_info(\"kallsyms_markers: {:#x}\".format(self.ro_base + self.offset_kallsyms_markers))\n\n        if self.kernel_version >= (6, 1, 42) and self.kernel_version < (6, 9, 0):\n            # locate kallsyms_seqs_of_names to get the table size of kallsyms_markers (used after).\n            #\n            # kallsyms_markers        (1) we found this\n            # kallsyms_seqs_of_names  (2) to know the end of kallsyms_markers, we need to find this\n            # kallsyms_token_table\n            # kallsyms_token_index\n            #\n            position = self.offset_kallsyms_markers + self.kallsyms_markers_table_element_size\n            # check MSB of the element of kallsyms_markers\n            while self.kernel_img[position + (self.kallsyms_markers_table_element_size - 1)] == 0:\n                a = u32(self.kernel_img[position - self.kallsyms_markers_table_element_size:position]) # prev\n                b = u32(self.kernel_img[position:position + self.kallsyms_markers_table_element_size]) # current\n                # kallsyms_markers are monotonically increasing.\n                # and it doesn't increase very dramatically.\n                if a > b or b - a > 0x10_0000:\n                    break\n                position += self.kallsyms_markers_table_element_size\n            self.offset_kallsyms_seqs_of_names = position\n            self.save_config(\"offset_kallsyms_seqs_of_names\")\n            self.verbose_info(\"kallsyms_seqs_of_names: {:#x}\".format(self.ro_base + self.offset_kallsyms_seqs_of_names))\n\n        return True\n\n    def find_kallsyms_names(self):\n        ret = self.get_saved_config([\"offset_kallsyms_names\"])\n        if ret:\n            return True\n\n        \"\"\"\n        [Search strategy]\n        - From kallsyms_markers, go back as far as we can definitively go back.\n        - This address is not accurate.\n\n        [Positional relationship]\n        ...\n        - kallsyms_names (this is not accurate address in this step)\n        - kallsyms_markers\n        - kallsyms_seqs_of_names (v6.1.42~v6.8)\n        - kallsyms_token_table\n        - kallsyms_token_index\n        ...\n        - kallsyms_seqs_of_names (v6.9~)\n        ...\n\n        [Sample values for 64bit]\n        gef> hexdump -n qword kallsyms_names\n        0xffffffff8b16e610:    0x0cf3ec0e78b6410a 0xf370ff4109fe61cb    |  .A.x.....a..A.p.  | <- kallsyms_names\n        0xffffffff8b16e620:    0x0c410774722cbdeb 0xa8410df67ef4285f    |  ..,rt.A._(.~..A.  |\n        0xffffffff8b16e630:    0x936bed62d8632c71 0x925f0c4107f67ef4    |  q,c.b.k..~..A._.  |\n        0xffffffff8b16e640:    0xfb646741067772f1 0x706563a4410add86    |  .rw.Agd....A.cep  |\n        ...\n        0xffffffff8b2b4b20:    0x616bd977fc6d7364 0x738df5ff440e61f6    |  dsm.w.ka.a.D...s  |\n        0xffffffff8b2b4b30:    0x6765625fbfe87263 0x63738df5ff440cf5    |  cr.._beg..D...sc  |\n        0xffffffff8b2b4b40:    0x000064ee5fbfe872 0x00000ab000000000    |  r.._.d..........  | <- kallsyms_markers\n        0xffffffff8b2b4b50:    0x00002316000016d3 0x00003cf800002f38    |  .....#..8/...<..  |\n\n        [Sample values for 32bit]\n        gef> hexdump -n qword kallsyms_names\n        0xc6cbce58:    0x335fd57472fb5c08 0x54039974f9540432    |  ...rt._32.T.t..T  | <- kallsyms_names\n        0xc6cbce68:    0x63ff72fb5c0799a6 0xd57472fb5c0a30a1    |  .....r.c.0...rt.  |\n        0xc6cbce78:    0x177407b6f932335f 0xa0ca0aa1f3796669    |  _32...t.ify.....  |\n        0xc6cbce88:    0xd7f49b2d63ecc37f 0x2d63ecc37fa0ca0a    |  ...c-.........c-  |\n        ...\n        0xc6e0dc78:    0x3a7262fe620d105f 0x10ff67ef796ccf65    |  _..b.br:e.ly.g..  |\n        0xc6e0dc88:    0x62fe420964164203 0x0000ec6d699b6b72    |  .B.d.B.brk.im...  |\n        0xc6e0dc98:    0x00000c6100000000 0x000026410000188f    |  ....a.......A&..  | <- kallsyms_markers\n        0xc6e0dca8:    0x000041a700003492 0x00005ace00004e6b    |  .4...A..kN...Z..  |\n        \"\"\"\n\n        # take the last element of kallsyms_marker\n        if hasattr(self, \"offset_kallsyms_seqs_of_names\"): # maybe 6.1.42~6.8\n            kallsyms_markers_end = self.offset_kallsyms_seqs_of_names\n        else:\n            kallsyms_markers_end = self.offset_kallsyms_token_table\n\n        kallsyms_markers_data = self.kernel_img[self.offset_kallsyms_markers:kallsyms_markers_end]\n        kallsyms_markers_entries = slice_unpack(kallsyms_markers_data, self.kallsyms_markers_table_element_size)\n        kallsyms_markers_last_entry = list(filter(None, kallsyms_markers_entries))[-1] # filter 0, maybe padding\n\n        # go back that number of bytes\n        position = self.offset_kallsyms_markers\n        position -= kallsyms_markers_last_entry\n        position += -position % self.kallsyms_markers_table_element_size\n\n        if position <= 0:\n            self.verbose_err(\"Could not find kallsyms_names\")\n            return False\n\n        # This value is provisional. It will be corrected in the next process (=find_kallsyms_num_syms).\n        self.offset_kallsyms_names = position\n        self.verbose_info(\"kallsyms_names: {:#x} (candidate)\".format(self.ro_base + self.offset_kallsyms_names))\n        return True\n\n    def find_kallsyms_num_syms(self):\n        ret = self.get_saved_config([\n            \"num_symbols\",\n            \"offset_kallsyms_names\",\n            \"offset_kallsyms_num_syms\",\n        ])\n        if ret:\n            self.verbose_info(\"num_symbols: {:#x}\".format(self.num_symbols))\n            self.verbose_info(\"kallsyms_names: {:#x}\".format(self.ro_base + self.offset_kallsyms_names))\n            self.verbose_info(\"kallsyms_num_syms: {:#x}\".format(self.ro_base + self.offset_kallsyms_num_syms))\n            return True\n\n        \"\"\"\n        [Search strategy]\n        - From candidate address of kallsyms_names, search backwards to the top of what can be correctly\n          interpreted as kallsyms_names.\n\n        [Positional relationship]\n        ...\n        - kallsyms_num_syms\n        - kallsyms_names (to be fixed in this step)\n        - kallsyms_markers\n        - kallsyms_seqs_of_names (v6.1.42~v6.8)\n        - kallsyms_token_table\n        - kallsyms_token_index\n        ...\n        - kallsyms_seqs_of_names (v6.9~)\n        ...\n\n        [Sample values for 64bit]\n        gef> hexdump -n qword kallsyms_num_syms\n        0xffffffff8b16e608:    0x000000000001982b 0x0cf3ec0e78b6410a    |  +........A.x....  |\n        0xffffffff8b16e618:    0xf370ff4109fe61cb 0x0c410774722cbdeb    |  .a..A.p...,rt.A.  |\n        0xffffffff8b16e628:    0xa8410df67ef4285f 0x936bed62d8632c71    |  _(.~..A.q,c.b.k.  |\n        0xffffffff8b16e638:    0x925f0c4107f67ef4 0xfb646741067772f1    |  .~..A._..rw.Agd.  |\n\n        [Sample values for 32bit]\n        gef> hexdump -n dword kallsyms_num_syms\n        0xc6cbce54:    0x00018eb8 0x72fb5c08 0x335fd574 0xf9540432    |  .......rt._32.T.  |\n        0xc6cbce64:    0x54039974 0x5c0799a6 0x63ff72fb 0x5c0a30a1    |  t..T.....r.c.0..  |\n        0xc6cbce74:    0xd57472fb 0xf932335f 0x177407b6 0xf3796669    |  .rt._32...t.ify.  |\n        \"\"\"\n\n        token_table = self.get_token_table()\n        possible_symbol_types = \"-?ABCDGINPRSTUVWabcdginprstuvw\" # from `man nm`\n        dp = []\n\n        position = self.offset_kallsyms_names\n        # kallsyms_names should be aligned.\n        # This optimization is based on experience and is applied for now.\n        position += -position % current_arch.ptrsize\n\n        while True:\n            if position < 0:\n                self.verbose_err(\"Could not find kallsyms_names\")\n                return False\n\n            # Do some types of checks.\n            # 1: check the token type is likely or not.\n            token_index = self.kernel_img[position + 1]\n            symbol_type = token_table[token_index][0]\n            if symbol_type not in possible_symbol_types:\n                position -= current_arch.ptrsize\n                continue\n\n            # 2: check the table (kallsyms_names) entirely.\n            # Each element of kallsyms_names consists of {number of tokens, tokens[number of tokens]}.\n            # tokens[0][0] is symbol type.\n            #\n            # The following is an example of last elements of kallsyms_names.\n            # gef> x/24xb 0xffffffffb46b4b48-0x10\n            # 0xffffffffb46b4b38: 0xf5   0x0c*  0x44   0xff   0xf5   0x8d   0x73   0x63 (*: start of last valid elements)\n            # 0xffffffffb46b4b40: 0x72   0xe8   0xbf   0x5f   0xee   0x64*  0x00** 0x00 (*: end of last valid elements, **: end marker)\n            # 0xffffffffb46b4b48: 0x00*  0x00   0x00   0x00   0xb0   0x0a   0x00   0x00 (*: start of kallsyms_markers)\n            #\n            # 0x0c: number of tokens\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x44]\n            # 'D' (= symbol type)\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0xff]\n            # '__'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0xf5]\n            # 'in'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x8d]\n            # 'it_'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x73]\n            # 's'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x63]\n            # 'c'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x72]\n            # 'r'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0xe8]\n            # 'at'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0xbf]\n            # 'ch'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x5f]\n            # '_'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0xee]\n            # 'en'\n            # gef> pi GCI[\"ksymaddr-remote\"].get_token_table()[0x64]\n            # 'd'\n            # (=`__init_scratch_end`)\n            #\n            # Finally, 0x00(**) is following, this is the marker that represents the end of kallsyms_names.\n            # This can be interpreted that the size of element is 0.\n            #\n            # However, this 0x00 may not exist.\n            # gef> x/16xb 0xffffffffadefc1d8-0x8\n            # 0xffffffffadefc1d0: 0x12   0x65   0x05*  0xbf   0x65   0xaf   0x74   0xa5** (*/**: start/end of last valid elements)\n            # 0xffffffffadefc1d8: 0x00*  0x00   0x00   0x00   0xb2   0x0b   0x00   0x00   (*: start of kallsyms_markers)\n            # Even in this case, the first byte of kallsyms_markers is always 0, so we use it.\n            #\n            # Check that this structure is correct or not, using bottom-up DP.\n            # dp[i] contains num_syms as interpreted from `kallsyms_makers - i` as the start of kallsyms_names.\n            # dp[i] == -1 means invalid.\n            range_start = position\n            range_end = self.offset_kallsyms_markers\n            range_end -= len(dp) # shortcut the already checked results.\n            for pos in range(range_end, range_start - 1, -1):\n                symbol_size = self.kernel_img[pos]\n                is_big_symbol = False # default\n\n                # check if big symbol (6.1~)\n                if self.kernel_version >= (6, 1, 0):\n                    if symbol_size & 0x80:\n                        low = symbol_size & 0x7f\n                        high = self.kernel_img[pos + 1]\n                        symbol_size = (high << 7) | low\n                        is_big_symbol = True\n\n                # 0xffffffffb46b4b38: 0xf5     0x0c     0x44     0xff     0xf5     0x8d     0x73     0x63\n                # 0xffffffffb46b4b40: 0x72     0xe8     0xbf     0x5f     0xee     0x64     0x00*    0x00*\n                #                                                                           dp[2]=0  dp[1]=0\n                # 0xffffffffb46b4b48: 0x00*    0x00     0x00     0x00     0xb0     0x0a     0x00     0x00\n                #                     dp[0]=0\n                if symbol_size == 0:\n                    dp.append(0) # maybe it is a last entry\n                    continue\n\n                # 0xffffffffb46b4b38: 0xf5     0x0c     0x44     0xff     0xf5     0x8d     0x73     0x63\n                # 0xffffffffb46b4b40: 0x72     0xe8     0xbf     0x5f     0xee     0x64*    0x00     0x00\n                #                                                                  dp[3]=-1 dp[2]=0  dp[1]=0\n                # 0xffffffffb46b4b48: 0x00*    0x00     0x00     0x00     0xb0     0x0a     0x00     0x00\n                #                     dp[0]=0\n                dp_len = len(dp)\n                if is_big_symbol:\n                    dp_len = len(dp) - 1\n                if symbol_size >= dp_len:\n                    dp.append(-1) # exceed the kallsyms_markers\n                    continue\n\n                # 0xffffffffb46b4b38: 0xf5     0x0c*    0x44     0xff     0xf5     0x8d     0x73     0x63\n                #                              dp[f]=1  dp[e]=-1 dp[d]=-1 dp[c]=-1 dp[b]=-1 dp[a]=-1 dp[9]=-1\n                # 0xffffffffb46b4b40: 0x72     0xe8     0xbf     0x5f     0xee     0x64     0x00**   0x00\n                #                     dp[8]=-1 dp[7]=-1 dp[6]=-1 dp[5]=-1 dp[4]=-1 dp[3]=-1 dp[2]=0  dp[1]=0\n                # 0xffffffffb46b4b48: 0x00*    0x00     0x00     0x00     0xb0     0x0a     0x00     0x00\n                #                     dp[0]=0\n                # when we see 0x0c(*), next element is 0x00(**).\n                # In this case, here, len(dp) == 15 (dp[15] does not exist, but dp[14] exists).\n                # dp[-(0xc + 1)] is dp[2]. d[2] is 0, not -1, so dp[15] is valid. If dp[2] is -1, dp[15] is invalid.\n                offset_of_next_element = -symbol_size - 1\n                if is_big_symbol:\n                    offset_of_next_element -= 1\n                if dp[offset_of_next_element] == -1:\n                    dp.append(-1)\n                    continue\n                # seems to be okay, append valid dp\n                dp.append(dp[offset_of_next_element] + 1)\n\n            num_symbols = dp[-1]\n            if num_symbols < 256:\n                # It is judged as NG because there are too few symbols.\n                position -= current_arch.ptrsize\n                continue\n\n            # 3: Find num_symbols from memory.\n            if self.kallsyms_markers_table_element_size == 4:\n                seq_to_find = p32(num_symbols)\n            elif self.kallsyms_markers_table_element_size == 8:\n                seq_to_find = p64(num_symbols)\n            # Depending on the environment, there are many zero padding after seq_to_find (=kallsyms_num_syms).\n            # This is probably because each variable is aligned in units of 256 bytes.\n            MAX_ALIGNMENT = 256\n            start = max(0, position - MAX_ALIGNMENT)\n            needle = self.kernel_img.rfind(seq_to_find, start, position)\n            if needle == -1:\n                position -= current_arch.ptrsize\n                continue\n\n            # it seems ok.\n            self.offset_kallsyms_names = position\n            self.offset_kallsyms_num_syms = needle\n            break\n\n        self.save_config(\"offset_kallsyms_names\")\n        self.save_config(\"offset_kallsyms_num_syms\")\n        self.num_symbols = num_symbols\n        self.save_config(\"num_symbols\")\n        self.verbose_info(\"num_symbols: {:#x}\".format(self.num_symbols))\n        self.verbose_info(\"kallsyms_names: {:#x}\".format(self.ro_base + self.offset_kallsyms_names))\n        self.verbose_info(\"kallsyms_num_syms: {:#x}\".format(self.ro_base + self.offset_kallsyms_num_syms))\n        return True\n\n    def find_kallsyms_offsets(self):\n        \"\"\"\n        [Search strategy]\n        - ~v6.3\n          - From kallsyms_num_syms, go back by num_symbols element sizes.\n          - num_symbols offsets are stored, so get them.\n        - v6.4~\n          - From kallsyms_token_index + 0x200, num_symbols offsets are stored, so get them.\n\n        [Positional relationship]\n        - ...\n        - kallsyms_offsets (v4.6~v6.3, CONFIG_KALLSYMS_BASE_RELATIVE=y)\n        - kallsyms_relative_base (v4.6~v6.3, CONFIG_KALLSYMS_BASE_RELATIVE=y)\n        - kallsyms_num_syms\n        - kallsyms_names\n        - kallsyms_markers\n        - kallsyms_seqs_of_names (v6.1.42~v6.8)\n        - kallsyms_token_table\n        - kallsyms_token_index\n        - kallsyms_offsets (v6.4~, CONFIG_KALLSYMS_BASE_RELATIVE=y)\n        - kallsyms_relative_base (v6.4~, CONFIG_KALLSYMS_BASE_RELATIVE=y)\n        - kallsyms_seqs_of_names (v6.9~)\n        - ...\n\n        [Sample values for 64bit ~v6.3, CONFIG_KALLSYMS_ABSOLUTE_PERCPU=n (use positive offset)]\n        gef> hexdump -n dword kallsyms_offsets\n        0xffffffff8b108550:    0x00000000 0x00000000 0x00001000 0x00002000    |  ............. ..  |\n        0xffffffff8b108560:    0x00006000 0x0000b000 0x0000c000 0x00018000    |  .`..............  |\n        0xffffffff8b108570:    0x00019000 0x00019008 0x00019010 0x00019020    |  ............ ...  |\n        0xffffffff8b108580:    0x00019420 0x00019440 0x00019448 0x00019450    |   ...@...H...P...  |\n\n        [Sample values for 64bit ~v6.3, CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y (use negative offset)]\n        gef> hexdump -n dword kallsyms_offsets\n        0xffffffffa72854b0:    0xffffffff 0xffffffff 0xffffffff 0xffffffbf    |  ................  |\n        0xffffffffa72854c0:    0xffffffba 0xfffffeef 0xfffffdef 0xfffffddf    |  ................  |\n        0xffffffffa72854d0:    0xfffffdcf 0xfffffa1f 0xfffff9cf 0xfffff9bf    |  ................  |\n        0xffffffffa72854e0:    0xfffff99f 0xfffff8ff 0xfffff76f 0xfffff73f    |  ........o...?...  |\n\n        [Sample values for 32bit ~v6.3, CONFIG_KALLSYMS_ABSOLUTE_PERCPU=n (use positive offset)]\n        gef> hexdump -n dword kallsyms_offsets\n        0xc6c59370:    0x00000000 0x00000000 0x00000000 0x00000070    |  ............p...  |\n        0xc6c59380:    0x00000080 0x000001d8 0x000002e0 0x00000320    |  ............ ...  |\n        0xc6c59390:    0x00000360 0x000003a8 0x000003e8 0x000004a8    |  `...............  |\n        0xc6c593a0:    0x000005a8 0x0000066c 0x0000073c 0x000007ac    |  ....l...<.......  |\n\n        [Sample values for 64bit v6.4~, CONFIG_KALLSYMS_ABSOLUTE_PERCPU=n (use positive offset)]\n        gef> hexdump -n word kallsyms_token_index\n        0xffffffff844fa178:    0x0000 0x0003 0x0006 0x000a 0x0010 0x0013 0x0016 0x0019    |  ................  |\n        0xffffffff844fa188:    0x001d 0x0029 0x002d 0x0030 0x0034 0x0037 0x003b 0x003e    |  ..).-.0.4.7.;.>.  |\n        0xffffffff844fa198:    0x0041 0x0056 0x005a 0x005e 0x0061 0x0064 0x0067 0x006a    |  A.V.Z.^.a.d.g.j.  |\n        ...\n        0xffffffff844fa358:    0x0386 0x0389 0x038c 0x038f 0x0392 0x0395 0x0398 0x039b    |  ................  |\n        0xffffffff844fa368:    0x039e 0x03a1 0x03a5 0x03a8 0x03ab 0x03ae 0x03b1 0x03b4    |  ................  |\n        gef> hexdump -n dword kallsyms_offset\n        0xffffffff844fa378:    0x00000000 0x00000000 0x00001000 0x00002000    |  ............. ..  |\n        0xffffffff844fa388:    0x00006000 0x0000b000 0x0000c000 0x00014000    |  .`...........@..  |\n        ...\n        0xffffffff8461e44c:    0xf89effff 0xf89dffff 0xf89d9fff 0xf89d9fff    |  ................  |\n        0xffffffff8461e45c:    0x00000000 0x81000000 0xffffffff 0x02fa0e02    |  ................  |\n        relative_base_address: 0xffffffff81000000\n\n        [Sample values for 64bit v6.4~, CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y (use negative offset)]\n        gef> hexdump -n word kallsyms_token_index\n        0xffffffff86744a38:    0x0000 0x0004 0x000c 0x0010 0x0014 0x0017 0x001b 0x0020    |  .............. .  |\n        0xffffffff86744a48:    0x002d 0x0034 0x0039 0x003d 0x0042 0x0045 0x0048 0x004b    |  -.4.9.=.B.E.H.K.  |\n        0xffffffff86744a58:    0x004f 0x0053 0x005d 0x0060 0x0064 0x0067 0x006b 0x0072    |  O.S.].`.d.g.k.r.  |\n        ...\n        0xffffffff86744c18:    0x0338 0x033b 0x033e 0x0341 0x0349 0x034c 0x034f 0x0357    |  8.;.>.A.I.L.O.W.  |\n        0xffffffff86744c28:    0x035a 0x035d 0x0360 0x0363 0x0369 0x036e 0x0372 0x0375    |  Z.].`.c.i.n.r.u.  |\n        gef> hexdump -n dword kallsyms_offset\n        0xffffffff86744c38:    0xffffffff 0xffffffff 0xffffffff 0xffffffaf    |  ................  |\n        0xffffffff86744c48:    0xffffffaa 0xfffffe9f 0xfffffe8f 0xfffffd8f    |  ................  |\n        ...\n        0xffffffff8677ed5c:    0xff09237f 0xff09218f 0xff09217f 0xff0920a9    |  .#...!...!... ..  |\n        0xffffffff8677ed6c:    0x00000000 0x85c00000 0xffffffff 0x00f0d800    |  ................  |\n        relative_base_address: 0xffffffff85c00000\n        \"\"\"\n\n        # const values\n        if Endian.is_big_endian():\n            endianness_marker = \">\"\n            endian_str = \"big\"\n        else:\n            endianness_marker = \"<\"\n            endian_str = \"little\"\n        offset_byte_size = 4\n        address_byte_size = current_arch.ptrsize\n\n        # get relative_base_address\n        if self.kernel_version < (6, 4, 0):\n            # ignore the 0 immediately above offset_kallsyms_num_syms.\n            position = self.offset_kallsyms_num_syms\n            while True:\n                previous_word = self.kernel_img[position - address_byte_size:position]\n                if previous_word != b\"\\0\" * address_byte_size:\n                    break\n                position -= address_byte_size\n\n            # Go backward by num_symbols.\n            position -= address_byte_size\n\n            # read from kallsyms_relative_base\n            relative_base_address = int.from_bytes(self.kernel_img[position:position + address_byte_size], endian_str)\n\n            if relative_base_address and (relative_base_address & get_pagesize_mask_low()) == 0:\n                \"\"\"\n                some environment has invalid address as relative_base_address.\n                so don't use the logic of is_valid_addr(relative_base_address).\n\n                gef> hexdump -n qword 0xffffafc5c2adb260-0x10 0x20\n                0xffffafc5c2adb250:    0xffffafc5c1750000 0x0000000000028193    |  ..u.............  |\n                0xffffafc5c2adb260:    0x6474107414bc5404 0x6c7463be6270d277    |  .T..t.tdw.pb.ctl  |\n                gef> x/16xg 0xffffafc5c1750000\n                0xffffafc5c1750000:     Cannot access memory at address 0xffffafc5c1750000\n                \"\"\"\n                while True:\n                    previous_word = self.kernel_img[position - offset_byte_size:position]\n                    if previous_word != b\"\\0\" * offset_byte_size:\n                        break\n                    position -= offset_byte_size\n                position -= self.num_symbols * offset_byte_size\n\n        else: # kernel_version >= (6, 4):\n            position = self.offset_kallsyms_token_index + 0x200\n            position_relative_base = align(position + self.num_symbols * offset_byte_size, current_arch.ptrsize)\n            relative_base_address_data = self.kernel_img[position_relative_base:position_relative_base + address_byte_size]\n            if len(relative_base_address_data) == 0:\n                self.verbose_err(\"kernel_img is not long enough.\")\n                return False\n            relative_base_address = int.from_bytes(relative_base_address_data, endian_str)\n            if not (relative_base_address and (relative_base_address & get_pagesize_mask_low()) == 0):\n                return True\n\n        # Getting here means that the relative_address and position have been detected correctly.\n        self.verbose_info(\"relative_base_address: {:#x}\".format(relative_base_address))\n\n        # Try to parse addresses or offsets.\n        fmt = \"{:s}{:d}i\".format(endianness_marker, self.num_symbols) # signed int\n        kallsyms_offsets_data = self.kernel_img[position:position + self.num_symbols * offset_byte_size]\n        ksym_offsets = struct.unpack(fmt, kallsyms_offsets_data)\n\n        # Check the ratio of the negative value\n        number_of_negative_items = len([offset for offset in ksym_offsets if offset < 0])\n        if number_of_negative_items / len(ksym_offsets) >= 0.5:\n            # the case CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y.\n            kernel_addresses = []\n            for offset in ksym_offsets:\n                if offset < 0:\n                    x = relative_base_address - 1 - offset\n                    kernel_addresses.append(x)\n                else:\n                    kernel_addresses.append(offset)\n        else:\n            # the case CONFIG_KALLSYMS_ABSOLUTE_PERCPU=n.\n            kernel_addresses = []\n            for offset in ksym_offsets:\n                x = offset + relative_base_address\n                kernel_addresses.append(x)\n\n        # Check the ratio of the null value.\n        number_of_null_items = kernel_addresses.count(0)\n        if number_of_null_items / len(kernel_addresses) >= 0.2:\n            return True\n\n        # It seems ok.\n        self.offset_kallsyms_addresses_or_offsets = position\n        self.kernel_addresses = kernel_addresses\n        self.verbose_info(\"kallsyms_offsets: {:#x}\".format(self.ro_base + self.offset_kallsyms_addresses_or_offsets))\n        return True\n\n    def find_kallsyms_addresses(self):\n        \"\"\"\n        [Search strategy]\n        - From kallsyms_num_syms, go back by num_symbols element sizes.\n        - num_symbols addresses are stored, so get them.\n\n        [Positional relationship]\n        - ...\n        - kallsyms_addresses (~v6.3, CONFIG_KALLSYMS_BASE_RELATIVE=n)\n        - kallsyms_num_syms\n        - kallsyms_names\n        - kallsyms_markers\n        - kallsyms_seqs_of_names (v6.1.42~v6.8)\n        - kallsyms_token_table\n        - kallsyms_token_index\n        - kallsyms_addresses (v6.4~?, CONFIG_KALLSYMS_BASE_RELATIVE=n) # Unimplemented, as this pattern has not been observed yet.\n        - kallsyms_seqs_of_names (v6.9~)\n        - ...\n\n        [Sample values for 64bit ~v6.3]\n        gef> hexdump -n qword kallsyms_addresses\n        0xffffffff81ae3cb8:    0x0000000000000000 0x0000000000000000    |  ................  |\n        0xffffffff81ae3cc8:    0x0000000000004000 0x0000000000009000    |  .@..............  |\n        ...\n        0xffffffff81ae4588:    0xffffffff81000000 0xffffffff81000000    |  ................  |\n        0xffffffff81ae4598:    0xffffffff81000110 0xffffffff810001a9    |  ................  |\n\n        [Sample values for 32bit ~v6.3]\n        gef> hexdump -n dword kallsyms_addresses\n        0xc1940888:    0xc1000000 0xc1000000 0xc10000bc 0xc10000cc    |  ................  |\n        0xc1940898:    0xc10000ed 0xc1000165 0xc10001e7 0xc1000239    |  ....e.......9...  |\n        0xc19408a8:    0xc1000283 0xc10002c1 0xc10002d0 0xc1000302    |  ................  |\n        0xc19408b8:    0xc1000328 0xc100032f 0xc1000338 0xc1000338    |  (.../...8...8...  |\n        \"\"\"\n\n        # const values\n        if Endian.is_big_endian():\n            endianness_marker = \">\"\n        else:\n            endianness_marker = \"<\"\n        address_byte_size = current_arch.ptrsize\n\n        # ignore the 0 immediately above offset_kallsyms_num_syms.\n        position = self.offset_kallsyms_num_syms\n        while True:\n            previous_word = self.kernel_img[position - address_byte_size:position]\n            if previous_word != b\"\\0\" * address_byte_size:\n                break\n            position -= address_byte_size\n\n        # Go backward by num_symbols.\n        position -= self.num_symbols * address_byte_size\n\n        # Try to parse addresses.\n        if address_byte_size == 8:\n            fmt = \"{:s}{:d}Q\".format(endianness_marker, self.num_symbols)\n        else:\n            fmt = \"{:s}{:d}I\".format(endianness_marker, self.num_symbols)\n        kallsyms_addresses_data = self.kernel_img[position:position + self.num_symbols * address_byte_size]\n        self.kernel_addresses = struct.unpack(fmt, kallsyms_addresses_data)\n        self.offset_kallsyms_addresses_or_offsets = position\n        self.verbose_info(\"kallsyms_addresses: {:#x}\".format(self.ro_base + self.offset_kallsyms_addresses_or_offsets))\n        return True\n\n    def initialize(self):\n        ret = self.get_kernel_version()\n        if not ret:\n            return False\n\n        if self.args.rescan:\n            cfg_file_name = self.get_cfg_name()\n            if os.path.exists(cfg_file_name):\n                os.remove(cfg_file_name)\n        else:\n            # the case of both kernel version string are same, but offset are different.\n            current_version_string_offset = self.version_string_offset # keep current\n            if self.get_saved_config([\"version_string_offset\"]): # load temporarily\n                if self.version_string_offset != current_version_string_offset:\n                    cfg_file_name = self.get_cfg_name()\n                    os.remove(cfg_file_name)\n                    self.version_string_offset = current_version_string_offset # set current again\n\n        ret = self.find_kallsyms_token_table()\n        if not ret:\n            return False\n\n        ret = self.find_kallsyms_token_index()\n        if not ret:\n            return False\n\n        ret = self.find_kallsyms_markers()\n        if not ret:\n            return False\n\n        ret = self.find_kallsyms_names()\n        if not ret:\n            return False\n\n        ret = self.find_kallsyms_num_syms()\n        if not ret:\n            return False\n\n        self.offset_kallsyms_addresses_or_offsets = None\n        if self.kernel_version >= (4, 6):\n            # On modern kernels, first check the case CONFIG_KALLSYMS_BASE_RELATIVE=y.\n            ret = self.find_kallsyms_offsets()\n            if not ret:\n                return False\n\n        if not self.offset_kallsyms_addresses_or_offsets:\n            # the case CONFIG_KALLSYMS_BASE_RELATIVE=n.\n            self.find_kallsyms_addresses()\n\n        self.save_config(\"version_string\")\n        self.save_config(\"version_string_offset\")\n        self.save_config(\"ro_size\")\n        return True\n\n    def arm64_fast_path(self):\n        if not is_in_kernel():\n            self.quiet_info(\"Use slow path\")\n            return False\n\n        # This path is more faster because it does not use pagewalk.\n        # Instead of finding ro_base from pagewalk results, it finds ro_base by scanning the kernel version.\n        # It is especially beneficial for ARM64, due to extensive pagetables and pagewalk take a long time.\n        # It may work on other architectures but limited to ARM64 as others gain little.\n\n        # First, search for the kernel version string from $pc.\n        # It is located at around top of ro_base, and ro_base is aligned by 0x10000.\n        current = (current_arch.pc & ~0xffff) + 0x10000 # Starting address to brute force ro_base\n        step_size = 0x10000\n        while True:\n            try:\n                # As kernel version string is near the top of ro_base, it is enough to check the first page.\n                candidate_rodata = read_memory(current, get_pagesize())\n            except gdb.MemoryError:\n                # reached to the end of ro_base\n                self.quiet_info(\"Use slow path\")\n                return False\n\n            # '\\n\\0' is needed to avoid false positives in the dmesg buffer.\n            r = re.search(rb\"Linux version (\\d+\\.[\\d.]*\\d)[ -~]+\\n\\0\", candidate_rodata)\n            if r:\n                # Found kernel version string\n                version_string_address = current + r.span()[0]\n                self.version_string = r.group(0)[:-2]\n                version_number = r.group(1).decode(\"ascii\")\n                self.kernel_version = self.get_kernel_version_triplet(version_number)\n                break\n            current += step_size\n\n        # We can make the hash from the kernel version string and load from saved config.\n        # At this point, following two parameters are enough.\n        ret = self.get_saved_config([\n            \"version_string_offset\",\n            \"ro_size\",\n        ])\n        if not ret:\n            self.quiet_info(\"Use slow path\")\n            return False\n\n        # Restore ro_base with considering kASLR.\n        self.quiet_info(\"Use fast path\")\n        self.ro_base = version_string_address - self.version_string_offset\n        self.verbose_info(\"ro_base: {:#x}-{:#x}\".format(self.ro_base, self.ro_base + self.ro_size))\n\n        # doit\n        self.kernel_img = read_memory(self.ro_base, self.ro_size)\n        ret = self.initialize()\n        if not ret:\n            self.quiet_info(\"Use slow path\")\n            return False\n\n        self.read_kallsyms()\n        return True\n\n    def parse_kallsyms(self):\n        if self.kallsyms:\n            return True # use cache\n\n        # Fast path when reattaching GDB after executing this command once (ARM64 only).\n        if is_arm64():\n            ret = self.arm64_fast_path()\n            if ret:\n                return True\n\n        # Slow path\n        try:\n            kinfo = Kernel.get_kernel_layout()\n            if kinfo.has_none:\n                return False\n        except gdb.MemoryError:\n            self.quiet_err(\"Memory read error\")\n            return False\n\n        if not kinfo.rwx:\n            # On modern kernels, ro_size can be trusted, so it only tries to parse once.\n            self.ro_base = kinfo.ro_base\n            self.ro_size = kinfo.ro_size\n            self.kernel_img = read_memory(self.ro_base, self.ro_size)\n            self.verbose_info(\"ro_base: {:#x}-{:#x}\".format(self.ro_base, self.ro_base + self.ro_size))\n            ret = self.initialize()\n            if not ret:\n                return False\n        else:\n            # Older kernel that has the RWX attribute don't trust ro_size.\n            # Very large values of ro_size can be detected.\n            # It will take a long time to parse if you just use it.\n            # Gradually increasing ro_size while searching can speed up several times.\n            self.ro_base = kinfo.ro_base\n            # This value is a heuristic threshold derived through testing across numerous kernel images.\n            # Unless there is a compelling reason, do not modify it.\n            base_size = 0x10_0000\n            step = 0x10_0000\n            for candidate_size in range(base_size, kinfo.ro_size, step):\n                self.ro_size = candidate_size\n                self.kernel_img = read_memory(self.ro_base, self.ro_size)\n                self.verbose_info(\"ro_base: {:#x}-{:#x}\".format(self.ro_base, self.ro_base + self.ro_size))\n                ret = self.initialize()\n                if ret:\n                    # found\n                    break\n            else:\n                # not found\n                return False\n\n        # here, we got all offsets to read kallsyms\n        self.read_kallsyms()\n        return True\n\n    def parse_main(self):\n        if self.kallsyms:\n            return True\n\n        # specified vmlinux parse\n        if self.args.vmlinux_file:\n            if not os.path.exists(self.args.vmlinux_file):\n                self.quiet_err(\"Could not find vmlinux file\")\n                return False\n            self.quiet_info(\"Parse from file: {!s}\".format(self.args.vmlinux_file))\n            self.parse_vmlinux(self.args.vmlinux_file)\n            return True\n\n        # loaded vmlinux parse\n        loaded_vmlinux = self.get_loaded_vmlinux_path()\n        if loaded_vmlinux:\n            self.quiet_info(\"Parse from file: {!s}\".format(loaded_vmlinux))\n            self.parse_vmlinux(loaded_vmlinux)\n            return True\n\n        # normal parse\n        self.quiet_info(\"Wait for memory scan\")\n        ret = self.parse_kallsyms()\n        if ret:\n            return True\n\n        # failed, but if args.rescan was not specified originally\n        if not self.args.rescan:\n            self.quiet_info(\"Try to rescan (ignore cached config)\")\n            self.kallsyms = []\n            ret = self.parse_kallsyms()\n            if ret:\n                return True\n\n        self.quiet_err(\"Failed to parse\")\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    def do_invoke(self, args):\n        if args.print_saved_config:\n            self.print_saved_config()\n            return\n\n        if self.args.rescan:\n            self.kallsyms = []\n\n        ret = self.parse_main()\n        if not ret:\n            return\n\n        self.print_kallsyms(args.keyword, args.type, args.smart)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass VmlinuxToElfApplyCommand(GenericCommand):\n    \"\"\"Apply symbol from kallsyms in memory using vmlinux-to-elf.\"\"\"\n\n    _cmdline_ = \"vmlinux-to-elf-apply\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\",\n                        help=\"force applying again. (default: reuse vmlinux-to-elf-dump-memory.elf if exists)\")\n    _syntax_ = parser.format_help()\n\n    @staticmethod\n    def dump_kernel_elf(rescan=False):\n        \"\"\"Dump the kernel from the memory, then apply vmlinux-to-elf to create symboled ELF.\"\"\"\n        # check\n        try:\n            vmlinux2elf = GefUtil.which(\"vmlinux-to-elf\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return None\n\n        # resolve kversion for saved file name\n        kversion = Kernel.kernel_version()\n        h = hashlib.sha256(String.str2bytes(kversion.version_string)).hexdigest()[-16:]\n        dumped_mem_file = os.path.join(GEF_TEMP_DIR, \"dump-memory-{:s}.raw\".format(h))\n        symboled_vmlinux_file = os.path.join(GEF_TEMP_DIR, \"dump-memory-{:s}.elf\".format(h))\n\n        # check if it can be reused\n        if (not rescan) and os.path.exists(symboled_vmlinux_file) and os.path.getsize(symboled_vmlinux_file) > 0:\n            info(\"A previously used file found, will be reused\")\n            return symboled_vmlinux_file\n\n        # resolve text_base, ro_base\n        kinfo = Kernel.get_kernel_layout()\n        if None in (kinfo.text_base, kinfo.text_size, kinfo.ro_base, kinfo.ro_size):\n            err(\"Failed to resolve\")\n            return None\n        gef_print(\"kernel base:   {:#x}-{:#x} ({:#x} bytes)\".format(kinfo.text_base, kinfo.text_end, kinfo.text_size))\n        gef_print(\"kernel rodata: {:#x}-{:#x} ({:#x} bytes)\".format(kinfo.ro_base, kinfo.ro_end, kinfo.ro_size))\n\n        info(\"Start memory dump\")\n        # rodata size detection may be inaccurate on kernels with RWX attribute regions.\n        # Since they tend to be very large, we put a size cap on the rodata to make it faster.\n        if kinfo.rwx:\n            # The number 0x400000 has no basis.\n            fixed_ro_base_size = min(0x40_0000, kinfo.ro_size)\n        else:\n            fixed_ro_base_size = kinfo.ro_size\n\n        # delete old file\n        if os.path.exists(dumped_mem_file):\n            gef_print(\"Delete old {:s}\".format(dumped_mem_file))\n            os.unlink(dumped_mem_file)\n        if os.path.exists(symboled_vmlinux_file):\n            gef_print(\"Delete old {:s}\".format(symboled_vmlinux_file))\n            os.unlink(symboled_vmlinux_file)\n\n        # delete files related to old file\n        for f in os.listdir(GEF_TEMP_DIR):\n            if os.path.basename(dumped_mem_file) in f:\n                remove_file = os.path.join(GEF_TEMP_DIR, f)\n                gef_print(\"Delete old {:s}\".format(remove_file))\n                os.unlink(remove_file)\n            if os.path.basename(symboled_vmlinux_file) in f:\n                remove_file = os.path.join(GEF_TEMP_DIR, f)\n                gef_print(\"Delete old {:s}\".format(remove_file))\n                os.unlink(remove_file)\n\n        # dump text\n        start = kinfo.text_base\n        end = start + kinfo.text_size\n        gef_print(\"Dumping .text area:   {:#x} - {:#x}\".format(start, end))\n        try:\n            gdb.execute(\"dump memory {} {:#x} {:#x}\".format(dumped_mem_file, start, end), to_string=True)\n        except gdb.MemoryError:\n            err(\"Memory read error. Make sure the context is in supervisor mode / Ring-0\")\n            return None\n\n        # dump sparse\n        text_end = kinfo.text_end\n        unmapped_size = kinfo.ro_base - text_end\n        if unmapped_size:\n            gef_print(\"Non-mapping area:     {:#x} - {:#x} (ZERO fill)\".format(text_end, kinfo.ro_base))\n            open(dumped_mem_file, \"a\").write(\"\\0\" * unmapped_size)\n\n        # dump rodata\n        start = kinfo.ro_base\n        end = start + fixed_ro_base_size\n        gef_print(\"Dumping .rodata area: {:#x} - {:#x}\".format(start, end))\n        try:\n            gdb.execute(\"append memory {} {:#x} {:#x}\".format(dumped_mem_file, start, end), to_string=True)\n        except gdb.MemoryError:\n            err(\"Memory read error. Make sure the context is in supervisor mode / Ring-0\")\n            return None\n\n        gef_print(\"Dumped to {:s}\".format(dumped_mem_file))\n\n        # apply vmlinux-to-elf\n        cmd = \"{!r} {!r} {!r} --base-address={:#x}\".format(vmlinux2elf, dumped_mem_file, symboled_vmlinux_file, kinfo.text_base)\n        warn(\"Execute `{:s}`\".format(cmd))\n        os.system(cmd)\n\n        # Error\n        if not os.path.exists(symboled_vmlinux_file) or os.path.getsize(symboled_vmlinux_file) == 0:\n            return None\n\n        # Success\n        return symboled_vmlinux_file\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        info(\"Wait for memory scan\")\n\n        text_base = Kernel.get_kernel_base()\n        if text_base is None:\n            err(\"Failed to resolve kbase\")\n            return\n\n        symboled_vmlinux_file = self.dump_kernel_elf(args.rescan)\n        if symboled_vmlinux_file is None:\n            err(\"Failed to create kernel ELF\")\n            return\n\n        # load symbol\n        info(\"Adding symbol\")\n        # Prior to gdb 8.x, add-symbol-file command requires a .text address\n        #   gdb 9.x: Usage: add-symbol-file FILE [-readnow | -readnever] [-o OFF] [ADDR] [-s SECT-NAME SECT-ADDR]...\n        #   gdb 8.x: Usage: add-symbol-file FILE ADDR [-readnow | -readnever | -s SECT-NAME SECT-ADDR]...\n        # But the created ELF has no .text, only a .kernel\n        # Applying an empty symbol has no effect, so tentatively specify the same address as the .kernel.\n        cmd = \"add-symbol-file {!r} {:#x} -s .kernel {:#x}\".format(symboled_vmlinux_file, text_base, text_base)\n        warn(\"Execute `{:s}`\".format(cmd))\n        gdb.execute(cmd)\n        return\n\n\n@register_command\nclass TcmallocDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"tcmalloc (google-perftools-2.16) free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"tcmalloc-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-c\", \"--central\", action=\"store_true\",\n                        help=\"show central cache instead of thread caches.\")\n    parser.add_argument(\"-f\", \"--force-heuristic\", action=\"store_true\", help=\"use heuristic detection.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}            # print freelist of thread cache for all thread\",\n        \"{0:s} --central  # print freelist of central cache\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    def initialize(self):\n        \"\"\"\n        gef> dt 'tcmalloc::ThreadCache'\n        struct tcmalloc::ThreadCache {\n            /* offset | size   */\n            /*        | 0x0008 */    class tcmalloc::ThreadCache * thread_heaps_;\n            /*        | 0x0004 */    int thread_heap_count_;\n            /*        | 0x0008 */    class tcmalloc::ThreadCache * next_memory_steal_;\n            /*        | 0x0008 */    struct std::atomic<unsigned long> min_per_thread_cache_size_;\n            /*        | 0x0008 */    size_t overall_thread_cache_size_;\n            /*        | 0x0008 */    volatile size_t per_thread_cache_size_;\n            /*        | 0x0008 */    ssize_t unclaimed_cache_space_;\n            /* 0x0000 | 0x1000 */    class tcmalloc::ThreadCache::FreeList [128] list_;\n            /* 0x1000 | 0x0004 */    int32_t size_;\n            /* 0x1004 | 0x0004 */    int32_t max_size_;\n            /* 0x1008 | 0x0018 */    class tcmalloc::Sampler sampler_;\n            /* 0x1020 | 0x0008 */    class tcmalloc::ThreadCache * next_;\n            /* 0x1028 | 0x0008 */    class tcmalloc::ThreadCache * prev_;\n        } // total: 0x1040 bytes\n        gef> p tcmalloc::Static::sizemap\n        \"\"\"\n        kClassSizesMax = 128\n        self.ThreadCache_offset_next = 0x1020\n        self.ThreadCache_offset_freelist_array = 0x0\n        self.ThreadCache_freelist_slot_count = kClassSizesMax\n\n        \"\"\"\n        gef> dt 'tcmalloc::ThreadCache::FreeList'\n        struct tcmalloc::ThreadCache::FreeList {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    void * list_;\n            /* 0x0008 | 0x0004 */    uint32_t length_;\n            /* 0x000c | 0x0004 */    uint32_t lowater_;\n            /* 0x0010 | 0x0004 */    uint32_t max_length_;\n            /* 0x0014 | 0x0004 */    uint32_t length_overages_;\n            /* 0x0018 | 0x0004 */    int32_t size_;\n        } // total: 0x20 bytes\n        gef>\n        \"\"\"\n        self.sizeof_FreeList = 0x20\n        self.FreeList_offset_list = 0x0\n        self.FreeList_offset_length = 0x8\n        self.FreeList_offset_size = 0x18\n\n        \"\"\"\n        gef> ptype 'tcmalloc::Static::central_cache_'\n        type = class tcmalloc::CentralFreeList {\n            ...\n        } [128]\n\n        gef> dt 'tcmalloc::CentralFreeList'\n        struct tcmalloc::CentralFreeList {\n            /* offset | size   */\n            /*        | 0x0004 */    const int kMaxNumTransferEntries;\n            /* 0x0000 | 0x0004 */    class SpinLock lock_;\n            /* 0x0008 | 0x0008 */    size_t size_class_;\n            /* 0x0010 | 0x0030 */    struct tcmalloc::Span empty_;\n            /* 0x0040 | 0x0030 */    struct tcmalloc::Span nonempty_;\n            /* 0x0070 | 0x0008 */    size_t num_spans_;\n            /* 0x0078 | 0x0008 */    size_t counter_;\n            /* 0x0080 | 0x0400 */    struct tcmalloc::CentralFreeList::TCEntry [64] tc_slots_;\n            /* 0x0480 | 0x0004 */    int32_t used_slots_;\n            /* 0x0484 | 0x0004 */    int32_t cache_size_;\n            /* 0x0488 | 0x0004 */    int32_t max_cache_size_;\n        } // total: 0x4c0 bytes\n        gef>\n\n        gef> dt 'tcmalloc::CentralFreeList::TCEntry'\n        struct tcmalloc::CentralFreeList::TCEntry {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    void * head;\n            /* 0x0008 | 0x0008 */    void * tail;\n        } // total: 0x10 bytes\n        gef>\n        \"\"\"\n        self.CentralCache_array_count = kClassSizesMax\n        kMaxNumTransferEntries = 64\n        self.CentralCache_freelist_slot_count = kMaxNumTransferEntries\n        self.sizeof_CentralCache = 0x4c0\n        self.CentralCache_offset_size_class_ = 0x8\n        self.CentralCache_offset_tc_slots_ = 0x80\n        self.CentralCache_offset_used_slots_ = 0x480\n\n        # for central cache\n        \"\"\"\n        gef> dt 'tcmalloc::SizeMap'\n        struct tcmalloc::SizeMap {\n            /* offset | size   */\n            /*        | 0x0004 */    const int kMaxSmallSize;\n            /*        | 0x0008 */    const size_t kClassArraySize;\n            /* 0x0000 | 0x0879 */    unsigned char [2169] class_array_;\n            /* 0x087c | 0x0200 */    int [128] num_objects_to_move_;\n            /* 0x0a7c | 0x0200 */    int32_t [128] class_to_size_;\n            /* 0x0c80 | 0x0400 */    size_t [128] class_to_pages_;\n            /* 0x1080 | 0x0008 */    size_t min_span_size_in_pages_;\n            /* 0x1088 | 0x0008 */    size_t num_size_classes;\n        } // total: 0x1090 bytes\n        gef>\n\n        gef> hexdump dword \"(long)&'tcmalloc::Static::sizemap_'+0xa7c\" 400\n        0x7ffff7fb03dc:    0x00000000 0x00000008 0x00000010 0x00000020\n        0x7ffff7fb03ec:    0x00000030 0x00000040 0x00000050 0x00000060\n        0x7ffff7fb03fc:    0x00000070 0x00000080 0x00000090 0x000000a0\n        0x7ffff7fb040c:    0x000000b0 0x000000c0 0x000000d0 0x000000e0\n        0x7ffff7fb041c:    0x000000f0 0x00000100 0x00000120 0x00000140\n        0x7ffff7fb042c:    0x00000160 0x00000180 0x000001a0 0x000001c0\n        0x7ffff7fb043c:    0x000001e0 0x00000200 0x00000240 0x00000280\n        0x7ffff7fb044c:    0x000002c0 0x00000300 0x00000380 0x00000400\n        0x7ffff7fb045c:    0x00000480 0x00000500 0x00000580 0x00000600\n        0x7ffff7fb046c:    0x00000700 0x00000800 0x00000900 0x00000a00\n        0x7ffff7fb047c:    0x00000b00 0x00000c00 0x00000d00 0x00001000\n        0x7ffff7fb048c:    0x00001200 0x00001400 0x00001800 0x00001a00\n        0x7ffff7fb049c:    0x00002000 0x00002400 0x00002800 0x00003000\n        0x7ffff7fb04ac:    0x00003400 0x00004000 0x00005000 0x00006000\n        0x7ffff7fb04bc:    0x00006800 0x00008000 0x0000a000 0x0000c000\n        0x7ffff7fb04cc:    0x0000e000 0x00010000 0x00012000 0x00014000\n        0x7ffff7fb04dc:    0x00016000 0x00018000 0x0001a000 0x0001c000\n        0x7ffff7fb04ec:    0x0001e000 0x00020000 0x00022000 0x00024000\n        0x7ffff7fb04fc:    0x00026000 0x00028000 0x0002a000 0x0002c000\n        0x7ffff7fb050c:    0x0002e000 0x00030000 0x00032000 0x00034000\n        0x7ffff7fb051c:    0x00036000 0x00038000 0x0003a000 0x0003c000\n        0x7ffff7fb052c:    0x0003e000 0x00040000 0x00000000 0x00000000\n        0x7ffff7fb053c:    0x00000000 0x00000000 0x00000000 0x00000000\n        *\n        gef>\n        \"\"\"\n        self.class_to_size_dic = [\n            0x00000000, 0x00000008, 0x00000010, 0x00000020,\n            0x00000030, 0x00000040, 0x00000050, 0x00000060,\n            0x00000070, 0x00000080, 0x00000090, 0x000000a0,\n            0x000000b0, 0x000000c0, 0x000000d0, 0x000000e0,\n            0x000000f0, 0x00000100, 0x00000120, 0x00000140,\n            0x00000160, 0x00000180, 0x000001a0, 0x000001c0,\n            0x000001e0, 0x00000200, 0x00000240, 0x00000280,\n            0x000002c0, 0x00000300, 0x00000380, 0x00000400,\n            0x00000480, 0x00000500, 0x00000580, 0x00000600,\n            0x00000700, 0x00000800, 0x00000900, 0x00000a00,\n            0x00000b00, 0x00000c00, 0x00000d00, 0x00001000,\n            0x00001200, 0x00001400, 0x00001800, 0x00001a00,\n            0x00002000, 0x00002400, 0x00002800, 0x00003000,\n            0x00003400, 0x00004000, 0x00005000, 0x00006000,\n            0x00006800, 0x00008000, 0x0000a000, 0x0000c000,\n            0x0000e000, 0x00010000, 0x00012000, 0x00014000,\n            0x00016000, 0x00018000, 0x0001a000, 0x0001c000,\n            0x0001e000, 0x00020000, 0x00022000, 0x00024000,\n            0x00026000, 0x00028000, 0x0002a000, 0x0002c000,\n            0x0002e000, 0x00030000, 0x00032000, 0x00034000,\n            0x00036000, 0x00038000, 0x0003a000, 0x0003c000,\n            0x0003e000, 0x00040000,\n        ]\n\n        return\n\n    def get_heap_key(self):\n        # for future use\n        return 0\n\n    def get_central_cache_(self):\n        if self.args.force_heuristic:\n            return None\n        try:\n            return AddressUtil.parse_address(\"&'tcmalloc::Static::central_cache_'\")\n        except gdb.error:\n            return None\n\n    def get_central_cache_heuristic(self):\n        self.quiet_info(\"Use heuristic search for central_cache_\")\n\n        \"\"\"\n        gef> dt 'tcmalloc::Span'\n        struct tcmalloc::Span {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    PageID start;\n            /* 0x0008 | 0x0008 */    Length length;\n            /* 0x0010 | 0x0008 */    struct tcmalloc::Span * next;\n            /* 0x0018 | 0x0008 */    struct tcmalloc::Span * prev;\n            /* 0x0020 | 0x0008 */    union {...} ;\n            /* 0x0028 | 0x0004 */    unsigned int refcount : 16;\n            /* 0x002a | 0x0004 */    unsigned int sizeclass : 8;\n            /* 0x002b | 0x0004 */    unsigned int location : 2;\n            /* 0x002b | 0x0004 */    unsigned int sample : 1;\n            /* 0x002b | 0x0001 */    bool has_span_iter : 1;\n        } // total: 0x30 bytes\n        gef>\n\n        gef> telescope 0x00007ffff7e06800 -n\n              0x7ffff7e06800|+0x0000|+000: 0x0000000000000000 // lock_\n              0x7ffff7e06808|+0x0008|+001: 0x0000000000000000 // size_class_\n              0x7ffff7e06810|+0x0010|+002: 0x0000000000000000 // empty_.start\n              0x7ffff7e06818|+0x0018|+003: 0x0000000000000000 // empty_.length\n              0x7ffff7e06820|+0x0020|+004: 0x00007ffff7e06810 // empty_.next\n              0x7ffff7e06828|+0x0028|+005: 0x00007ffff7e06810 // empty_.prev\n              0x7ffff7e06830|+0x0030|+006: 0x0000000000000000 // empty_.union\n              0x7ffff7e06838|+0x0038|+007: 0x0000000000000000 // empty_.union\n              0x7ffff7e06840|+0x0040|+008: 0x0000000000000000 // nonempty_.start\n              0x7ffff7e06848|+0x0048|+009: 0x0000000000000000 // nonempty_.length\n              0x7ffff7e06850|+0x0050|+010: 0x00007ffff7e06840 // nonempty_.next\n              0x7ffff7e06858|+0x0058|+011: 0x00007ffff7e06840 // nonempty_.prev\n              0x7ffff7e06860|+0x0060|+012: 0x0000000000000000 // nonempty_.union\n              0x7ffff7e06868|+0x0068|+013: 0x0000000000000000 // nonempty_.union\n              0x7ffff7e06870|+0x0070|+014: 0x0000000000000000\n        \"\"\"\n        offset_next1 = 0x20\n        offset_prev1 = 0x28\n        offset_next2 = 0x50\n        offset_prev2 = 0x58\n\n        for m in ProcessMap.get_process_maps():\n            if \"[heap]\" in m.path:\n                continue\n            if m.permission != Permission.READ | Permission.WRITE:\n                continue\n            for current_page in range(m.page_start, m.page_end, get_pagesize()):\n                # fast check\n                x = read_memory(current_page, get_pagesize())\n                if set(x) == {0}:\n                    continue\n\n                # exact check\n                for current in range(current_page, current_page + get_pagesize(), current_arch.ptrsize):\n                    error = False\n                    for i in range(self.CentralCache_array_count):\n                        base = current + self.sizeof_CentralCache * i\n                        try:\n                            n1 = read_int_from_memory(base + offset_next1)\n                            p1 = read_int_from_memory(base + offset_prev1)\n                            n2 = read_int_from_memory(base + offset_next2)\n                            p2 = read_int_from_memory(base + offset_prev2)\n                        except gdb.MemoryError:\n                            error = True\n                            break\n                        if not is_valid_addr(n1):\n                            break\n                        if not is_valid_addr(p1):\n                            break\n                        if not is_valid_addr(n2):\n                            break\n                        if not is_valid_addr(p2):\n                            break\n                    if error:\n                        break\n                    if i > 40: # heuristic threshold\n                        return current\n        return None\n\n    def get_thread_heaps_(self):\n        if self.args.force_heuristic:\n            return None\n        try:\n            return AddressUtil.parse_address(\"&'tcmalloc::ThreadCache::thread_heaps_'\")\n        except gdb.error:\n            return None\n\n    def get_thread_heap_list_heuristic(self):\n        \"\"\"thread_heap_ itself cannot be found, so it returns the detected list.\"\"\"\n        self.quiet_info(\"Use heuristic search for thread_heap_\")\n\n        \"\"\"\n        gef> tls\n        $tls = 0x7ffff7c5e080\n        --------------------------------- TLS-0x80 ---------------------------------\n              0x7ffff7c5e000|+0x0000|+000: 0x00007ffff7bbffc0\n              0x7ffff7c5e008|+0x0008|+001: 0x00007ffff7bc08c0\n              0x7ffff7c5e010|+0x0010|+002: 0x0000000000000000\n              0x7ffff7c5e018|+0x0018|+003: 0x0000000000000000\n              0x7ffff7c5e020|+0x0020|+004: 0x0000000000000000\n              0x7ffff7c5e028|+0x0028|+005: 0x0000000000000000\n              0x7ffff7c5e030|+0x0030|+006: 0x0000000000000000\n              0x7ffff7c5e038|+0x0038|+007: 0x0000000000000000\n              0x7ffff7c5e040|+0x0040|+008: 0x0000000000000000\n              0x7ffff7c5e048|+0x0048|+009: 0x0000000000000000\n              0x7ffff7c5e050|+0x0050|+010: 0x0000000000000000\n              0x7ffff7c5e058|+0x0058|+011: 0x0000000000000000\n              0x7ffff7c5e060|+0x0060|+012: 0x0000000000000000\n              0x7ffff7c5e068|+0x0068|+013: 0x0000000000000000\n              0x7ffff7c5e070|+0x0070|+014: 0x0000555555599000  <-- here\n              0x7ffff7c5e078|+0x0078|+015: 0x0000000000000000\n        ------------------------------------ TLS -----------------------------------\n              0x7ffff7c5e080|+0x0000|+000: 0x00007ffff7c5e080\n              ...\n        \"\"\"\n\n        # search offset\n        for i in range(1, 8):\n            orig_thread = gdb.selected_thread()\n            orig_frame = gdb.selected_frame()\n\n            found = True\n            candidate_thread_heaps = []\n            candidate_next = []\n            candidate_prev = []\n            for thread in gdb.selected_inferior().threads():\n                thread.switch() # change thread\n\n                # search thread_heaps\n                tls = current_arch.get_tls()\n                if tls is None:\n                    continue\n\n                val = read_int_from_memory(tls - current_arch.ptrsize * i)\n                if not is_valid_addr(val):\n                    found = False\n                    break\n\n                p = read_int_from_memory(val + self.ThreadCache_offset_next)\n                b = read_int_from_memory(val + self.ThreadCache_offset_next + current_arch.ptrsize)\n                candidate_next.append(p)\n                candidate_next.append(b)\n                candidate_thread_heaps.append(val)\n\n            orig_thread.switch() # revert thread\n            orig_frame.select()\n\n            if not candidate_thread_heaps:\n                found = False\n\n            elif set(candidate_next) | set(candidate_prev) != set(candidate_thread_heaps) | {0}:\n                found = False\n\n            if found:\n                return candidate_thread_heaps\n\n        return None\n\n    def dump_thread_heap_freelist_single(self, freelist, idx):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        chunk = read_int_from_memory(freelist + self.FreeList_offset_list)\n        length = read_int_from_memory(freelist + self.FreeList_offset_length) & 0xffff_ffff\n        real_length = 0\n        error = False\n        if chunk != 0: # freelist exists\n            seen = []\n            out = []\n            while chunk != 0:\n                real_length += 1\n                seen.append(chunk)\n                # corrupted memory check\n                try:\n                    new_chunk = read_int_from_memory(chunk)\n                    out.append(\" -> \" + Color.colorify_hex(chunk, freed_address_color))\n                    chunk = new_chunk\n                except gdb.MemoryError:\n                    out.append(Color.colorify(\" -> {:#x} (corrupted)\".format(chunk), corrupted_msg_color))\n                    error = True\n                    break\n                # heap key decode\n                chunk ^= self.get_heap_key()\n                # loop check\n                if chunk in seen:\n                    out.append(Color.colorify(\" -> {:#x} (loop)\".format(chunk), corrupted_msg_color))\n                    error = True\n                    break\n            # corrupted length check\n            if length != real_length and error is False:\n                out.append(Color.colorify(\"    (length corrupted; len != {:d})\".format(length), corrupted_msg_color))\n                error = True\n\n            chunksize = read_int_from_memory(freelist + self.FreeList_offset_size)\n\n            # print\n            self.out.append(\"freelist[idx={:d}, size={:s}, len={:d}] @ {!s}\".format(\n                idx,\n                Color.colorify_hex(chunksize, chunk_size_color),\n                length,\n                ProcessMap.lookup_address(freelist),\n            ))\n            self.out.extend(out)\n        return\n\n    def dump_thread_heaps(self):\n        # exact way\n        thread_heap_head = self.get_thread_heaps_()\n        if thread_heap_head:\n            self.out.append(titlify(\"thread_heaps_ (head) @ {:#x}\".format(thread_heap_head)))\n\n            thread_heap = read_int_from_memory(thread_heap_head)\n            thread_heaps = []\n            while thread_heap:\n                thread_heaps.append(thread_heap)\n                thread_heap = read_int_from_memory(thread_heap + self.ThreadCache_offset_next)\n        else:\n            # heuristic way\n            thread_heaps = self.get_thread_heap_list_heuristic()\n            if thread_heaps is None:\n                err(\"Could not find tcmalloc::ThreadCache::thread_heaps_\")\n                return\n\n        heap_key = self.get_heap_key()\n        if heap_key != 0:\n            self.out.append(\"heap_key: {:#x} (xor chunk->fd)\".format(heap_key))\n\n        for thread_heap in thread_heaps:\n            self.out.append(titlify('thread cache @ {:#x}'.format(thread_heap)))\n            freelist = thread_heap + self.ThreadCache_offset_freelist_array\n            for i in range(self.ThreadCache_freelist_slot_count):\n                self.dump_thread_heap_freelist_single(freelist, i)\n                freelist += self.sizeof_FreeList\n        return\n\n    def dump_central_cache_freelist_single(self, freelist, i, j):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        chunk = read_int_from_memory(freelist + self.FreeList_offset_list)\n        if chunk != 0: # freelist exists\n            seen = []\n            out = []\n            while chunk != 0:\n                seen.append(chunk)\n                # corrupted memory check\n                try:\n                    new_chunk = read_int_from_memory(chunk)\n                    out.append(\" -> \" + Color.colorify_hex(chunk, freed_address_color))\n                    chunk = new_chunk\n                except gdb.MemoryError:\n                    out.append(Color.colorify(\" -> {:#x} (corrupted)\".format(chunk), corrupted_msg_color))\n                    break\n                # heap key decode\n                chunk ^= self.get_heap_key()\n                # loop check\n                if chunk in seen:\n                    out.append(Color.colorify(\" -> {:#x} (loop)\".format(chunk), corrupted_msg_color))\n                    break\n            # print\n            self.out.append(\"central_cache_[{:d}].tc_slot[{:d}] @ {!s}\".format(\n                i, j, ProcessMap.lookup_address(freelist),\n            ))\n            self.out.extend(out)\n        return\n\n    def dump_central_cache(self):\n        central_cache_ = self.get_central_cache_()\n        if central_cache_ is None:\n            central_cache_ = self.get_central_cache_heuristic()\n            if central_cache_ is None:\n                err(\"Could not find tcmalloc::Static::central_cache_\")\n                return\n        self.out.append(titlify(\"central_cache_ @ {:#x}\".format(central_cache_)))\n\n        heap_key = self.get_heap_key()\n        if heap_key != 0:\n            self.out.append(\"heap_key: {:#x} (xor chunk->fd)\".format(heap_key))\n\n        for i in range(self.CentralCache_array_count):\n            central_cache_i = central_cache_ + i * self.sizeof_CentralCache # &central_cache[i]\n\n            # check slot count\n            used_slots = read_int32_from_memory(central_cache_i + self.CentralCache_offset_used_slots_)\n            max_slots = self.CentralCache_freelist_slot_count\n            if used_slots == 0:\n                continue\n\n            # calc class -> size\n            size_class = read_int_from_memory(central_cache_i + self.CentralCache_offset_size_class_)\n            size_byte = self.class_to_size_dic[size_class]\n\n            # dump\n            self.out.append(titlify(\n                \"central_cache_[{:d}] @ {:#x} (used_slots:{:d}/{:d}, size_class:{:#x}, chunk_size:{:#x})\".format(\n                    i, central_cache_i, used_slots, max_slots, size_class, size_byte,\n                ),\n            ))\n            tc_slots = central_cache_i + self.CentralCache_offset_tc_slots_ # &central_cache[i].tc_slots_\n            for j in range(min(used_slots, self.CentralCache_freelist_slot_count)):\n                addr = tc_slots + j * 0x10 # &central_cache[i].tc_slots_[j]\n                self.dump_central_cache_freelist_single(addr, i, j)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        self.out = []\n        self.initialize()\n        if args.central:\n            self.dump_central_cache()\n        else:\n            self.dump_thread_heaps()\n        self.print_output()\n        return\n\n\n@register_command\nclass GoHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"go language v1.24.4 mheap dumper (x64 only).\"\"\"\n\n    _cmdline_ = \"go-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    # TODO: arena, central, mspan->next\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--mheap\", type=AddressUtil.parse_address, help=\"the address of runtime.mheap_.\")\n    parser.add_argument(\"--mspan\", type=AddressUtil.parse_address, help=\"the address of the target mspan.\")\n    parser.add_argument(\"-d\", \"--dump\", action=\"store_true\", help=\"with hexdump.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display also empty slots.\")\n    _syntax_ = parser.format_help()\n\n    class_to_size_dic = [\n        0x0,    0x8,    0x10,   0x18,\n        0x20,   0x30,   0x40,   0x50,\n        0x60,   0x70,   0x80,   0x90,\n        0xa0,   0xb0,   0xc0,   0xd0,\n        0xe0,   0xf0,   0x100,  0x120,\n        0x140,  0x160,  0x180,  0x1a0,\n        0x1c0,  0x1e0,  0x200,  0x240,\n        0x280,  0x2c0,  0x300,  0x380,\n        0x400,  0x480,  0x500,  0x580,\n        0x600,  0x700,  0x800,  0x900,\n        0xa80,  0xc00,  0xc80,  0xd80,\n        0x1000, 0x1300, 0x1500, 0x1800,\n        0x1980, 0x1a80, 0x1b00, 0x2000,\n        0x2500, 0x2600, 0x2800, 0x2a80,\n        0x3000, 0x3500, 0x3800, 0x4000,\n        0x4800, 0x4a80, 0x5000, 0x5500,\n        0x6000, 0x6a80, 0x7000, 0x8000,\n    ]\n\n    def get_struct_offset(self, type_name, member_name):\n        tp = GefUtil.cached_lookup_type(type_name)\n        if tp is None:\n            return None\n        if member_name not in tp:\n            return None\n        field = tp[member_name]\n        if not hasattr(field, \"bitpos\"):\n            return None\n        return field.bitpos // 8\n\n    def get_struct_size(self, type_name):\n        tp = GefUtil.cached_lookup_type(type_name)\n        if tp is None:\n            return None\n        return tp.sizeof\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        self.PageShift = 13\n        self.PageSize = 1 << self.PageShift\n\n        # assume 1.22.2 (Ubuntu 24.04)\n        \"\"\"\n        struct runtime.mheap {\n            /* offset | size   */\n            ...\n            /* 0x10148 | 0x0018 */    []*runtime.mspan allspans;\n            ...\n            /* 0x101d8 | 0x0008 */    [1]*[4194304]*runtime.heapArena arenas;\n            ...\n            /* 0x10288 | 0x6600 */    [136]struct { runtime.mcentral runtime.mcentral; runtime.pad [24]uint8 } central;\n            ...\n        } // total: 0x16ab8 bytes\n        \"\"\"\n\n        self.offset_allspans = self.get_struct_offset(\"runtime.mheap\", \"allspans\") or 0x10148\n        self.sizeof_mheap = self.get_struct_size(\"runtime.mheap\") or 0x16ab8\n\n        \"\"\"\n        struct runtime.mspan {\n            /* offset | size   */\n            ...\n            /* 0x0000 | 0x0008 */    runtime.mspan * next;\n            /* 0x0008 | 0x0008 */    runtime.mspan * prev;\n            ...\n            /* 0x0018 | 0x0008 */    uintptr startAddr;\n            /* 0x0020 | 0x0008 */    uintptr npages;\n            ...\n            /* 0x0032 | 0x0002 */    uint16 nelems;\n            ...\n            /* 0x0040 | 0x0008 */    runtime.gcBits * allocBits;\n            ...\n            /* 0x0062 | 0x0001 */    runtime.spanClass spanclass;\n            ...\n        } // total: 0xa0 bytes\n        \"\"\"\n        self.offset_next = self.get_struct_offset(\"runtime.mspan\", \"next\") or 0x0\n        self.offset_prev = self.get_struct_offset(\"runtime.mspan\", \"next\") or 0x8\n        self.offset_startAddr = self.get_struct_offset(\"runtime.mspan\", \"startAddr\") or 0x18\n        self.offset_npages = self.get_struct_offset(\"runtime.mspan\", \"npages\") or 0x20\n        self.offset_nelems = self.get_struct_offset(\"runtime.mspan\", \"nelems\") or 0x32\n        self.offset_allocBits = self.get_struct_offset(\"runtime.mspan\", \"allocBits\") or 0x40\n        self.offset_spanclass = self.get_struct_offset(\"runtime.mspan\", \"spanClass\") or 0x62\n\n        self.initialized = True\n        return True\n\n    def get_mheap_(self):\n        # use symbol\n        try:\n            return AddressUtil.parse_address(\"&'runtime.mheap_'\")\n        except gdb.error:\n            pass\n\n        # use heuristic search (TODO: Check if it is always correct)\n        elf = Elf.get_elf()\n        if elf is None or not elf.is_valid():\n            return None\n\n        bss = elf.get_shdr(\".bss\")\n        mheap = bss.sh_addr + bss.sh_size - self.sizeof_mheap\n        if is_valid_addr(mheap):\n            return mheap\n        return None\n\n    def parse_mheap(self, mheap):\n        self.out.append(titlify(\"runtime.mheap_ @ {:#x}\".format(mheap)))\n\n        current = read_int_from_memory(mheap + self.offset_allspans)\n        mspans = []\n        while True:\n            try:\n                mspan_addr = read_int_from_memory(current)\n            except gdb.MemoryError:\n                self.out.append(\"Memory read error\")\n                return []\n            if not mspan_addr:\n                break\n            mspan = self.parse_mspan(mspan_addr)\n            if mspan:\n                mspans.append(mspan)\n            current += current_arch.ptrsize\n\n        mspans = sorted(mspans, key=lambda m: (m.chunk_size, m.address))\n        return mspans\n\n    def parse_mspan(self, mspan):\n        # read member\n        try:\n            start_addr = read_int_from_memory(mspan + self.offset_startAddr)\n        except gdb.MemoryError:\n            self.out.append(\"Memory read error\")\n            return None\n        if not self.args.verbose and start_addr == 0:\n            return None\n\n        # spanclass = (sizeclass << 1) | (noscan bit)\n        spanclass = read_int8_from_memory(mspan + self.offset_spanclass) >> 1\n        chunk_size = self.class_to_size_dic[spanclass]\n        if not self.args.verbose and chunk_size == 0:\n            return None\n\n        next_ = read_int_from_memory(mspan + self.offset_next)\n        prev_ = read_int_from_memory(mspan + self.offset_prev)\n        npages = read_int_from_memory(mspan + self.offset_npages)\n        end_addr = start_addr + npages * self.PageSize\n\n        aligned_nelems = nelems = read_int_from_memory(mspan + self.offset_nelems) & 0xffff\n        while aligned_nelems % 8:\n            aligned_nelems += 1\n        allocBits_addr = read_int_from_memory(mspan + self.offset_allocBits)\n        allocBits_data = read_memory(allocBits_addr, aligned_nelems)\n        allocBits_array = [((b >> i) & 1) for b in allocBits_data for i in range(8)]\n\n        Mspan = collections.namedtuple(\"Mspan\", [\n            \"address\", \"next\", \"prev\", \"start_addr\", \"end_addr\", \"npages\", \"chunk_size\", \"nelems\", \"alloc_bits\",\n        ])\n        mspan = Mspan(mspan, next_, prev_, start_addr, end_addr, npages, chunk_size, nelems, allocBits_array[:nelems])\n        return mspan\n\n    def dump_mspan_data(self, mspan):\n        chunk_data = read_memory(mspan.start_addr, mspan.end_addr - mspan.start_addr)\n        chunk_hexdump = hexdump(chunk_data, base=mspan.start_addr, color=False, unit=8)\n        lines = chunk_hexdump.splitlines()\n\n        color_dic = {\n            # (b, idx % 2): color name\n            (0, 0): \"bright_yellow\",\n            (0, 1): \"yellow\",\n            (1, 0): \"graphite\",\n            (1, 1): \"bright_black\",\n        }\n\n        # coloring\n        for i in range(len(lines)):\n            line = lines[i]\n\n            offset1 = i * 0x10\n            idx1 = offset1 // mspan.chunk_size\n            if idx1 >= mspan.nelems:\n                color1 = \"\"\n            else:\n                b1 = mspan.alloc_bits[idx1]\n                color1 = color_dic[b1, idx1 % 2]\n\n            offset2 = i * 0x10 + 8\n            idx2 = offset2 // mspan.chunk_size\n            if idx2 >= mspan.nelems:\n                color2 = \"\"\n            else:\n                b2 = mspan.alloc_bits[idx2]\n                color2 = color_dic[b2, idx2 % 2]\n\n            lines[i] = \"{:s}{:s}{:s}{:s}{:s}\".format(\n                line[:19],\n                Color.colorify(line[19:37], color1),\n                line[37:38],\n                Color.colorify(line[38:56], color2),\n                line[56:],\n            )\n\n        self.out.extend(lines)\n        return\n\n    def dump_mspans(self, mspans):\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        page_address_color = Config.get_gef_setting(\"theme.heap_page_address\")\n\n        for mspan in mspans:\n            # meta data\n            chunk_size_str = Color.colorify_hex(mspan.chunk_size, chunk_size_color)\n            range_addr_str = Color.colorify_hex(mspan.start_addr, page_address_color)\n            range_addr_str += \"-\"\n            range_addr_str += Color.colorify_hex(mspan.end_addr, page_address_color)\n            range_size = mspan.end_addr - mspan.start_addr\n            msg = \"mspan @ {!s} [{:s} sz={:#x} chunk_size={:s} next={!s}, prev:{!s}]\".format(\n                ProcessMap.lookup_address(mspan.address),\n                range_addr_str, range_size, chunk_size_str,\n                ProcessMap.lookup_address(mspan.next),\n                ProcessMap.lookup_address(mspan.prev),\n            )\n            self.out.append(msg)\n            if self.args.dump:\n                self.dump_mspan_data(mspan)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        self.out = []\n        self.initialize()\n\n        if args.mspan is not None:\n            mspans = [self.parse_mspan(args.mspan)]\n        elif args.mheap:\n            mspans = self.parse_mheap(args.mheap)\n        else:\n            mheap = self.get_mheap_()\n            if mheap is None:\n                err(\"Could not find runtime.mheap_\")\n                return\n            mspans = self.parse_mheap(mheap)\n\n        mspans = [x for x in mspans if x is not None]\n        self.dump_mspans(mspans)\n        self.print_output()\n        return\n\n\n@register_command\nclass TlsfHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"TLSF (Two-Level Segregated Fit) v2.4.6 free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"tlsf-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--pool\", type=AddressUtil.parse_address, help=\"the address of memory pool.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display also empty slots.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__()\n\n        self.REAL_FLI = 24\n        self.MAX_SLI = 32\n\n        self.size_dic = {}\n        for i in range(1, 8):\n            self.size_dic[0, i * 4] = (0x10 * i, 0x10 * (i + 1))\n        for i in range(8):\n            self.size_dic[1, i * 4] = (0x80 + 0x10 * i, 0x80 + 0x10 * (i + 1))\n        for i in range(16):\n            self.size_dic[2, i * 2] = (0x100 + 0x10 * i, 0x100 + 0x10 * (i + 1))\n        for fl in range(3, self.REAL_FLI):\n            base = 0x200 * (2 ** (fl - 3))\n            step = 0x10 * (2 ** (fl - 3))\n            for i in range(self.MAX_SLI):\n                self.size_dic[fl, i] = (base + step * i, base + step * (i + 1))\n        return\n\n    def get_pool(self):\n        try:\n            mp = AddressUtil.parse_address(\"&mp\")\n        except gdb.error:\n            return None\n\n        if not is_valid_addr(mp):\n            return None\n\n        pool = read_int_from_memory(mp)\n        if not is_valid_addr(pool):\n            return None\n\n        if read_int32_from_memory(pool) == 0x2A59FA59: # TLSF_SIGNATURE\n            return pool\n        return None\n\n    def parse_pool(self, pool):\n        \"\"\"\n        typedef struct TLSF_struct {\n            u32_t tlsf_signature;\n\n        #if TLSF_USE_LOCKS\n            pthread_mutex_t lock;\n        #endif\n\n        #if TLSF_STATISTIC\n            size_t used_size;\n            size_t max_size;\n        #endif\n\n            area_info_t *area_head;\n            u32_t fl_bitmap;\n            u32_t sl_bitmap[REAL_FLI];\n            bhdr_t *matrix[REAL_FLI][MAX_SLI];\n        } tlsf_t;\n        \"\"\"\n        sig = read_int32_from_memory(pool)\n        if sig != 0x2A59FA59:\n            return None\n\n        area_head = None\n        if area_head is None:\n            # !TLSF_USE_LOCKS && !TLSF_STATISTIC\n            x = read_int_from_memory(pool + current_arch.ptrsize)\n            if is_valid_addr(x):\n                area_head = x\n                offset_area_head = current_arch.ptrsize\n        if area_head is None:\n            # !TLSF_USE_LOCKS && TLSF_STATISTIC\n            x = read_int_from_memory(pool + current_arch.ptrsize * 3)\n            if is_valid_addr(x):\n                area_head = x\n                offset_area_head = current_arch.ptrsize * 3\n        if area_head is None:\n            # TLSF_USE_LOCKS && !TLSF_STATISTIC\n            x = read_int_from_memory(pool + current_arch.ptrsize * 6)\n            if is_valid_addr(x):\n                area_head = x\n                offset_area_head = current_arch.ptrsize * 6\n        if area_head is None:\n            # TLSF_USE_LOCKS && TLSF_STATISTIC\n            x = read_int_from_memory(pool + current_arch.ptrsize * 8)\n            if is_valid_addr(x):\n                area_head = x\n                offset_area_head = current_arch.ptrsize * 8\n        if area_head is None:\n            return None\n\n        offset_fl_bitmap = offset_area_head + current_arch.ptrsize\n        fl_bitmap = read_int32_from_memory(pool + offset_fl_bitmap)\n\n        offset_sl_bitmap = offset_fl_bitmap + 4\n        sl_bitmap = read_memory(pool + offset_sl_bitmap, 4 * self.REAL_FLI)\n        sl_bitmap = slice_unpack(sl_bitmap, 4)\n\n        offset_matrix = align_to_ptrsize(offset_sl_bitmap + 4 * self.REAL_FLI)\n        matrix = read_memory(pool + offset_matrix, current_arch.ptrsize * self.REAL_FLI * self.MAX_SLI)\n        matrix = slice_unpack(matrix, current_arch.ptrsize)\n        matrix = slicer(matrix, self.MAX_SLI)\n\n        matrix_addr = [pool + offset_matrix + current_arch.ptrsize * i for i in range(self.REAL_FLI * self.MAX_SLI)]\n        matrix_addr = slicer(matrix_addr, self.MAX_SLI)\n\n        Pool = collections.namedtuple(\"Pool\", [\"addr\", \"sig\", \"area_head\", \"fl_bitmap\", \"sl_bitmap\", \"matrix\", \"matrix_addr\"])\n        return Pool(pool, sig, area_head, fl_bitmap, sl_bitmap, matrix, matrix_addr)\n\n    def dump_pool(self, pool):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        self.out.append(\"pool: {:#x}\".format(pool.addr))\n        self.out.append(\"pool->area_head: {:#x}\".format(pool.area_head))\n        for i, j in itertools.product(range(self.REAL_FLI), range(self.MAX_SLI)):\n            if self.args.verbose or pool.matrix[i][j]:\n                matrix_addr = pool.matrix_addr[i][j]\n                min_size, max_size = self.size_dic.get((i, j), (0, 0))\n                if min_size == max_size == 0:\n                    title = \"pool->matrix[{:2d}][{:2d}] @{:#x} (chunk_size=???-???)\".format(i, j, matrix_addr)\n                elif min_size + 0x10 == max_size:\n                    title = \"pool->matrix[{:2d}][{:2d}] @{:#x} (chunk_size={:#x})\".format(i, j, matrix_addr, min_size)\n                else:\n                    title = \"pool->matrix[{:2d}][{:2d}] @{:#x} (chunk_size={:#x}-{:#x})\".format(i, j, matrix_addr, min_size, max_size)\n                self.out.append(titlify(title))\n\n                current = pool.matrix[i][j]\n                seen = []\n                while True:\n                    if not is_valid_addr(current):\n                        if current == 0:\n                            msg = \" -> {:s}\".format(Color.colorify_hex(current, freed_address_color))\n                        else:\n                            msg = \" -> {:s} (corrupted)\".format(Color.colorify_hex(current, corrupted_msg_color))\n                        self.out.append(msg)\n                        break\n\n                    if current in seen:\n                        msg = \" -> {:s} (loop detected)\".format(Color.colorify_hex(current, corrupted_msg_color))\n                        self.out.append(msg)\n                        break\n\n                    seen.append(current)\n\n                    prev_hdr = read_int_from_memory(current + current_arch.ptrsize * 0)\n                    size = read_int_from_memory(current + current_arch.ptrsize * 1)\n                    prev_ = read_int_from_memory(current + current_arch.ptrsize * 2)\n                    next_ = read_int_from_memory(current + current_arch.ptrsize * 3)\n\n                    msg = \" -> {:s} (prev_hdr={:#x}, size={:s}, prev={!s}, next={!s})\".format(\n                        Color.colorify_hex(current, freed_address_color),\n                        prev_hdr,\n                        Color.colorify_hex(size & ~0xf, chunk_size_color),\n                        ProcessMap.lookup_address(prev_),\n                        ProcessMap.lookup_address(next_),\n                    )\n                    self.out.append(msg)\n                    current = next_\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        if args.pool:\n            pool_addr = args.pool\n        else:\n            pool_addr = self.get_pool()\n            if pool_addr is None:\n                err(\"Could not find pool\")\n                return\n\n        pool = self.parse_pool(pool_addr)\n        if pool is None:\n            err(\"Failed to parse pool\")\n            return\n\n        self.out = []\n        self.dump_pool(pool)\n        self.print_output()\n        return\n\n\n@register_command\nclass HoardHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Hoard v3.2 (2025/12/31) heap free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"hoard-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-b\", \"--superblock\", type=AddressUtil.parse_address, action=\"append\",\n                        help=\"the address of superblock.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_super_blocks(self):\n        super_blocks = []\n        for m in ProcessMap.get_process_maps():\n            if m.path.startswith((\"/\", \"[\")):\n                continue\n            if m.permission != Permission.READ | Permission.WRITE:\n                continue\n            for p in range(m.page_start, m.page_end, get_pagesize()):\n                if not is_valid_addr(p):\n                    continue\n                v = read_int_from_memory(p)\n                # vtable check\n                if not is_valid_addr(v):\n                    continue\n                # magic check\n                m = read_int_from_memory(p + current_arch.ptrsize)\n                if p ^ m != 0xcafe_d00d:\n                    continue\n                super_blocks.append(p)\n        return super_blocks\n\n    @Cache.cache_until_next\n    def get_all_freelist_head_candidate_from_tls(self):\n        orig_thread = gdb.selected_thread()\n        orig_frame = gdb.selected_frame()\n        threads = gdb.selected_inferior().threads()\n        if not threads:\n            return\n\n        direction = TlsCommand.get_direction()\n\n        head_candidates = []\n        for thread in threads:\n            try:\n                thread.switch()\n            except gdb.error:\n                continue\n            tls = current_arch.get_tls()\n\n            for i in range(1, 0x20):\n                head_candidate_addr = tls + current_arch.ptrsize * i * direction\n                head_candidate = read_int_from_memory(head_candidate_addr)\n                if not is_single_link_list(head_candidate):\n                    continue\n                head_candidates.append(head_candidate)\n        orig_thread.switch() # revert thread\n        orig_frame.select()\n        return head_candidates\n\n    def get_freelist_start(self, sb):\n        # pattern1: HoardSuperblockHeaderHelper->_freeList\n        freeList = read_int_from_memory(sb + current_arch.ptrsize * 11)\n        if freeList:\n            return freeList\n\n        # pattern2: thread variable holds it\n        objectSize = read_int_from_memory(sb + current_arch.ptrsize * 2)\n        totalObjects = read_int32_from_memory(sb + current_arch.ptrsize * 3 + 4)\n\n        sizeof_super_block_header = 0x70\n        sb_start = sb + sizeof_super_block_header\n        sb_end = sb_start + objectSize * totalObjects\n\n        heads = self.get_all_freelist_head_candidate_from_tls()\n        candidates = [h for h in heads if sb_start <= h < sb_end]\n        return candidates\n\n    def dump_super_block(self, sb):\n        \"\"\"\n        struct Hoard::HoardSuperblockHeaderHelper<...> {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    int (**)(void) _vptr.HoardSuperblockHeaderHelper;\n            /* 0x0008 | 0x0008 */    const size_t _magicNumber;\n            /* 0x0010 | 0x0008 */    const size_t _objectSize;\n            /* 0x0018 | 0x0001 */    const bool _objectSizeIsPowerOfTwo;\n            /* 0x001c | 0x0004 */    const unsigned int _totalObjects;\n            /* 0x0020 | 0x0001 */    class HL::SpinLockType _theLock;\n            /* 0x0028 | 0x0008 */    class Hoard::SmallHeap * _owner;\n            /* 0x0030 | 0x0008 */    Hoard::HoardSuperblockHeaderHelper<...>::BlockType * _prev;\n            /* 0x0038 | 0x0008 */    Hoard::HoardSuperblockHeaderHelper<...>::BlockType * _next;\n            /* 0x0040 | 0x0004 */    unsigned int _reapableObjects;\n            /* 0x0044 | 0x0004 */    unsigned int _objectsFree;\n            /* 0x0048 | 0x0008 */    const char * _start;\n            /* 0x0050 | 0x0008 */    char * _position;\n            /* 0x0058 | 0x0008 */    class FreeSLList _freeList; // or TLS\n        } // total: 0x60 bytes (+ 0x10 bytes padding)\n\n        struct FreeSLList::Entry {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    class FreeSLList::Entry * next;\n        } // total: 0x8 bytes\n        \"\"\"\n\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        sz = read_int_from_memory(sb + current_arch.ptrsize * 2)\n        self.out.append(titlify(\"superblock @{:#x} (chunk_size={:#x})\".format(sb, sz)))\n        reap_count = read_int32_from_memory(sb + current_arch.ptrsize * 8)\n        free_count = read_int32_from_memory(sb + current_arch.ptrsize * 8 + 4)\n\n        if reap_count == free_count == 0:\n            self.out.append(\"Uninitialized\")\n            return\n\n        self.out.append(\"Before allocating from freelist, you must use up all unused blocks\")\n        self.out.append(\"There are {:s} unused blocks left\".format(Color.colorify_hex(reap_count, \"bold\")))\n\n        for current in self.get_freelist_start(sb):\n            self.out.append(\"freelist @{:#x}:\".format(current))\n            seen = []\n            while True:\n                if current in seen:\n                    self.out.append(Color.colorify(\" -> {:#x} (loop) \".format(current), corrupted_msg_color))\n                    break\n                seen.append(current)\n                if current and not is_valid_addr(current):\n                    self.out.append(Color.colorify(\" -> {:#x} (corrupted) \".format(current), corrupted_msg_color))\n                    break\n                self.out.append(\" -> {:s}\".format(Color.colorify_hex(current, freed_address_color)))\n                if current == 0:\n                    break\n                current = read_int_from_memory(current)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        if args.superblock:\n            super_blocks = args.superblock\n        else:\n            super_blocks = self.get_super_blocks()\n            if super_blocks is None:\n                err(\"Could not find superblock\")\n                return\n\n        self.out = []\n        for super_block in super_blocks:\n            self.dump_super_block(super_block)\n        self.print_output()\n        return\n\n\n@register_command\nclass MimallocHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"mimalloc heap free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"mimalloc-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-m\", \"--mi-heap-main\", type=AddressUtil.parse_address,\n                        help=\"the address of _mi_heap_main (v2.x) / heap_main (v3.x).\")\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"--v21x\", action=\"store_true\", help=\"for mimalloc v2.1.x.\")\n    group.add_argument(\"--v22x\", action=\"store_true\", help=\"for mimalloc v2.2.x.\")\n    group.add_argument(\"--v30x\", action=\"store_true\", help=\"for mimalloc v3.0.x.\")\n    parser.add_argument(\"-d\", \"--use-decode\", action=\"store_true\", help=\"use pointer decoding (for debug build).\")\n    parser.add_argument(\"-D\", \"--dump-chunk\", action=\"store_true\", help=\"dump each chunks.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"In mimalloc, the member offsets of important structures vary depending on the version.\",\n        \"You should be able to check the version with a command like `strings libmimalloc.so | grep git`.\",\n        \"If you cannot determine it, please choose an option that can successfully decode it.\",\n        \"\",\n        \"For _mi_heap_main (v2.x) or heap_main (v3.x), GEF tries to resolve the address from symbol.\",\n        \"If symbols are not available, GEF scans the TLS area for automatic detection.\",\n        \"If, for some reason, detection fails, please specify the address manually.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if self.args.v21x:\n            \"\"\"\n            struct mi_heap_s { // v2.1.9\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    mi_tld_t * tld;\n                /* 0x0008 | 0x0008 */    mi_block_t * _Atomic thread_delayed_free;\n                /* 0x0010 | 0x0008 */    mi_threadid_t thread_id;\n                /* 0x0018 | 0x0004 */    mi_arena_id_t arena_id;\n                /* 0x0020 | 0x0008 */    uintptr_t cookie;\n                /* 0x0028 | 0x0010 */    uintptr_t [2] keys;\n                /* 0x0038 | 0x0088 */    mi_random_ctx_t random;\n                /* 0x00c0 | 0x0008 */    size_t page_count;\n                /* 0x00c8 | 0x0008 */    size_t page_retired_min;\n                /* 0x00d0 | 0x0008 */    size_t page_retired_max;\n                /* 0x00d8 | 0x0008 */    mi_heap_t * next;\n                /* 0x00e0 | 0x0001 */    _Bool no_reclaim;\n                /* 0x00e1 | 0x0001 */    uint8_t tag;\n                /* 0x00e8 | 0x0410 */    mi_page_t *[130] pages_free_direct;\n                /* 0x04f8 | 0x0708 */    mi_page_queue_t [75] pages;\n            } // total: 0xc00 bytes\n            \"\"\"\n            self.offset_next = 0xd8\n            self.offset_pages_free_direct = 0xe8\n            self.MI_PAGES_DIRECT = 130\n            \"\"\"\n            struct mi_page_s {\n                /* offset | size   */\n                /* 0x0000 | 0x0004 */    uint32_t slice_count;\n                /* 0x0004 | 0x0004 */    uint32_t slice_offset;\n                /* 0x0008 | 0x0001 */    uint8_t is_committed : 1;\n                /* 0x0008 | 0x0001 */    uint8_t is_zero_init : 1;\n                /* 0x0008 | 0x0001 */    uint8_t is_huge : 1;\n                /* 0x000a | 0x0002 */    uint16_t capacity;\n                /* 0x000c | 0x0002 */    uint16_t reserved;\n                /* 0x000e | 0x0001 */    mi_page_flags_t flags;\n                /* 0x000f | 0x0001 */    uint8_t free_is_zero : 1;\n                /* 0x000f | 0x0001 */    uint8_t retire_expire : 7;\n                /* 0x0010 | 0x0008 */    mi_block_t * free;\n                /* 0x0018 | 0x0008 */    mi_block_t * local_free;\n                /* 0x0020 | 0x0002 */    uint16_t used;\n                /* 0x0022 | 0x0001 */    uint8_t block_size_shift;\n                /* 0x0023 | 0x0001 */    uint8_t heap_tag;\n                /* 0x0028 | 0x0008 */    size_t block_size;\n                /* 0x0030 | 0x0008 */    uint8_t * page_start;\n                /* 0x0038 | 0x0010 */    uintptr_t [2] keys;\n                /* 0x0048 | 0x0008 */    _Atomic mi_thread_free_t xthread_free;\n                /* 0x0050 | 0x0008 */    _Atomic uintptr_t xheap;\n                /* 0x0058 | 0x0008 */    struct mi_page_s * next;\n                /* 0x0060 | 0x0008 */    struct mi_page_s * prev;\n                /* 0x0068 | 0x0008 */    void *[1] padding;\n            } // total: 0x70 bytes\n            \"\"\"\n            self.offset_capacity = 0x4 * 2 + 2 # with padding\n            self.offset_free = 0x10\n            self.offset_local_free = 0x18\n            self.offset_used = 0x20\n            self.offset_block_size = 0x28\n            self.offset_keys0 = 0x38\n            self.offset_keys1 = 0x40\n\n        elif self.args.v22x:\n            \"\"\"\n            struct mi_heap_s {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    mi_tld_t * tld;\n                /* 0x0008 | 0x0008 */    mi_block_t * _Atomic thread_delayed_free;\n                /* 0x0010 | 0x0008 */    mi_threadid_t thread_id;\n                /* 0x0018 | 0x0004 */    mi_arena_id_t arena_id;\n                /* 0x0020 | 0x0008 */    uintptr_t cookie;\n                /* 0x0028 | 0x0010 */    uintptr_t [2] keys;\n                /* 0x0038 | 0x0088 */    mi_random_ctx_t random;\n                /* 0x00c0 | 0x0008 */    size_t page_count;\n                /* 0x00c8 | 0x0008 */    size_t page_retired_min;\n                /* 0x00d0 | 0x0008 */    size_t page_retired_max;\n                /* 0x00d8 | 0x0008 */    long generic_count;\n                /* 0x00e0 | 0x0008 */    long generic_collect_count;\n                /* 0x00e8 | 0x0008 */    mi_heap_t * next;\n                /* 0x00f0 | 0x0001 */    _Bool no_reclaim;\n                /* 0x00f1 | 0x0001 */    uint8_t tag;\n                /* 0x00f8 | 0x0410 */    mi_page_t *[130] pages_free_direct;\n                /* 0x0508 | 0x0708 */    mi_page_queue_t [75] pages;\n            } // total: 0xc10 bytes\n            \"\"\"\n            self.offset_next = 0xe8\n            self.offset_pages_free_direct = 0xf8\n            self.MI_PAGES_DIRECT = 130\n            \"\"\"\n            struct mi_page_s {\n                /* offset | size   */\n                /* 0x0000 | 0x0004 */    uint32_t slice_count;\n                /* 0x0004 | 0x0004 */    uint32_t slice_offset;\n                /* 0x0008 | 0x0001 */    uint8_t is_committed : 1;\n                /* 0x0008 | 0x0001 */    uint8_t is_zero_init : 1;\n                /* 0x0008 | 0x0001 */    uint8_t is_huge : 1;\n                /* 0x000a | 0x0002 */    uint16_t capacity;\n                /* 0x000c | 0x0002 */    uint16_t reserved;\n                /* 0x000e | 0x0001 */    mi_page_flags_t flags;\n                /* 0x000f | 0x0001 */    uint8_t free_is_zero : 1;\n                /* 0x000f | 0x0001 */    uint8_t retire_expire : 7;\n                /* 0x0010 | 0x0008 */    mi_block_t * free;\n                /* 0x0018 | 0x0008 */    mi_block_t * local_free;\n                /* 0x0020 | 0x0002 */    uint16_t used;\n                /* 0x0022 | 0x0001 */    uint8_t block_size_shift;\n                /* 0x0023 | 0x0001 */    uint8_t heap_tag;\n                /* 0x0028 | 0x0008 */    size_t block_size;\n                /* 0x0030 | 0x0008 */    uint8_t * page_start;\n                /* 0x0038 | 0x0010 */    uintptr_t [2] keys;\n                /* 0x0048 | 0x0008 */    _Atomic mi_thread_free_t xthread_free;\n                /* 0x0050 | 0x0008 */    _Atomic uintptr_t xheap;\n                /* 0x0058 | 0x0008 */    struct mi_page_s * next;\n                /* 0x0060 | 0x0008 */    struct mi_page_s * prev;\n                /* 0x0068 | 0x0008 */    void *[1] padding;\n            } // total: 0x70 bytes\n            \"\"\"\n            self.offset_capacity = 0x4 * 2 + 2 # with padding\n            self.offset_free = 0x10\n            self.offset_local_free = 0x18\n            self.offset_used = 0x20\n            self.offset_block_size = 0x28\n            self.offset_keys0 = 0x38\n            self.offset_keys1 = 0x40\n\n        elif self.args.v30x:\n            \"\"\"\n            struct mi_heap_s {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    mi_tld_t * tld;\n                /* 0x0008 | 0x0008 */    mi_arena_t * exclusive_arena;\n                /* 0x0010 | 0x0008 */    uintptr_t cookie;\n                /* 0x0018 | 0x0088 */    mi_random_ctx_t random;\n                /* 0x00a0 | 0x0008 */    size_t page_count;\n                /* 0x00a8 | 0x0008 */    size_t page_retired_min;\n                /* 0x00b0 | 0x0008 */    size_t page_retired_max;\n                /* 0x00b8 | 0x0008 */    size_t generic_count;\n                /* 0x00c0 | 0x0008 */    mi_heap_t * next;\n                /* 0x00c8 | 0x0008 */    long full_page_retain;\n                /* 0x00d0 | 0x0001 */    _Bool allow_page_reclaim;\n                /* 0x00d1 | 0x0001 */    _Bool allow_page_abandon;\n                /* 0x00d2 | 0x0001 */    uint8_t tag;\n                /* 0x00d8 | 0x0410 */    mi_page_t *[130] pages_free_direct;\n                /* 0x04e8 | 0x0708 */    mi_page_queue_t [75] pages;\n                /* 0x0bf0 | 0x0018 */    mi_memid_t memid;\n            } // total: 0xc08 bytes\n            \"\"\"\n            self.offset_next = 0xc0\n            self.offset_pages_free_direct = 0xd8\n            self.MI_PAGES_DIRECT = 130\n            \"\"\"\n            struct mi_page_s {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    _Atomic mi_threadid_t xthread_id;\n                /* 0x0008 | 0x0008 */    mi_block_t * free;\n                /* 0x0010 | 0x0002 */    uint16_t used;\n                /* 0x0012 | 0x0002 */    uint16_t capacity;\n                /* 0x0014 | 0x0002 */    uint16_t reserved;\n                /* 0x0016 | 0x0001 */    uint8_t block_size_shift;\n                /* 0x0017 | 0x0001 */    uint8_t retire_expire;\n                /* 0x0018 | 0x0008 */    mi_block_t * local_free;\n                /* 0x0020 | 0x0008 */    _Atomic mi_thread_free_t xthread_free;\n                /* 0x0028 | 0x0008 */    size_t block_size;\n                /* 0x0030 | 0x0008 */    uint8_t * page_start;\n                /* 0x0038 | 0x0001 */    mi_heaptag_t heap_tag;\n                /* 0x0039 | 0x0001 */    _Bool free_is_zero;\n                /* 0x0040 | 0x0010 */    uintptr_t [2] keys;\n                /* 0x0050 | 0x0008 */    mi_heap_t * heap;\n                /* 0x0058 | 0x0008 */    struct mi_page_s * next;\n                /* 0x0060 | 0x0008 */    struct mi_page_s * prev;\n                /* 0x0068 | 0x0008 */    size_t slice_committed;\n                /* 0x0070 | 0x0018 */    mi_memid_t memid;\n            } // total: 0x88 bytes\n            \"\"\"\n            self.offset_capacity = 0x12\n            self.offset_free = 0x08\n            self.offset_local_free = 0x18\n            self.offset_used = 0x10\n            self.offset_block_size = 0x28\n            self.offset_keys0 = 0x40\n            self.offset_keys1 = 0x48\n        return\n\n    def get_mi_heap_main(self):\n        try:\n            if self.args.v30x:\n                return AddressUtil.parse_address(\"&heap_main\")\n            else:\n                return AddressUtil.parse_address(\"&_mi_heap_main\")\n        except gdb.error:\n            pass\n\n        tls = current_arch.get_tls()\n        for i in range(1, 10):\n            offset = current_arch.ptrsize * i\n            if not is_valid_addr(tls - offset):\n                continue\n\n            mi_heap_main = read_int_from_memory(tls - offset)\n            if not is_valid_addr(mi_heap_main):\n                continue\n\n            tld_main = read_int_from_memory(mi_heap_main)\n            if not is_valid_addr(tld_main):\n                continue\n\n            thread_id = read_int_from_memory(tld_main)\n            if not is_valid_addr(thread_id):\n                continue\n            return mi_heap_main\n        return None\n\n    def dump_list(self, head, current, key0, key1, bs):\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        def ptr_decode(addr, key0, key1):\n            addr = (addr - key0) & 0xffff_ffff_ffff_ffff\n            shift = key0 & 0x3f\n            return ror(addr, shift) ^ key1\n\n        seen = []\n        while True:\n            # loop check\n            if current in seen:\n                self.out.append(Color.colorify(\" -> {:#x} (loop) \".format(current), corrupted_msg_color))\n                break\n            seen.append(current)\n\n            # check wrong value\n            if current != 0 and not is_valid_addr(current):\n                self.out.append(Color.colorify(\" -> {:#x} (corrupted) \".format(current), corrupted_msg_color))\n                break\n\n            # ok\n            self.out.append(\" -> {:s}\".format(Color.colorify_hex(current, freed_address_color)))\n\n            # check the end of the list\n            if current == 0 or current == head:\n                break\n\n            # dump\n            if self.args.dump_chunk:\n                data = read_memory(current, bs)\n                out = hexdump(data, show_symbol=False, base=current, unit=8)\n                self.out.append(out)\n\n            # get next\n            current = read_int_from_memory(current)\n            if self.args.use_decode:\n                current = ptr_decode(current, key0, key1)\n        return\n\n    def dump_page(self, mi_page):\n        bs = read_int_from_memory(mi_page + self.offset_block_size)\n        cap = read_int16_from_memory(mi_page + self.offset_capacity)\n        used = read_int16_from_memory(mi_page + self.offset_used)\n        key0 = read_int64_from_memory(mi_page + self.offset_keys0)\n        key1 = read_int64_from_memory(mi_page + self.offset_keys1)\n        if self.args.use_decode:\n            self.out.append(titlify(\n                \"mi_page_t @{:#x} (block_size={:#x}, capacity={:#x}, used={:#x}, key0={:#x}, key1={:#x})\".format(\n                    mi_page, bs, cap, used, key0, key1,\n                ),\n            ))\n        else:\n            self.out.append(titlify(\n                \"mi_page_t @{:#x} (block_size={:#x}, capacity={:#x}, used={:#x})\".format(\n                    mi_page, bs, cap, used,\n                ),\n            ))\n\n        # freelist\n        freelist_addr = mi_page + self.offset_free\n        self.out.append(\"freelist @{:#x}:\".format(freelist_addr))\n        current = read_int_from_memory(freelist_addr)\n        self.dump_list(mi_page, current, key0, key1, bs)\n\n        # local freelist\n        local_freelist_addr = mi_page + self.offset_local_free\n        self.out.append(\"local_freelist @{:#x}:\".format(local_freelist_addr))\n        current = read_int_from_memory(local_freelist_addr)\n        self.dump_list(mi_page, current, key0, key1, bs)\n        return\n\n    def dump_heap(self, mi_heap):\n        seen = []\n        for i in range(self.MI_PAGES_DIRECT):\n            mi_page_t = read_int_from_memory(mi_heap + self.offset_pages_free_direct + current_arch.ptrsize * i)\n            if not is_valid_addr(mi_page_t):\n                continue\n            x = read_int_from_memory(mi_page_t)\n            if x == 0:\n                \"\"\"\n                0x7ffff7e72448|+0x00e8|+029: 0x00007ffff7e6be80 <_mi_page_empty>  ->  0x0000000000000000\n                0x7ffff7e72450|+0x00f0|+030: 0x00007ffff7e6be80 <_mi_page_empty>  ->  0x0000000000000000\n                0x7ffff7e72458|+0x00f8|+031: 0x0000040203400088  ->  0x01000eb001000700  <-  $rcx\n                0x7ffff7e72460|+0x0100|+032: 0x00007ffff7e6be80 <_mi_page_empty>  ->  0x0000000000000000\n                0x7ffff7e72468|+0x0108|+033: 0x00007ffff7e6be80 <_mi_page_empty>  ->  0x0000000000000000\n                \"\"\"\n                continue\n            if mi_page_t in seen:\n                continue\n            self.dump_page(mi_page_t)\n            seen.append(mi_page_t)\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        if int(args.v21x) + int(args.v22x) + int(args.v30x) > 1:\n            err(\"Version error\")\n            return\n\n        self.initialize()\n\n        if args.mi_heap_main:\n            mi_heap_main = args.mi_heap_main\n        else:\n            mi_heap_main = self.get_mi_heap_main()\n            if mi_heap_main is None:\n                err(\"Could not find _mi_heap_main\")\n                return\n\n        self.out = []\n        self.out.append(\"mi_heap_main: {:#x}\".format(mi_heap_main))\n\n        mi_heap = mi_heap_main\n        while is_valid_addr(mi_heap):\n            self.dump_heap(mi_heap)\n            mi_heap = read_int_from_memory(mi_heap + self.offset_next)\n\n        self.print_output()\n        return\n\n\n@register_command\nclass SnmallocHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"snmalloc (as of June 2025) heap free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"snmalloc-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--all\", action=\"store_true\", help=\"dump all thread_alloc.\")\n    parser.add_argument(\"-l\", \"--laden\", action=\"store_true\", help=\"dump laden (large or inactive slabs).\")\n    parser.add_argument(\"-r\", \"--remote\", action=\"store_true\", help=\"dump remote_alloc (WIP).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display also empty freelists.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command dumps the following four categories:\",\n        \"- small_fast_free_lists: Free list per small size class (fast path).\",\n        \"- alloc_classes: Per size class list of active slabs.\",\n        \"- laden: The set of all slabs and large allocations from this allocator that are full or almost full.\",\n        \"    - The end of the list may not be dumped correctly.\",\n        \"- remote_alloc: Message queue for allocations being returned to this allocator.\",\n        \"    - Currently status: WIP.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_current_thread_alloc(self):\n        # fast path\n        try:\n            thread_alloc = AddressUtil.parse_address(\"&'snmalloc::ThreadAlloc::alloc'\")\n            return read_int_from_memory(thread_alloc)\n        except gdb.error:\n            pass\n\n        # slow path\n        \"\"\"\n        gef> tls\n        ------------------------ TLS-0x80 -----------------------\n              ...\n              0x7ffff7f3f758|+0x0058|+011: 0x00007fbff7800000  <- here\n              0x7ffff7f3f760|+0x0060|+012: 0x0000000000000001\n              0x7ffff7f3f768|+0x0068|+013: 0x0000000000000000\n              0x7ffff7f3f770|+0x0070|+014: 0x0000000000000000\n              0x7ffff7f3f778|+0x0078|+015: 0x0000000000000000\n        -------------------------- TLS --------------------------\n              0x7ffff7f3f780|+0x0000|+000: 0x00007ffff7f3f780\n              0x7ffff7f3f788|+0x0008|+001: 0x00007ffff7f40120\n        \"\"\"\n        tls = current_arch.get_tls()\n        for i in range(1, 16):\n            addr = tls - (current_arch.ptrsize * i)\n            val = read_int_from_memory(addr)\n            if not is_valid_addr(val):\n                continue\n            if val & 0xf_ffff:\n                continue\n            if not is_single_link_list(val):\n                continue\n            return val\n        return None\n\n    def get_thread_alloc_list(self, all_thread=False):\n        if all_thread:\n            # travarse all threads\n            orig_thread = gdb.selected_thread()\n            orig_frame = gdb.selected_frame()\n            thread_allocs = []\n            for thread in gdb.selected_inferior().threads():\n                thread.switch() # change thread\n                thread_alloc = self.get_current_thread_alloc()\n                if thread_alloc:\n                    thread_allocs.append((thread.num, thread_alloc))\n            orig_thread.switch() # revert thread\n            orig_frame.select()\n            return thread_allocs\n        else:\n            thread_alloc = self.get_current_thread_alloc()\n            if thread_alloc:\n                return [(gdb.selected_thread().num, thread_alloc)]\n        return None\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        try:\n            self.NUM_SMALL_SIZECLASSES = AddressUtil.parse_address('snmalloc::NUM_SMALL_SIZECLASSES')\n        except gdb.error:\n            self.NUM_SMALL_SIZECLASSES = 43 # hardcoded value\n\n        try:\n            self.INTERMEDIATE_BITS = AddressUtil.parse_address('snmalloc::INTERMEDIATE_BITS')\n        except gdb.error:\n            self.INTERMEDIATE_BITS = 2 # hardcoded value\n\n        try:\n            self.MIN_ALLOC_BITS = AddressUtil.parse_address('snmalloc::MIN_ALLOC_STEP_BITS')\n        except gdb.error:\n            self.MIN_ALLOC_BITS = 4 # hardcoded value\n\n        \"\"\"\n        gef> dt 'snmalloc::Alloc'\n        struct snmalloc::Allocator<...> {\n            /* offset | size   */\n            /* 0x0000 | 0x0158 */    struct snmalloc::FastFreeLists snmalloc::FastFreeLists; // = 43 * 8 bytes\n            /* 0x0158 | 0x0018 */    class snmalloc::Pooled<...> snmalloc::Pooled<...>;\n            /* 0x0170 | 0x1a10 */    struct snmalloc::RemoteDeallocCache<...> remote_dealloc_cache;\n            /* 0x1b80 | 0x0408 */    struct snmalloc::Allocator<...>::SlabMetadataCache [43] alloc_classes; // 43 * 0x18 bytes\n            /* 0x1f88 | 0x0010 */    class snmalloc::SeqSet<...> laden;\n            /* 0x1f98 | 0x0028 */    class snmalloc::LocalEntropy entropy;\n            /* 0x2000 | 0x0100 */    std::conditional_t remote_alloc;\n            /* 0x2100 | 0x0240 */    std::conditional_t backend_state;\n            /* 0x2340 | 0x0018 */    class snmalloc::Ticker<...> ticker;\n        } // total: 0x2400 bytes\n        gef>\n        \"\"\"\n\n        try:\n            self.offset_alloc_classes = AddressUtil.parse_address(\"&((('snmalloc::Alloc'*)0)->alloc_classes)\")\n        except gdb.error:\n            self.offset_alloc_classes = 0x1b80 # hardcoded value\n\n        try:\n            self.offset_laden = AddressUtil.parse_address(\"&((('snmalloc::Alloc'*)0)->laden)\")\n        except gdb.error:\n            self.offset_laden = 0x1f88 # hardcoded value\n\n        try:\n            self.offset_remote_alloc = AddressUtil.parse_address(\"&((('snmalloc::Alloc'*)0)->remote_alloc)\")\n        except gdb.error:\n            self.offset_remote_alloc = 0x2000 # hardcoded value\n\n        self.initialized = True\n        return True\n\n    @Cache.cache_this_session\n    def class_to_size(self, cl):\n\n        def from_exp_mant(m_e, MANTISSA_BITS, LOW_BITS):\n            if MANTISSA_BITS > 0:\n                m_e = m_e + 1\n                MANTISSA_MASK = (1 << MANTISSA_BITS) - 1\n                m = m_e & MANTISSA_MASK\n                e = m_e >> MANTISSA_BITS\n                b = 0 if e == 0 else 1\n                shifted_e = e - b\n                extended_m = (m + (b << MANTISSA_BITS))\n                return extended_m << (shifted_e + LOW_BITS)\n            else:\n                return 1 << (m_e + LOW_BITS)\n\n        return from_exp_mant(cl, self.INTERMEDIATE_BITS, self.MIN_ALLOC_BITS)\n\n    def parse_single_link_list(self, head):\n        \"\"\"Return the single linked list (including the head) and error message.\"\"\"\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        # travase next\n        cur = head\n        seen = []\n        while True:\n            if cur == 0:\n                seen.append(cur)\n                break\n            if not is_valid_addr(cur):\n                seen.append(cur)\n                return seen, Color.colorify(\"(corrupted)\", corrupted_msg_color)\n            if cur in seen:\n                seen.append(cur)\n                return seen, Color.colorify(\"(loop detected)\", corrupted_msg_color)\n            seen.append(cur)\n            cur = read_int_from_memory(cur)\n        return seen, None\n\n    def parse_double_link_list(self, head):\n        \"\"\"Return the double linked list (excluding the head) and error message.\"\"\"\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n\n        # travarse next\n        cur = head\n        seen = []\n        while True:\n            if not is_valid_addr(cur):\n                seen.append(cur)\n                return seen, Color.colorify(\"(corrupted)\", corrupted_msg_color)\n            if cur in seen:\n                break\n            seen.append(cur)\n            cur = read_int_from_memory(cur)\n\n        if cur != seen[0]:\n            return seen, Color.colorify(\"(loop detected)\", corrupted_msg_color)\n\n        # check prev\n        for i, x in enumerate(seen):\n            p = read_int_from_memory(x + current_arch.ptrsize)\n            if p != seen[i - 1]:\n                return seen, Color.colorify(\"(corrupted)\", corrupted_msg_color)\n\n        if head in seen:\n            seen = [x for x in seen if x != head]\n        return seen, None\n\n    def dump_small_fast(self, thread_alloc):\n        \"\"\"\n        gef> dt snmalloc::FastFreeLists\n        struct snmalloc::FastFreeLists {\n            /* offset | size   */\n            /* 0x0000 | 0x0158 */    class snmalloc::freelist::Iter<...> [43] small_fast_free_lists; // -> freed chunk\n        } // total: 0x158 bytes\n        gef>\n        \"\"\"\n\n        self.out.append(titlify(\"FastFreeLists.small_fast_free_lists[{:d}] @ {:#x}\".format(\n            self.NUM_SMALL_SIZECLASSES,\n            thread_alloc,\n        )))\n\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        # travarse small_fast_free_lists[0-42]\n        printed_flag = False\n        for i in range(self.NUM_SMALL_SIZECLASSES):\n            free_list_i = thread_alloc + current_arch.ptrsize * i\n            head = read_int_from_memory(free_list_i)\n            free_list, error = self.parse_single_link_list(head)\n\n            # skip if empty\n            if not self.args.verbose:\n                if len(free_list) == 1 and free_list[0] == 0:\n                    continue\n\n            # print\n            self.out.append(\"small_fast_free_lists[{:d}, size={:s}] @ {!s}:\".format(\n                i,\n                Color.colorify_hex(self.class_to_size(i), Config.get_gef_setting(\"theme.heap_chunk_size\")),\n                ProcessMap.lookup_address(free_list_i),\n            ))\n            for i, chunk in enumerate(free_list):\n                chunk_str = Color.colorify_hex(chunk, freed_address_color)\n\n                # skip if empty\n                if not self.args.verbose:\n                    if 4 <= i < len(free_list) - 5:\n                        if i == 4:\n                            self.out.append(\" ...\")\n                        continue\n\n                if i < len(free_list) - 1:\n                    self.out.append(\" -> {:s}\".format(chunk_str))\n                elif error:\n                    self.out.append(\" -> {:s} {:s}\".format(chunk_str, error))\n                else:\n                    self.out.append(\" -> {:s} (num: {:#x})\".format(chunk_str, len(free_list) - 1))\n\n            printed_flag = True\n\n        if printed_flag is False:\n            self.out.append(\"Nothing to dump\")\n        return\n\n    def dump_slab_meta(self, slab_meta, cl):\n        \"\"\"\n        gef> dt 'snmalloc::FrontendSlabMetadata<snmalloc::DefaultSlabMetadata<snmalloc::NoClientMetaDataProvider>, \\\\\n        snmalloc::NoClientMetaDataProvider>'\n        struct snmalloc::FrontendSlabMetadata<...> {\n            /* offset | size   */\n            /* 0x0000 | 0x0001 */    class snmalloc::FrontendSlabMetadata_Trait snmalloc::FrontendSlabMetadata_Trait;\n            /* 0x0000 | 0x0010 */    class snmalloc::SeqSet<...>::Node node;\n            /* 0x0010 | 0x0018 */    class snmalloc::freelist::Builder<...> free_queue; // -> freed chunk\n            /* 0x0022 | 0x0002 */    uint16_t needed_;\n            /* 0x0024 | 0x0001 */    bool sleeping_;\n            /* 0x0025 | 0x0001 */    bool large_;\n            /* 0x0000 | 0x0001 */    snmalloc::NoClientMetaDataProvider::StorageType client_meta_;\n        } // total: 0x28 bytes\n        gef>\n\n        gef> dt 'snmalloc::freelist::Builder<false, false, snmalloc::capptr::bound<(snmalloc::capptr::dimension::Spatial)0, \\\\\n        (snmalloc::capptr::dimension::AddressSpaceControl)0, (snmalloc::capptr::dimension::Wildness)1>, \\\\\n        snmalloc::capptr::bound<(snmalloc::capptr::dimension::Spatial)0, (snmalloc::capptr::dimension::AddressSpaceControl)0, \\\\\n        (snmalloc::capptr::dimension::Wildness)0> >'\n        struct snmalloc::freelist::Builder<...> {\n            /* offset | size   */\n            /*        | 0x0008 */    const size_t LENGTH;\n            /* 0x0000 | 0x0008 */    snmalloc::stl::Array head;\n            /* 0x0008 | 0x0008 */    snmalloc::stl::Array end;\n            /* 0x0010 | 0x0001 */    snmalloc::stl::Array length;\n        } // total: 0x18 bytes\n        gef>\n        \"\"\"\n\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        offset_free_queue = 0x10\n        offset_needed_ = 0x22\n        offset_sleeping_ = 0x24\n        offset_large_ = 0x25\n\n        free_queue = slab_meta + offset_free_queue\n        head = read_int_from_memory(free_queue)\n        free_list, error = self.parse_single_link_list(head)\n\n        # skip if empty\n        if not self.args.verbose:\n            if len(free_list) == 1 and free_list[0] == 0:\n                return False\n\n        if cl is None:\n            cl_msg = \"???\"\n        else:\n            cl_msg = Color.colorify_hex(self.class_to_size(cl), Config.get_gef_setting(\"theme.heap_chunk_size\"))\n        is_laden = cl is None\n\n        needed_ = read_int16_from_memory(slab_meta + offset_needed_)\n        sleeping_ = read_int8_from_memory(slab_meta + offset_sleeping_)\n        large_ = read_int8_from_memory(slab_meta + offset_large_)\n\n        # print\n        self.out.append(\"free_queue[size={:s}, needed_={:#x}, sleeping_={:#x}, large_={:#x}] @ {!s}:\".format(\n            cl_msg, needed_, sleeping_, large_, ProcessMap.lookup_address(free_queue),\n        ))\n        for i, chunk in enumerate(free_list):\n            if is_laden:\n                chunk_str = hex(chunk)\n            else:\n                chunk_str = Color.colorify_hex(chunk, freed_address_color)\n\n            # skip if empty\n            if not self.args.verbose:\n                if 4 <= i < len(free_list) - 5:\n                    if i == 4:\n                        self.out.append(\" ...\")\n                    continue\n\n            if i < len(free_list) - 1:\n                self.out.append(\" -> {:s}\".format(chunk_str))\n            elif error:\n                if is_laden:\n                    self.out.append(\" -> {:s} {:s} (but expected)\".format(chunk_str, error))\n                else:\n                    self.out.append(\" -> {:s} {:s}\".format(chunk_str, error))\n            else:\n                self.out.append(\" -> {:s} (num: {:#x})\".format(chunk_str, len(free_list) - 1))\n        return True\n\n    def dump_alloc_classes(self, thread_alloc):\n        \"\"\"\n        gef> dt 'struct snmalloc::Allocator<snmalloc::StandardConfigClientMeta<snmalloc::NoClientMetaDataProvider> >\\\\\n        ::SlabMetadataCache'\n        struct snmalloc::Allocator<...>::SlabMetadataCache {\n            /* offset | size   */\n            /* 0x0000 | 0x0010 */    class snmalloc::SeqSet<...> available; // -> struct snmalloc::FrontendSlabMetadata<...>\n            /* 0x0010 | 0x0002 */    uint16_t unused;\n            /* 0x0012 | 0x0002 */    uint16_t length;\n        } // total: 0x18 bytes\n        \"\"\"\n\n        self.out.append(titlify(\"alloc_classes (SlabMetadataCache[{:d}]) @ {:#x}\".format(\n            self.NUM_SMALL_SIZECLASSES,\n            thread_alloc + self.offset_alloc_classes,\n        )))\n\n        offset_length = 0x12\n        sizeof_slab_meta = 0x18\n\n        # travarse SlabMetadataCache[0-42]\n        printed_flag = False\n        for i in range(self.NUM_SMALL_SIZECLASSES):\n            entry = thread_alloc + self.offset_alloc_classes + (sizeof_slab_meta * i)\n\n            slab_meta_list, error = self.parse_double_link_list(entry)\n            length = read_int16_from_memory(entry + offset_length)\n\n            if not self.args.verbose:\n                if slab_meta_list == [] and error is None:\n                    if length == 0:\n                        continue  # unused\n\n            self.out.append(\"SlabMetadataCache[{:d}, size={:s}] @ {!s}: {:#x} slab(s)\".format(\n                i,\n                Color.colorify_hex(self.class_to_size(i), Config.get_gef_setting(\"theme.heap_chunk_size\")),\n                ProcessMap.lookup_address(entry),\n                length,\n            ))\n\n            # travarse SlabMetadataCache[i].available\n            for slab_meta in slab_meta_list:\n                self.dump_slab_meta(slab_meta, cl=i)\n\n            printed_flag = True\n\n        if printed_flag is False:\n            self.out.append(\"Nothing to dump\")\n        return\n\n    def dump_laden(self, thread_alloc):\n        self.out.append(titlify(\"laden (SeqSet<BackendSlabMetadata>) @ {:#x}\".format(\n            thread_alloc + self.offset_laden,\n        )))\n\n        slab_meta_list, error = self.parse_double_link_list(thread_alloc + self.offset_laden)\n\n        if not self.args.verbose:\n            if slab_meta_list == [] and error is None:\n                self.out.append(\"Nothing to dump\")\n                return\n\n        printed_flag = False\n        for slab_meta in slab_meta_list:\n            printed_flag |= self.dump_slab_meta(slab_meta, cl=None)\n\n        if printed_flag is False:\n            self.out.append(\"Nothing to dump\")\n        return\n\n    def dump_remote_alloc(self, thread_alloc):\n        \"\"\"\n        struct snmalloc::RemoteAllocator {\n            /* offset | size   */\n            /*        | 0x0018 */    struct snmalloc::FreeListKey key_global; // static\n            /* 0x0000 | 0x0100 */    struct snmalloc::FreeListMPSCQ<snmalloc::RemoteAllocator::key_global, 0> list;\n        } // total: 0x100 bytes\n        gef>\n\n        gef> dt 'snmalloc::FreeListMPSCQ<snmalloc::RemoteAllocator::key_global, 0>'\n        struct snmalloc::FreeListMPSCQ<snmalloc::RemoteAllocator::key_global, 0> {\n            /* offset | size   */\n            /* 0x0000 | 0x0008 */    snmalloc::freelist::AtomicQueuePtr back;\n            /* 0x0040 | 0x0008 */    snmalloc::freelist::AtomicQueuePtr front;\n        } // total: 0x100 bytes\n        gef>\n        \"\"\"\n\n        self.out.append(titlify(\"remote_alloc (RemoteAllocator) @ {:#x}\".format(\n            thread_alloc + self.offset_remote_alloc,\n        )))\n\n        offset_front = 0x40\n        remote_alloc = thread_alloc + self.offset_remote_alloc\n        head = read_int_from_memory(remote_alloc + offset_front)\n        obj_list, error = self.parse_single_link_list(head)\n\n        if obj_list == [0] and error is None:\n            self.out.append(\"Nothing to dump\")\n            return\n\n        for obj in obj_list:\n            # TODO: WIP\n            self.out.append(\" -> {:#x}\".format(obj))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        self.out = []\n        if self.initialize() is False:\n            return\n\n        # get thread_alloc\n        self.thread_alloc_list = self.get_thread_alloc_list(args.all)\n        if not self.thread_alloc_list:\n            self.quiet_err(\"Could not find snmalloc::ThreadAlloc::alloc\")\n            return\n\n        # dump\n        for th_num, thread_alloc in self.thread_alloc_list:\n            self.out.append(titlify(\"ThreadAlloc @ {:#x} (Thread Id:{:d})\".format(\n                thread_alloc, th_num,\n            ), color=\"bold\", msg_color=\"bold\"))\n            self.dump_small_fast(thread_alloc) # FastFreeLists\n            self.dump_alloc_classes(thread_alloc) # SlabMetadataCache\n            if self.args.laden:\n                self.dump_laden(thread_alloc) # SeqSet<BackendSlabMetadata>\n            if self.args.remote:\n                self.dump_remote_alloc(thread_alloc) # RemoteAllocator\n\n        # print\n        self.print_output()\n        return\n\n\n@register_command\nclass CageCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display v8 (Chromium and d8) ubercage area.\"\"\"\n\n    _cmdline_ = \"cage\"\n    _category_ = \"05-b. Heap - Chromium/V8\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address for filtering.\")\n    parser.add_argument(\"-f\", \"--force-heuristic\", action=\"store_true\", help=\"use heuristic detection.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show with zero page.\")\n    parser.add_argument(\"-vv\", \"--vverbose\", action=\"store_true\", help=\"show with permission NONE.\")\n    parser.add_argument(\"-vvv\", \"--vvverbose\", action=\"store_true\", help=\"show all maps (=~ vmmap).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def get_sym_addr(self, sym, force_heuristic=False):\n        if force_heuristic:\n            return None\n        try:\n            x = AddressUtil.parse_address(f\"&{sym}\")\n            return read_int_from_memory(x)\n        except Exception:\n            pass\n        return None\n\n    def get_sym_value(self, sym, force_heuristic=False):\n        if force_heuristic:\n            return None\n        try:\n            return AddressUtil.parse_address(f\"{sym}\")\n        except Exception:\n            pass\n        return None\n\n    @Cache.cache_until_next\n    def get_isolate(self, force_heuristic=False):\n        sym = \"&'v8::internal::g_current_isolate_'.isolate_data_\"\n        addr = self.get_sym_value(sym, force_heuristic)\n        if addr:\n            return addr\n\n        tls = current_arch.get_tls()\n        for i in range(256 * 4): # heuristic; d8: 256, chromium: 1024\n            try:\n                x = read_int_from_memory(tls - current_arch.ptrsize * i)\n            except gdb.MemoryError:\n                continue\n            if x == 0:\n                continue\n            if x & 7:\n                continue\n            if not is_valid_addr(x):\n                continue\n            try:\n                y = read_int_from_memory(x)\n            except gdb.MemoryError:\n                continue\n            if y == 0:\n                continue\n            if y & 0xffff_ffff:\n                continue\n            if not is_valid_addr(y):\n                continue\n            return x\n        return None\n\n    @Cache.cache_until_next\n    def get_cage_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.cage_base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        addr = self.get_isolate(force_heuristic)\n        if addr:\n            return read_int_from_memory(addr)\n        return None\n\n    @Cache.cache_until_next\n    def get_table_candidates(self):\n        isolate = self.get_isolate(force_heuristic=True)\n        if not isolate:\n            return None\n\n        \"\"\"\n        gef> dt 'v8::internal::IsolateData'\n        struct v8::internal::IsolateData {\n            /* offset | size   */\n            /*        | 0x0008 */    const intptr_t kIsolateRootBias;\n            /* 0x0000 | 0x0008 */    const v8::internal::Address cage_base_;\n            /* 0x0008 | 0x0040 */    v8::internal::StackGuard stack_guard_;\n            /* 0x0048 | 0x0001 */    uint8_t is_marking_flag_;\n            /* 0x0049 | 0x0001 */    uint8_t is_minor_marking_flag_;\n            /* 0x004a | 0x0001 */    uint8_t is_shared_space_isolate_flag_;\n            /* 0x004b | 0x0001 */    uint8_t uses_shared_heap_flag_;\n            /* 0x004c | 0x0001 */    v8::base::Flags<...> execution_mode_;\n            /* 0x004d | 0x0001 */    uint8_t stack_is_iterable_;\n            /* 0x004e | 0x0001 */    uint8_t error_message_param_;\n            /* 0x004f | 0x0001 */    uint8_t [1] tables_alignment_padding_;\n            /* 0x0050 | 0x0008 */    int32_t * regexp_static_result_offsets_vector_;\n            /* 0x0058 | 0x0038 */    v8::internal::Address [7] builtin_tier0_entry_table_;\n            /* 0x0090 | 0x0038 */    v8::internal::Address [7] builtin_tier0_table_;\n            /* 0x00c8 | 0x0018 */    v8::internal::LinearAllocationArea new_allocation_info_;\n            /* 0x00e0 | 0x0018 */    v8::internal::LinearAllocationArea old_allocation_info_;\n            /* 0x00f8 | 0x0028 */    v8::internal::Address [5] fast_c_call_alignment_padding_;\n            /* 0x0120 | 0x0010 */    struct {...} ;\n            /* 0x0130 | 0x0008 */    v8::internal::Address fast_api_call_target_;\n            /* 0x0138 | 0x0008 */    size_t long_task_stats_counter_;\n            /* 0x0140 | 0x00f0 */    v8::internal::ThreadLocalTop thread_local_top_;\n            /* 0x0230 | 0x0018 */    v8::internal::HandleScopeData handle_scope_data_;\n            /* 0x0248 | 0x0020 */    void *[4] embedder_data_;\n            /* 0x0268 | 0x0030 */    v8::internal::ExternalPointerTable external_pointer_table_;\n            /* 0x0298 | 0x0008 */    v8::internal::ExternalPointerTable * shared_external_pointer_table_;\n            /* 0x02a0 | 0x0030 */    v8::internal::CppHeapPointerTable cpp_heap_pointer_table_;\n            /* 0x02d0 | 0x0008 */    const v8::internal::Address trusted_cage_base_;\n            /* 0x02d8 | 0x0030 */    v8::internal::TrustedPointerTable trusted_pointer_table_;\n            /* 0x0308 | 0x0008 */    v8::internal::TrustedPointerTable * shared_trusted_pointer_table_;\n            /* 0x0310 | 0x0008 */    v8::internal::TrustedPointerPublishingScope * trusted_pointer_publishing_scope_;\n            /* 0x0318 | 0x0008 */    const v8::internal::Address code_pointer_table_base_address_;\n            /* 0x0320 | 0x0008 */    v8::internal::Address api_callback_thunk_argument_;\n            /* 0x0328 | 0x0008 */    v8::internal::Address js_dispatch_table_base_;\n            /* 0x0330 | 0x0008 */    v8::internal::Address regexp_exec_vector_argument_;\n            /* 0x0338 | 0x0008 */    v8::internal::Tagged<...> continuation_preserved_embedder_data_;\n            /* 0x0340 | 0x23b8 */    v8::internal::RootsTable roots_table_;\n            /* 0x26f8 | 0x3320 */    v8::internal::ExternalReferenceTable external_reference_table_;\n            /* 0x5a18 | 0x49b8 */    v8::internal::Address [2359] builtin_entry_table_;\n            /* 0xa3d0 | 0x49b8 */    v8::internal::Address [2359] builtin_table_;\n            /* 0xed88 | 0x0008 */    v8::internal::wasm::StackMemory * active_stack_;\n            /* 0xed90 | 0x0008 */    v8::internal::Tagged<...> active_suspender_;\n            /* 0xed98 | 0x0004 */    int32_t date_cache_stamp_;\n            /* 0xed9c | 0x0001 */    uint8_t is_date_cache_used_;\n            /* 0xed9d | 0x0003 */    uint8_t [3] raw_arguments_padding_;\n            /* 0xeda0 | 0x0010 */    v8::internal::IsolateData::RawArgument [2] raw_arguments_;\n            /* 0xedb0 | 0x0000 */    uint8_t [0] trailing_padding_;\n        } // total: 0xedb0 bytes\n        gef>\n\n        [d8]\n        gef> telescope 0x555555857000 256 -M 0xfff -P r__ -n \\\n                -t 0 cage_base_ \\\n                -t 77 external_pointer_table_.base \\\n                -t 84 cpp_heap_pointer_table_.base \\\n                -t 90 trusted_cage_base_ \\\n                -t 91 trusted_pointer_table_ \\\n                -t 99 code_pointer_table_base_address_ \\\n                -t 101 js_dispatch_table_base_\n              0x555555857000|+0x0000|+000: cage_base_                      : 0x00001adc00000000  ->  0x0000000000081140\n              0x5555558570d8|+0x00d8|+027:                                 : 0x00001adc001c0000  ->  0x0000000000081140\n              0x5555558570f0|+0x00f0|+030:                                 : 0x00001adc00080000  ->  0x0000000000081140\n              0x555555857268|+0x0268|+077: external_pointer_table_.base    : 0x00007fff4c000000  ->  0x0000000000000000\n              0x5555558572a0|+0x02a0|+084: cpp_heap_pointer_table_.base    : 0x00007fff2c000000  ->  0x0000000000000000\n              0x5555558572d8|+0x02d8|+091: trusted_pointer_table_          : 0x00007fff28000000  ->  0x0000000000000000\n              0x555555857318|+0x0318|+099: code_pointer_table_base_address_: 0x00007fffa4000000  ->  0x0000000000000000\n              0x555555857328|+0x0328|+101: js_dispatch_table_base_         : 0x00007fff94000000  ->  0x0000000000000000\n        gef>\n\n        [chromium]\n        gef> telescope 0x3ea4004a4000 256 -M 0xfff -P r__ -n \\\n                -t 0 cage_base_ \\\n                -t 77 external_pointer_table_.base \\\n                -t 84 cpp_heap_pointer_table_.base \\\n                -t 90 trusted_cage_base_ \\\n                -t 91 trusted_pointer_table_ \\\n                -t 99 code_pointer_table_base_address_ \\\n                -t 100 js_dispatch_table_base_\n              0x3ea4004a4000|+0x0000|+000: cage_base_                      : 0x0000321700000000  ->  0x0000000000000000\n              0x3ea4004a4268|+0x0268|+077: external_pointer_table_.base    : 0x0000720dbb154000  ->  0x0000000000000000\n              0x3ea4004a42a0|+0x02a0|+084: cpp_heap_pointer_table_.base    : 0x0000720d9b154000  ->  0x0000000000000000\n              0x3ea4004a42d8|+0x02d8|+091: trusted_pointer_table_          : 0x0000720d97154000  ->  0x0000000000000000\n              0x3ea4004a4318|+0x0318|+099: code_pointer_table_base_address_: 0x0000720de3154000  ->  0x0000000000000000\n              0x3ea4004a4320|+0x0320|+100: js_dispatch_table_base_         : 0x0000720d87154000  ->  0x0000000000000000\n        gef>\n        \"\"\"\n\n        # In d8 it is aligned to 0x100_0000 bytes.\n        candidates_z_ffffff = []\n        # In chromium it is aligned to 0x1000 bytes.\n        candidates_z_fff = []\n\n        for i in range(256):\n            addr = isolate + current_arch.ptrsize * i\n            try:\n                value = read_int_from_memory(addr)\n            except gdb.MemoryError:\n                return []\n            if value & 0xfff:\n                continue\n            if not is_valid_addr(value):\n                continue\n            pm = ProcessMap.lookup_address(value)\n            try:\n                if pm.section.permission.value != Permission.READ:\n                    continue\n            except Exception:\n                continue\n            if value & 0xff_ffff == 0:\n                candidates_z_ffffff.append(value)\n            candidates_z_fff.append(value)\n\n        if len(candidates_z_ffffff) >= 6:\n            return candidates_z_ffffff\n        return candidates_z_fff\n\n    @Cache.cache_until_next\n    def get_external_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.external_pointer_table_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_table_candidates()\n        if candidates and len(candidates) > 1:\n            return candidates[1]\n        return None\n\n    @Cache.cache_until_next\n    def get_external_pointer_table_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.external_pointer_table_.kReservationSize\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_shared_external_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.shared_external_pointer_table_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n        return None\n\n    @Cache.cache_until_next\n    def get_shared_external_pointer_table_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.shared_external_pointer_table_.kReservationSize\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_cpp_heap_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.cpp_heap_pointer_table_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_table_candidates()\n        if candidates and len(candidates) > 2:\n            return candidates[2]\n        return None\n\n    @Cache.cache_until_next\n    def get_cpp_heap_pointer_table_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.cpp_heap_pointer_table_.kReservationSize\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_trusted_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.trusted_pointer_table_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_table_candidates()\n        if candidates and len(candidates) > 3:\n            return candidates[3]\n        return None\n\n    @Cache.cache_until_next\n    def get_trusted_pointer_table_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.trusted_pointer_table_.kReservationSize\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_shared_trusted_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.shared_trusted_pointer_table_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n        return None\n\n    @Cache.cache_until_next\n    def get_shared_trusted_pointer_table_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.shared_trusted_pointer_table_.kReservationSize\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_code_pointer_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.code_pointer_table_base_address_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_table_candidates()\n        if candidates and len(candidates) > 4:\n            return candidates[4]\n        return None\n\n    @Cache.cache_until_next\n    def get_code_pointer_table_size(self, force_heuristic=False):\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_js_dispatch_table_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.js_dispatch_table_base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_table_candidates()\n        if candidates and len(candidates) > 5:\n            return candidates[5]\n        return None\n\n    @Cache.cache_until_next\n    def get_js_dispatch_table_size(self, force_heuristic=False):\n        return 0x400_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_code_range_base(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'->heap_.code_range_.base_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        maps = ProcessMap.get_process_maps()\n        if not maps:\n            return None\n        for i, m in enumerate(maps):\n            if m.permission.value != Permission.READ | Permission.WRITE | Permission.EXECUTE:\n                continue\n            if (m.page_start & 0xffff) != 0:\n                continue\n            if m.size > 0x2000_0000:\n                continue\n            if m.size == 0x2000_0000:\n                return m.page_start\n            if m.size < 0x2000_0000:\n                if i == len(maps) - 1:\n                    continue\n                if maps[i + 1].permission.value & Permission.EXECUTE == 0:\n                    continue\n                return m.page_start\n        return None\n\n    @Cache.cache_until_next\n    def get_code_range_size(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'->heap_.code_range_.size_\"\n        value = self.get_sym_value(sym, force_heuristic)\n        if value:\n            return value\n        return 0x2000_0000 # hard-coded\n\n    @Cache.cache_until_next\n    def get_cage_rw_space_candidates(self):\n        maps = ProcessMap.get_process_maps()\n        if not maps:\n            return None\n        candidates = []\n        for m in maps:\n            if m.permission.value != Permission.READ | Permission.WRITE:\n                continue\n            if not self.is_cage(m):\n                continue\n            candidates.append(m)\n        return candidates\n\n    @Cache.cache_until_next\n    def get_new_space_start(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.new_allocation_info_.start_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_cage_rw_space_candidates()\n        if candidates and len(candidates) > 1:\n            return candidates[1].page_start\n        return None\n\n    @Cache.cache_until_next\n    def get_new_space_limit(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.new_allocation_info_.limit_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_cage_rw_space_candidates()\n        if candidates and len(candidates) > 1:\n            return candidates[1].page_end\n        return None\n\n    @Cache.cache_until_next\n    def get_old_space_start(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.old_allocation_info_.start_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_cage_rw_space_candidates()\n        if candidates and len(candidates) > 0:\n            return candidates[0].page_start\n        return None\n\n    @Cache.cache_until_next\n    def get_old_space_limit(self, force_heuristic=False):\n        sym = \"'v8::internal::g_current_isolate_'.isolate_data_.old_allocation_info_.limit_\"\n        addr = self.get_sym_addr(sym, force_heuristic)\n        if addr:\n            return addr\n\n        candidates = self.get_cage_rw_space_candidates()\n        if candidates and len(candidates) > 0:\n            return candidates[0].page_end\n        return None\n\n    def dump_entry(self, entry, path):\n        # get color\n        line_color = \"\"\n        if entry.path.startswith(\"[stack]\"):\n            line_color = Config.get_gef_setting(\"theme.address_stack\")\n        elif entry.path.startswith(\"[heap]\"):\n            line_color = Config.get_gef_setting(\"theme.address_heap\")\n        elif entry.permission.value & Permission.EXECUTE:\n            line_color = Config.get_gef_setting(\"theme.address_code\")\n        elif entry.permission.value & Permission.WRITE:\n            line_color = Config.get_gef_setting(\"theme.address_writable\")\n        elif entry.permission.value & Permission.READ:\n            line_color = Config.get_gef_setting(\"theme.address_readonly\")\n        elif entry.permission.value == Permission.NONE:\n            line_color = Config.get_gef_setting(\"theme.address_valid_but_none\")\n        if entry.permission.value == (Permission.READ | Permission.WRITE | Permission.EXECUTE):\n            line_color += \" \" + Config.get_gef_setting(\"theme.address_rwx\")\n\n        # make line\n        lines = []\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.page_start, current_arch.ptrsize, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.page_end, current_arch.ptrsize, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.size, current_arch.ptrsize, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            AddressUtil.format_address(entry.offset, current_arch.ptrsize, long_fmt=True), line_color,\n        ))\n        lines.append(Color.colorify(\n            str(entry.permission), line_color,\n        ))\n\n        if entry.path and path:\n            path = entry.path + \",\" + path\n        elif entry.path:\n            path = entry.path\n        lines.append(Color.colorify(path, line_color))\n\n        self.out.append(\" \".join(lines))\n        return\n\n    def is_external_pointer_table(self, entry):\n        area_start = self.get_external_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_external_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_shared_external_pointer_table(self, entry):\n        area_start = self.get_shared_external_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_shared_external_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_cpp_heap_pointer_table(self, entry):\n        area_start = self.get_cpp_heap_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_cpp_heap_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_trusted_pointer_table(self, entry):\n        area_start = self.get_trusted_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_trusted_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            if area_start <= entry.page_start < area_end:\n                # keep trusted space address\n                if entry.permission.value == Permission.READ | Permission.WRITE:\n                    v = read_int_from_memory(entry.page_start)\n                    self.trusted_space_high = v & 0x0000_ffff_0000_0000\n                    return True\n        return False\n\n    def is_shared_trusted_pointer_table(self, entry):\n        area_start = self.get_shared_trusted_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_shared_trusted_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_code_pointer_table(self, entry):\n        area_start = self.get_code_pointer_table_base(self.args.force_heuristic)\n        area_size = self.get_code_pointer_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_js_dispatch_table_space(self, entry):\n        area_start = self.get_js_dispatch_table_base(self.args.force_heuristic)\n        area_size = self.get_js_dispatch_table_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_code_range(self, entry):\n        area_start = self.get_code_range_base(self.args.force_heuristic)\n        area_size = self.get_code_range_size(self.args.force_heuristic)\n        if area_start is not None and area_size is not None:\n            area_end = area_start + area_size\n            return area_start <= entry.page_start < area_end\n        return False\n\n    def is_new_space(self, entry):\n        area_start = self.get_new_space_start(self.args.force_heuristic)\n        area_end = self.get_new_space_limit(self.args.force_heuristic)\n        if area_start is None or area_end is None:\n            return False\n        return entry.page_start <= area_start < area_end <= entry.page_end\n\n    def is_old_space(self, entry):\n        area_start = self.get_old_space_start(self.args.force_heuristic)\n        area_end = self.get_old_space_limit(self.args.force_heuristic)\n        if area_start is None or area_end is None:\n            return False\n        return entry.page_start <= area_start < area_end <= entry.page_end\n\n    def is_ro_space(self, entry):\n        if self.is_cage(entry):\n            return entry.permission.value == Permission.READ\n        return False\n\n    def is_array_buffer(self, entry):\n        if self.is_cage(entry):\n            if entry.permission.value == Permission.READ | Permission.WRITE:\n                if (entry.page_start & 0xffff_ffff) == 0:\n                    return True\n        return False\n\n    def is_cage(self, entry):\n        area_start = self.get_cage_base(self.args.force_heuristic)\n        if area_start is None:\n            return False\n        area_end = area_start + (1 * 1024 * 1024 * 1024 * 1024) # 1TB\n        return area_start <= entry.page_start < area_end\n\n    def is_trusted_space(self, entry):\n        if not hasattr(self, \"trusted_space_high\"):\n            return False\n        if self.trusted_space_high == (entry.page_start & 0x0000_ffff_0000_0000):\n            return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        maps = ProcessMap.get_process_maps()\n        if not maps:\n            err(\"Could not find any maps\")\n            return\n\n        if args.vvverbose:\n            args.vverbose = True\n        if args.vverbose:\n            args.verbose = True\n\n        self.out = []\n        # To find the trusted_space from the trusted_pointer_table, traverse it in reverse order\n        for entry in maps[::-1]:\n            # location filtering\n            if args.location is not None:\n                if args.location < entry.page_start or entry.page_end <= args.location:\n                    continue\n\n            if not args.vverbose:\n                # None permission filtering\n                if entry.permission.value == Permission.NONE:\n                    continue\n\n            if not args.verbose:\n                # zero contents filtering\n                try:\n                    if entry.size <= 0x10_0000:\n                        d = read_memory(entry.page_start, entry.size)\n                        if set(d) == {0}:\n                            continue\n                except gdb.error:\n                    pass\n\n            # known already entry filtering\n            if entry.path and not entry.path.startswith(\"[anon:v8\"):\n                if args.vvverbose:\n                    self.dump_entry(entry, \"\")\n                continue\n\n            # display the cage regions\n            if self.is_external_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:external_pointer_table]\")\n            elif self.is_shared_external_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:shared_external_pointer_table]\")\n            elif self.is_cpp_heap_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:cpp_heap_pointer_table]\")\n            elif self.is_trusted_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:trusted_pointer_table]\")\n            elif self.is_shared_trusted_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:shared_trusted_pointer_table]\")\n            elif self.is_code_pointer_table(entry):\n                self.dump_entry(entry, \"[v8:code_pointer_table]\")\n            elif self.is_js_dispatch_table_space(entry):\n                self.dump_entry(entry, \"[v8:js_dispatch_table]\")\n            elif self.is_code_range(entry):\n                self.dump_entry(entry, \"[v8:code_range]\")\n            elif self.is_new_space(entry):\n                self.dump_entry(entry, \"[v8:new_space]\")\n            elif self.is_old_space(entry):\n                self.dump_entry(entry, \"[v8:old_space]\")\n            elif self.is_ro_space(entry):\n                self.dump_entry(entry, \"[v8:ro_space]\")\n            elif self.is_array_buffer(entry):\n                self.dump_entry(entry, \"[v8:ArrayBuffer]\")\n            elif self.is_cage(entry):\n                self.dump_entry(entry, \"[v8:cage]\")\n            elif self.is_trusted_space(entry):\n                self.dump_entry(entry, \"[v8:trusted_space]\")\n            else:\n                if args.vvverbose:\n                    self.dump_entry(entry, \"\")\n\n        # Order the results in ascending order\n        self.out = self.out[::-1]\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass V8ListMapsCommand(GenericCommand, BufferingOutput):\n    \"\"\"List v8 (Chromium and d8) built-in maps.\"\"\"\n\n    _cmdline_ = \"v8-list-maps\"\n    _category_ = \"05-b. Heap - Chromium/V8\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use map cache.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified built-in maps structure:\",\n        \"\",\n        \"                             +-cage-------------+\",\n        \"chromium: partition-alloc    | +-ro_space-----+ |\",\n        \"+-d8: glibc-heap-+           | | ...          | |\",\n        \"| ...            |           | | ...          | |\",\n        \"| *map           |------------>| map          | |\",\n        \"| *map           |------------>| map          | |\",\n        \"| *map1          |------------>| map1         |<----+\",\n        \"| *map           |------------>| map          | |   |\",\n        \"| *map           |------------>| map          | |   |\",\n        \"| ...            |           | | ...          | |   + cage_base\",\n        \"+----------------+           | | ...          | |   |\",\n        \"                             | +-old_space----+ |   |\",\n        \"                             | | ...          | |   |\",\n        \"                             | | +0x10: ofs   |-----+\",\n        \"                             | | ...          | |\",\n        \"                             | +--------------+ |\",\n        \"                             | | ...          | |\",\n        \"                             | +--------------+ |\",\n        \"                             | | ...          | |\",\n        \"                             | +--------------+ |\",\n        \"                             | ...              |\",\n        \"                             +------------------+\",\n        \"\",\n        \"For Chromium: this command needs `--no-sandbox` to bypass `seccomp`.\",\n        \"Also, since it uses V8 commands internally, `_v8_internal_Print_Object` must be resolvable.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @staticmethod\n    def redirect_stdout(output_path):\n        syscall_table = get_syscall_table()\n\n        # dup\n        ret = ExecSyscall(syscall_table.name_table[\"dup\"].nr, [1]).exec_code()\n        stdout_oldfd = ret[\"reg\"][current_arch.return_register]\n\n        # open\n        p = PatchCommand.PatchInfo(current_arch.sp, output_path.encode() + b\"\\0\")\n        p.patch(silent=True)\n        flags = 0o100 | 0o1 | 0o1000 # O_CREAT | O_WRONLY | O_TRUNC\n        ret = ExecSyscall(syscall_table.name_table[\"open\"].nr, [current_arch.sp, flags, 0o666]).exec_code()\n        file_fd = ret[\"reg\"][current_arch.return_register]\n        PatchCommand.PatchInfo.revert_to_tag(p.tag, silent=True)\n\n        def u2i(x):\n            x = struct.pack(\"<Q\", x & 0xffff_ffff_ffff_ffff)\n            return struct.unpack(\"<q\", x)[0]\n\n        if u2i(file_fd) < 0:\n            # fail, revert dup\n            ExecSyscall(syscall_table.name_table[\"dup2\"].nr, [stdout_oldfd, 1]).exec_code()\n            return None\n\n        # dup2\n        ExecSyscall(syscall_table.name_table[\"dup2\"].nr, [file_fd, 1]).exec_code()\n\n        # close\n        ExecSyscall(syscall_table.name_table[\"close\"].nr, [file_fd]).exec_code()\n        return stdout_oldfd\n\n    @staticmethod\n    def revert_stdout(stdout_oldfd):\n        if stdout_oldfd is None:\n            return\n\n        syscall_table = get_syscall_table()\n\n        # dup2\n        ExecSyscall(syscall_table.name_table[\"dup2\"].nr, [stdout_oldfd, 1]).exec_code()\n\n        # close\n        ExecSyscall(syscall_table.name_table[\"close\"].nr, [stdout_oldfd]).exec_code()\n        return\n\n    @staticmethod\n    def get_cage_base():\n        res = gdb.execute(\"cage --no-pager\", to_string=True)\n        if \"Not found\" in res:\n            return None\n\n        for line in res.splitlines():\n            line = Color.remove_color(line)\n            if \"[v8:cage]\" in line or \"[v8:ro_space]\" in line:\n                cage_base, *_ = line.split(None, 1)\n                cage_base = int(cage_base, 16)\n                return cage_base & 0x0000_ffff_0000_0000\n        return None\n\n    def get_old_space(self):\n        res = gdb.execute(\"cage --no-pager\", to_string=True)\n        if \"Not found\" in res:\n            return None\n\n        for line in res.splitlines():\n            line = Color.remove_color(line)\n            if \"[v8:old_space]\" not in line:\n                continue\n            start, *_ = line.split()\n            return int(start, 16)\n        return None\n\n    def get_heap_contents(self, map1):\n        maps = ProcessMap.get_process_maps()\n        pa_maps = [m for m in maps if m.path == \"[anon:partition_alloc]\"]\n        if pa_maps:\n            # get partition-alloc (for chromium)\n            for m in pa_maps:\n                if m.permission.value != Permission.READ | Permission.WRITE:\n                    continue\n                heap_contents = read_memory(m.page_start, m.size)\n                heap_contents = slice_unpack(heap_contents, current_arch.ptrsize)\n                if map1 in heap_contents:\n                    break\n            else:\n                err(\"Could not find the partition-alloc heap\")\n                return None\n        else:\n            # get glibc heap (for d8)\n            heap_base = HeapbaseCommand.heap_base()\n            if not heap_base:\n                err(\"Could not find the glibc heap\")\n                return None\n            heap_section = ProcessMap.lookup_address(heap_base).section\n            heap_contents = read_memory(heap_base, heap_section.size)\n            heap_contents = slice_unpack(heap_contents, current_arch.ptrsize)\n        return heap_contents\n\n    def do_list_maps(self, region, cage_base):\n        # old_space+0x10 has heap_object\n        ofs = read_int32_from_memory(region + 0x10)\n        map1 = cage_base + ofs\n        if not is_valid_addr(map1):\n            err(\"Memory access error\")\n            return\n\n        # get heap contents\n        heap_contents = self.get_heap_contents(map1)\n        if heap_contents is None:\n            return\n\n        # get reference index (from glibc heap)\n        try:\n            sidx = eidx = heap_contents.index(map1)\n        except ValueError:\n            err(\"Could not find wanted maps\")\n            return\n\n        \"\"\"\n        0x555555859178|+0x0000|+000: 0x000011b7000013e5  ->  0xa54b000013000004  <- cage_base + 0x10\n        0x555555859180|+0x0008|+001: 0x000011b70000140d  ->  0xa64b000003000004\n        0x555555859188|+0x0010|+002: 0x000011b700001435  ->  0xa74b000008000004\n        0x555555859190|+0x0018|+003: 0x000011b70000145d  ->  0xa84b000004000004\n        0x555555859198|+0x0020|+004: 0x000011b700001485  ->  0xa94b000003000004\n        0x5555558591a0|+0x0028|+005: 0x000011b7000014ad  ->  0xaa4b000003000004\n        0x5555558591a8|+0x0030|+006: 0x000011b7000014d5  ->  0xab4b000003000004\n        0x5555558591b0|+0x0038|+007: 0x000011b7000014fd  ->  0xac4b000002000004\n        \"\"\"\n\n        # glibc heap contains a array of addresses of v8 heap objects\n        # find the top of the array\n        cage_mask = cage_base & 0xffff_ffff_0000_0000\n        while sidx >= 0:\n            v = heap_contents[sidx]\n            if v & 1 == 0:\n                break\n            if cage_mask != (v & 0xffff_ffff_0000_0000):\n                break\n            sidx -= 1\n        sidx += 1\n\n        # find the tail of the array\n        while eidx < len(heap_contents):\n            v = heap_contents[eidx]\n            if v & 1 == 0:\n                break\n            if cage_mask != (v & 0xffff_ffff_0000_0000):\n                break\n            eidx += 1\n\n        # dump\n        try:\n            # The v8 command simply invokes V8's own dump functions via an inferior function call.\n            # The output is printed to stdout, but since it is not a GDB command, GDB cannot capture that output directly.\n            # Therefore, GEF temporarily redirect stdout to collect the results.\n            stdout_oldfd = None\n            stdout_oldfd = V8ListMapsCommand.redirect_stdout(self.output_path)\n            if stdout_oldfd is None:\n                raise RuntimeError(\"Failed to redirect: {:s}\".format(self.output_path))\n            tqdm = GefUtil.get_tqdm()\n            for idx in tqdm(range(sidx, eidx), leave=False):\n                v = heap_contents[idx]\n                gdb.execute(\"v8 {:#x}\".format(v), to_string=True)\n        finally:\n            V8ListMapsCommand.revert_stdout(stdout_oldfd)\n        return\n\n    def list_maps(self, region, cage_base):\n        self.output_path = os.path.join(GEF_TEMP_DIR, \"v8-list-maps-{:#x}.txt\".format(cage_base))\n\n        # not found a cache file\n        if self.args.rescan or not os.path.exists(self.output_path):\n            self.do_list_maps(region, cage_base)\n        else:\n            info(\"Use cache\")\n\n        res = open(self.output_path).read()\n        for line in res.splitlines():\n            line = re.sub(r\"^(0x[0-9a-f]+)\", lambda x:Color.blueify(x.group(1)), line)\n            self.out.append(line)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        cage_base = V8ListMapsCommand.get_cage_base()\n        if not cage_base:\n            err(\"Could not find cage base\")\n            return\n\n        old_space_region = self.get_old_space()\n        if not old_space_region:\n            err(\"Could not find old space\")\n            return\n\n        self.out = []\n        self.list_maps(old_space_region, cage_base)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass V8DumpSpaceCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump v8 (Chromium and d8) heap objects in each space.\"\"\"\n\n    _cmdline_ = \"v8-dump-space\"\n    _category_ = \"05-b. Heap - Chromium/V8\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    spaces = [\"old_space\", \"new_space\", \"ro_space\", \"trusted_space\", \"all\", \"o\", \"n\", \"r\", \"t\", \"a\"]\n    parser.add_argument(\"target_space\", metavar=\"TARGET_SPACE\", choices=spaces, nargs=\"?\", default=\"all\",\n                        help=\"the space name to dump.\")\n    parser.add_argument(\"-m\", \"--max-count\", type=AddressUtil.parse_address, default=0,\n                        help=\"max count for each space.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"display also object details for string like objects (slow!).\")\n    parser.add_argument(\"-vv\", \"--vverbose\", action=\"store_true\",\n                        help=\"display also object details for all objects (very slow!).\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"It only works with the debug build of d8 or Chromium.\",\n        \"Since many parts are detected heuristically and testing is insufficient,\",\n        \"it is highly likely that it will not work depending on the version of v8.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_target_regions(self):\n        res = gdb.execute(\"cage --no-pager\", to_string=True)\n        if \"Not found\" in res:\n            return []\n\n        regions = []\n        for line in res.splitlines():\n            line = Color.remove_color(line)\n            if self.args.target_space in [\"all\", \"a\"]:\n                if \"_space]\" not in line:\n                    continue\n            elif self.args.target_space in [\"old_space\", \"o\"]:\n                if \"[v8:old_space]\" not in line:\n                    continue\n            elif self.args.target_space in [\"new_space\", \"n\"]:\n                if \"[v8:new_space]\" not in line:\n                    continue\n            elif self.args.target_space in [\"ro_space\", \"r\"]:\n                if \"[v8:ro_space]\" not in line:\n                    continue\n            elif self.args.target_space in [\"trusted_space\", \"t\"]:\n                if \"[v8:trusted_space]\" not in line:\n                    continue\n            start, limit, _, _, perm, path = line.split()\n            start = int(start, 16)\n            limit = int(limit, 16)\n            regions.append([start, limit, perm, path])\n        return regions\n\n    def is_map(self, value, cage_base):\n        if value & 1 == 0:\n            return False # not a tagged pointer\n\n        map_addr = cage_base + (value - 1) # untag\n        if not is_valid_addr(map_addr):\n            return False\n\n        value2 = read_int32_from_memory(map_addr)\n        if value2 & 1 == 0:\n            return False # not a metamap\n\n        meta_map_addr = cage_base + (value2 - 1) # untag\n        if not is_valid_addr(meta_map_addr):\n            return False\n        return True\n\n    instance_type_dic = {}\n\n    def load_instance_type_dict(self):\n        lines = open(self.instace_type_cache_path).read().splitlines()\n        for line in lines:\n            instance_type, type_name = line.split(\"=\")\n            self.instance_type_dic[int(instance_type)] = type_name\n        return\n\n    def append_instance_type_dict(self, instance_type, type_name):\n        self.instance_type_dic[instance_type] = type_name\n\n        with open(self.instace_type_cache_path, \"a\") as f:\n            f.write(\"{:d}={:s}\\n\".format(instance_type, type_name))\n        return\n\n    def get_instance_name(self, map_addr):\n        # load from cache file\n        if not self.instance_type_dic:\n            if os.path.exists(self.instace_type_cache_path):\n                self.load_instance_type_dict()\n\n        # fast path: load from cache\n        instance_type = read_int16_from_memory((map_addr & ~1) + 8)\n        if instance_type in self.instance_type_dic:\n            return self.instance_type_dic[instance_type]\n\n        # slow path\n        try:\n            stdout_oldfd = None\n            stdout_oldfd = V8ListMapsCommand.redirect_stdout(self.output_path)\n            if stdout_oldfd is None:\n                raise RuntimeError(\"Failed to redirect: {:s}\".format(self.output_path))\n            gdb.execute(\"v8 {:#x}\".format(map_addr | 1), to_string=True)\n        finally:\n            V8ListMapsCommand.revert_stdout(stdout_oldfd)\n\n        map_content = open(self.output_path).read()\n        if V8Command.is_chromium():\n            # 0x06c300000475 <MetaMap (0x06c30000002d <null>)>\n            r = re.search(r\"<MetaMap \", map_content)\n            if r:\n                type_name = \"MAP_TYPE\"\n                self.append_instance_type_dict(instance_type, type_name)\n                return type_name\n\n            # 0x06c30000049d <Map[28](ODDBALL_TYPE)>\n            r = re.search(r\"\\(([A-Z_]+?)\\)>$\", map_content)\n            if r:\n                type_name = r.group(1)\n                self.append_instance_type_dict(instance_type, type_name)\n                return type_name\n        else:\n            r = re.search(r\"- type: (.+)\", map_content) # for d8\n            if r:\n                type_name = r.group(1)\n                self.append_instance_type_dict(instance_type, type_name)\n                return type_name\n        return \"???\"\n\n    def get_object_size(self, addr, map_addr, cage_base, area_end):\n        \"\"\"get header size and variable size\"\"\"\n\n        \"\"\"\n        https://github.com/v8/v8/blob/main/src/objects/map.h\n        Map layout:\n          TaggedPointer   map - Always a pointer to the MetaMap root\n          Int             The first int field\n            Byte          [instance_size]\n            ...\n          Int             The second int field\n            Short         [instance_type]\n            ...\n          ...\n        \"\"\"\n        # fixed length pattern (map has instance size)\n        instance_size = read_int8_from_memory(map_addr + 4)\n        if instance_size > 0:\n            return instance_size * 4, None\n\n        # instance_size == 0\n        instance_name = self.get_instance_name(map_addr)\n\n        # Object sizes are manually specified by referencing src/objects.h etc.\n        # TODO: inline property <-> external property\n        if instance_name == \"ARRAY_LIST_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 12, length * 4\n        elif instance_name == \"BIG_INT_BASE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            return 8, length * 4\n        elif instance_name == \"BYTECODE_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            length >>= 1\n            length = align(length, 4)\n            return 0x28, length\n        elif instance_name == \"BYTE_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            length = align(length, 4)\n            return 8, length\n        elif instance_name == \"CLOSURE_FEEDBACK_CELL_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"CODE_TYPE\":\n            return 0x44, 0\n        elif instance_name == \"COVERAGE_INFO_TYPE\":\n            length = read_int16_from_memory(addr + 4)\n            return 8, length * 4 * 4\n        elif instance_name == \"DESCRIPTOR_ARRAY_TYPE\":\n            length = read_int16_from_memory(addr + 4)\n            return 0x14, length * 4 * 3\n        elif instance_name == \"DOUBLE_STRING_CACHE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            return 8, length * 12\n        elif instance_name == \"EMBEDDER_DATA_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            return 8, length * 4\n        elif instance_name == \"EPHEMERON_HASH_TABLE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"FEEDBACK_METADATA_TYPE\":\n            length1 = read_int32_from_memory(addr + 4)\n            if length1 != 0:\n                length1 = (length1 - 1) // 6 + 1 # 5-bit encode\n            length2 = read_int32_from_memory(addr + 8)\n            length = align(length1 * 4 + length2 * 2, 4)\n            return 12, length\n        elif instance_name == \"FEEDBACK_VECTOR_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            return 0x1c, length * 4\n        elif instance_name == \"FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"FIXED_DOUBLE_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 8\n        elif instance_name == \"FREE_SPACE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            length -= 2 # size of the free space including the header\n            return 8, length * 4\n        elif instance_name == \"GLOBAL_DICTIONARY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"HASH_TABLE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"INSTRUCTION_STREAM_TYPE\": # in code_range\n            header = 0x10\n            length = read_int32_from_memory(addr + 12)\n            length = align(header + length, 0x40)\n            return header, length - header\n        elif instance_name == \"INTERNALIZED_ONE_BYTE_STRING_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            length = align(length, 4)\n            return 12, length\n        elif instance_name == \"INTERNALIZED_TWO_BYTE_STRING_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            length = align(length * 2, 4)\n            return 12, length\n        elif instance_name == \"NAME_DICTIONARY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"NAME_TO_INDEX_HASH_TABLE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"NATIVE_CONTEXT_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, (length * 4) + (2 * 4)\n        elif instance_name == \"NUMBER_DICTIONARY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"OBJECT_BOILERPLATE_DESCRIPTION_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 0x10, length * 4\n        elif instance_name == \"ORDERED_HASH_MAP_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"ORDERED_HASH_SET_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"ORDERED_NAME_DICTIONARY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"PREPARSE_DATA_TYPE\":\n            data_length = read_int32_from_memory(addr + 4)\n            children_length = read_int32_from_memory(addr + 8)\n            padding = align(data_length, 4)\n            length = data_length + padding + children_length * 4\n            return 12, length\n        elif instance_name == \"PROPERTY_ARRAY_TYPE\":\n            length_or_hash = read_int32_from_memory(addr + 4)\n            length = length_or_hash & 0x3ff\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"PROTECTED_FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"PROTECTED_WEAK_FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"REGISTERED_SYMBOL_TABLE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"REG_EXP_MATCH_INFO_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 0x14, length * 4\n        elif instance_name == \"SCOPE_INFO_TYPE\":\n            # The logic is very complicated, so the v8 command is used instead.\n            try:\n                stdout_oldfd = None\n                stdout_oldfd = V8ListMapsCommand.redirect_stdout(self.output_path)\n                if stdout_oldfd is None:\n                    raise RuntimeError(\"Failed to redirect: {:s}\".format(self.output_path))\n                gdb.execute(\"v8 {:#x}\".format(addr | 1), to_string=True)\n            finally:\n                V8ListMapsCommand.revert_stdout(stdout_oldfd)\n            content = open(self.output_path).read()\n            r = re.search(r\"- length: (\\d+)\", content)\n            if r:\n                return 4, int(r.group(1)) * 4\n            else:\n                return 4, 5 * 4\n        elif instance_name == \"SCRIPT_CONTEXT_TABLE_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 0x10, length * 4\n        elif instance_name == \"SCRIPT_CONTEXT_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"SEQ_ONE_BYTE_STRING_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            length = align(length, 4)\n            return 12, length\n        elif instance_name == \"SEQ_TWO_BYTE_STRING_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            length = align(length * 2, 4)\n            return 12, length\n        elif instance_name == \"SHARED_SEQ_ONE_BYTE_STRING_TYPE\":\n            pass # TODO\n        elif instance_name == \"SHARED_SEQ_TWO_BYTE_STRING_TYPE\":\n            pass # TODO\n        elif instance_name == \"SIMPLE_NAME_DICTIONARY_TYPE\":\n            pass # TODO\n        elif instance_name == \"SIMPLE_NUMBER_DICTIONARY_TYPE\":\n            pass # TODO\n        elif instance_name == \"SLOPPY_ARGUMENTS_ELEMENTS_TYPE\":\n            pass # TODO\n        elif instance_name == \"SMALL_ORDERED_HASH_MAP_TYPE\":\n            pass # TODO\n        elif instance_name == \"SMALL_ORDERED_HASH_SET_TYPE\":\n            pass # TODO\n        elif instance_name == \"SMALL_ORDERED_NAME_DICTIONARY_TYPE\":\n            pass # TODO\n        elif instance_name == \"STRONG_DESCRIPTOR_ARRAY_TYPE\":\n            pass # TODO\n        elif instance_name == \"SWISS_NAME_DICTIONARY_TYPE\":\n            length = read_int32_from_memory(addr + 8)\n            data_table_len = length * 2 * 4\n            ctrl_table_len = align(length + 0x10, 4)\n            property_details_table_len = align(length, 4)\n            return 0x10, data_table_len + ctrl_table_len + property_details_table_len\n        elif instance_name == \"TRANSITION_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"TRUSTED_BYTE_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            length = align(length, 4)\n            return 8, length\n        elif instance_name == \"TRUSTED_FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"TRUSTED_WEAK_FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n        elif instance_name == \"TURBOSHAFT_FLOAT64_SET_TYPE_TYPE\":\n            pass # TODO\n        elif instance_name == \"TURBOSHAFT_WORD32_SET_TYPE_TYPE\":\n            pass # TODO\n        elif instance_name == \"TURBOSHAFT_WORD64_SET_TYPE_TYPE\":\n            pass # TODO\n        elif instance_name == \"WASM_DISPATCH_TABLE_TYPE\": # ???\n            return 0x1c, 0\n        elif instance_name == \"WASM_NULL_TYPE\":\n            pass # TODO\n        elif instance_name == \"WASM_TYPE_INFO_TYPE\":\n            pass # TODO\n        elif instance_name == \"WEAK_ARRAY_LIST_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 12, length * 4\n        elif instance_name == \"WEAK_FIXED_ARRAY_TYPE\":\n            length = read_int32_from_memory(addr + 4)\n            length >>= 1\n            return 8, length * 4\n\n        instance_type = read_int16_from_memory((map_addr & ~1) + 8)\n        self.warn_add_out(\"Unknown instance_type: {:#x}\".format(instance_type))\n        return 0, 0\n\n    def walk_space(self, start, limit, cage_base):\n        v = read_int32_from_memory(start)\n        if v & 1:\n            addr = start\n        else:\n            addr = start + 0x10\n\n        try:\n            from tqdm import tqdm\n        except ImportError:\n            tqdm = None\n        if tqdm:\n            pbar = tqdm(total=limit - start, leave=False)\n\n        count = 0\n        while addr < limit:\n            # check max_count\n            if self.args.max_count:\n                if count >= self.args.max_count:\n                    return\n\n            # get compressed pointer\n            try:\n                map_raw = read_int32_from_memory(addr)\n            except gdb.MemoryError:\n                self.warn_add_out(\"Cannot read memory at {:#x}\".format(addr))\n                return\n\n            # check if magic number\n            if map_raw == 0xbeadbeef:\n                self.info_add_out(\"End of objects\")\n                return\n\n            # check if it is a map\n            if not self.is_map(map_raw, cage_base):\n                self.warn_add_out(\"Could not find map\")\n                return\n            map_addr = cage_base + map_raw - 1 # untag\n\n            # get size, type, name\n            header_size, variable_size = self.get_object_size(addr, map_addr, cage_base, limit)\n            instance_type = read_int16_from_memory(map_addr + 8)\n            instance_name = self.get_instance_name(map_addr + 1)\n\n            # dump\n            if variable_size is not None:\n                size_str = \"{:#x}+{:#x},\".format(header_size, variable_size)\n            else:\n                size_str = \"{:#x},\".format(header_size)\n\n            line = \"{:s}: map:{:#x}, sz={:12s} type={:#05x}(={:s})\".format(\n                Color.colorify_hex(addr + 1, 'blue'),\n                map_addr + 1, size_str, instance_type, instance_name,\n            )\n            self.out.append(line)\n\n            # dump details\n            if (self.args.verbose and \"STRING\" in instance_name) or self.args.vverbose:\n                try:\n                    stdout_oldfd = None\n                    stdout_oldfd = V8ListMapsCommand.redirect_stdout(self.output_path)\n                    if stdout_oldfd is None:\n                        raise RuntimeError(\"Failed to redirect: {:s}\".format(self.output_path))\n                    gdb.execute(\"v8 {:#x}\".format(addr | 1), to_string=True)\n                finally:\n                    V8ListMapsCommand.revert_stdout(stdout_oldfd)\n                content = open(self.output_path).read()\n                if not content:\n                    self.warn_add_out(\"No content; Something is wrong\")\n                    return\n                self.out.extend(content.splitlines()[:20])\n\n            # check if last\n            if instance_name == \"FREE_SPACE_TYPE\":\n                self.info_add_out(\"End of objects\")\n                return\n\n            # goto next\n            if header_size == 0:\n                return\n            if variable_size is None:\n                total_size = header_size\n            else:\n                total_size = header_size + variable_size\n            addr += total_size\n\n            if tqdm:\n                pbar.update(total_size)\n\n            count += 1\n        return\n\n    def walk_spaces(self, target_regions, cage_base):\n        tqdm = GefUtil.get_tqdm()\n        for start, limit, perm, path in tqdm(target_regions, leave=False):\n            self.out.append(titlify(\"{:#x}-{:#x} {:s} {:s}\".format(start, limit, perm, path)))\n            self.walk_space(start, limit, cage_base)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        cage_base = V8ListMapsCommand.get_cage_base()\n        if not cage_base:\n            err(\"Cannot determine cage base\")\n            return\n        info(\"The cage base: {:#x}\".format(cage_base))\n\n        self.output_path = os.path.join(GEF_TEMP_DIR, \"v8-dump-space-{:#x}.txt\".format(cage_base))\n        self.instace_type_cache_path = os.path.join(GEF_TEMP_DIR, \"v8-dump-space-instance-type.txt\")\n\n        target_regions = self.get_target_regions()\n        if not target_regions:\n            err(\"Cannot determine target space address range\")\n            return\n\n        self.out = []\n        self.walk_spaces(target_regions, cage_base)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass V8Command(GenericCommand):\n    \"\"\"Print v8 tagged object, or load more commands from internet.\"\"\"\n\n    _cmdline_ = \"v8\"\n    _category_ = \"05-b. Heap - Chromium/V8\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, nargs=\"?\",\n                       help=\"target map address.\")\n    group.add_argument(\"-l\", \"--load-v8-gdbinit\", action=\"store_true\",\n                       help=\"load gdbinit for v8 from internet.\")\n    group.add_argument(\"-L\", \"--list-command\", action=\"store_true\",\n                       help=\"show newly added commands from v8 gdbinit.\")\n    _syntax_ = parser.format_help()\n\n    def get_gdbinit(self):\n        gdbinit_filename = os.path.join(GEF_TEMP_DIR, \"gdbinit-v8\")\n        if not os.path.exists(gdbinit_filename):\n            # https://chromium.googlesource.com/v8/v8/+/refs/heads/main/tools/gdbinit\n            url = \"https://chromium.googlesource.com/v8/v8/+/refs/heads/main/tools/gdbinit?format=TEXT\"\n            gdbinit_data = http_get(url)\n            import base64\n            gdbinit_data = base64.b64decode(gdbinit_data)\n            open(gdbinit_filename, \"wb\").write(gdbinit_data)\n            info(\"Download gdbinit from internet\")\n        else:\n            info(\"Reuse gdbinit cached previously\")\n        return gdbinit_filename\n\n    @staticmethod\n    @Cache.cache_this_session\n    def is_chromium():\n        maps = ProcessMap.get_process_maps()\n        for m in maps:\n            if m.path.startswith(\"[anon:partition_alloc]\"):\n                return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.load_v8_gdbinit:\n            gdbinit_filename = self.get_gdbinit()\n            try:\n                gdb.execute(\"source {:s}\".format(gdbinit_filename))\n                info(\"Successfully loaded\")\n            except gdb.error:\n                err(\"Failed to load\")\n            return\n\n        if args.list_command:\n            gdb.execute(\"v8 -l\", to_string=True)\n            gdbinit_filename = self.get_gdbinit()\n            data = open(gdbinit_filename).read()\n            for line in data.splitlines():\n                line = line.strip()\n                if line.startswith((\"alias \", \"define \")):\n                    comm = line.split()[1]\n                    gef_print(titlify(comm))\n                    gdb.execute(\"help {:s}\".format(comm))\n                elif line.startswith((\"super(\", \"super (\")) and '\"' in line:\n                    comm = line.split('\"')[-2]\n                    gef_print(titlify(comm))\n                    gdb.execute(\"help {:s}\".format(comm))\n            return\n\n        if args.address:\n            try:\n                # Since this command is used so often, it can be implemented without loading from internet.\n                cmd = \"call (void) _v8_internal_Print_Object((void*)({:#x}))\".format(args.address)\n                gdb.execute(cmd)\n                # When attached to chromium and run, the newline is not generated,\n                # so it is not displayed immediately due to buffering. As a workaround, run putchar('\\n') and fflush(0).\n                if V8Command.is_chromium():\n                    cmd = \"call (void) putchar(0x0a)\"\n                    gdb.execute(cmd)\n                    cmd = \"call (void) fflush(0)\"\n                    gdb.execute(cmd)\n            except gdb.error:\n                pass\n        return\n\n\n@register_command\nclass PartitionAllocDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"PartitionAlloc free-list viewer for chromium stable.\"\"\"\n\n    _cmdline_ = \"partition-alloc-dump\"\n    _category_ = \"05-b. Heap - Chromium/V8\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [\"fast_malloc\", \"array_buffer\", \"buffer\", \"fm\", \"ab\", \"b\"]\n    parser.add_argument(\"target_buffer_root\", choices=modes,\n                        help=\"the target buffer_root. The last three are abbreviated forms.\")\n    parser.add_argument(\"-f\", \"--force-heuristic\", action=\"store_true\",\n                        help=\"use heuristic roots detection.\")\n    parser.add_argument(\"-r\", \"--root\", type=AddressUtil.parse_address,\n                        help=\"the memory address of target {buffer,array_buffer,fast_malloc}_root_.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display also empty slots.\")\n    parser.add_argument(\"--debug\", action=\"store_true\", help=\"[FOR DEVELOPER] enable debug print.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} array_buffer  # walk from array_buffer_root_\",\n        \"{0:s} ab            # same above\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Chromium mainline is too fast to develop. So if parse is failed, you need fix this gef.py.\",\n        \"\",\n        \"Simplified partition alloc structure:\",\n        \"\",\n        \" +-root-----------------+\",\n        \" | ...                  |    +---->+-extent------------+  +-->+-extent------------+  +-> ...\",\n        \" | next_super_page_     |    |     | next              |--+   | next              |--+\",\n        \" | next_partition_page_ |    |     +-------------------+      +-------------------+\",\n        \" | ...                  |    |\",\n        \" | first_extent_        |----+\",\n        \" | direct_map_list_     |--------->+-direct_map_extent-+  +-->+-direct_map_extent-+  +-> ...\",\n        \" | ...                  |          | bucket            |  |   | bucket            |  |\",\n        \" |                      |          | next_extent       |--+   | next_extent       |--+\",\n        \" |                      |          +-------------------+      +-------------------+\",\n        \" |                      |\",\n        \" +-bucket[0](0x20)------+\",\n        \" | head                 |--------->+-slot_span---------+  +-->+-slot_span---------+  +-> ...\",\n        \" | slot_size            |<---------| bucket            |  |   | bucket            |  |\",\n        \" | ...                  |    +-----| freelist_head     |  |   | freelist_head     |  |\",\n        \" +-bucket[1](0x20)------+    |     | next_slot_span    |--+   | next_slot_span    |--+\",\n        \" | head                 |    |     +-------------------+      +-------------------+\",\n        \" | slot_size            |    |\",\n        \" | ...                  |    |\",\n        \" +----------------------+    +---->+-slot--------------+\",\n        \" | ...                  |          | next              |---+\",\n        \" |                      |          | (freed)           |   |\",\n        \" +----------------------+          +-slot--------------+   |\",\n        \"                                   |                   |   |\",\n        \"                                   | (used)            |   |\",\n        \"                                   +-slot--------------+<--+\",\n        \"                               +---| next              |\",\n        \"                               |   | (freed)           |\",\n        \"                               |   +-slot--------------+\",\n        \"                               |   |                   |\",\n        \"                               |   | (used)            |\",\n        \"                               +-->+-slot--------------+\",\n        \"                                   | next              |---> NULL\",\n        \"                                   | (freed)           |\",\n        \"                                   +-slot--------------+\",\n        \"                                   |                   |\",\n        \"                                   |                   |\",\n        \"                                   +-------------------+\",\n        \"\",\n        \"`extent`, `slot_span` and `slot` are in super_page.\",\n        \"\",\n        \"      [~v144.x]                    [v145.x~; PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE)=y]\",\n        \"      +-super_page-(2MB)-----+      +-super_page(for meta)-+ +-super_page(for chunk)+\",\n        \" 4KB  | Guard Page           |      | Guard Page           | | Guard Page           |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \" 4KB  | extent * 1           |      | extend * 1           | | Unused               |\",\n        \"      | slot_span * 126      |      | slot_span * 126      | |                      |\",\n        \"      | unused * 1           |      | unused * 1           | |                      |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \" 8KB  | Guard Page           |      | Guard Page           | | Guard Page           |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \" 16KB | Partition Page #1    |      | ...                  | | Partition Page #1    |\",\n        \"      |   slot               |      |                      | |   slot               |\",\n        \"      |   slot               |      |                      | |   slot               |\",\n        \"      |   ...                |      |                      | |   ...                |\",\n        \"      +----------------------+      |                      | +----------------------+\",\n        \"      | ...                  |      |                      | | ...                  |\",\n        \"      +----------------------+      |                      | +----------------------|\",\n        \" 16KB | Partition Page #126  |      |                      | | Partition Page #126  |\",\n        \"      |   slot               |      |                      | |   slot               |\",\n        \"      |   slot               |      |                      | |   slot               |\",\n        \"      |   ...                |      |                      | |   ...                |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \" 12KB | Unused               |      | Unused               | | Unused               |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \"  4KB | Guard Page           |      | Guard Page           | | Guard Page           |\",\n        \"      +----------------------+      +----------------------+ +----------------------+\",\n        \"\",\n        \"                                    * super_page_for_meta - metadata_offset_ == super_page_for_chunk\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    @Cache.cache_this_session\n    def get_roots_heuristic(self):\n        \"\"\"Search for fast_malloc_root, array_buffer_root_ and buffer_root_\"\"\"\n\n        # the pointers to each root are in the RW area.\n        # first, we list the RW area.\n        filepath = Path.get_filepath(append_proc_root_prefix=False)\n        maps = ProcessMap.get_process_maps()\n        if is_64bit():\n            codebase = ProcessMap.get_section_base_address(filepath)\n            mask = 0x0000_ffff_0000_0000\n            chromium_rw_maps = [p for p in maps if p.permission.value == Permission.READ | Permission.WRITE]\n            chromium_rw_maps = [p for p in chromium_rw_maps if (p.page_start & mask) == (codebase & mask) and p.path != filepath]\n        elif is_32bit():\n            mask = 0xff00_0000\n            heapbase = HeapbaseCommand.heap_base()\n            chromium_rw_maps = [p for p in maps if p.permission.value == Permission.READ | Permission.WRITE]\n            chromium_rw_maps = [p for p in chromium_rw_maps if p.page_start < heapbase and p.path != filepath]\n\n        # n_gram([1,2,3,4,5], 3) -> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]\n        def n_gram(target, n):\n            for idx in range(len(target) - n + 1):\n                yield target[idx:idx + n]\n\n        # Check the RW area\n        roots = []\n        for maps in chromium_rw_maps:\n            # explode to each qword (if 64 bit arch) or dword (if 32 bit arch)\n            data_list = slice_unpack(read_memory(maps.page_start, maps.size), current_arch.ptrsize)\n            addr_list = list(range(maps.page_start, maps.page_end, current_arch.ptrsize))\n\n            \"\"\"\n            https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/  \\\n            platform/wtf/allocator/partitions.cc\n\n            partition_alloc::PartitionRoot* Partitions::fast_malloc_root_ = nullptr;\n            partition_alloc::PartitionRoot* Partitions::array_buffer_root_ = nullptr;\n            partition_alloc::PartitionRoot* Partitions::buffer_root_ = nullptr;\n\n            0x5a849775d5a8 <WTF::Partitions::fast_malloc_root_>:                                         0x0000000000000000\n            0x5a849775d5b0 <WTF::Partitions::array_buffer_root_>:                                        0x00005a8497761040\n            0x5a849775d5b8 <WTF::Partitions::buffer_root_>:                                              0x00005a849775d600\n            0x5a849775d5c0 <guard variable for WTF::Partitions::Initialize()::initialized>:              0x0000000100000101\n            ...\n            0x5a8497759bc0 <WTF::Partitions::InitializeOnce()::fast_malloc_allocator>:                   0x0000000000000000\n            ...\n            0x5a849775d600 <WTF::Partitions::InitializeOnce()::buffer_allocator>:                        0x0000000000010000\n            ...\n            0x5a8497761040 <WTF::Partitions::InitializeArrayBufferPartition()::array_buffer_allocator>:  0x0000000000000000\n            \"\"\"\n            # check consecutive quadruples\n            for addr, data in zip(n_gram(addr_list, 4), n_gram(data_list, 4)):\n                # root pointer address and root address are close (see above example)\n                if data[0] != 0 and (addr[0] & mask) != (data[0] & mask):\n                    # fast_malloc_root_ may be zero. but if non-zero, it holds address close to itself\n                    continue\n                if (addr[1] & mask) != (data[1] & mask):\n                    # array_buffer_root_ is must be non-zero. it holds address close to itself\n                    continue\n                if (addr[2] & mask) != (data[2] & mask):\n                    # buffer_root_ is must be non-zero. it holds address close to itself\n                    continue\n                # they should be aligned\n                if data[0] & 0x7:\n                    continue\n                if data[1] & 0x7:\n                    continue\n                if data[2] & 0x7:\n                    continue\n                # initialized must be bool 0x01\n                if (data[3] & 0xff) != 0x01:\n                    continue\n                # check root size\n                buffer_root_size = data[1] - data[2]\n                if buffer_root_size < 0x300: # 0x300 is heuristic value\n                    continue\n                if buffer_root_size > 0x4000: # 0x4000 is heuristic value\n                    continue\n                # check root struct.\n                \"\"\"\n                The first 64 bytes of root are mostly 0 due to padding considering the cache line.\n                This is same both at 64-bit and 32bit arch.\n\n                [WTF::Partitions::InitializeOnce()::buffer_allocator]\n                0x5a849775d600: 0x0000000000010000      0x0000000000000004\n                0x5a849775d610: 0x0000000000000000      0x00000000ffffffff\n                0x5a849775d620: 0x0000000400000001      0xfffffe7fec785000\n                0x5a849775d630: 0x0000000000000000      0x0000000000000000\n\n                [WTF::Partitions::InitializeArrayBufferPartition()::array_buffer_allocator]\n                0x5a8497761040: 0x0000000000000000      0x0000000000000000\n                0x5a8497761050: 0x0000000000000001      0x00000000ffffffff\n                0x5a8497761060: 0x0000000000000000      0xffffcefbec787000\n                0x5a8497761070: 0x0000000000000000      0x0000000000000000\n                \"\"\"\n                if b\"\\0\" * 8 not in read_memory(data[1], 64):\n                    continue\n                if b\"\\0\" * 8 not in read_memory(data[2], 64):\n                    continue\n                if self.args.debug:\n                    info(f\"buffer_root_size: {buffer_root_size:#x}\")\n                    gdb.execute(f\"ml x/8xg {data[1]:#x}; x/8xg {data[2]:#x}\")\n                # add candidate\n                Root = collections.namedtuple(\"Root\", [\"name\", \"address\"])\n                root_candidate = [\n                    Root(\"fast_malloc_root_\", addr[0]),\n                    Root(\"array_buffer_root_\", addr[1]),\n                    Root(\"buffer_root_\", addr[2]),\n                ]\n                roots.append(root_candidate)\n\n        # debug print\n        if len(roots) == 0:\n            err(\"Could not find any roots, try check code\")\n            return []\n\n        if len(roots) == 1:\n            for r in roots[0]:\n                info(\"Found: {:s}: {:#x}\".format(r.name, r.address))\n            return roots[0]\n\n        err(\"Candidates for root are found in multiple locates, try check code\")\n        for root in roots:\n            for r in root:\n                gef_print(\"  candidate: {:20s} {:#x}\".format(r.name, r.address))\n            gef_print()\n        return []\n\n    def get_roots(self, force_heuristic):\n\n        def get_root(root_string):\n            # newer version\n            try:\n                root_addr = AddressUtil.parse_address(\"&'blink::Partitions::{:s}'\".format(root_string))\n                Root = collections.namedtuple(\"Root\", [\"name\", \"address\"])\n                return [Root(root_string, root_addr)]\n            except gdb.error:\n                pass\n            # older version\n            try:\n                root_addr = AddressUtil.parse_address(\"&'WTF::Partitions::{:s}'\".format(root_string))\n                Root = collections.namedtuple(\"Root\", [\"name\", \"address\"])\n                return [Root(root_string, root_addr)]\n            except gdb.error:\n                pass\n            return []\n\n        roots = []\n        # user specific\n        if self.args.root:\n            Root = collections.namedtuple(\"Root\", [\"name\", \"address\"])\n            roots += [Root(self.args.target_buffer_root + \"_root_\", self.args.root)]\n            return roots\n        # try from symbols\n        if not force_heuristic:\n            for root_string in [\"fast_malloc_root_\", \"array_buffer_root_\", \"buffer_root_\"]:\n                roots += get_root(root_string)\n        # maybe no symbols, try heuristic\n        if len(roots) == 0:\n            info(\"Use heuristic search\")\n            roots = self.get_roots_heuristic()\n        # retry checking\n        if len(roots) == 0:\n            info(\"Could not find the symbol\")\n        return roots\n\n    @Cache.cache_until_next\n    def get_sentinel_slot_spans(self):\n        \"\"\"sentinel_slot_span is default slot_span, so search for it.\"\"\"\n        sentinel = []\n\n        # new version\n        try:\n            ns = \"partition_alloc::internal::SlotSpanMetadata<(partition_alloc::internal::MetadataKind)1>\"\n            t = AddressUtil.parse_address(\"&'{:s}::sentinel_slot_span_'\".format(ns))\n            sentinel.append(t)\n            return sentinel\n        except gdb.error:\n            pass\n\n        # old version\n        try:\n            t = AddressUtil.parse_address(\"&'base::internal::SlotSpanMetadata<true>::sentinel_slot_span_'\")\n            sentinel.append(t)\n        except gdb.error:\n            pass\n        try:\n            f = AddressUtil.parse_address(\"&'base::internal::SlotSpanMetadata<false>::sentinel_slot_span_'\")\n            sentinel.append(f)\n        except gdb.error:\n            pass\n        return sentinel\n\n    def read_root(self, addr, name):\n        ptrsize = current_arch.ptrsize\n        root = {}\n        root[\"name\"] = name\n        root[\"addr\"] = current = read_int_from_memory(addr)\n        \"\"\"\n        https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/  \\\n        src/partition_alloc/partition_root.h\n\n        struct base::PartitionRoot {\n            struct alignas(internal::kPartitionCachelineSize) Settings {\n                BucketDistribution bucket_distribution = BucketDistribution::kNeutral; // uint8_t\n                size_t thread_cache_index = internal::kInvalidThreadCacheIndex;\n                bool with_thread_cache = false;\n                bool use_cookie = false;\n                bool brp_enabled_ = false;\n                size_t in_slot_metadata_size = 0;\n                internal::pool_handle pool_handle = internal::pool_handle::kNullPoolHandle;\n                internal::PoolOffsetLookup offset_lookup;\n                internal::ReservationOffsetTable reservation_offset_table;\n                bool eventually_zero_freed_memory = false;\n                internal::SchedulerLoopQuarantineConfig scheduler_loop_quarantine;\n                bool memory_tagging_enabled_ = false;\n                bool use_random_memory_tagging_enabled_ = false;\n                TagViolationReportingMode memory_tagging_reporting_mode_ = TagViolationReportingMode::kUndefined;\n                ThreadIsolationOption thread_isolation;\n                uint32_t extras_size = 0;\n                std::ptrdiff_t metadata_offset_ = 0;\n                bool enable_free_with_size = false;\n                bool enable_strict_free_size_check = true;\n            } settings_; // 0x40 bytes or 0x80 bytes or 0xc0 bytes\n            internal::Lock lock_;  // 8 bytes\n            Bucket buckets_[BucketIndexLookup::kNumBuckets] = {};\n            Bucket sentinel_bucket_{};\n            bool initialized_ = false;\n            std::atomic<size_t> total_size_of_committed_pages_{0};\n            std::atomic<size_t> max_size_of_committed_pages_{0};\n            std::atomic<size_t> total_size_of_super_pages_{0};\n            std::atomic<size_t> total_size_of_direct_mapped_pages_{0};\n            std::atomic<size_t> total_size_of_allocated_bytes_{0};\n            std::atomic<size_t> max_size_of_allocated_bytes_{0};\n            std::atomic<uint64_t> syscall_count_;\n            std::atomic<uint64_t> syscall_total_time_ns_;\n            std::atomic<size_t> total_size_of_brp_quarantined_bytes{0};\n            std::atomic<size_t> total_count_of_brp_quarantined_slots_{0};\n            std::atomic<size_t> cumulative_size_of_brp_quarantined_bytes_{0};\n            std::atomic<size_t> cumulative_count_of_brp_quarantined_slots_{0};\n            size_t empty_slot_spans_dirty_bytes_ PA_GUARDED_BY(internal::PartitionRootLock(this)) = 0;\n            int max_empty_slot_spans_dirty_bytes_shift_ = 3;\n            uintptr_t next_super_page_ = 0;\n            uintptr_t next_partition_page_ = 0;\n            uintptr_t next_partition_page_end_ = 0;\n            SuperPageExtentEntry* current_extent_ = nullptr;\n            SuperPageExtentEntry* first_extent_ = nullptr;\n            DirectMapExtent* direct_map_list_ PA_GUARDED_BY(internal::PartitionRootLock(this)) = nullptr;\n            SlotSpanMetadata* global_empty_slot_span_ring_[internal::kMaxEmptySlotSpanRingSize] \\\n                PA_GUARDED_BY(internal::PartitionRootLock(this)) = {};\n            int16_t global_empty_slot_span_ring_index_ PA_GUARDED_BY(internal::PartitionRootLock(this)) = 0;\n            int16_t global_empty_slot_span_ring_size_ PA_GUARDED_BY(internal::PartitionRootLock(this)) = \\\n                internal::kDefaultEmptySlotSpanRingSize;\n            uintptr_t inverted_self_ = 0;\n            internal::Lock thread_cache_construction_lock_; // 8 bytes\n            size_t scheduler_loop_quarantine_branch_capacity_in_bytes_ = 0;\n            internal::SchedulerLoopQuarantineRoot scheduler_loop_quarantine_root_;\n            internal::GlobalSchedulerLoopQuarantineBranch scheduler_loop_quarantine_;\n            internal::GlobalSchedulerLoopQuarantineBranch scheduler_loop_quarantine_for_advanced_memory_safety_checks_;\n        };\n        \"\"\"\n        x = read_int_from_memory(current + 0x40 + 8) # sizeof(struct Settings) + sizeof(lock_)\n        if is_valid_addr(x): # buckets[0]->active_slot_spans_head\n            current += 0x40 # sizeof(struct Settings) is 1 cache line\n        else:\n            x = read_int_from_memory(current + 0x80 + 8) # sizeof(struct Settings) + sizeof(lock_)\n            if is_valid_addr(x): # buckets[0]->active_slot_spans_head\n                current += 0x80 # sizeof(struct Settings) is 2 cache lines\n            else:\n                current += 0xc0 # sizeof(struct Settings) is 3 cache lines\n\n        def get_metadata_offset(root_addr, current_addr):\n            \"\"\"\n            # v145.x~ has PA_CONFIG(MOVE_METADATA_OUT_OF_GIGACAGE)\n            0x599a3e48af40|+0x0000|+000: settings (=&root)        : 0x0000000000010000\n            0x599a3e48af48|+0x0008|+001:                          : 0x0000000000000004\n            0x599a3e48af50|+0x0010|+002:                          : 0x0000000000000002\n            0x599a3e48af58|+0x0018|+003:                          : 0x000009f400000000\n            0x599a3e48af60|+0x0020|+004:                          : 0xfffffffc00000000\n            0x599a3e48af68|+0x0028|+005:                          : 0x0000599a3e1dc018\n            0x599a3e48af70|+0x0030|+006:                          : 0x000009f400000000\n            0x599a3e48af78|+0x0038|+007:                          : 0xfffffffc00000000\n            0x599a3e48af80|+0x0040|+008:                          : 0x0000000000000000\n            0x599a3e48af88|+0x0048|+009:                          : 0x0000000000000000\n            0x599a3e48af90|+0x0050|+010:                          : 0xaaaaaaaaaa000000\n            0x599a3e48af98|+0x0058|+011:                          : 0x00000000000f0000\n            0x599a3e48afa0|+0x0060|+012:                          : 0x0000000000000000\n            0x599a3e48afa8|+0x0068|+013:                          : 0x0000000000000000\n            0x599a3e48afb0|+0x0070|+014:                          : 0x0000000000000000\n            0x599a3e48afb8|+0x0078|+015:                          : 0x0000000000000000\n            0x599a3e48afc0|+0x0080|+016:                          : 0x00000000ffffffff\n            0x599a3e48afc8|+0x0088|+017:                          : 0x0000000000000004\n            0x599a3e48afd0|+0x0090|+018: settings.metadata_offset_: 0x00002e37f278b000 <-- here\n            0x599a3e48afd8|+0x0098|+019:                          : 0x0000000000000100\n            0x599a3e48afe0|+0x00a0|+020:                          : 0x0000000000000000\n            0x599a3e48afe8|+0x00a8|+021:                          : 0x0000000000000000\n            0x599a3e48aff0|+0x00b0|+022:                          : 0x0000000000000000\n            0x599a3e48aff8|+0x00b8|+023:                          : 0x0000000000000000\n            0x599a3e48b000|+0x00c0|+024: lock_                    : 0x0000000000000000\n            0x599a3e48b008|+0x00c8|+025: buckets[0]               : 0x0000382bf298b920\n            0x599a3e48b010|+0x00d0|+026: buckets[0]               : 0x0000000000000000\n            0x599a3e48b018|+0x00d8|+027: buckets[0]               : 0x0000000000000000\n            0x599a3e48b020|+0x00e0|+028: buckets[0]               : 0x0000000400000010\n            0x599a3e48b028|+0x00e8|+029: buckets[0]               : 0x0000004000000000\n            0x599a3e48b030|+0x00f0|+030: buckets[0]               : 0x0000000000000000\n            \"\"\"\n            if current_addr - root_addr != 0xc0:\n                return get_pagesize()\n            data = read_memory(root_addr + 0x80, 0x40)\n            for x in slice_unpack(data, current_arch.ptrsize):\n                if x & 0xfff:\n                    continue\n                if x == 0:\n                    continue\n                if (root_addr & 0x0000_ffff_ff00_0000) == (x & 0x0000_ffff_ff00_0000):\n                    continue\n                if (x & 0xffff_ffff) == 0:\n                    continue\n                return x\n            return get_pagesize()\n\n        root[\"metadata_offset_\"] = get_metadata_offset(root[\"addr\"], current)\n\n        root[\"lock_\"] = read_int64_from_memory(current)\n        current += 8\n\n        # for 32bit, there is 2 patterns because aligned or packed\n        if is_32bit():\n            if self.align_pad is None:\n                x = read_int_from_memory(current)\n                if x == 0:\n                    self.align_pad = True\n                else:\n                    self.align_pad = False\n            if self.align_pad:\n                current += ptrsize\n\n        root[\"buckets_\"] = []\n        while True:\n            if read_int_from_memory(current) == 1: # search for `bool initialized`\n                break\n            bucket, current = self.read_bucket(current)\n            root[\"buckets_\"].append(bucket)\n\n        root[\"sentinel_bucket_\"] = root[\"buckets_\"].pop()\n\n        root[\"initialized_\"] = read_int_from_memory(current) & 0xff\n        current += ptrsize # with pad\n        root[\"total_size_of_committed_pages_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"max_size_of_committed_pages_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"total_size_of_super_pages_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"total_size_of_direct_mapped_pages_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"total_size_of_allocated_bytes_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"max_size_of_allocated_bytes_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"syscall_count_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"syscall_total_time_ns_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"total_size_of_brp_quarantined_bytes\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"total_count_of_brp_quarantined_slots_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"cumulative_size_of_brp_quarantined_bytes_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"cumulative_count_of_brp_quarantined_slots_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"empty_slot_spans_dirty_bytes_\"] = read_int32_from_memory(current)\n        current += ptrsize # with pad\n        root[\"max_empty_slot_spans_dirty_bytes_shift_\"] = read_int32_from_memory(current)\n        current += ptrsize # with pad\n        root[\"next_super_page_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"next_partition_page_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"next_partition_page_end_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"current_extent_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"first_extent_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"direct_map_list_\"] = read_int_from_memory(current)\n        current += ptrsize\n\n        root[\"global_empty_slot_span_ring_\"] = []\n        inv = root[\"addr\"] ^ AddressUtil.get_vmem_end_mask()\n        while True:\n            if read_int_from_memory(current + ptrsize) == inv: # search for `inverted_self_`\n                break\n            x = read_int_from_memory(current)\n            current += ptrsize\n            root[\"global_empty_slot_span_ring_\"].append(x)\n        root[\"global_empty_slot_span_ring_index_\"] = read_int16_from_memory(current)\n        current += 2\n        root[\"global_empty_slot_span_ring_size_\"] = read_int16_from_memory(current)\n        current += 2\n        if is_64bit():\n            current += 4 # pad\n        root[\"inverted_self_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"thread_cache_construction_lock_\"] = read_int64_from_memory(current)\n        current += 8\n        root[\"scheduler_loop_quarantine_branch_capacity_in_bytes_\"] = read_int32_from_memory(current)\n        current += ptrsize # with pad\n        root[\"scheduler_loop_quarantine_root_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"scheduler_loop_quarantine_\"] = read_int_from_memory(current)\n        current += ptrsize\n        root[\"scheduler_loop_quarantine_for_advanced_memory_safety_checks_\"] = read_int_from_memory(current)\n        current += ptrsize\n\n        Root = collections.namedtuple(\"Root\", root.keys())\n        root = Root(*root.values())\n        return root, current\n\n    @Cache.cache_until_next\n    def read_bucket(self, addr):\n        ptrsize = current_arch.ptrsize\n        bucket = {}\n        bucket[\"addr\"] = current = addr\n        \"\"\"\n        https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/  \\\n        src/partition_alloc/partition_bucket.h\n\n        struct base::internal::PartitionBucket {\n            SlotSpanMetadata* active_slot_spans_head;\n            SlotSpanMetadata* empty_slot_spans_head;\n            SlotSpanMetadata* decommitted_slot_spans_head;\n            uint32_t slot_size;\n            uint32_t num_system_pages_per_slot_span : 8;\n            uint32_t num_full_slot_spans : 24;\n            uint64_t slot_size_reciprocal;\n            bool can_store_raw_size;\n        };\n        \"\"\"\n        bucket[\"active_slot_spans_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        bucket[\"empty_slot_spans_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        bucket[\"decommitted_slot_spans_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        bucket[\"slot_size\"] = read_int32_from_memory(current)\n        current += 4\n        x = read_int32_from_memory(current)\n        bucket[\"num_system_pages_per_slot_span\"] = x & 0xff\n        bucket[\"num_full_slot_spans\"] = (x >> 8) & 0xff_ffff\n        current += 4\n\n        # for 32bit, there is 2 patterns because aligned or packed\n        if is_32bit() and self.align_pad:\n            current += 4\n        bucket[\"slot_size_reciprocal\"] = read_int64_from_memory(current)\n        current += 8\n\n        x = read_int32_from_memory(current)\n        bucket[\"can_store_raw_size\"] = x & 0xff\n        current += ptrsize # with pad\n\n        Bucket = collections.namedtuple(\"Bucket\", bucket.keys())\n        bucket = Bucket(*bucket.values())\n        return bucket, current\n\n    @Cache.cache_until_next\n    def read_extent(self, addr):\n        ptrsize = current_arch.ptrsize\n        extent = {}\n        extent[\"addr\"] = current = addr\n        extent[\"super_page_base\"] = current - 0x1000\n        \"\"\"\n        https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/  \\\n        src/partition_alloc/partition_superpage_extent_entry.h\n\n        struct PartitionSuperPageExtentEntry {\n          PartitionRootBase* root;\n          PartitionSuperPageExtentEntry* next;\n          uint16_t number_of_consecutive_super_pages;\n          uint16_t number_of_nonempty_slot_spans;\n        };\n        \"\"\"\n        extent[\"root\"] = read_int_from_memory(current)\n        current += ptrsize\n        extent[\"next\"] = read_int_from_memory(current)\n        current += ptrsize\n        extent[\"number_of_consecutive_super_pages\"] = read_int16_from_memory(current)\n        current += 2\n        extent[\"number_of_nonempty_slot_spans\"] = read_int16_from_memory(current)\n        current += 2\n        extent[\"super_page_end\"] = extent[\"super_page_base\"] + extent[\"number_of_consecutive_super_pages\"] * 0x20_0000\n\n        Extent = collections.namedtuple(\"Extent\", extent.keys())\n        extent = Extent(*extent.values())\n        return extent, current\n\n    @Cache.cache_until_next\n    def read_direct_map(self, addr):\n        ptrsize = current_arch.ptrsize\n        direct_map = {}\n        direct_map[\"addr\"] = current = addr\n        \"\"\"\n        https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/  \\\n        src/partition_alloc/partition_direct_map_extent.h\n\n        struct PartitionDirectMapExtent {\n          PartitionDirectMapExtent* next_extent;\n          PartitionDirectMapExtent* prev_extent;\n          const PartitionBucket* bucket;\n          size_t reservation_size;\n          size_t padding_for_alignment;\n        };\n        \"\"\"\n        direct_map[\"next_extent\"] = read_int_from_memory(current)\n        current += ptrsize\n        direct_map[\"prev_extent\"] = read_int_from_memory(current)\n        current += ptrsize\n        direct_map[\"bucket\"] = read_int_from_memory(current)\n        current += ptrsize\n        direct_map[\"reservation_size\"] = read_int_from_memory(current)\n        current += ptrsize\n        direct_map[\"padding_for_alignment\"] = read_int_from_memory(current)\n        current += ptrsize\n\n        DirectMap = collections.namedtuple(\"DirectMap\", direct_map.keys())\n        direct_map = DirectMap(*direct_map.values())\n        return direct_map, current\n\n    @Cache.cache_until_next\n    def read_slot_span(self, addr):\n        ptrsize = current_arch.ptrsize\n        slot_span = {}\n        slot_span[\"addr\"] = current = addr\n        slot_span[\"super_page_addr\"] = AddressUtil.align_address(\n            (slot_span[\"addr\"] & get_pagesize_mask_high()) - self.root.metadata_offset_,\n        )\n        slot_span[\"partition_page_index\"] = (slot_span[\"addr\"] & get_pagesize_mask_low()) // 0x20\n        super_page_addr_offset = slot_span[\"partition_page_index\"] * get_pagesize() * 4\n        slot_span[\"partition_page_start\"] = slot_span[\"super_page_addr\"] + super_page_addr_offset\n        \"\"\"\n        https://source.chromium.org/chromium/chromium/src/+/main:base/allocator/partition_allocator/  \\\n        src/partition_alloc/partition_page.h\n\n        struct SlotSpanMetadata {\n          FreelistEntry* freelist_head = nullptr;\n          SlotSpanMetadata* next_slot_span = nullptr;\n          PartitionBucket* const bucket = nullptr;\n          uint32_t num_allocated_slots : kMaxSlotsPerSlotSpanBits; // 15 bits\n          uint32_t num_unprovisioned_slots : kMaxSlotsPerSlotSpanBits; // 15 bits\n          uint32_t marked_full : 1;\n          const uint32_t can_store_raw_size_ : 1;\n          uint16_t freelist_is_sorted_ : 1;\n          uint16_t in_empty_cache_ : 1;\n          uint16_t empty_cache_index_ : internal::base::bits::BitWidth(kMaxEmptySlotSpanRingSize - 1); // 7 or 10 bits\n        };\n        \"\"\"\n        slot_span[\"freelist_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        slot_span[\"next_slot_span\"] = read_int_from_memory(current)\n        current += ptrsize\n        slot_span[\"bucket\"] = read_int_from_memory(current)\n        current += ptrsize\n        x = read_int32_from_memory(current)\n        current += 4\n        slot_span[\"num_allocated_slots\"] = (x >> 0) & 0x7fff\n        slot_span[\"num_unprovisioned_slots\"] = (x >> 15) & 0x7fff\n        slot_span[\"marked_full\"] = (x >> 30) & 1\n        slot_span[\"can_store_raw_size_\"] = (x >> 31) & 1\n\n        x = read_int16_from_memory(current)\n        current += 2\n        slot_span[\"freelist_is_sorted_\"] = (x >> 0) & 1\n        slot_span[\"in_empty_cache_\"] = (x >> 1) & 1\n        slot_span[\"empty_cache_index_\"] = (x >> 2) & 0x3ff\n\n        SlotSpan = collections.namedtuple(\"SlotSpan\", slot_span.keys())\n        slot_span = SlotSpan(*slot_span.values())\n        return slot_span, current\n\n    def C(self, address):\n        # coloring function for heap address\n        management_color = Config.get_gef_setting(\"theme.heap_management_address\")\n\n        # in extent\n        current = self.root.current_extent_\n        while current:\n            extent, _ = self.read_extent(current)\n            if extent.super_page_base <= address < extent.super_page_end:\n                return Color.colorify_hex(address, management_color)\n            current = extent.next\n\n        # not in extent, but valid\n        if is_valid_addr(address):\n            return str(ProcessMap.lookup_address(address))\n\n        # not valid\n        return \"{:#x}\".format(address)\n\n    def P(self, address):\n        # coloring function for heap page address\n        page_address_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        return Color.colorify_hex(address, page_address_color)\n\n    def dump_root(self, root):\n        self.out.append(titlify(\"*{} @ {:#x}\".format(root.name, root.addr)))\n        self.out.append(\"struct Settings settings_:                                      ...\")\n        self.out.append(\"std::ptrdiff_t settings.metadata_offset_:                       {:#x}\".format(\n            root.metadata_offset_,\n        ))\n        self.out.append(\"::partition_alloc::Lock lock_:                                  {:#x}\".format(\n            root.lock_,\n        ))\n        self.out.append(\"Bucket buckets_[{:3d}]:\".format(len(root.buckets_)))\n        for idx, bucket in enumerate(root.buckets_):\n            self.dump_bucket(bucket, root, idx)\n        if self.args.verbose:\n            self.out.append(\"Bucket sentinel_bucket_:\")\n            self.dump_bucket(root.sentinel_bucket_, root)\n        else:\n            self.out.append(\"Bucket sentinel_bucket_:                                        ...\")\n        self.out.append(\"bool initialized_:                                              {:#x}\".format(\n            root.initialized_,\n        ))\n        self.out.append(\"std::atomic<size_t> total_size_of_committed_pages_:             {:#x}\".format(\n            root.total_size_of_committed_pages_,\n        ))\n        self.out.append(\"std::atomic<size_t> max_size_of_committed_pages_:               {:#x}\".format(\n            root.max_size_of_committed_pages_,\n        ))\n        self.out.append(\"std::atomic<size_t> total_size_of_super_pages_:                 {:#x}\".format(\n            root.total_size_of_super_pages_,\n        ))\n        self.out.append(\"std::atomic<size_t> total_size_of_direct_mapped_pages_:         {:#x}\".format(\n            root.total_size_of_direct_mapped_pages_,\n        ))\n        self.out.append(\"std::atomic<size_t> total_size_of_allocated_bytes_:             {:#x}\".format(\n            root.total_size_of_allocated_bytes_,\n        ))\n        self.out.append(\"std::atomic<size_t> max_size_of_allocated_bytes_:               {:#x}\".format(\n            root.max_size_of_allocated_bytes_,\n        ))\n        self.out.append(\"std::atomic<uint64_t> syscall_count_:                           {:#x}\".format(\n            root.syscall_count_,\n        ))\n        self.out.append(\"std::atomic<uint64_t> syscall_total_time_ns_:                   {:#x}\".format(\n            root.syscall_total_time_ns_,\n        ))\n        self.out.append(\"std::atomic<size_t> total_size_of_brp_quarantined_bytes:        {:#x}\".format(\n            root.total_size_of_brp_quarantined_bytes,\n        ))\n        self.out.append(\"std::atomic<size_t> total_count_of_brp_quarantined_slots_:      {:#x}\".format(\n            root.total_count_of_brp_quarantined_slots_,\n        ))\n        self.out.append(\"std::atomic<size_t> cumulative_size_of_brp_quarantined_bytes_:  {:#x}\".format(\n            root.cumulative_size_of_brp_quarantined_bytes_,\n        ))\n        self.out.append(\"std::atomic<size_t> cumulative_count_of_brp_quarantined_slots_: {:#x}\".format(\n            root.cumulative_count_of_brp_quarantined_slots_,\n        ))\n        self.out.append(\"size_t empty_slot_spans_dirty_bytes_:                           {:#x}\".format(\n            root.empty_slot_spans_dirty_bytes_,\n        ))\n        self.out.append(\"int max_empty_slot_spans_dirty_bytes_shift_:                    {:#x}\".format(\n            root.max_empty_slot_spans_dirty_bytes_shift_,\n        ))\n        self.out.append(\"uintptr_t next_super_page_:                                     {:s}\".format(\n            self.P(root.next_super_page_),\n        ))\n        self.out.append(\"uintptr_t next_partition_page_:                                 {:s}\".format(\n            self.P(root.next_partition_page_),\n        ))\n        self.out.append(\"uintptr_t next_partition_page_end_:                             {:s}\".format(\n            self.P(root.next_partition_page_end_),\n        ))\n        self.out.append(\"SuperPageExtentEntry* current_extent_:                          {:s}\".format(\n            self.C(root.current_extent_),\n        ))\n        self.dump_extent_list(root.current_extent_)\n        self.out.append(\"SuperPageExtentEntry* first_extent_:                            {:s}\".format(\n            self.C(root.first_extent_),\n        ))\n        self.dump_extent_list(root.first_extent_)\n        self.out.append(\"DirectMapExtent* direct_map_list_:                              {:s}\".format(\n            self.C(root.direct_map_list_),\n        ))\n        self.dump_direct_map_list(root.direct_map_list_, root)\n        ring_len = len(root.global_empty_slot_span_ring_)\n        if self.args.verbose:\n            self.out.append(\"SlotSpanMetadata* global_empty_slot_span_ring_[{:4d}]:\".format(\n                ring_len,\n            ))\n            for i in range(len(root.global_empty_slot_span_ring_)):\n                colored_slot_span = self.C(root.global_empty_slot_span_ring_[i])\n                self.out.append(\"    global_empty_slot_span_ring_[{:4d}]:                         {:s}\".format(\n                    i, colored_slot_span,\n                ))\n        else:\n            self.out.append(\"SlotSpanMetadata* global_empty_slot_span_ring_[{:4d}]:           ...\".format(\n                ring_len,\n            ))\n        self.out.append(\"int16_t global_empty_slot_span_ring_index_:                     {:#x}\".format(\n            root.global_empty_slot_span_ring_index_,\n        ))\n        self.out.append(\"int16_t global_empty_slot_span_ring_size_:                      {:#x}\".format(\n            root.global_empty_slot_span_ring_size_,\n        ))\n        inv_inv = root.inverted_self_ ^ AddressUtil.get_vmem_end_mask()\n        self.out.append(\"uintptr_t inverted_self_:                                       {:#x} (=~{!s})\".format(\n            root.inverted_self_, ProcessMap.lookup_address(inv_inv),\n        ))\n        self.out.append(\"internal::Lock thread_cache_construction_lock_:                 {:#x}\".format(\n            root.thread_cache_construction_lock_,\n        ))\n        self.out.append(\"size_t scheduler_loop_quarantine_branch_capacity_in_bytes_:     {:#x}\".format(\n            root.scheduler_loop_quarantine_branch_capacity_in_bytes_,\n        ))\n        self.out.append(\"internal::SchedulerLoopQuarantineRoot scheduler_loop_quarantine_root_: {:#x}\".format(\n            root.scheduler_loop_quarantine_root_,\n        ))\n        self.out.append(\"internal::GlobalSchedulerLoopQuarantineBranch scheduler_loop_quarantine_: {:#x}\".format(\n            root.scheduler_loop_quarantine_,\n        ))\n        self.out.append(\"internal::GlobalSchedulerLoopQuarantineBranch \"\n                        \"scheduler_loop_quarantine_for_advanced_memory_safety_checks_: {:#x}\".format(\n            root.scheduler_loop_quarantine_for_advanced_memory_safety_checks_,\n        ))\n        return\n\n    def dump_extent_list(self, head):\n        try:\n            current = head\n            while current:\n                extent, _ = self.read_extent(current)\n                self.out.append(\"    -> extent @{:s}\".format(\n                    self.C(extent.addr),\n                ))\n                self.out.append(\"           root:{!s} \".format(\n                    ProcessMap.lookup_address(extent.root),\n                ))\n                super_page_info = \"{:s} - {:s}\".format(\n                    self.P(extent.super_page_base), self.P(extent.super_page_end),\n                )\n                page_info = \"(total 0x200000(2MB) * {:d} pages)\".format(\n                    extent.number_of_consecutive_super_pages,\n                )\n                self.out.append(\"           super_page:{:s} {:s}\".format(\n                    super_page_info, page_info,\n                ))\n                self.out.append(\"           non_empty_slot_spans:{:d} \".format(\n                    extent.number_of_nonempty_slot_spans,\n                ))\n                self.out.append(\"           next:{:s}\".format(\n                    self.C(extent.next),\n                ))\n                current = extent.next\n        except Exception:\n            self.err_add_out(\"Corrupted?\")\n        return\n\n    def dump_direct_map_list(self, head, root):\n        try:\n            current = head\n            while current:\n                direct_map, _ = self.read_direct_map(current)\n                self.out.append(\"    -> direct_map @{:s}: \".format(\n                    self.C(direct_map.addr),\n                ))\n                self.out.append(\"           next_extent:{:s} \".format(\n                    self.C(direct_map.next_extent),\n                ))\n                self.out.append(\"           prev_extent:{:s} \".format(\n                    self.C(direct_map.prev_extent),\n                ))\n                self.out.append(\"           bucket:{:s} \".format(\n                    self.C(direct_map.bucket),\n                ))\n                self.out.append(\"           reservation_size:{:#x}\".format(\n                    direct_map.reservation_size,\n                ))\n                self.out.append(\"           padding_for_alignment:{:#x}\".format(\n                    direct_map.padding_for_alignment,\n                ))\n                bucket, _ = self.read_bucket(direct_map.bucket)\n                self.dump_bucket(bucket, root)\n                current = direct_map.next_extent\n        except Exception:\n            self.err_add_out(\"Corrupted?\")\n        return\n\n    def dump_bucket(self, bucket, root, idx=None):\n        sentinel1 = self.get_sentinel_slot_spans() # from symbol\n        sentinel2 = [root.sentinel_bucket_.active_slot_spans_head] # from heuristic search\n        sentinel_or_0 = list(set(sentinel1 + sentinel2 + [0x0])) # uniq\n\n        if not self.args.verbose:\n            if bucket.active_slot_spans_head in sentinel_or_0:\n                return # skip printing\n\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        label_active_color = Config.get_gef_setting(\"theme.heap_label_active\")\n        label_inactive_color = Config.get_gef_setting(\"theme.heap_label_inactive\")\n\n        slot_size = Color.colorify(\"{:#7x}\".format(bucket.slot_size), chunk_size_color)\n        if idx is not None:\n            self.out.append(\"    buckets_[{:3d}](slot_size:{:s}) @{!s}\".format(\n                idx, slot_size, ProcessMap.lookup_address(bucket.addr),\n            ))\n        else:\n            self.out.append(\"    bucket(slot_size:{:s}) @{!s}\".format(\n                slot_size, ProcessMap.lookup_address(bucket.addr),\n            ))\n        self.out.append(\"        num_system_pages_per_slot_span:{:#x} \".format(\n            bucket.num_system_pages_per_slot_span,\n        ))\n        self.out.append(\"        num_full_slot_spans:{:#x} \".format(bucket.num_full_slot_spans))\n        self.out.append(\"        slot_size_reciprocal:{:#x}\".format(bucket.slot_size_reciprocal))\n        self.out.append(\"        can_store_raw_size:{:#x}\".format(bucket.can_store_raw_size))\n\n        if self.args.verbose:\n            target_list = [\"active_slot_spans_head\", \"empty_slot_spans_head\", \"decommitted_slot_spans_head\"]\n        else:\n            target_list = [\"active_slot_spans_head\"]\n\n        for key in target_list:\n            head = getattr(bucket, key)\n            # sentinel can be ignored, so skip\n            if not self.args.verbose and head in sentinel_or_0:\n                continue\n            if head in sentinel_or_0:\n                # print sentinel (verbose)\n                colored_key = Color.colorify(key, label_inactive_color)\n                self.out.append(\"        {:s}:{:s} (=sentinel_pages)\".format(colored_key, self.C(head)))\n            else:\n                # default\n                colored_key = Color.colorify(key, label_active_color)\n                self.out.append(\"        {:s}:{:s}\".format(colored_key, self.C(head)))\n            self.dump_slot_span(head, bucket)\n        return\n\n    def dump_slot_span(self, head, bucket):\n        current = head\n        while current:\n            try:\n                slot_span, _ = self.read_slot_span(current)\n            except Exception:\n                self.err_add_out(\"Corrupted?\")\n                break\n            self.out.append(\"            -> slot_span @{:s} (#{:3d} of super_page @{:s})\".format(\n                self.C(slot_span.addr), slot_span.partition_page_index, self.P(slot_span.super_page_addr),\n            ))\n            self.out.append(\"                   next_slot_span:{:s} \".format(\n                self.C(slot_span.next_slot_span),\n            ))\n            self.out.append(\"                   slot_span_area:{:s}-{:s} \".format(\n                self.P(slot_span.partition_page_start),\n                self.P(slot_span.partition_page_start + bucket.num_system_pages_per_slot_span * get_pagesize()),\n            ))\n            self.out.append(\"                   num_allocated_slots:{:#x}\".format(\n                slot_span.num_allocated_slots),\n            )\n            self.dump_freelist(slot_span.freelist_head, bucket, slot_span)\n            current = slot_span.next_slot_span\n        return\n\n    def dump_freelist(self, head, bucket, slot_span):\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        self.out.append(\"                   freelist_head:{:s} \".format(self.C(head)))\n\n        slot_size = bucket.slot_size\n        page_start = slot_span.partition_page_start\n        page_end = page_start + bucket.num_system_pages_per_slot_span * get_pagesize()\n\n        text = \"\"\n        cnt = 0\n        chunk = head\n        seen = []\n        while chunk:\n            if cnt % 6 == 0:\n                if cnt > 0:\n                    text += \"\\n\"\n                text += \" \" * 23\n\n            if chunk in seen:\n                text += Color.colorify(\"-> {:#x} (loop) \".format(chunk), corrupted_msg_color)\n                break\n\n            if chunk < page_start or page_end <= chunk:\n                text += Color.colorify(\"-> {:#x} (corrupted: out of range {:#x}-{:#x}) \".format(\n                    chunk, page_start, page_end,\n                ), corrupted_msg_color)\n                break\n\n            if (chunk - page_start) % slot_size != 0:\n                text += Color.colorify(\"-> {:#x} (corrupted: not aligned) \".format(chunk), corrupted_msg_color)\n                break\n\n            try:\n                next_chunk = byteswap(read_int_from_memory(chunk))\n                if is_64bit() and next_chunk:\n                    next_chunk |= chunk & 0xffff_ffff_0000_0000\n            except gdb.MemoryError:\n                text += Color.colorify(\"-> {:#x} (corrupted: invalid address) \".format(chunk), corrupted_msg_color)\n                break\n\n            text += \"-> \" + Color.colorify_hex(chunk, freed_address_color) + \" \"\n            cnt += 1\n            seen.append(chunk)\n            chunk = next_chunk\n\n        if cnt > 0:\n            text += \"(num: {:#x})\".format(cnt)\n\n        if text:\n            self.out.append(text)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if is_32bit():\n            self.align_pad = None\n\n        if self.args.target_buffer_root == \"fm\":\n            self.args.target_buffer_root = \"fast_malloc\"\n        elif self.args.target_buffer_root == \"b\":\n            self.args.target_buffer_root = \"buffer\"\n        elif self.args.target_buffer_root == \"ab\":\n            self.args.target_buffer_root = \"array_buffer\"\n\n        self.out = []\n        for r in self.get_roots(args.force_heuristic):\n\n            ok = False\n            if args.target_buffer_root == \"fast_malloc\":\n                if r.name == \"fast_malloc_root_\":\n                    ok = True\n            if args.target_buffer_root == \"array_buffer\":\n                if r.name == \"array_buffer_root_\":\n                    ok = True\n            if args.target_buffer_root == \"buffer\":\n                if r.name == \"buffer_root_\":\n                    ok = True\n\n            if not ok:\n                continue\n\n            try:\n                root, _ = self.read_root(r.address, r.name)\n            except Exception:\n                mem_value = read_int_from_memory(r.address)\n                err(\"Parse error {:s}: @ {:#x} -> {:#x}\".format(r.name, r.address, mem_value))\n                exc_type, exc_value, exc_traceback = sys.exc_info()\n                gef_print(exc_value)\n                continue\n\n            self.root = root # for coloring\n            self.dump_root(root)\n\n        self.print_output()\n        return\n\n\n@register_command\nclass ScallocHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"scalloc heap free-list viewer (x64 only).\"\"\"\n\n    _cmdline_ = \"scalloc-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--object_space\", type=AddressUtil.parse_address,\n                        help=\"use specific address for object_space.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def class_to_objects(self, cl):\n        # number of objects in each span\n        class_to_objects_list = [\n            0x0, 0x7f8, 0x3fc, 0x2a8, 0x1fe, 0x198, 0x154, 0x123,\n            0xff, 0xe2, 0xcc, 0xb9, 0xaa, 0x9c, 0x91, 0x88,\n            0x7f, 0x40, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10,\n            0x10, 0x8, 0x4, 0x2, 0x1,\n        ]\n        assert cl < len(class_to_objects_list)\n        return class_to_objects_list[cl]\n\n    def class_to_size(self, cl):\n        class_to_size_list = [\n            0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,\n            0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,\n            0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,\n            0x10000, 0x20000, 0x40000, 0x80000, 0x100000,\n        ]\n        assert cl < len(class_to_size_list)\n        return class_to_size_list[cl]\n\n    def read_arena(self, addr, arena_name):\n        if addr is None:\n            return None\n        \"\"\"\n        class Arena {\n            const char* name_;\n            uintptr_t start_;\n            uintptr_t end_;\n            uintptr_t len_;\n            UNUSED uint8_t pad[64 - ((sizeof(name_) + sizeof(start_) + sizeof(end_) + sizeof(len_)) % 64)];\n            std::atomic<uintptr_t> current_;\n            UNUSED uint8_t pad2_[64  - ((sizeof(current_)) % 64)];\n        }\n        \"\"\"\n        dic = {}\n        dic[\"addr\"] = addr\n        dic[\"name\"] = arena_name\n        dic[\"name_\"] = read_cstring_from_memory(read_int_from_memory(addr))\n        dic[\"start\"] = read_int_from_memory(addr + current_arch.ptrsize * 1)\n        dic[\"end\"] = read_int_from_memory(addr + current_arch.ptrsize * 2)\n        dic[\"len\"] = read_int_from_memory(addr + current_arch.ptrsize * 3)\n        dic[\"current\"] = read_int_from_memory(addr + 0x40)\n        Arena = collections.namedtuple(\"Arena\", dic.keys())\n        arena = Arena(*dic.values())\n        return arena\n\n    def get_object_space_heuristic(self):\n        maps = ProcessMap.get_process_maps()\n        for m in maps:\n            if m.path != \"\":\n                continue\n            if m.size > 0x100_0000: # heuristic\n                continue\n            for addr in range(m.page_start, m.page_end, current_arch.ptrsize):\n                v = read_int_from_memory(addr)\n                if v == 0 or not is_valid_addr(v):\n                    continue\n                if read_cstring_from_memory(v) != \"object\":\n                    continue\n                start = read_int_from_memory(addr + current_arch.ptrsize)\n                if not is_valid_addr(start):\n                    continue\n                end = read_int_from_memory(addr + current_arch.ptrsize * 2)\n                if not is_valid_addr(end - 1):\n                    continue\n                len_ = read_int_from_memory(addr + current_arch.ptrsize * 3)\n                if end - start != len_:\n                    continue\n                pad1 = read_int_from_memory(addr + current_arch.ptrsize * 4)\n                if pad1 != 0:\n                    continue\n                pad2 = read_int_from_memory(addr + current_arch.ptrsize * 5)\n                if pad2 != 0:\n                    continue\n                pad3 = read_int_from_memory(addr + current_arch.ptrsize * 6)\n                if pad3 != 0:\n                    continue\n                pad4 = read_int_from_memory(addr + current_arch.ptrsize * 7)\n                if pad4 != 0:\n                    continue\n                current = read_int_from_memory(addr + current_arch.ptrsize * 8)\n                if not is_valid_addr(current):\n                    continue\n                return addr\n        return None\n\n    def get_object_space(self):\n        object_space = None\n\n        # use specific address\n        if self.args.object_space:\n            object_space = self.args.object_space\n\n        ## use symbol\n        if object_space is None:\n            try:\n                object_space = AddressUtil.parse_address(\"&_ZN7scalloc12object_spaceE\")\n            except gdb.error:\n                object_space = None\n\n        # heuristic search\n        if object_space is None:\n            object_space = self.get_object_space_heuristic()\n\n        object_space = self.read_arena(object_space, \"object_space\")\n        return object_space\n\n    def decode_top(self, raw):\n        kValueBits = 48\n        kValueMask= (1 << kValueBits) - 1\n        kExtendMask = 0xffff_ffff_ffff_ffff\n        return (raw & kValueMask) | (((raw >> (kValueBits - 1)) & 0x1) * kExtendMask)\n\n    def read_span(self, addr):\n        \"\"\"\n        class Span {\n            DoubleListNode {\n                DoubleListNode* next_;\n                DoubleListNode* prev_;\n            } span_link_;\n            AtomicCoreID owner_;\n            std::atomic<int32_t> epoch_;\n            int32_t size_class_;\n            UNUSED char padding_[8];\n            IncrementalFreeList {\n                void* list_;         // Incremental free list.\n                intptr_t bump_pointer_;\n                int32_t len_;        // Number of free objects.\n                int32_t increment_;  // Size of an object.\n            } local_free_list_;\n            RemoteFreeList {\n                AtomicTaggedValue<void*> top_;\n                int8_t pad_[64 - (sizeof(top_) % 64)];\n            } remote_free_list_;\n        }\n        \"\"\"\n        dic = {}\n        dic[\"addr\"] = addr\n        dic[\"next\"] = read_int_from_memory(addr + current_arch.ptrsize * 0)\n        dic[\"prev\"] = read_int_from_memory(addr + current_arch.ptrsize * 1)\n        dic[\"owner\"] = read_int_from_memory(addr + current_arch.ptrsize * 2)\n        dic[\"epoch\"] = read_int32_from_memory(addr + current_arch.ptrsize * 3)\n        dic[\"size_class\"] = read_int32_from_memory(addr + current_arch.ptrsize * 3 + 4)\n        dic[\"object_num\"] = self.class_to_objects(dic[\"size_class\"]) # number of objects in each span\n        dic[\"object_size\"] = self.class_to_size(dic[\"size_class\"])\n        dic[\"freelist\"] = read_int_from_memory(addr + current_arch.ptrsize * 5)\n        dic[\"freelist_addr\"] = addr + current_arch.ptrsize * 5\n        dic[\"bump_pointer\"] = read_int_from_memory(addr + current_arch.ptrsize * 6) # top pointer in glibc\n        dic[\"freelist_len\"] = read_int32_from_memory(addr + current_arch.ptrsize * 7)\n        dic[\"freelist_increment\"] = read_int32_from_memory(addr + current_arch.ptrsize * 7 + 4) # = object_size\n        dic[\"top\"] = read_int_from_memory(addr + current_arch.ptrsize * 8) # encoded remote freelist\n        dic[\"top_addr\"] = addr + current_arch.ptrsize * 8\n        dic[\"top_decoded\"] = self.decode_top(dic[\"top\"])\n        Span = collections.namedtuple(\"Span\", dic.keys())\n        span = Span(*dic.values())\n        return span\n\n    def dump_freelist(self, head):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n\n        cur = head\n        cnt = 0\n        while True:\n            if cur == 0 and cnt > 0:\n                self.out.append(\" -> {:s} (num: {:#x})\".format(Color.colorify_hex(cur, freed_address_color), cnt))\n            else:\n                self.out.append(\" -> {:s}\".format(Color.colorify_hex(cur, freed_address_color)))\n            if cur == 0:\n                break\n            cur = read_int_from_memory(cur)\n            cnt += 1\n        return cnt\n\n    def dump_spans(self, arena):\n        self.out.append(titlify(\"Arena ({:s}) @{:#x}\".format(arena.name, arena.addr)))\n        current = arena.start\n        while current < arena.current:\n            span = self.read_span(current)\n            if span.object_size != 0:\n                self.out.append(titlify(\"Span @{:#x} (size: {:#x}, capacity: {:#x}, available: {:#x})\".format(\n                    span.addr, span.object_size, span.object_num, span.freelist_len,\n                )))\n                self.out.append(\"freelist @ {!s}:\".format(ProcessMap.lookup_address(span.freelist_addr)))\n                cnt = self.dump_freelist(span.freelist)\n                self.out.append(\"bump_pointer: {!s} (num: {:#x})\".format(\n                    ProcessMap.lookup_address(span.bump_pointer),\n                    span.freelist_len - cnt,\n                ))\n                self.out.append(\"remote freelist @ {!s}:\".format(ProcessMap.lookup_address(span.top_addr)))\n                self.dump_freelist(span.top_decoded)\n            current += 0x20_0000 # kVirtualSpanSize\n        return span\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    def do_invoke(self, args):\n        object_space = self.get_object_space()\n        if object_space is None:\n            err(\"Could not find object_space\")\n            return\n\n        self.out = []\n        self.dump_spans(object_space)\n        self.print_output()\n        return\n\n\n@register_command\nclass MuslHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"musl v1.2.5 (src/malloc/mallocng) heap reusable chunks viewer (x64/x86 only).\"\"\"\n\n    # See https://h-noson.hatenablog.jp/entry/2021/05/03/161933#-177pts-mooosl\n    _cmdline_ = \"musl-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [\"ctx\", \"unused\"]\n    parser.add_argument(\"command\", choices=modes, nargs=\"?\", default=\"unused\",\n                        help=\"dump mode (default: %(default)s).\")\n    parser.add_argument(\"-i\", \"--active-idx\", type=int, help=\"the active index of dump target.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"also dump an empty active index.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    def get_malloc_context_heuristic(self):\n        try:\n            # search for malloc\n            malloc = AddressUtil.parse_address(\"malloc\")\n            self.info_add_out(\"malloc: {:#x}\".format(malloc))\n\n            # search for __libc_malloc_impl\n            \"\"\"\n            [pattern 1]\n               0x7ffff7d7dde0 <malloc>:     jmp    0x7ffff7d8ece2 <__libc_malloc_impl>\n\n            [pattern 2]\n               0x7ffff7f71650 <malloc>:     endbr64\n               0x7ffff7f71654 <malloc+4>:   jmp    0x7ffff7f72ff0\n\n            [pattern 3]\n               0xf7f78bf0 <malloc>: jmp    0xf7f8bc3c\n            \"\"\"\n            res = gdb.execute(\"x/10i {:#x}\".format(malloc), to_string=True)\n            for line in res.splitlines():\n                m = re.search(r\"jmp\\s*(0x\\w+)\", line)\n                if not m:\n                    continue\n                __libc_malloc_impl = int(m.group(1), 16)\n                break\n            self.info_add_out(\"__libc_malloc_impl: {:#x}\".format(__libc_malloc_impl))\n\n            # search for __malloc_alloc_meta\n            \"\"\"\n            [pattern 1]\n               0x7ffff7d8ed0a <__libc_malloc_impl+40>:      call   0x7ffff7d88dc1 <__errno_location>\n               0x7ffff7d8ed34 <__libc_malloc_impl+82>:      call   0x7ffff7da0c3b <mmap64>\n               0x7ffff7d8ed48 <__libc_malloc_impl+102>:     call   0x7ffff7d8e36b <wrlock>\n               0x7ffff7d8ed4d <__libc_malloc_impl+107>:     call   0x7ffff7d8e382 <step_seq>\n               0x7ffff7d8ed52 <__libc_malloc_impl+112>:     call   0x7ffff7d8e45a <__malloc_alloc_meta>\n\n            [pattern 2]\n               0x7ffff7f7303b:      call   0x7ffff7f8a640 <mmap64>\n               0x7ffff7f73074:      call   0x7ffff7f72290\n\n            [pattern 3]\n               0xf7f8bc40:  call   0xf7f7cf84\n               0xf7f8bc67:  call   0xf7f84e85 <__errno_location>\n               0xf7f8bc88:  call   0xf7f9cd53 <mmap64>\n               0xf7f8bc9b:  call   0xf7f8b3aa\n               0xf7f8bca0:  call   0xf7f8b3d2\n               0xf7f8bca5:  call   0xf7f8b439\n            \"\"\"\n            __malloc_alloc_meta_candidate = []\n            res = gdb.execute(\"x/100i {:#x}\".format(__libc_malloc_impl), to_string=True)\n            for line in res.splitlines():\n                m = re.search(r\"call\\s*(0x\\w+)\", line)\n                if not m:\n                    continue\n                addr = int(m.group(1), 16)\n                __malloc_alloc_meta_candidate.append(addr)\n\n            # search for __malloc_context\n            \"\"\"\n            [pattern 1]\n               0x7ffff7d8e45a <__malloc_alloc_meta>:        push   r12\n               0x7ffff7d8e45c <__malloc_alloc_meta+2>:      push   rbp\n               0x7ffff7d8e45d <__malloc_alloc_meta+3>:      push   rbx\n               0x7ffff7d8e45e <__malloc_alloc_meta+4>:      sub    rsp,0x10\n               0x7ffff7d8e462 <__malloc_alloc_meta+8>:      cmp    DWORD PTR [rip+0x26d67f],0x0  # 0x7ffff7ffbae8 <__malloc_context+8>\n\n            [pattern 2]\n               0x7ffff7f72290:      endbr64\n               0x7ffff7f72294:      push   r12\n               0x7ffff7f72296:      push   rbp\n               0x7ffff7f72297:      push   rbx\n               0x7ffff7f72298:      sub    rsp,0x10\n               0x7ffff7f7229c:      mov    rax,QWORD PTR fs:0x28\n               0x7ffff7f722a5:      mov    QWORD PTR [rsp+0x8],rax\n               0x7ffff7f722aa:      xor    eax,eax\n               0x7ffff7f722ac:      mov    eax,DWORD PTR [rip+0x89816]  # 0x7ffff7ffbac8\n               0x7ffff7f722b2:      test   eax,eax\n\n            [pattern 3]\n               0xf7f8b439:  push   ebp\n               0xf7f8b43a:  push   edi\n               0xf7f8b43b:  push   esi\n               0xf7f8b43c:  push   ebx\n               0xf7f8b43d:  call   0xf7f7cf84\n               0xf7f8b442:  add    ebx,0x6fbbe       # libc_bss_base\n               0xf7f8b448:  sub    esp,0x1c\n               0xf7f8b44b:  cmp    DWORD PTR [ebx+0x708],0x0\n            \"\"\"\n            for cand in __malloc_alloc_meta_candidate:\n                self.info_add_out(\"alloc_meta (candidate): {:#x}\".format(cand))\n                res = gdb.execute(\"x/10i {:#x}\".format(cand), to_string=True)\n                for line in res.splitlines():\n                    if is_x86_64():\n                        m = re.search(r\"DWORD PTR \\[rip\\+0x\\w+\\].*#\\s*(0x\\w+)\", line)\n                        if not m:\n                            continue\n                        __malloc_context_init_done = int(m.group(1), 16)\n                    else:\n                        m = re.search(r\"DWORD PTR \\[e[abcd]x\\+(0x\\w+)\\]\", line)\n                        if not m:\n                            continue\n                        __malloc_context_init_done_offset = int(m.group(1), 16)\n                        maps = ProcessMap.get_process_maps()\n                        rw_maps = [p for p in maps if p.permission.value == Permission.READ | Permission.WRITE]\n                        rw_maps = [p for p in rw_maps if \"libc.so\" in p.path]\n                        libc_bss_base = rw_maps[0].page_start\n                        __malloc_context_init_done = libc_bss_base + __malloc_context_init_done_offset\n                    # check\n                    value = read_int32_from_memory(__malloc_context_init_done)\n                    if value not in [0, 1]: # init_done is 1 or 0\n                        continue\n                    # found\n                    self.info_add_out(\"__malloc_context.init_done: {:#x}\".format(__malloc_context_init_done))\n                    __malloc_context = __malloc_context_init_done - current_arch.ptrsize\n                    x = read_int_from_memory(__malloc_context)\n                    if x == get_pagesize():\n                        __malloc_context -= current_arch.ptrsize\n                    self.info_add_out(\"__malloc_context: {:#x}\".format(__malloc_context))\n                    return __malloc_context\n            return None\n        except Exception:\n            err(\"Could not find &__malloc_context\")\n            return None\n\n    def get_malloc_context(self):\n        try:\n            return AddressUtil.parse_address(\"&__malloc_context\")\n        except gdb.error:\n            self.info_add_out(\"Could not find the symbol, GEF will use heuristic search\")\n            return self.get_malloc_context_heuristic()\n\n    def class_to_size(self, cl):\n        class_to_size_list = [\n            1, 2, 3, 4, 5, 6, 7, 8,\n            9, 10, 12, 15,\n            18, 20, 25, 31,\n            36, 42, 50, 63,\n            72, 84, 102, 127,\n            146, 170, 204, 255,\n            292, 340, 409, 511,\n            584, 682, 818, 1023,\n            1169, 1364, 1637, 2047,\n            2340, 2730, 3276, 4095,\n            4680, 5460, 6552, 8191,\n        ]\n        assert cl < len(class_to_size_list)\n        return class_to_size_list[cl] * 0x10\n\n    def read_ctx(self):\n        ptrsize = current_arch.ptrsize\n        ctx = {}\n        ctx[\"addr\"] = current = self.get_malloc_context()\n        if current is None:\n            return None\n        \"\"\"\n        struct malloc_context {\n            uint64_t secret;\n        #ifndef PAGESIZE\n            size_t pagesize;\n        #endif\n            int init_done;\n            unsigned mmap_counter;\n            struct meta *free_meta_head;\n            struct meta *avail_meta;\n            size_t avail_meta_count;\n            size_t avail_meta_area_count;\n            size_t meta_alloc_shift;\n            struct meta_area *meta_area_head;\n            struct meta_area *meta_area_tail;\n            unsigned char *avail_meta_areas;\n            struct meta *active[48];\n            size_t usage_by_class[48];\n            uint8_t unmap_seq[32];\n            uint8_t bounces[32];\n            uint8_t seq;\n            uintptr_t brk;\n        };\n        \"\"\"\n        ctx[\"secret\"] = read_int64_from_memory(current)\n        current += 8\n        x = read_int_from_memory(current)\n        if x == get_pagesize():\n            ctx[\"pagesize\"] = x\n            current += ptrsize\n        else:\n            ctx[\"pagesize\"] = None\n\n        ctx[\"init_done\"] = read_int32_from_memory(current)\n        current += 4\n        ctx[\"mmap_counter\"] = read_int32_from_memory(current)\n        current += 4\n        ctx[\"free_meta_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"avail_meta\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"avail_meta_count\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"avail_meta_area_count\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"alloc_shift\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"meta_area_head\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"meta_area_tail\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"avail_meta_areas\"] = read_int_from_memory(current)\n        current += ptrsize\n        ctx[\"active\"] = []\n        for _ in range(48):\n            ctx[\"active\"].append(read_int_from_memory(current))\n            current += ptrsize\n        ctx[\"usage_by_class\"] = []\n        for _ in range(48):\n            ctx[\"usage_by_class\"].append(read_int_from_memory(current))\n            current += ptrsize\n        ctx[\"unmap_seq\"] = read_memory(current, 32)\n        current += 32\n        ctx[\"bounces\"] = read_memory(current, 32)\n        current += 32\n        ctx[\"seq\"] = ord(read_memory(current, 1))\n        current += ptrsize # with padding\n        ctx[\"brk\"] = read_int_from_memory(current)\n        current += ptrsize\n\n        Ctx = collections.namedtuple(\"Ctx\", ctx.keys())\n        return Ctx(*ctx.values())\n\n    def dump_ctx(self, ctx):\n        self.out.append(titlify(\"__malloc_context: {:#x}\".format(ctx.addr)))\n        self.out.append(\"  uint64_t secret:                    {:#x}\".format(ctx.secret))\n        if ctx.pagesize:\n            self.out.append(\"  size_t pagesize:                    {:#x}\".format(ctx.pagesize))\n        self.out.append(\"  int init_done:                      {:#x}\".format(ctx.init_done))\n        self.out.append(\"  unsigned int mmap_counter:          {:#x}\".format(ctx.mmap_counter))\n        self.out.append(\"  struct meta* free_meta_head:        {!s}\".format(ProcessMap.lookup_address(ctx.free_meta_head)))\n        self.out.append(\"  struct meta* avail_meta:            {!s}\".format(ProcessMap.lookup_address(ctx.avail_meta)))\n        self.out.append(\"  size_t avail_meta_count:            {:#x}\".format(ctx.avail_meta_count))\n        self.out.append(\"  size_t avail_meta_area_count:       {:#x}\".format(ctx.avail_meta_area_count))\n        self.out.append(\"  size_t alloc_shift:                 {:#x}\".format(ctx.alloc_shift))\n        self.out.append(\"  struct meta_area* meta_area_head:   {!s}\".format(ProcessMap.lookup_address(ctx.meta_area_head)))\n        self.out.append(\"  struct meta_area* meta_area_tail:   {!s}\".format(ProcessMap.lookup_address(ctx.meta_area_tail)))\n        self.out.append(\"  unsigned char* avail_meta_areas:    {!s}\".format(ProcessMap.lookup_address(ctx.avail_meta_areas)))\n        self.out.append(\"  struct meta* active[48]:\")\n        for i in range(48):\n            self.out.append(\"     active[{:2d}] (for chunk_size={:#7x}):     {:#x}\".format(i, self.class_to_size(i), ctx.active[i]))\n        self.out.append(\"  size_t usage_by_class[48]:\")\n        for i in range(48):\n            self.out.append(\"     usage_by_class[{:2d}]:                     {:#x}\".format(i, ctx.usage_by_class[i]))\n        self.out.append(\"  uint8_t unmap_seq[32]:              {}\".format(\" \".join([\"{:02x}\".format(x) for x in ctx.unmap_seq])))\n        self.out.append(\"  uint8_t bounces[32]:                {}\".format(\" \".join([\"{:02x}\".format(x) for x in ctx.bounces])))\n        self.out.append(\"  uint8_t seq:                        {:#x}\".format(ctx.seq))\n        self.out.append(\"  uintptr_t brk:                      {!s}\".format(ProcessMap.lookup_address(ctx.brk)))\n        return\n\n    def read_meta(self, addr):\n        ptrsize = current_arch.ptrsize\n        meta = {}\n        meta[\"addr\"] = current = addr\n        \"\"\"\n        struct meta {\n            struct meta *prev;\n            struct meta *next;\n            struct group *mem;\n            volatile int avail_mask;\n            volatile int freed_mask;\n            uintptr_t last_idx:5;\n            uintptr_t freeable:1;\n            uintptr_t sizeclass:6;\n            uintptr_t maplen:8*sizeof(uintptr_t)-12;\n        };\n        \"\"\"\n        meta[\"prev\"] = read_int_from_memory(current)\n        current += ptrsize\n        meta[\"next\"] = read_int_from_memory(current)\n        current += ptrsize\n        meta[\"mem\"] = read_int_from_memory(current)\n        current += ptrsize\n        meta[\"avail_mask\"] = read_int32_from_memory(current)\n        current += 4\n        meta[\"freed_mask\"] = read_int32_from_memory(current)\n        current += 4\n        x = read_int_from_memory(current)\n        meta[\"last_idx\"] = x & 0b11111\n        meta[\"freeable\"] = (x >> 5) & 0b1\n        meta[\"sizeclass\"] = (x >> 6) & 0b111111\n        meta[\"maplen\"] = (x >> 12)\n        current += ptrsize\n\n        Meta = collections.namedtuple(\"Meta\", meta.keys())\n        return Meta(*meta.values())\n\n    def make_state(self, meta):\n        avail_mask = meta.avail_mask\n        freed_mask = meta.freed_mask\n\n        text = \"\"\n        for _ in range(meta.last_idx + 1):\n            if avail_mask & 1:\n                text = \"A\" + text\n            elif freed_mask & 1:\n                text = \"F\" + text\n            else:\n                text = \"U\" + text\n            avail_mask >>= 1\n            freed_mask >>= 1\n        return text\n\n    def read_group(self, meta, offset):\n        ptrsize = current_arch.ptrsize\n        group = {}\n        group[\"addr\"] = current = meta.mem + offset\n        group[\"data\"] = read_memory(group[\"addr\"], self.class_to_size(meta.sizeclass))\n        \"\"\"\n        from source code:\n        struct group {\n            struct meta *meta;\n            unsigned char active_idx:5;\n            char pad[UNIT - sizeof(struct meta *) - 1]; // UNIT = 16\n            unsigned char storage[];\n        };\n\n        however, the actual usage is as follows. (x64)\n        struct group {\n            struct meta *meta;\n            unsigned int slot_offset32;\n            unsigned char is_slot_offset32;\n            unsigned char slot_index:5;\n            unsigned char reserved:3;\n            unsigned short slot_offset16;\n        };\n        \"\"\"\n        group[\"meta\"] = read_int_from_memory(current)\n        current += ptrsize\n        x = read_int32_from_memory(current)\n        current += 4 if is_x86_64() else 8\n        y = read_int32_from_memory(current)\n        group[\"reserved\"] = (x >> 13) & 0b111\n        group[\"slot_idx\"] = (y >> 8) & 0b11111\n        if y & 0xff:\n            group[\"slot_offset\"] = x\n        else:\n            group[\"slot_offset\"] = (y >> 16) & 0xffff\n        current += ptrsize\n\n        Group = collections.namedtuple(\"Group\", group.keys())\n        return Group(*group.values())\n\n    def dump_chunk(self, group, state):\n        chunk_used_color = Config.get_gef_setting(\"theme.heap_chunk_used\")\n        chunk_freed_color = Config.get_gef_setting(\"theme.heap_chunk_freed\")\n\n        subinfo = \"state:{:5s} meta:{:<#14x} reserved:{:#x}\".format(state, group.meta, group.reserved)\n        if state == \"Used\":\n            subinfo += \" slot_idx:{:<#3x} slot_offset:{:#x}\".format(group.slot_idx, group.slot_offset)\n\n        data = slicer(group.data, current_arch.ptrsize * 2)\n        addr = group.addr\n        group_line_threshold = 8\n\n        # create dump text\n        unpack = u32 if current_arch.ptrsize == 4 else u64\n        width = current_arch.ptrsize * 2 + 2\n        done = False\n        for blk, blks in itertools.groupby(data):\n            repeat_count = len(list(blks))\n            d1, d2 = unpack(blk[:current_arch.ptrsize]), unpack(blk[current_arch.ptrsize:])\n            dascii = \"\".join([chr(x) if 0x20 <= x < 0x7f else \".\" for x in blk])\n            fmt = \"{:#x}: {:#0{:d}x} {:#0{:d}x} | {:s} | {:s}\"\n            if repeat_count < group_line_threshold:\n                for _ in range(repeat_count):\n                    dump = fmt.format(addr, d1, width, d2, width, dascii, subinfo)\n                    if state == \"Used\":\n                        self.out.append(Color.colorify(dump, chunk_used_color))\n                    else:\n                        self.out.append(Color.colorify(dump, chunk_freed_color))\n                    addr += current_arch.ptrsize * 2\n                    if subinfo:\n                        subinfo = \"\"\n            else:\n                dump = fmt.format(addr, d1, width, d2, width, dascii, subinfo)\n                dump += \"* {:#d} lines, {:#x} bytes\".format(repeat_count - 1, (repeat_count - 1) * current_arch.ptrsize * 2)\n                if state == \"Used\":\n                    self.out.append(Color.colorify(dump, chunk_used_color))\n                else:\n                    self.out.append(Color.colorify(dump, chunk_freed_color))\n                addr += current_arch.ptrsize * 2 * repeat_count\n                if subinfo:\n                    subinfo = \"\"\n            if done:\n                break\n\n        # print\n        dump = dump.rstrip()\n        return\n\n    def dump_meta(self, ctx):\n        self.out.append(\"Legend for `Unused chunks list`: A:Avail F:Freed U:Used\")\n        self.out.append(\"  1. Search most right 'A' and return it\")\n        self.out.append(\"  2. Search most right 'F' and return it\")\n        self.out.append(\"  3. If nothing is found, create new meta\")\n\n        # iterate __malloc_context.active\n        for idx in range(48):\n            if self.args.active_idx is not None and idx != self.args.active_idx:\n                continue\n            current = ctx.active[idx]\n            if current == 0:\n                continue\n\n            self.out.append(titlify(\"active[{:2d}] (chunk_size={:#x})\".format(idx, self.class_to_size(idx))))\n            management_color = Config.get_gef_setting(\"theme.heap_management_address\")\n\n            # iterate list of meta\n            seen = []\n            while current not in seen:\n                meta = self.read_meta(current)\n                self.out.append(\"meta @ {:s}\".format(Color.colorify_hex(meta.addr, management_color)))\n                text = \"  \"\n                colored_prev = Color.colorify_hex(meta.prev, management_color)\n                colored_next = Color.colorify_hex(meta.next, management_color)\n                text += \"prev:{:s} next:{:s} \".format(colored_prev, colored_next)\n                colored_mem = Color.colorify_hex(meta.mem, management_color)\n                text += \"meta:{:s} \".format(colored_mem)\n                text += \"avail_mask:{:#x} freed_mask:{:#x} \".format(meta.avail_mask, meta.freed_mask)\n                text += \"last_idx:{:#x} freeable:{:#x} \".format(meta.last_idx, meta.freeable)\n                text += \"sizeclass:{:#x} maplen:{:#x}\".format(meta.sizeclass, meta.maplen)\n                self.out.append(text)\n\n                state = self.make_state(meta)\n                self.out.append(\"  Unused chunks list: {}\".format(repr(state)))\n\n                # dump chunks\n                if state != \"F\" or self.args.verbose:\n                    dic = {\"A\": \"Avail\", \"F\": \"Freed\", \"U\": \"Used\"}\n                    for i in range(meta.last_idx + 1):\n                        offset = self.class_to_size(idx) * i\n                        group = self.read_group(meta, offset)\n                        self.dump_chunk(group, dic[state[-i - 1]])\n                    self.out.append(\"\")\n\n                seen.append(current)\n                current = meta.next\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        self.out = []\n\n        ctx = self.read_ctx()\n        if ctx is None:\n            return\n        if args.command == \"ctx\":\n            self.dump_ctx(ctx)\n        elif args.command == \"unused\":\n            self.dump_meta(ctx)\n\n        self.print_output()\n        return\n\n\nclass uClibcNgHeap:\n    \"\"\"Manage uClibc heap-specific settings.\"\"\"\n\n    class uClibcChunk:\n        \"\"\"uClibc chunk class.\"\"\"\n\n        def __init__(self, addr, from_base=False):\n            self.ptrsize = current_arch.ptrsize\n            if from_base:\n                self.chunk_base_address = addr\n                self.address = addr + 2 * self.ptrsize\n            else:\n                self.chunk_base_address = AddressUtil.align_address(addr - 2 * self.ptrsize)\n                self.address = addr\n\n            self.size_addr = AddressUtil.align_address(self.address - self.ptrsize)\n            return\n\n        def get_chunk_size(self):\n            return read_int_from_memory(self.size_addr) & (~0x03)\n\n        @property\n        def size(self):\n            return self.get_chunk_size()\n\n        # if freed functions\n        def get_fwd_ptr(self, sll):\n            try:\n                # Not a single-linked-list (sll) or no Safe-Linking support yet\n                if not sll:\n                    return read_int_from_memory(self.address)\n                # Unmask (\"reveal\") the Safe-Linking pointer\n                else:\n                    return read_int_from_memory(self.address) ^ (self.address >> 12)\n            except gdb.MemoryError:\n                return None\n\n        @property\n        def fwd(self):\n            return self.get_fwd_ptr(False)\n\n        fd = fwd # for compat\n\n        def get_bkw_ptr(self):\n            return read_int_from_memory(self.address + self.ptrsize)\n\n        @property\n        def bck(self):\n            return self.get_bkw_ptr()\n\n        bk = bck # for compat\n        # endif freed functions\n\n        def has_p_bit(self):\n            return read_int_from_memory(self.size_addr) & 0x01\n\n        def has_m_bit(self):\n            return read_int_from_memory(self.size_addr) & 0x02\n\n        def flags_as_string(self):\n            flags = []\n            if self.has_p_bit():\n                flags.append(Color.colorify(\"PREV_INUSE\", Config.get_gef_setting(\"theme.heap_chunk_flag_prev_inuse\")))\n            if self.has_m_bit():\n                flags.append(Color.colorify(\"IS_MMAPPED\", Config.get_gef_setting(\"theme.heap_chunk_flag_is_mmapped\")))\n            return \"|\".join(flags)\n\n        def to_str(self, is_fastbin=False):\n            chunk_c = Color.colorify(\"Chunk\", Config.get_gef_setting(\"theme.heap_chunk_label\"))\n            size_c = Color.colorify_hex(self.get_chunk_size(), Config.get_gef_setting(\"theme.heap_chunk_size\"))\n            base_c = Color.colorify_hex(self.chunk_base_address, Config.get_gef_setting(\"theme.heap_chunk_address_freed\"))\n            addr_c = Color.colorify_hex(self.address, Config.get_gef_setting(\"theme.heap_chunk_address_freed\"))\n            flags = self.flags_as_string()\n\n            if is_fastbin:\n                decoded_fd = ProcessMap.lookup_address(self.get_fwd_ptr(sll=True))\n                fd = self.get_fwd_ptr(sll=False)\n                msg = \"{:s}(base={:s}, addr={:s}, size={:s}, flags={:s}, fd={:#x}(={!s})\".format(\n                    chunk_c, base_c, addr_c, size_c, flags, fd, decoded_fd,\n                )\n            else:\n                fd = ProcessMap.lookup_address(self.fd)\n                bk = ProcessMap.lookup_address(self.bk)\n                msg = \"{:s}(base={:s}, addr={:s}, size={:s}, flags={:s}, fd={!s}, bk={!s})\".format(\n                    chunk_c, base_c, addr_c, size_c, flags, fd, bk,\n                )\n            return msg\n\n\n@register_command\nclass UclibcNgHeapDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"uclibc-ng (libc/stdlib/malloc-standard) heap reusable chunks viewer (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"uclibc-ng-heap-dump\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--malloc_state\", type=AddressUtil.parse_address,\n                        help=\"use specific address for malloc_context.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"also dump an empty active index.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"The main structural differences between uclibc-ng (malloc-standard) and glibc are:\",\n        \"- No tcache. There are fastbins, an unsorted bin, small bins, and large bins.\",\n        \"- No thread arena. Therefore, chunks do not have the NON_MAIN_ARENA flag.\",\n        \"The structure of malloc-standard has remained largely unchanged from version 1.0 to the latest.\",\n        \"As a result, it should be usable with any version.\",\n        \"Since the final version of uclibc (not uclibc-ng) uses the same structure,\",\n        \"this command should also be usable with uclibc.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    fast_size_table = [\n        # 64bit  32bit\n        [\"none\", 0x10],\n        [\"none\", 0x18],\n        [0x20,   0x20],\n        [\"none\", 0x28],\n        [0x30,   0x30],\n        [\"none\", 0x38],\n        [0x40,   0x40],\n        [\"none\", 0x48],\n        [0x50,   \"none\"],\n        [\"none\", \"none\"],\n        [\"none\", None],\n    ]\n\n    size_table = [\n        # 64bit                32bit\n        [\"none\",               \"none\"],\n        [\"any\",                \"any\"],\n        [\"none\",               (0x10, 0x18)],\n        [\"none\",               (0x18, 0x20)],\n        [(0x20, 0x30),         (0x20, 0x28)],\n        [\"none\",               (0x28, 0x30)],\n        [(0x30, 0x40),         (0x30, 0x38)],\n        [\"none\",               (0x38, 0x40)],\n        [(0x40, 0x50),         (0x40, 0x48)],\n        [\"none\",               (0x48, 0x50)],\n        [(0x50, 0x60),         (0x50, 0x58)],\n        [\"none\",               (0x58, 0x60)],\n        [(0x60, 0x70),         (0x60, 0x68)],\n        [\"none\",               (0x68, 0x70)],\n        [(0x70, 0x80),         (0x70, 0x78)],\n        [\"none\",               (0x78, 0x80)],\n        [(0x80, 0x90),         (0x80, 0x88)],\n        [\"none\",               (0x88, 0x90)],\n        [(0x90, 0xa0),         (0x90, 0x98)],\n        [\"none\",               (0x98, 0xa0)],\n        [(0xa0, 0xb0),         (0xa0, 0xa8)],\n        [\"none\",               (0xa8, 0xb0)],\n        [(0xb0, 0xc0),         (0xb0, 0xb8)],\n        [\"none\",               (0xb8, 0xc0)],\n        [(0xc0, 0xd0),         (0xc0, 0xc8)],\n        [\"none\",               (0xc8, 0xd0)],\n        [(0xd0, 0xe0),         (0xd0, 0xd8)],\n        [\"none\",               (0xd8, 0xe0)],\n        [(0xe0, 0xf0),         (0xe0, 0xe8)],\n        [\"none\",               (0xe8, 0xf0)],\n        [(0xf0, 0x100),        (0xf0, 0xf8)],\n        [\"none\",               (0xf8, 0x100)],\n        [(0x100, 0x140),       (0x100, 0x140)],\n        [(0x140, 0x180),       (0x140, 0x180)],\n        [(0x180, 0x1c0),       (0x180, 0x1c0)],\n        [(0x1c0, 0x200),       (0x1c0, 0x200)],\n        [(0x200, 0x280),       (0x200, 0x280)],\n        [(0x280, 0x300),       (0x280, 0x300)],\n        [(0x300, 0x380),       (0x300, 0x380)],\n        [(0x380, 0x400),       (0x380, 0x400)],\n        [(0x400, 0x500),       (0x400, 0x500)],\n        [(0x500, 0x600),       (0x500, 0x600)],\n        [(0x600, 0x700),       (0x600, 0x700)],\n        [(0x700, 0x800),       (0x700, 0x800)],\n        [(0x800, 0xa00),       (0x800, 0xa00)],\n        [(0xa00, 0xc00),       (0xa00, 0xc00)],\n        [(0xc00, 0xe00),       (0xc00, 0xe00)],\n        [(0xe00, 0x1000),      (0xe00, 0x1000)],\n        [(0x1000, 0x1400),     (0x1000, 0x1400)],\n        [(0x1400, 0x1800),     (0x1400, 0x1800)],\n        [(0x1800, 0x1c00),     (0x1800, 0x1c00)],\n        [(0x1c00, 0x2000),     (0x1c00, 0x2000)],\n        [(0x2000, 0x2800),     (0x2000, 0x2800)],\n        [(0x2800, 0x3000),     (0x2800, 0x3000)],\n        [(0x3000, 0x3800),     (0x3000, 0x3800)],\n        [(0x3800, 0x4000),     (0x3800, 0x4000)],\n        [(0x4000, 0x5000),     (0x4000, 0x5000)],\n        [(0x5000, 0x6000),     (0x5000, 0x6000)],\n        [(0x6000, 0x7000),     (0x6000, 0x7000)],\n        [(0x7000, 0x8000),     (0x7000, 0x8000)],\n        [(0x8000, 0xa000),     (0x8000, 0xa000)],\n        [(0xa000, 0xc000),     (0xa000, 0xc000)],\n        [(0xc000, 0xe000),     (0xc000, 0xe000)],\n        [(0xe000, 0x10000),    (0xe000, 0x10000)],\n        [(0x10000, 0x14000),   (0x10000, 0x14000)],\n        [(0x14000, 0x18000),   (0x14000, 0x18000)],\n        [(0x18000, 0x1c000),   (0x18000, 0x1c000)],\n        [(0x1c000, 0x20000),   (0x1c000, 0x20000)],\n        [(0x20000, 0x28000),   (0x20000, 0x28000)],\n        [(0x28000, 0x30000),   (0x28000, 0x30000)],\n        [(0x30000, 0x38000),   (0x30000, 0x38000)],\n        [(0x38000, 0x40000),   (0x38000, 0x40000)],\n        [(0x40000, 0x50000),   (0x40000, 0x50000)],\n        [(0x50000, 0x60000),   (0x50000, 0x60000)],\n        [(0x60000, 0x70000),   (0x60000, 0x70000)],\n        [(0x70000, 0x80000),   (0x70000, 0x80000)],\n        [(0x80000, 0xa0000),   (0x80000, 0xa0000)],\n        [(0xa0000, 0xc0000),   (0xa0000, 0xc0000)],\n        [(0xc0000, 0xe0000),   (0xc0000, 0xe0000)],\n        [(0xe0000, 0x100000),  (0xe0000, 0x100000)],\n        [(0x100000, 0x140000), (0x100000, 0x140000)],\n        [(0x140000, 0x180000), (0x140000, 0x180000)],\n        [(0x180000, 0x1c0000), (0x180000, 0x1c0000)],\n        [(0x1c0000, 0x200000), (0x1c0000, 0x200000)],\n        [(0x200000, 0x280000), (0x200000, 0x280000)],\n        [(0x280000, 0x300000), (0x280000, 0x300000)],\n        [(0x300000, 0x380000), (0x300000, 0x380000)],\n        [(0x380000, 0x400000), (0x380000, 0x400000)],\n        [(0x400000, 0x500000), (0x400000, 0x500000)],\n        [(0x500000, 0x600000), (0x500000, 0x600000)],\n        [(0x600000, 0x700000), (0x600000, 0x700000)],\n        [(0x700000, 0x800000), (0x700000, 0x800000)],\n        [(0x800000, 0xa00000), (0x800000, 0xa00000)],\n        [(0xa00000, 0xc00000), (0xa00000, 0xc00000)],\n        [(0xc00000, 0xe00000), (0xc00000, 0xe00000)],\n        [(0xe00000, 0x0),      (0xe00000, 0x0)],\n    ]\n\n    def get_malloc_state(self):\n        # fast path\n        try:\n            return AddressUtil.parse_address(\"&__malloc_state\")\n        except gdb.error:\n            pass\n\n        # slow path\n        # Do not use AddressUtil.parse_address(\"malloc\").\n        # For libc without symbols, the malloc@plt of the main binary will be resolved.\n        # You can definitely get the address of malloc by finding the libc path and looking for the GOT of libc itself.\n        libc = ProcessMap.process_lookup_path(\"libuClibc-\")\n        if libc is None:\n            return None\n        ret = gdb.execute(\"got --no-pager --quiet --file {!r} <malloc>\".format(libc.path), to_string=True)\n        if not ret:\n            return None\n        elem = Color.remove_color(ret).splitlines()[0].split()\n        if elem[-1].endswith(\">\"):\n            malloc = int(elem[-2], 16)\n        else:\n            malloc = int(elem[-1], 16)\n\n        # heuristic search from assembly\n        lines = gdb.execute(\"x/40i {:#x}\".format(malloc), to_string=True)\n        if is_x86_64():\n            for line in lines.splitlines():\n                m = re.search(r\"\\[rip\\+0x\\w+\\].*#\\s*(0x\\w+)\", line)\n                if m:\n                    malloc_state = int(m.group(1), 16)\n                    if is_valid_addr(malloc_state):\n                        max_fast = read_int_from_memory(malloc_state)\n                        if max_fast != 0 and (max_fast & ~0x3) <= 0xb0:\n                            return malloc_state\n        elif is_x86_32():\n            base = None\n            regname = None\n            for line in lines.splitlines():\n                if base is None:\n                    m = re.search(r\"^\\s*(0x\\w+).+:\\s+add\\s+(\\S+),\\s*(0x\\w+)\", line)\n                    if m:\n                        base = int(m.group(1), 16) + int(m.group(3), 16)\n                        regname = m.group(2)\n                        continue\n                else:\n                    m = re.search(r\"DWORD PTR \\[(\\S+)\\+(0x\\S+)\\]\", line)\n                    if m and m.group(1) == regname:\n                        malloc_state = base + int(m.group(2), 16)\n                        if is_valid_addr(malloc_state):\n                            max_fast = read_int_from_memory(malloc_state)\n                            if max_fast != 0 and (max_fast & ~0x3) <= 0xb0:\n                                return malloc_state\n\n        # TODO\n        # - Other architecture\n        # - static build + stripped\n        return None\n\n    def read_malloc_state(self, specified_malloc_state_ptr):\n        \"\"\"\n        struct malloc_state {\n          /* The maximum chunk size to be eligible for fastbin */\n          size_t  max_fast;   /* low 2 bits used as flags */\n\n          /* Fastbins */\n          mfastbinptr      fastbins[NFASTBINS];\n\n          /* Base of the topmost chunk -- not otherwise kept in a bin */\n          mchunkptr        top;\n\n          /* The remainder from the most recent split of a small request */\n          mchunkptr        last_remainder;\n\n          /* Normal bins packed as described above */\n          mchunkptr        bins[NBINS * 2];\n\n          /* Bitmap of bins. Trailing zero map handles cases of largest binned size */\n          unsigned int     binmap[BINMAPSIZE+1];\n\n          /* Tunable parameters */\n          unsigned long     trim_threshold;\n          size_t  top_pad;\n          size_t  mmap_threshold;\n\n          /* Memory map support */\n          int              n_mmaps;\n          int              n_mmaps_max;\n          int              max_n_mmaps;\n\n          /* Cache malloc_getpagesize */\n          unsigned int     pagesize;\n\n          /* Track properties of MORECORE */\n          unsigned int     morecore_properties;\n\n          /* Statistics */\n          size_t  mmapped_mem;\n          size_t  sbrked_mem;\n          size_t  max_sbrked_mem;\n          size_t  max_mmapped_mem;\n          size_t  max_total_mem;\n        };\n        \"\"\"\n\n        malloc_state = {}\n        if specified_malloc_state_ptr is None:\n            malloc_state[\"address\"] = current = self.get_malloc_state()\n            if current is None:\n                return None\n        else:\n            malloc_state[\"address\"] = current = specified_malloc_state_ptr\n\n        malloc_state[\"max_fast\"] = max_fast = read_int_from_memory(current)\n        current += current_arch.ptrsize\n\n        malloc_state[\"max_fast_flags\"] = []\n        if max_fast & 1:\n            malloc_state[\"max_fast_flags\"] += [\"ANYCHUNKS_BIT\"]\n        if max_fast & 2:\n            malloc_state[\"max_fast_flags\"] += [\"FASTCHUNKS_BIT\"]\n\n        if is_64bit():\n            self.NFASTBINS = 11\n        else:\n            self.NFASTBINS = 10\n        malloc_state[\"fastbins\"] = []\n        for i in range(self.NFASTBINS):\n            n = read_int_from_memory(current)\n            size = self.fast_size_table[i][is_32bit()]\n            malloc_state[\"fastbins\"].append((current, n, size))\n            current += current_arch.ptrsize\n\n        malloc_state[\"top\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"last_remainder\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n\n        self.NBINS = 96\n        self.NSMALLBINS = 32\n        self.NLARGEBINS = self.NBINS - self.NSMALLBINS\n\n        malloc_state[\"smallbins\"] = []\n        for i in range(self.NSMALLBINS):\n            n = read_int_from_memory(current)\n            p = read_int_from_memory(current + current_arch.ptrsize)\n            size = self.size_table[i][is_32bit()]\n            malloc_state[\"smallbins\"].append((current, n, p, size))\n            current += current_arch.ptrsize * 2\n\n        malloc_state[\"largebins\"] = []\n        for i in range(self.NLARGEBINS):\n            n = read_int_from_memory(current)\n            p = read_int_from_memory(current + current_arch.ptrsize)\n            size = self.size_table[i + self.NSMALLBINS][is_32bit()]\n            malloc_state[\"largebins\"].append((current, n, p, size))\n            current += current_arch.ptrsize * 2\n\n        self.BINMAPSIZE = 3\n        malloc_state[\"binmap\"] = []\n        for _ in range(self.BINMAPSIZE + 1):\n            x = read_int32_from_memory(current)\n            malloc_state[\"binmap\"].append(x)\n            current += 4\n\n        malloc_state[\"trim_threshold\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"top_pad\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"mmap_threshold\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"n_mmaps\"] = read_int32_from_memory(current)\n        current += 4\n        malloc_state[\"n_mmaps_max\"] = read_int32_from_memory(current)\n        current += 4\n        malloc_state[\"max_n_mmaps\"] = read_int32_from_memory(current)\n        current += 4\n        malloc_state[\"pagesize\"] = read_int32_from_memory(current)\n        current += 4\n        malloc_state[\"morecore_properties\"] = morecore_properties = read_int32_from_memory(current)\n        current += 4\n        malloc_state[\"morecore_properties_flags\"] = []\n        if morecore_properties & 1:\n            malloc_state[\"morecore_properties_flags\"] += [\"MORECORE_CONTIGUOUS_BIT\"]\n        if is_64bit():\n            current += 4 # pad\n        malloc_state[\"mmaped_mem\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"sbrked_mem\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"max_sbrked_mem\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"max_mmaped_mem\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_state[\"max_total_mem\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n\n        try:\n            top_sz = read_int_from_memory(malloc_state[\"top\"] + current_arch.ptrsize) & ~0b11\n            heap_end = malloc_state[\"top\"] + top_sz\n            malloc_state[\"heap_base\"] = heap_end - malloc_state[\"sbrked_mem\"]\n        except gdb.MemoryError:\n            malloc_state[\"heap_base\"] = 0\n\n        MallocState = collections.namedtuple(\"MallocState\", malloc_state.keys())\n        return MallocState(*malloc_state.values())\n\n    def dump_malloc_state(self, malloc_state):\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        self.verbose_add_out(\"malloc_state: {!s}\".format(ProcessMap.lookup_address(malloc_state.address)))\n        max_fast_flags = \"|\".join(malloc_state.max_fast_flags)\n        self.verbose_add_out(\"max_fast:            {:#x} ({:s})\".format(malloc_state.max_fast, max_fast_flags))\n\n        self.out.append(titlify(\"Fast Bins\"))\n        for i in range(self.NFASTBINS):\n            addr, n, size = malloc_state.fastbins[i]\n            if n != 0 or self.args.verbose:\n                if isinstance(size, int):\n                    colored_size = Color.colorify(\"{:#4x}\".format(size), chunk_size_color)\n                else:\n                    colored_size = Color.colorify(size, chunk_size_color)\n                self.out.append(\"fastbins[idx={:d}, size={:s}, @{!s}]: fd={!s}\".format(\n                    i, colored_size,\n                    ProcessMap.lookup_address(addr),\n                    ProcessMap.lookup_address(n),\n                ))\n\n            if n != 0:\n                seen = []\n                while is_valid_addr(n) and n not in seen:\n                    seen.append(n)\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    self.out.append(\" -> {}\".format(chunk.to_str(is_fastbin=True)))\n                    n = chunk.get_fwd_ptr(True)\n\n        self.verbose_add_out(\"top:                 {!s}\".format(ProcessMap.lookup_address(malloc_state.top)))\n        self.verbose_add_out(\"last_remainder:      {!s}\".format(ProcessMap.lookup_address(malloc_state.last_remainder)))\n\n        self.out.append(titlify(\"Unsorted Bin / Small Bins\"))\n        for i in range(len(malloc_state.smallbins)):\n            addr, n, p, size = malloc_state.smallbins[i]\n            if (n and addr - current_arch.ptrsize * 2 != n) or self.args.verbose:\n                if isinstance(size, tuple):\n                    colored_size = Color.colorify(\"{:#x}-{:#x}\".format(*size), chunk_size_color)\n                else:\n                    colored_size = Color.colorify(size, chunk_size_color)\n                self.out.append(\"{:s}[idx={:d}, size={:s}, @{!s}]: fd={!s}, bk={!s}\".format(\n                    [\"small_bins\", \"unsorted_bin\"][i == 1],\n                    i, colored_size,\n                    ProcessMap.lookup_address(addr),\n                    ProcessMap.lookup_address(n),\n                    ProcessMap.lookup_address(p),\n                ))\n\n            if n and addr - current_arch.ptrsize * 2 != n:\n                seen = [addr - current_arch.ptrsize * 2]\n                while is_valid_addr(n) and n not in seen:\n                    seen.append(n)\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    self.out.append(\" -> {}\".format(chunk.to_str()))\n                    n = chunk.fwd\n\n        self.out.append(titlify(\"Large Bins\"))\n        for i in range(len(malloc_state.largebins)):\n            addr, n, p, size = malloc_state.largebins[i]\n            if addr - current_arch.ptrsize * 2 != n or self.args.verbose:\n                if isinstance(size, tuple):\n                    colored_size = Color.colorify(\"{:#x}-{:#x}\".format(*size), chunk_size_color)\n                else:\n                    colored_size = Color.colorify(size, chunk_size_color)\n                self.out.append(\"large_bins[idx={:d}, size={:s}, @{!s}]: fd={!s}, bk={!s}\".format(\n                    self.NSMALLBINS + i, colored_size,\n                    ProcessMap.lookup_address(addr),\n                    ProcessMap.lookup_address(n),\n                    ProcessMap.lookup_address(p),\n                ))\n\n            if addr - current_arch.ptrsize * 2 != n:\n                seen = [addr - current_arch.ptrsize * 2]\n                while is_valid_addr(n) and n not in seen:\n                    seen.append(n)\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    self.out.append(\" -> {}\".format(chunk.to_str()))\n                    n = chunk.fwd\n\n        for i in range(self.BINMAPSIZE + 1):\n            self.verbose_add_out(\"binmap[{:d}]:           {:#x}\".format(i, malloc_state.binmap[i]))\n        self.verbose_add_out(\"trim_threshold:      {:#x}\".format(malloc_state.trim_threshold))\n        self.verbose_add_out(\"top_pad:             {:#x}\".format(malloc_state.top_pad))\n        self.verbose_add_out(\"mmap_threshold:      {:#x}\".format(malloc_state.mmap_threshold))\n        self.verbose_add_out(\"n_mmaps:             {:#x}\".format(malloc_state.n_mmaps))\n        self.verbose_add_out(\"n_mmaps_max:         {:#x}\".format(malloc_state.n_mmaps_max))\n        self.verbose_add_out(\"max_n_mmaps:         {:#x}\".format(malloc_state.max_n_mmaps))\n        self.verbose_add_out(\"pagesize:            {:#x}\".format(malloc_state.pagesize))\n        mp_flags = \"|\".join(malloc_state.morecore_properties_flags)\n        self.verbose_add_out(\"morecore_properties: {:#x} ({:s})\".format(malloc_state.morecore_properties, mp_flags))\n        self.verbose_add_out(\"mmaped_mem:          {:#x}\".format(malloc_state.mmaped_mem))\n        self.verbose_add_out(\"sbrked_mem:          {:#x}\".format(malloc_state.sbrked_mem))\n        self.verbose_add_out(\"max_sbrked_mem:      {:#x}\".format(malloc_state.max_sbrked_mem))\n        self.verbose_add_out(\"max_mmaped_mem:      {:#x}\".format(malloc_state.max_mmaped_mem))\n        self.verbose_add_out(\"max_total_mem:       {:#x}\".format(malloc_state.max_total_mem))\n        self.verbose_add_out(\"(heap_base):         {:#x}\".format(malloc_state.heap_base))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        self.out = []\n\n        malloc_state = self.read_malloc_state(args.malloc_state)\n        if malloc_state is None:\n            err(\"Could not find malloc_state\")\n            return\n        self.dump_malloc_state(malloc_state)\n        self.print_output()\n        return\n\n\n@register_command\nclass UclibcNgVisualHeapCommand(UclibcNgHeapDumpCommand, BufferingOutput):\n    \"\"\"Visualize chunks on a heap for uClibc-ng.\"\"\"\n\n    _cmdline_ = \"uclibc-ng-visual-heap\"\n    _category_ = \"05-c. Heap - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address interpreted as the beginning of a contiguous chunk. (default: [heap] of vmmap)\")\n    parser.add_argument(\"--malloc_state\", type=AddressUtil.parse_address,\n                        help=\"use specific address for malloc_context.\")\n    parser.add_argument(\"-c\", dest=\"max_count\", type=AddressUtil.parse_address,\n                        help=\"Maximum count to parse. It is used when there is a very large amount of chunks.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\",\n                        help=\"display the same line without omitting.\")\n    parser.add_argument(\"-d\", \"--dark-color\", action=\"store_true\",\n                        help=\"use the dark color if chunk is allocated.\")\n    parser.add_argument(\"-s\", \"--safe-linking-decode\", action=\"store_true\",\n                        help=\"decode safe-linking encoded pointer if tcache or fastbins.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    normal_colors = [\n        Color.redify,\n        Color.greenify,\n        Color.blueify,\n        Color.yellowify,\n    ]\n    dark_colors = [\n        lambda x: Color.colorify(x, \"bright_black\"),\n        lambda x: Color.colorify(x, \"graphite\"),\n    ]\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def init_bins_info(self, malloc_state):\n        self.bins_info = {\n            \"fastbins\": {},\n            \"small_bins\": {},\n            \"large_bins\": {},\n        }\n        # fastbins\n        for i in range(self.NFASTBINS):\n            addr, n, size = malloc_state.fastbins[i]\n            seen = []\n            while n and n not in seen:\n                seen.append(n)\n                try:\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    n = chunk.get_fwd_ptr(True)\n                except gdb.MemoryError:\n                    break\n            self.bins_info[\"fastbins\"][i] = seen\n        # smallbins / unsortedbin\n        for i in range(len(malloc_state.smallbins)):\n            addr, n, p, size = malloc_state.smallbins[i]\n            seen = []\n            while n and addr - current_arch.ptrsize * 2 != n and n not in seen:\n                seen.append(n)\n                try:\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    n = chunk.fwd\n                except gdb.MemoryError:\n                    break\n            self.bins_info[\"small_bins\"][i] = seen\n        # largebins\n        for i in range(len(malloc_state.largebins)):\n            addr, n, p, size = malloc_state.largebins[i]\n            seen = []\n            while n and addr - current_arch.ptrsize * 2 != n and n not in seen:\n                seen.append(n)\n                try:\n                    chunk = uClibcNgHeap.uClibcChunk(n, from_base=True)\n                    n = chunk.fwd\n                except gdb.MemoryError:\n                    break\n            self.bins_info[\"large_bins\"][i] = seen\n\n        # make table\n        # dict[address] = [\"bins info1\", \"bins info2\", ...]\n        self.bins_dict_for_address = {}\n        for fastbin_idx, fastbin_list in self.bins_info[\"fastbins\"].items():\n            for address in fastbin_list:\n                pos = \",\".join([str(i + 1) for i, x in enumerate(fastbin_list) if x == address])\n                sz = self.fast_size_table[fastbin_idx][is_32bit()]\n                m = \"fastbins[idx={:d},sz={:#x}][{:s}/{:d}]\".format(fastbin_idx, sz, pos, len(fastbin_list))\n                self.bins_dict_for_address[address] = self.bins_dict_for_address.get(address, []) + [m]\n        for smallbin_idx, smallbin_list in self.bins_info[\"small_bins\"].items():\n            for address in smallbin_list:\n                pos = \",\".join([str(i + 1) for i, x in enumerate(smallbin_list) if x == address])\n                if smallbin_idx == 0:\n                    m = \"unsortedbins[{:s}/{:d}]\".format(pos, len(smallbin_list))\n                else:\n                    size = self.size_table[smallbin_idx][is_32bit()]\n                    if isinstance(size, tuple):\n                        sz = \"{:#x}-{:#x}\".format(size[0], size[1])\n                    else:\n                        sz = size\n                    m = \"smallbins[idx={:d},sz={:s}][{:s}/{:d}]\".format(smallbin_idx, sz, pos, len(smallbin_list))\n                self.bins_dict_for_address[address] = self.bins_dict_for_address.get(address, []) + [m]\n        for largebin_idx, largebin_list in self.bins_info[\"large_bins\"].items():\n            for address in largebin_list:\n                pos = \",\".join([str(i + 1) for i, x in enumerate(largebin_list) if x == address])\n                size = self.size_table[self.NSMALLBINS + largebin_idx][is_32bit()]\n                if isinstance(size, tuple):\n                    sz = \"{:#x}-{:#x}\".format(size[0], size[1])\n                else:\n                    sz = size\n                m = \"largebins[idx={:d},sz={:s}][{:s}/{:d}]\".format(\n                    self.NSMALLBINS + largebin_idx, sz, pos, len(largebin_list),\n                )\n                self.bins_dict_for_address[address] = self.bins_dict_for_address.get(address, []) + [m]\n        return\n\n    def get_bins_info(self, malloc_state, address):\n        info = self.bins_dict_for_address.get(address, [])\n        if address == malloc_state.top:\n            info.append(\"top\")\n        return info\n\n    def generate_visual_chunk(self, malloc_state, chunk, idx):\n        unpack = u32 if current_arch.ptrsize == 4 else u64\n        data = slicer(chunk.data, current_arch.ptrsize * 2)\n        group_line_threshold = 8\n\n        addr = chunk.chunk_base_address\n        width = current_arch.ptrsize * 2 + 2\n        exceed_top = False\n        has_bins_info = False\n\n        out_tmp = []\n        # Group rows to display rows with the same value together.\n        prev_bins_info = \"\"\n        for blk, blks in itertools.groupby(data):\n            repeat_count = len(list(blks))\n            d1, d2 = unpack(blk[:current_arch.ptrsize]), unpack(blk[current_arch.ptrsize:])\n            dascii = \"\".join([chr(x) if 0x20 <= x < 0x7f else \".\" for x in blk])\n\n            if self.args.full or repeat_count < group_line_threshold:\n                # non-collapsed line\n                for _ in range(repeat_count):\n                    bins_info = self.get_bins_info(malloc_state, addr)\n                    if bins_info:\n                        bins_info = \" <-  {:s}\".format(\", \".join(bins_info))\n                        has_bins_info = True\n                    else:\n                        bins_info = \"\"\n\n                    if self.args.safe_linking_decode:\n                        if chunk.address == addr and \"fastbins\" in prev_bins_info:\n                            d1 = chunk.get_fwd_ptr(True)\n\n                    offset1 = addr - chunk.chunk_base_address\n                    offset2 = addr - malloc_state.heap_base\n                    out_tmp.append(\"{:#x}|{:+#08x}|{:+#08x}: {:#0{:d}x} {:#0{:d}x} | {:s} | {:s}\".format(\n                        addr, offset1, offset2, d1, width, d2, width, dascii, bins_info,\n                    ).rstrip())\n                    addr += current_arch.ptrsize * 2\n                    prev_bins_info = bins_info\n\n                    if addr > malloc_state.top + current_arch.ptrsize * 4:\n                        exceed_top = True\n                        break\n            else:\n                # collapsed line\n                bins_info = self.get_bins_info(malloc_state, addr)\n                if bins_info:\n                    bins_info = \" <-  {:s}\".format(\", \".join(bins_info))\n                    has_bins_info = True\n                else:\n                    bins_info = \"\"\n\n                offset1 = addr - chunk.chunk_base_address\n                offset2 = addr - malloc_state.heap_base\n                out_tmp.append(\"{:#x}|{:+#08x}|{:+#08x}: {:#0{:d}x} {:#0{:d}x} | {:s} | {:s}\".format(\n                    addr, offset1, offset2, d1, width, d2, width, dascii, bins_info,\n                ).rstrip())\n                addr += current_arch.ptrsize * 2 * repeat_count\n                out_tmp.append(\"* {:#d} lines, {:#x} bytes\".format(\n                    repeat_count - 1, (repeat_count - 1) * current_arch.ptrsize * 2,\n                ))\n\n            prev_bins_info = bins_info\n\n            if exceed_top:\n                break\n\n        # coloring\n        if self.args.dark_color and not has_bins_info:\n            color_func = self.dark_colors[idx % len(self.dark_colors)]\n        else:\n            color_func = self.normal_colors[idx % len(self.normal_colors)]\n        self.out.append(\"\\n\".join(map(color_func, out_tmp)))\n\n        # corrupted case\n        if exceed_top:\n            self.out.append(Color.boldify(\"...\"))\n        return\n\n    def generate_visual_heap(self, malloc_state, dump_start, max_count):\n        sect = ProcessMap.process_lookup_address(dump_start)\n        if sect:\n            end = sect.page_end\n        else:\n            # If qemu-user 8.1 or higher, the process_lookup_address to obtain the section list uses\n            # info proc mappings internally.\n            # This is fast, but does not return an accurate list in some cases.\n            # For example, sparc64 may not include the heap area.\n            # So it detects the end of the page from malloc_state.top.\n            end = malloc_state.top + uClibcNgHeap.uClibcChunk(malloc_state.top, from_base=True).size\n\n        try:\n            from tqdm import tqdm\n        except ImportError:\n            tqdm = None\n        if tqdm:\n            pbar = tqdm(total=end - dump_start, leave=False)\n\n        addr = dump_start\n        i = 0\n\n        while addr < end:\n            chunk = uClibcNgHeap.uClibcChunk(addr + current_arch.ptrsize * 2)\n            # corrupt check\n            if chunk.size == 0:\n                msg = \"{} Corrupted (chunk.size == 0)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(malloc_state.top - addr + 0x10, 0))\n                self.generate_visual_chunk(malloc_state, chunk, i)\n                break\n            elif addr != malloc_state.top and addr + chunk.size > malloc_state.top:\n                msg = \"{} Corrupted (addr + chunk.size > malloc_state.top)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(malloc_state.top - addr + 0x10, 0))\n                self.generate_visual_chunk(malloc_state, chunk, i)\n                break\n            elif addr + chunk.size > end:\n                msg = \"{} Corrupted (addr + chunk.size > sect.page_end)\".format(Color.colorify(\"[!]\", \"bold red\"))\n                self.out.append(msg)\n                chunk.data = read_memory(addr, max(malloc_state.top - addr + 0x10, 0))\n                self.generate_visual_chunk(malloc_state, chunk, i)\n                break\n            # maybe not corrupted\n            try:\n                chunk.data = read_memory(addr, chunk.size)\n            except gdb.MemoryError:\n                break\n            self.generate_visual_chunk(malloc_state, chunk, i)\n            addr += chunk.size\n            i += 1\n\n            if tqdm:\n                pbar.update(chunk.size)\n\n            if max_count and max_count <= i:\n                break\n\n        if tqdm:\n            pbar.close()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        malloc_state = self.read_malloc_state(args.malloc_state)\n        if malloc_state is None:\n           err(\"Could not find malloc_state\")\n           return\n\n        if malloc_state.heap_base is None or not is_valid_addr(malloc_state.heap_base):\n            err(\"Could not find the heap base\")\n            return\n\n        self.init_bins_info(malloc_state)\n\n        if args.location is None:\n            dump_start = malloc_state.heap_base\n        else:\n            dump_start = args.location\n\n        self.out = []\n        Cache.reset_gef_caches(all=True)\n        self.generate_visual_heap(malloc_state, dump_start, args.max_count)\n        self.print_output()\n        return\n\n\n@register_command\nclass XStringCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump string like x/s command, but with hex-string style.\"\"\"\n\n    _cmdline_ = \"xs\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", help=\"repeat count for displaying.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"dump target address.\")\n    parser.add_argument(\"-l\", \"--max-length\", type=AddressUtil.parse_address,\n                        help=\"maximum number of characters to display. 0 means unlimited.\")\n    parser.add_argument(\"-H\", \"--hex\", action=\"store_true\", help=\"show in hex style.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def dump_string(self, address, count, max_length, tohex, quiet):\n        for _ in range(count):\n            if not is_valid_addr(address):\n                err(\"Memory read error at {:#x}\".format(address))\n                break\n\n            # read string\n            current = address\n            size = get_pagesize() - (address & get_pagesize_mask_low())\n            s = b\"\"\n            while True:\n                # check accessibility\n                if not is_valid_addr(current):\n                    break\n\n                # read string\n                s += read_memory(current, size)\n                pos = s.find(b\"\\0\")\n                if pos != -1:\n                    s = s[:pos]\n                    break\n\n                # not found 0x0, read more\n                current += size\n                size = get_pagesize()\n\n            # cut off\n            if max_length and len(s) >= max_length:\n                cs = s[:max_length] + b\"...\"\n            else:\n                cs = s\n\n            if tohex:\n                cs = cs.hex()\n            else:\n                cs = repr(cs)\n\n            if quiet:\n                self.out.append(\"{:s}\".format(cs))\n            else:\n                self.out.append(\"{!s}: {:s} ({:#x} bytes)\".format(\n                    ProcessMap.lookup_address(address), cs, len(s),\n                ))\n\n            # go to next address\n            if pos == -1:\n                address += 1\n            else:\n                address += pos + 1\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.count is None:\n            count = 1\n        else:\n            count = args.count\n            if args.count.startswith(\"/\"):\n                count = count[1:]\n            if args.count.endswith(\"s\"):\n                count = count[:-1]\n            try:\n                count = int(count)\n            except ValueError:\n                err(\"Failed to parse: {}\".format(args.count))\n                return\n\n        if args.max_length is not None:\n            max_length = args.max_length\n        else:\n            max_length = Config.get_gef_setting(\"context.nb_max_string_length\")\n\n        self.out = []\n        self.dump_string(args.address, count, max_length, args.hex, args.quiet)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XColoredCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump address like x/x command, but with coloring at some intervals.\"\"\"\n\n    _cmdline_ = \"xc\"\n    _category_ = \"03-b. Memory - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"format\", metavar=\"FMT\", nargs=\"?\", default=\"\", help=\"dump format.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"dump address.\")\n    parser.add_argument(\"-i\", \"--interval\", type=AddressUtil.parse_address,\n                        help=\"the line of interval for coloring.\")\n    parser.add_argument(\"-c\", \"--color-num\", type=AddressUtil.parse_address, default=4,\n                        help=\"the number of colors used (1-5).\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    colors = [\n        Color.greenify,\n        Color.redify,\n        Color.blueify,\n        Color.yellowify,\n        Color.cyanify,\n    ]\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.color_num < 1 or len(self.colors) < args.color_num:\n            err(\"Invalid --color-num\")\n            return\n\n        try:\n            ret = gdb.execute(\"x{:s} {:#x}\".format(args.format, args.address), to_string=True)\n            ret = ret.strip()\n        except gdb.error as e:\n            err(e)\n            return\n\n        self.out = []\n        for i, line in enumerate(ret.splitlines()):\n            if args.interval and args.interval > 0:\n                color_func = self.colors[:args.color_num][(i // args.interval) % args.color_num]\n            else:\n                color_func = self.colors[:args.color_num][0]\n            self.out.append(color_func(line))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XphysAddrCommand(GenericCommand):\n    \"\"\"Dump physical memory taking into account ROM mapping.\"\"\"\n\n    _cmdline_ = \"xp\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"format\", metavar=\"/FMT\", help=\"specified output format.\")\n    parser.add_argument(\"location\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"dump target address.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} /16xg 0x11223344\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @staticmethod\n    def print_fmt_i(target, data, count):\n        kwargs = {}\n        kwargs[\"code\"] = data.hex()\n        if is_x86_32():\n            kwargs[\"arch\"] = \"X86\"\n            kwargs[\"mode\"] = \"32\"\n        elif is_x86_64():\n            kwargs[\"arch\"] = \"X86\"\n            kwargs[\"mode\"] = \"64\"\n        elif is_arm32():\n            kwargs[\"arch\"] = \"ARM\"\n            if target & 1:\n                kwargs[\"mode\"] = \"THUMB\"\n            else:\n                kwargs[\"mode\"] = \"ARM\"\n        elif is_arm64():\n            kwargs[\"arch\"] = \"ARM64\"\n            kwargs[\"mode\"] = \"ARM\"\n\n        out = []\n        try:\n            for insn in Disasm.capstone_disassemble(target, count, **kwargs):\n                msg = \"    {:s}\".format(insn.colored_text(12, highlight=False))\n                out.append(msg)\n        except gdb.error:\n            pass\n        out = \"\\n\".join(out)\n        return out\n\n    @staticmethod\n    def parse_type_unit_count(fmt):\n        m = re.search(r\"/(\\d*)([xibhwg]*)\", fmt)\n        if not m:\n            return None\n\n        dump_type = \"x\"\n        dump_unit = current_arch.ptrsize\n        dump_count = 1\n\n        if m.group(1):\n            dump_count = int(m.group(1))\n\n        for c in m.group(2):\n            if c in [\"x\", \"i\"]:\n                dump_type = c\n            elif c in [\"b\", \"h\", \"w\", \"g\"]:\n                dump_unit = {\"b\": 1, \"h\": 2, \"w\": 4, \"g\": 8}[c]\n            else:\n                err(\"Unsupported format: {}\".format(c))\n                return None\n        return dump_type, dump_unit, dump_count\n\n    @staticmethod\n    def fix_size_and_target(dump_type, dump_unit, dump_count, target):\n        if dump_type == \"x\":\n            dump_size = dump_count * dump_unit\n            return dump_size, target\n\n        if dump_type == \"i\":\n            if is_x86():\n                # The length is unknown, so it is read in 10-byte chunks.\n                dump_size = dump_count * 10\n                return dump_size, target\n\n            if target & 1: # fix thumb2\n                if is_arm32():\n                    target -= 1\n                else:\n                    err(\"Unsupported odd address: {}\".format(target))\n                    return None\n            # ARM opcode is at most 4byte\n            dump_size = dump_count * 4\n            return dump_size, target\n\n        return None\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    def do_invoke(self, args):\n        # arg parse\n        ret = XphysAddrCommand.parse_type_unit_count(args.format)\n        if ret is None:\n            self.usage()\n            return\n        dump_type, dump_unit, dump_count = ret\n\n        # fix for size and target (when thumb2)\n        ret = XphysAddrCommand.fix_size_and_target(dump_type, dump_unit, dump_count, args.location)\n        if ret is None:\n            return\n        dump_size, target = ret\n\n        # read\n        data = read_physmem(target, dump_size)\n        if data is None:\n            err(\"Memory read error\")\n            return\n\n        # print\n        if dump_type == \"x\":\n            out = hexdump(data, show_symbol=False, base=args.location, unit=dump_unit)\n        elif dump_type == \"i\":\n            out = XphysAddrCommand.print_fmt_i(args.location, data, dump_count)\n        gef_print(out)\n        return\n\n\n@register_command\nclass XSecureMemAddrCommand(GenericCommand):\n    \"\"\"Dump secure memory via qemu-system memory map.\"\"\"\n\n    _cmdline_ = \"xsm\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"--phys\", action=\"store_true\", help=\"treat ADDRESS as a physical address.\")\n    group.add_argument(\"--off\", action=\"store_true\", help=\"treat ADDRESS as an offset of secure memory top.\")\n    group.add_argument(\"--virt\", action=\"store_true\", help=\"treat ADDRESS as a virtual address.\")\n    parser.add_argument(\"format\", metavar=\"/FMT\", help=\"specified output format.\")\n    parser.add_argument(\"location\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"dump target address.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} /16xw --phys 0xe11e3d0   # absolute (physical/non-ASLR) address of secure memory\",\n        \"{0:s} /16xw --off 0x11e3d0     # the offset from secure memory area\",\n        \"{0:s} /16xw --virt 0x783ae3d0  # secure memory ASLR is supported\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @staticmethod\n    def v2p_secure(vaddr, verbose=False): # vaddr -> addr1 or None\n        maps = PageMap.get_page_maps(FORCE_PREFIX_S=True, verbose=verbose)\n        if maps is None:\n            return None\n        for vstart, vend, pstart, _pend in maps:\n            if vstart <= vaddr < vend:\n                offset = vaddr - vstart\n                paddr = pstart + offset\n                if verbose:\n                    info(\"v2p: {:#x} -> {:#x}\".format(vaddr, paddr))\n                return paddr\n        return None\n\n    @staticmethod\n    def p2v_secure(paddr, verbose=False): # paddr -> [addr1, addr2, ...] or []\n        maps = PageMap.get_page_maps(FORCE_PREFIX_S=True, verbose=verbose)\n        if maps is None:\n            return []\n        result = []\n        for vstart, _vend, pstart, pend in maps:\n            if pstart <= paddr < pend:\n                offset = paddr - pstart\n                vaddr = vstart + offset\n                if verbose:\n                    info(\"p2v: {:#x} -> {:#x}\".format(paddr, vaddr))\n                result.append(vaddr)\n        return result\n\n    @staticmethod\n    def read_secure_memory(sm, offset, dump_size, verbose=False):\n        qemu_system_pid = Pid.get_pid()\n        if qemu_system_pid is None:\n            err(\"Could not find qemu-system pid\")\n            return None\n\n        if dump_size > sm.size:\n            dump_size = sm.size\n\n        if verbose:\n            info(\"Target offset: {:#x}\".format(offset))\n            info(\"Read address: {:#x}, size:{:#x}\".format(sm.page_start + offset, dump_size))\n\n        with open(\"/proc/{:d}/mem\".format(qemu_system_pid), \"rb\") as fd:\n            try:\n                fd.seek(sm.page_start + offset, 0)\n                data = fd.read(dump_size)\n            except Exception:\n                return None\n        if verbose:\n            info(\"Read size result: {:#x}\".format(len(data)))\n        return data\n\n    @staticmethod\n    def get_sm_offset(sm, args):\n        if args.phys:\n            if sm.sm_base <= args.location < sm.sm_base + sm.sm_size:\n                return args.location - sm.sm_base\n\n            err(\"Phys {:#x} is not default secure memory ({:#x}-{:#x})\".format(\n                args.location, sm.sm_base, sm.sm_base + sm.sm_size,\n            ))\n            return None\n\n        elif args.off:\n            if 0 <= args.location < sm.size:\n                return args.location\n\n            err(\"Offset {:#x} is not default secure memory ({:#x}-{:#x})\".format(\n                args.location, sm.sm_base, sm.sm_base + sm.sm_size,\n            ))\n            return None\n\n        elif args.virt:\n            target_phys = XSecureMemAddrCommand.v2p_secure(args.location, args.verbose)\n            if target_phys is None:\n                err(\"Could not find physical address\")\n                return None\n\n            if sm.sm_base <= target_phys < sm.sm_base + sm.sm_size:\n                return target_phys - sm.sm_base\n\n            err(\"Virt {:#x} is not default secure memory ({:#x}-{:#x})\".format(\n                args.location, sm.sm_base, sm.sm_base + sm.sm_size,\n            ))\n            return None\n\n        return None\n\n    def redirect_to_xp(self, dump_count, dump_type, dump_unit):\n        if self.args.off:\n            return\n\n        if self.args.phys:\n            phys_addr = self.args.location\n            info(\"Redirect to xp command\")\n\n        elif self.args.virt:\n            maps = PageMap.get_page_maps_arm64_optee_secure_memory()\n            for m in maps:\n                if m[2] == 0:\n                    continue\n                if m[0] <= self.args.location < m[1]:\n                    phys_base = m[2]\n                    offset = self.args.location - m[0]\n                    phys_addr = phys_base + offset\n                    info(\"Redirect to xp command (virt:{:#x} -> phys:{:#x})\".format(\n                        self.args.location, phys_addr,\n                    ))\n                    break\n            else:\n                return\n\n        gdb.execute(\"xp/{:d}{:s}{:s} {:#x}\".format(\n            dump_count,\n            dump_type,\n            {1: \"b\", 2: \"h\", 4: \"w\", 8: \"g\"}[dump_unit],\n            phys_addr,\n        ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        # arg parse\n        ret = XphysAddrCommand.parse_type_unit_count(args.format)\n        if ret is None:\n            self.usage()\n            return\n        dump_type, dump_unit, dump_count = ret\n\n        # get offset\n        sm = QemuMonitor.get_secure_memory_map(args.verbose)\n        if sm is None:\n            err(\"Could not find secure memory maps\")\n            return\n        target_offset = XSecureMemAddrCommand.get_sm_offset(sm, args)\n        if target_offset is None:\n            self.redirect_to_xp(dump_count, dump_type, dump_unit)\n            return\n\n        # fix for size and offset (when thumb2)\n        ret = XphysAddrCommand.fix_size_and_target(dump_type, dump_unit, dump_count, target_offset)\n        if ret is None:\n            return\n        dump_size, target_offset = ret\n\n        # read\n        data = XSecureMemAddrCommand.read_secure_memory(sm, target_offset, dump_size, args.verbose)\n        if data is None:\n            err(\"Memory read error\")\n            return\n\n        # print\n        if dump_type == \"x\":\n            out = hexdump(data, show_symbol=False, base=args.location, unit=dump_unit)\n        elif dump_type == \"i\":\n            out = XphysAddrCommand.print_fmt_i(args.location, data, dump_count)\n        gef_print(out)\n        return\n\n\nclass TemporaryDummyBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to avoid gdb cache problem.\"\"\"\n\n    # The wsm command directly modifies /proc/<PID>/mem of qemu-system.\n    # However, even when the memory modification succeeds, the change may not be reflected in code behavior.\n    # The cause is unknown; one possible explanation is qemu's internal caching.\n    # Setting a breakpoint appears to bypass this cache, so a temporary breakpoint is used as a workaround.\n\n    def __init__(self):\n        super().__init__(\"*{:#x}\".format(0x0), type=gdb.BP_BREAKPOINT, internal=True, temporary=True)\n        return\n\n    def stop(self):\n        EventHandler.__gef_check_disabled_bp__ = True\n        self.enabled = False\n        return False\n\n\n@register_command\nclass WSecureMemAddrCommand(GenericCommand):\n    \"\"\"Write secure memory via qemu-system memory map.\"\"\"\n\n    _cmdline_ = \"wsm\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [\"byte\", \"short\", \"dword\", \"qword\", \"string\", \"hex\"]\n    parser.add_argument(\"mode\", choices=modes, help=\"the mode that represents the value of the argument.\")\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"--phys\", action=\"store_true\", help=\"treat ADDRESS as a physical address.\")\n    group.add_argument(\"--off\", action=\"store_true\", help=\"treat ADDRESS as an offset of secure memory top.\")\n    group.add_argument(\"--virt\", action=\"store_true\", help=\"treat ADDRESS as a virtual address.\")\n    parser.add_argument(\"value\", metavar=\"VALUE\", help=\"write value.\")\n    parser.add_argument(\"location\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"write target address.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} dword 0x41414141 --phys 0xe11e3d0     # absolute (physical/non-ASLR) address of secure memory\",\n        '{0:s} string \"AA\\\\\\\\x41\\\\\\\\x41\" --off 0x11e3d0  # the offset of secure memory',\n        '{0:s} hex \"4141 4141\" --off 0x11e3d0        # hex string is supported (invalid character is ignored)',\n        \"{0:s} byte 0x41 --virt 0x783ae3d0           # secure memory ASLR is supported\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def complete(self, text, word): # noqa\n        if text.strip() in self.modes:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix\n            return [s for s in self.modes if ((word is None) or (s and word in s))]\n\n        # finally, look for possible values for given prefix\n        return [s for s in self.modes if s and s.startswith(text.strip())]\n\n    @staticmethod\n    def write_secure_memory(sm, offset, data, verbose=False):\n        qemu_system_pid = Pid.get_pid()\n        if qemu_system_pid is None:\n            return None\n\n        write_size = len(data)\n        if write_size > sm.size:\n            write_size = sm.size\n            data = data[:write_size]\n\n        if verbose:\n            info(\"Target offset: {:#x}\".format(offset))\n            info(\"Write address: {:#x}, size:{:#x}\".format(sm.page_start + offset, write_size))\n\n        with open(\"/proc/{:d}/mem\".format(qemu_system_pid), \"r+b\") as fd:\n            try:\n                fd.seek(sm.page_start + offset, 0)\n                ret = fd.write(data)\n            except Exception:\n                return None\n        if verbose:\n            info(\"Written size result: {:#x}\".format(ret))\n\n        # avoid qemu-system caches\n        TemporaryDummyBreakpoint()\n\n        # By default, \"context code\" uses Disasm.gdb_disassemble.\n        # However, due to gdb's cache, secure memory changes may not appear in disassembly.\n        # Therefore, if capstone is available, change it to disassemble by capstone.\n        if Config.get_gef_setting(\"context_code.use_capstone\") is False:\n            Config.set_gef_setting(\"context_code.use_capstone\", True)\n        return ret\n\n    def redirect_to_write_physmem(self, data):\n        if self.args.off:\n            return\n\n        if self.args.phys:\n            phys_addr = self.args.location\n            info(\"Redirect to write_physmem\")\n\n        elif self.args.virt:\n            maps = PageMap.get_page_maps_arm64_optee_secure_memory()\n            for m in maps:\n                if m[2] == 0:\n                    continue\n                if m[0] <= self.args.location < m[1]:\n                    phys_base = m[2]\n                    offset = self.args.location - m[0]\n                    phys_addr = phys_base + offset\n                    info(\"Redirect to write_physmem (virt:{:#x} -> phys:{:#x})\".format(\n                        self.args.location, phys_addr,\n                    ))\n                    break\n            else:\n                return\n\n        try:\n            write_physmem(phys_addr, data)\n        except Exception:\n            err(\"Failed to write adata\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        try:\n            if args.mode == \"byte\":\n                data = p8(int(args.value, 0))\n            elif args.mode == \"short\":\n                data = p16(int(args.value, 0))\n            elif args.mode == \"dword\":\n                data = p32(int(args.value, 0))\n            elif args.mode == \"qword\":\n                data = p64(int(args.value, 0))\n            elif args.mode == \"string\":\n                try:\n                    data = codecs.escape_decode(args.value)[0]\n                except binascii.Error:\n                    err('Could not decode \"\\\\xXX\" encoded string')\n                    return\n            elif args.mode == \"hex\":\n                data = \"\"\n                for c in args.value.lower():\n                    if c in \"0123456789abcdef\":\n                        data += c\n                data = bytes.fromhex(data)\n        except Exception:\n            self.usage()\n            return\n\n        # initialize\n        sm = QemuMonitor.get_secure_memory_map(args.verbose)\n        if sm is None:\n            err(\"Could not find secure memory maps\")\n            return\n        target_offset = XSecureMemAddrCommand.get_sm_offset(sm, args)\n        if target_offset is None:\n            self.redirect_to_write_physmem(data)\n            return\n\n        # write\n        ret = WSecureMemAddrCommand.write_secure_memory(sm, target_offset, data, args.verbose)\n        if ret is None:\n            err(\"Memory write error\")\n        return\n\n\n@register_command\nclass BreakSecureMemAddrCommand(GenericCommand):\n    \"\"\"Set a breakpoint in virtual memory by specifying the physical memory of the secure world.\"\"\"\n\n    _cmdline_ = \"bsm\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"PHYS_ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the target physical address to set a breakpoint.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0xe1008d8\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def aarch64_get_page_maps_el3(self):\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk 3 --quiet --no-pager --no-merge --disable-color\")\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n        maps = []\n        for line in res:\n            vrange, prange, *_ = line.split()\n            vstart, vend = [int(x, 16) for x in vrange.split(\"-\")]\n            pstart, pend = [int(x, 16) for x in prange.split(\"-\")]\n            maps.append((vstart, vend, pstart, pend))\n        if maps == []:\n            warn(\"Make sure you are in EL1 (=kernel mode)\")\n            warn(\"Make sure qemu 3.x or higher\")\n            return None\n        return maps\n\n    def aarch64_switch_el(self, target_el):\n        cpsr = get_register(\"$cpsr\") & 0xffff_ffff\n        current_el = int((cpsr >> 2) & 0b11)\n        if target_el == current_el:\n            info(\"Current EL{:d} == Target EL{:d}\".format(current_el, target_el))\n            return 0\n\n        # change EL\n        try:\n            saved_cpsr = cpsr\n            cpsr = cpsr & ~(0b11 << 2) # clear EL\n            cpsr |= target_el << 2 # set desired EL\n            gdb.parse_and_eval(\"$cpsr = {:#x}\".format(cpsr))\n            info(\"Moving to EL{:d}\".format(target_el))\n        except gdb.error:\n            err(\"Maybe unsupported to change to EL{:d}\".format(target_el))\n            return 0\n        return saved_cpsr\n\n    def aarch64_revert_el(self, saved_cpsr):\n        if saved_cpsr == 0:\n            return\n        gdb.parse_and_eval(\"$cpsr = {:#x}\".format(saved_cpsr))\n        saved_el = (saved_cpsr >> 2) & 0b11\n        info(\"Moving back to EL{:d}\".format(saved_el))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        if args.verbose:\n            info(\"Phys address: {:#x}\".format(args.location))\n\n        if is_arm64():\n            maps = self.aarch64_get_page_maps_el3()\n            if maps:\n                virt_addrs = PageMap.p2v_from_map(args.location, maps)\n                # change to EL3 and set bp\n                saved_cpsr = self.aarch64_switch_el(target_el=3)\n                for virt_addr in virt_addrs:\n                    gdb.execute(\"break *{:#x}\".format(virt_addr))\n                self.aarch64_revert_el(saved_cpsr)\n                # found any, fast return\n                if virt_addrs:\n                    return\n\n        virt_addrs = XSecureMemAddrCommand.p2v_secure(args.location, args.verbose)\n        if virt_addrs == []:\n            warn(\"Could not find virtual address\")\n            return\n\n        for virt_addr in virt_addrs:\n            gdb.execute(\"break *{:#x}\".format(virt_addr))\n        return\n\n\nclass OpteeThreadEnterUserModeBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to thread_enter_user_mode.\"\"\"\n\n    def __init__(self, vaddr, ta_offset, verbose):\n        super().__init__(\"*{:#x}\".format(vaddr), type=gdb.BP_BREAKPOINT, internal=True)\n        self.ta_offset = ta_offset\n        self.verbose = verbose\n        return\n\n    @staticmethod\n    def get_ta_loaded_address(verbose=False):\n        Cache.reset_gef_caches()\n        if is_arm32():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk -S --quiet --no-pager --disable-color\")\n            if verbose:\n                gef_print(res)\n            res = sorted(set(res.splitlines()))\n            res = list(filter(lambda line: \"PL0/R-X\" in line, res))\n        elif is_arm64():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk 1 --quiet --no-pager --disable-color\")\n            if verbose:\n                gef_print(res)\n            res = sorted(set(res.splitlines()))\n            res = list(filter(lambda line: \"EL0/R-X\" in line, res))\n        maps = []\n        for line in res:\n            vrange, prange, *_ = line.split()\n            vstart, vend = [int(x, 16) for x in vrange.split(\"-\")]\n            pstart, pend = [int(x, 16) for x in prange.split(\"-\")]\n            maps.append((vstart, vend, pstart, pend))\n        if len(maps) == 2:\n            return maps[1]\n        else:\n            return None\n\n    def stop(self):\n        ta_address = self.get_ta_loaded_address(self.verbose)\n        if ta_address is None:\n            info(\"Could not find TA address, so continue (this is 1st stop?)\")\n            return False\n\n        ta_vstart, ta_vend, _, _ = ta_address\n        info(\"TA address: {:#x}\".format(ta_vstart))\n\n        ta_vsize = ta_vend - ta_vstart\n        if self.ta_offset >= ta_vsize:\n            err(\"TA offset {:#x} is greater than the size of TA R-X area ({:#x})\".format(self.ta_offset, ta_vsize))\n            self.enabled = False\n            return False\n\n        gdb.execute(\"tbreak *{:#x}\".format(ta_vstart + self.ta_offset))\n        return False\n\n\n@register_command\nclass OpteeBreakTaAddrCommand(GenericCommand):\n    \"\"\"Set a breakpoint to OPTEE-TA.\"\"\"\n\n    _cmdline_ = \"optee-break-ta\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"ta_offset\", metavar=\"TA_OFFSET\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"The breakpoint target offset of OPTEE-TA.\")\n    group.add_argument(\"-f\", \"--ta-file\", help=\"parse the TA file (or ELF file) and stop at the entry point.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"show memory map if stopped at __thread_enter_user_mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x2784\",\n        \"{0:s} -f /path/to/deadbeef-dead-dead-dead-deaddeadbeef.ta\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"It is not straightforward to set a breakpoint on a Trusted Application (TA) while you are still\",\n        \"in the normal world, because at that moment the TA has not yet been loaded into the secure world.\",\n        \"\",\n        \"The TA is loaded only when the TEE OS routine thread_enter_user_mode stops for the second time.\",\n        \" - At the 1st stop, only ldelf (the user-space loader that actually loads the TA) is executed, so the TA is still absent.\",\n        \" - At the 2nd stop, ldelf has finished and the TA is finally present in memory.\",\n        \"\",\n        \"Now, thread_enter_user_mode calls __thread_enter_user_mode.\",\n        \"This __thread_enter_user_mode in TEE OS is written directly in assembly.\",\n        \"Because of this, it is immune to compiler optimizations. By searching memory for the fixed byte sequence\",\n        \"of this assembly routine, we can reliably locate its offset and set your breakpoint there.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def get_secure_memory_maps(self):\n        maps = PageMap.get_page_maps_by_pagewalk(\"pagewalk --optee --quiet --no-pager --disable-color\").splitlines()\n        if not maps:\n            err(\"Could not find memory maps\")\n            return None\n\n        for m in maps:\n            s = m.split(None, 3)\n            if len(s) != 4:\n                continue\n            virt_range, phys_range, size, hint = s\n            if \"TEE-OS .text\" not in hint:\n                continue\n            virt_start = int(virt_range.split(\"-\")[0], 16)\n            phys_start = int(phys_range.split(\"-\")[0], 16)\n            size = int(size, 16)\n            break\n        else:\n            err(\"Could not find memory maps\")\n            return None\n        return virt_start, phys_start, size\n\n    def search_thread_enter_user_mode(self):\n        ret = self.get_secure_memory_maps()\n        if ret is None:\n            return\n        virt_start, phys_start, size = ret\n\n        data = read_physmem(phys_start, size)\n        if not data:\n            err(\"Memory read error\")\n            return None\n\n        if is_arm32():\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/thread_a32.S\n            \"\"\"\n            FUNC __thread_enter_user_mode , :\n                push {r4-r12,lr}\n                cps #CPSR_MODE_SYS\n                mov r4, sp\n                ...\n\n            gef> xp/3xi 0x0E101158\n                0xe101158 f05f2de9   <NO_SYMBOL>   push   {r4, r5, r6, r7, r8, sb, sl, fp, ip, lr}\n                0xe10115c 1f0002f1   <NO_SYMBOL>   cps    #0x1f\n                0xe101160 0d40a0e1   <NO_SYMBOL>   mov    r4, sp\n            gef>\n            \"\"\"\n            byte_seq = b\"\\xf0\\x5f\\x2d\\xe9\" + b\"\\x1f\\x00\\x02\\xf1\" + b\"\\x0d\\x40\\xa0\\xe1\"\n        else:\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/thread_a64.S\n            \"\"\"\n            FUNC __thread_enter_user_mode , :\n                sub sp, sp, #THREAD_USER_MODE_REC_SIZE                  // size may change in future\n                store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 0, 2 // macro\n                store_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30        // macro\n                mov x19, sp\n                msr spsel, #1\n                ...\n\n            gef> xp/11i 0xE1030C0\n                0xe1030c0 ff0302d1                  <NO_SYMBOL>   sub    sp, sp, #0x80\n                0xe1030c4 e00700a9                  <NO_SYMBOL>   stp    x0, x1, [sp] <--- here\n                0xe1030c8 e20b00f9                  <NO_SYMBOL>   str    x2, [sp, #0x10]\n                0xe1030cc f35302a9                  <NO_SYMBOL>   stp    x19, x20, [sp, #0x20]\n                0xe1030d0 f55b03a9                  <NO_SYMBOL>   stp    x21, x22, [sp, #0x30]\n                0xe1030d4 f76304a9                  <NO_SYMBOL>   stp    x23, x24, [sp, #0x40]\n                0xe1030d8 f96b05a9                  <NO_SYMBOL>   stp    x25, x26, [sp, #0x50]\n                0xe1030dc fb7306a9                  <NO_SYMBOL>   stp    x27, x28, [sp, #0x60]\n                0xe1030e0 fd7b07a9                  <NO_SYMBOL>   stp    x29, x30, [sp, #0x70]\n                0xe1030e4 f3030091                  <NO_SYMBOL>   mov    x19, sp      <--- here\n                0xe1030e8 bf4100d5                  <NO_SYMBOL>   msr    spsel, #1    <--- here\n            gef>\n            \"\"\"\n            byte_seq = b\"\\xf3\\x03\\x00\\x91\" + b\"\\xbf\\x41\\x00\\xd5\"\n\n        x = data.split(byte_seq)\n        if len(x) == 1:\n            err(\"Could not find __thread_enter_user_mode\")\n            return None\n        if len(x) > 2:\n            err(\"Found multiple candidates\")\n            return None\n\n        if is_arm32():\n            __thread_enter_user_mode = virt_start + len(x[0])\n\n        else:\n            r = x[0].rfind(b\"\\xe0\\x07\\x00\\xa9\")\n            if r == -1 or r < 4:\n                err(\"Could not find __thread_enter_user_mode\")\n                return None\n            __thread_enter_user_mode = virt_start + (r - 4)\n\n        return __thread_enter_user_mode\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        thread_enter_user_mode_virt = self.search_thread_enter_user_mode()\n        if thread_enter_user_mode_virt is None:\n            return\n\n        if args.ta_offset is not None:\n            ta_offset = args.ta_offset\n        else:\n            if not os.path.exists(self.args.ta_file):\n                err(\"Could not find TA\")\n                return\n            contents = open(self.args.ta_file, \"rb\").read()\n            if not contents.startswith((b\"HSTO\", b\"\\x7fELF\")):\n                err(\"Invalid TA/ELF\")\n                return\n\n            elf_header_off = contents.find(b\"\\x7fELF\")\n            if elf_header_off == -1:\n                err(\"Could not find ELF header\")\n                return\n\n            elf = Elf(self.args.ta_file, elf_header_off)\n            if elf is None:\n                err(\"Invalid ELF\")\n                return\n            ta_offset = elf.e_entry\n\n        if ta_offset is None:\n            return\n\n        info(\"__thread_enter_user_mode @ OPTEE-OS: {:#x}\".format(thread_enter_user_mode_virt))\n        info(\"Breakpoint target offset of TA: {:#x}\".format(ta_offset))\n\n        OpteeThreadEnterUserModeBreakpoint(thread_enter_user_mode_virt, ta_offset, args.verbose)\n        info(\"Temporarily breakpoint at {:#x}\".format(thread_enter_user_mode_virt))\n        return\n\n\n@register_command\nclass OpteeSmcServiceDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump the OPTEE SMC (EL3) service (specifically, the arm-trusted-firmware implementation).\"\"\"\n\n    _cmdline_ = \"optee-smc-service-dump\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    def find_service(self, sm, data):\n        \"\"\"search services from *.secure-ram.\"\"\"\n\n        def is_valid_secure_addr(addr):\n            return sm.sm_base <= addr < sm.sm_base + sm.sm_size\n\n        def read_cstring_from_secure_memory(addr):\n            if not is_valid_secure_addr(addr):\n                return None\n\n            offset = addr - sm.sm_base\n            s = \"\"\n            i = 0\n            while offset + i < len(data):\n                c = data[offset + i]\n                if 0x20 <= c < 0x7f:\n                    s += chr(c)\n                    i += 1\n                    continue\n                if c == 0x00:\n                    return s\n                break\n            return None\n\n        \"\"\"\n        typedef struct rt_svc_desc {\n            uint8_t start_oen;\n            uint8_t end_oen;\n            uint8_t call_type;\n            const char *name;\n            rt_svc_init_t init;\n            rt_svc_handle_t handle;\n        } rt_svc_desc_t;\n        \"\"\"\n        candidate_services = []\n        data_list = slice_unpack(data, current_arch.ptrsize)\n        for i in range(len(data_list) - 3):\n            # https://github.com/ARM-software/arm-trusted-firmware/blob/master/include/lib/smccc.h\n\n            # start_oen, end_oen\n            v = data_list[i]\n            start_oen = v & 0xff\n            end_oen = (v >> 8) & 0xff\n            if start_oen > 64 or end_oen > 64:\n                continue\n            if start_oen > end_oen:\n                continue\n\n            # call_type\n            call_type = (v >> 16) & 0xff\n            if call_type > 1:\n                continue\n\n            # padding\n            if (v >> 24) != 0:\n                continue\n\n            # name\n            name_ptr = data_list[i + 1]\n            if not is_valid_secure_addr(name_ptr):\n                continue\n            name = read_cstring_from_secure_memory(name_ptr)\n            if not name:\n                continue\n\n            # init\n            init_ptr = data_list[i + 2]\n            if init_ptr != 0 and not is_valid_secure_addr(init_ptr):\n                continue\n\n            # handle\n            handle_ptr = data_list[i + 3]\n            if not is_valid_secure_addr(handle_ptr):\n                continue\n\n            s = {}\n            s[\"address\"] = sm.sm_base + i * current_arch.ptrsize\n            s[\"start_oen\"] = start_oen\n            s[\"end_oen\"] = end_oen\n            s[\"call_type\"] = call_type\n            s[\"name\"] = name_ptr\n            s[\"name_string\"] = name\n            s[\"init\"] = init_ptr\n            s[\"handle\"] = handle_ptr\n            Service = collections.namedtuple(\"Service\", s.keys())\n            candidate_services.append(Service(*s.values()))\n\n        # filter false positive\n        valid_services = []\n        for s in candidate_services:\n            if s.name_string == \"opteed_fast\":\n                valid_services.append(s)\n                valid_min_addr = s.address\n                valid_max_addr = s.address\n                break\n        else:\n            return []\n\n        while True:\n            for s in candidate_services:\n                if valid_min_addr - current_arch.ptrsize * 4 == s.address:\n                    valid_min_addr = s.address\n                    valid_services.append(s)\n                    break\n                if valid_max_addr + current_arch.ptrsize * 4 == s.address:\n                    valid_max_addr = s.address\n                    valid_services.append(s)\n                    break\n            else:\n                break\n\n        return sorted(valid_services, key=lambda x: x.address)\n\n    def dump_service(self, services):\n        legend = [\"Address\", \"start_oen\", \"end_oen\", \"call_type\", \"init\", \"handle\", \"name\"]\n        fmt = \"{:10s}  {:9s}  {:7s}  {:9s}  {:10s}  {:10s}  {:s}\"\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for s in services:\n            self.out.append(\"{:#010x}  {:<#9x}  {:<#7x}  {:<#9x}  {:#010x}  {:#010x}  {:s}\".format(\n                s.address, s.start_oen, s.end_oen, s.call_type, s.init, s.handle, s.name_string,\n            ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        sm = QemuMonitor.get_secure_memory_map(args.verbose)\n        if sm is None:\n            err(\"Could not find secure memory maps\")\n            return None\n\n        self.out = []\n        data = XSecureMemAddrCommand.read_secure_memory(sm, 0x0, sm.size, args.verbose)\n        services = self.find_service(sm, data)\n        self.dump_service(services)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass OpteeTaDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to dump OPTEE Trusted Application.\"\"\"\n\n    _cmdline_ = \"optee-ta-dump\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"memory\")\n    subparsers.add_parser(\"dir\")\n    _syntax_ = parser.format_help()\n\n    uuid_hint = {\n        \"023f8f1a-292a-432b-8fc4-de8471358067\": \"avb\",\n        \"02a42f43-d8b7-4a57-aa4d-87bd9b5587cb\": \"crypto_perf\",\n        \"057f4b66-bdab-11eb-96cf-33d6e41cc849\": \"acipher-rs\",\n        \"0864c8ec-bdab-11eb-8926-c7fa47a8c92d\": \"aes-rs\",\n        \"0a5a06b2-bdab-11eb-add0-77f29de31296\": \"authentication-rs\",\n        \"0bef16a2-bdab-11eb-94be-6f9815f37c21\": \"bigint-rs\",\n        \"0e6bf4fe-bdab-11eb-9bc5-3f4ecb50aee7\": \"diffie_hellman-rs\",\n        \"10de87e2-bdab-11eb-b73c-63fec73e597c\": \"digest-rs\",\n        \"12345678-5b69-11e4-9dbb-101f74f00099\": \"sdp_basic\",\n        \"133af0ca-bdab-11eb-9130-43bf7873bf67\": \"hello_world-rs\",\n        \"1585d412-bdab-11eb-ba91-3b085fd2601f\": \"hotp-rs\",\n        \"17556a46-bdab-11eb-b325-d38c9a9af725\": \"message_passing_interface-rs\",\n        \"197c710c-bdab-11eb-8f3f-17a5f698d23b\": \"random-rs\",\n        \"1b5f5b74-e9cf-4e62-8c3e-7e41da6d76f6\": \"mnist-rs (train)\",\n        \"1cd6d392-bdab-11eb-9082-abc902ac5cd4\": \"secure_storage-rs\",\n        \"1ed47816-bdab-11eb-9ebd-3ffe0648da93\": \"serde-rs\",\n        \"21b1a1da-bdab-11eb-b614-275a7098826f\": \"time-rs\",\n        \"25497083-a58a-4fc5-8a72-1ad7b69b8562\": \"large\",\n        \"255fc838-de89-42d3-9a8e-d044c50fa57c\": \"supp_plugin-rs (ta)\",\n        \"2a287631-de1b-4fdd-a55c-b9312e40769a\": \"optee_example_plugins\",\n        \"3616069b-504d-4044-9497-feb84a073a14\": \"bti_test\",\n        \"380231ac-fb99-47ad-a689-9e017eb6e78a\": \"supp_plugin\",\n        \"3a2f8978-5dc0-11e8-9c2d-fa7ae01bbebc\": \"inter_ta-rs (system)\",\n        \"3b996a7d-2c2b-4a49-a896-e1fb5766d2f4\": \"socket (?)\",\n        \"484d4143-2d53-4841-3120-4a6f636b6542\": \"optee_example_hotp\",\n        \"4d573443-6a56-4272-ac6f-2425af9ef9bb\": \"gatekeeper\",\n        \"528938ce-fc59-11e8-8eb2-f2801f1b9fd1\": \"miss\",\n        \"59db8536-e5e6-11eb-8e9b-a316ce7a6568\": \"tcp_client-rs\",\n        \"5b9e0e40-2636-11e1-ad9e-0002a5d5c51b\": \"os_test\",\n        \"5c206987-16a3-59cc-ab0f-64b9cfc9e758\": \"subkey1\",\n        \"5ce0c432-0ab0-40e5-a056-782ca0e6aba2\": \"concurrent_large\",\n        \"5dbac793-f574-4871-8ad3-04331ec17f24\": \"optee_example_aes\",\n        \"60276949-7ff3-4920-9bce-840c9dcf3098\": \"tmesg\",\n        \"614789f2-39c0-4ebf-b235-92b32ac107ed\": \"sha_perf\",\n        \"68373894-5bb3-403c-9eec-3114a1f5d3fc\": \"teep-agent-ta\",\n        \"69547de6-f47e-11eb-994e-f34e88d5c2b4\": \"tls_server-rs\",\n        \"6e256cba-fc4d-4941-ad09-2ca1860342dd\": \"secstor_ta_mgmt\",\n        \"7011a688-ddde-4053-a5a9-7b3c4ddf13b8\": \"device.pta\",\n        \"731e279e-aafb-4575-a771-38caa6f0cca6\": \"storage2\",\n        \"80a4c275-0a47-4905-8285-1486a9771a08\": \"remoteproc\",\n        \"873bcd08-c2c3-11e6-a937-d0bf9c45c61c\": \"socket\",\n        \"87c2d78e-eb7b-11eb-8d25-df4d5338f285\": \"udp_socket-rs\",\n        \"8aaaf200-2450-11e4-abe2-0002a5d5c51b\": \"optee_example_hello_world\",\n        \"8d82573a-926d-4754-9353-32dc29997f74\": \"hello-teep-ta\",\n        \"a3859d33-b540-4a69-8d29-696dde9115cc\": \"property-rs\",\n        \"a4c04d50-f180-11e8-8eb2-f2801f1b9fd1\": \"sims_keepalive\",\n        \"a720ccbb-51da-417d-b82e-e5445d474a7a\": \"subkey2\",\n        \"a734eed9-d6a1-4244-aa50-7c99719e7b7b\": \"optee_example_acipher\",\n        \"a8cfe406-d4f5-4a2e-9f8d-a25dc754c099\": \"stm32_pwr.pta (?)\",\n        \"b3091a65-9751-4784-abf7-0298a7cc35ba\": \"os_test_lib_dl\",\n        \"b689f2a7-8adf-477a-9f99-32e90c0ad0a2\": \"storage\",\n        \"b6c53aba-9669-4668-a7f2-205629d00f86\": \"optee_example_random\",\n        \"bc50d971-d4c9-42c4-82cb-343fb7f37896\": \"optee-ftpm\",\n        \"bcac6292-5b9d-4b20-a2e5-b389d5e8ae2f\": \"build_with_optee_utee_sys-rs\",\n        \"c3f6e2c0-3548-11e1-b86c-0800200c9a66\": \"create_fail_test\",\n        \"c7e478c2-89b3-46eb-ac19-571e66c3830d\": \"signature_verification-rs\",\n        \"c9d73f40-ba45-4315-92c4-cf1255958729\": \"client_pool-rs\",\n        \"cb3e5ba0-adf1-11e0-998b-0002a5d5c51b\": \"crypt\",\n        \"d17f73a0-36ef-11e1-984a-0002a5d5c51b\": \"rpc_test\",\n        \"d96a5b40-c3e5-21e3-8794-1002a5d5c61b\": \"invoke_tests.pta\",\n        \"d96a5b40-e2c7-b1af-8794-1002a5d5c61b\": \"stats\",\n        \"dba51a17-0563-11e7-93b1-6fa7b0071a51\": \"keymaster\",\n        \"e13010e0-2ae1-11e5-896a-0002a5d5c51b\": \"concurrent\",\n        \"e55291e1-521c-4dca-aa24-51e34ab32ad9\": \"secure_db_abstraction-rs\",\n        \"e626662e-c0e2-485c-b8c8-09fbce6edf3d\": \"aes_perf\",\n        \"e6a33ed4-562b-463a-bb7e-ff5e15a493c8\": \"sims\",\n        \"ebb6f4b5-7e33-4ad2-9802-e64f2a7cc20c\": \"basicAlgUse\",\n        \"ec55bfe2-d9c7-11eb-8b0e-f3f8fad927f7\": \"tls_client-rs\",\n        \"ec59c1fc-b9e0-4c3c-8756-0a3cc48f0088\": \"error_handling-rs\",\n        \"ee90d523-90ad-46a0-859d-8eea0b150086\": \"tpm_log_test\",\n        \"ef620757-fa2b-4f19-a1c4-6e51cfe4c0f9\": \"supp_plugin-rs (plugin)\",\n        \"f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c\": \"trusted_keys\",\n        \"f07bfc66-958c-4a15-99c0-260e4e7375dd\": \"tee-supplicant plugin\",\n        \"f157cda0-550c-11e5-a6fa-0002a5d5c51b\": \"storage_benchmark\",\n        \"f4e750bb-1437-4fbf-8785-8d3580c34994\": \"optee_example_secure_storage\",\n        \"fd02c9da-306c-48c7-a49c-bbd827ae86ee\": \"pkcs11\",\n        \"fa9ea860-ef3b-4d59-8457-5564a60c0379\": \"inter_ta-rs\",\n        \"ff09aa8a-fbb9-4734-ae8c-d7cd1a3f6744\": \"mnist-rs (inference)\",\n        \"ffd2bded-ab7d-4988-95ee-e4962fff7154\": \"os_test_lib\",\n    }\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass OpteeTaDumpMemoryCommand(OpteeTaDumpCommand):\n    \"\"\"Dump the OPTEE-Trusted-App list from OPTEE kernel memory.\"\"\"\n\n    _cmdline_ = \"optee-ta-dump memory\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-o\", \"--for-old-version\", action=\"store_true\", help=\"for OP-TEE OS before v3.12.0.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Walk the global TEE context list (`tee_ctxes`) and print `struct tee_ta_ctx` currently linked to it.\",\n        \"- A context is added to this list the first time its TA is successfully loaded.\",\n        \"  (that is: after `ldelf` has relocated the ELF and handed the entry point back to the OP-TEE core)\",\n        \"- A TA that has never been loaded will therefore not appear here.\",\n        \"- For normal user TAs the entry is removed automatically when the last session is closed and the context is freed,\",\n        \"  so terminated TAs usually vanish from the list.\",\n        \"- `TA_FLAG_SINGLE_INSTANCE`, `TA_FLAG_INSTANCE_KEEP_ALIVE`, early-TAs and pseudo-TAs stay linked once they\",\n        \"  have been created because the core keeps them resident.\",\n        \"- ref_count shows the number of sessions currently open for that TA (the live open-session reference counter),\",\n        \"  not a cumulative load count.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def find_list_head(self, data, virt_start):\n\n        def is_valid_rw_addr(addr):\n            return virt_start <= addr < virt_start + len(data)\n\n        def read_int_from_memory(addr):\n            if not is_valid_rw_addr(addr):\n                return None\n            index = (addr - virt_start) // current_arch.ptrsize\n            return data_list[index]\n\n        def is_tailq_head(addr, head_next, head_prev, offset):\n            current = head_next\n            prev = addr\n            while True:\n                current_next = read_int_from_memory(current + offset)\n                if current_next is None:\n                    return False\n\n                current_prev = read_int_from_memory(current + offset + current_arch.ptrsize)\n                if current_prev is None:\n                    return False\n                if prev != current_prev:\n                    return False\n\n                if current_next == 0:\n                    return current + offset == head_prev\n\n                prev = current + offset\n                current = current_next\n            return False\n\n        \"\"\"\n        struct tee_ta_ctx_head tee_ctxes = TAILQ_HEAD_INITIALIZER(tee_ctxes);\n\n        struct list { // TAILQ_ENTRY\n            struct list  *tqe_next;\n            struct list **tqe_prev;\n        }\n\n        [OP-TEE OS v3.12.0~]\n        struct tee_ta_ctx {\n            uint32_t flags; /* TA_FLAGS from TA header */\n            TAILQ_ENTRY(tee_ta_ctx) link;\n            struct ts_ctx {\n                struct TEE_UUID {\n                    uint32_t timeLow;\n                    uint16_t timeMid;\n                    uint16_t timeHiAndVersion;\n                    uint8_t clockSeqAndNode[8];\n                } uuid;\n                const struct ts_ops *ops;\n            } ts_ctx;\n            uint32_t panicked; /* True if TA has panicked, written from asm */\n            uint32_t panic_code; /* Code supplied for panic */\n            uint32_t ref_count; /* Reference counter for multi session TA */\n            bool busy; /* Context is busy and cannot be entered */\n            bool is_initializing; /* Context initialization is not completed */\n            bool is_releasing; /* Context is about to be released */\n            struct condvar {\n                unsigned int spin_lock;\n                struct mutex *m;\n            } busy_cv; /* CV used when context is busy */\n        };\n\n        [OP-TEE OS ~v3.11.0]\n        struct tee_ta_ctx {\n            struct TEE_UUID {\n                uint32_t timeLow;\n                uint16_t timeMid;\n                uint16_t timeHiAndVersion;\n                uint8_t clockSeqAndNode[8];\n            } uuid;\n            const struct tee_ta_ops *ops;\n            uint32_t flags; /* TA_FLAGS from TA header */\n            TAILQ_ENTRY(tee_ta_ctx) link;\n            uint32_t panicked; /* True if TA has panicked, written from asm */\n            uint32_t panic_code; /* Code supplied for panic */\n            uint32_t ref_count; /* Reference counter for multi session TA */\n            bool busy; /* Context is busy and cannot be entered */\n            bool initializing; /* Context is initializing */\n            struct condvar {\n                unsigned int spin_lock;\n                struct mutex *m;\n            } busy_cv; /* CV used when context is busy */\n        };\n        \"\"\"\n\n        if not self.args.for_old_version:\n            offsetof_link = current_arch.ptrsize\n        else:\n            offsetof_link = 16 + current_arch.ptrsize * 2\n\n        candidate_head = []\n        data_list = slice_unpack(data, current_arch.ptrsize)\n        for i in range(len(data_list) - 1):\n            # check if head\n            addr = virt_start + current_arch.ptrsize * i\n            next_value = data_list[i]\n            prev_value = data_list[i + 1]\n            if not is_tailq_head(addr, next_value, prev_value, offsetof_link):\n                continue\n\n            j = (next_value - virt_start) // current_arch.ptrsize\n\n            if not self.args.for_old_version:\n                # check flags\n                if is_valid_rw_addr(data_list[j]):\n                    continue\n\n                # check uuid\n                if is_64bit():\n                    if is_valid_rw_addr(data_list[j + 3]) or \\\n                       is_valid_rw_addr(data_list[j + 4]):\n                        continue\n                else:\n                    if is_valid_rw_addr(data_list[j + 3]) or \\\n                       is_valid_rw_addr(data_list[j + 4]) or \\\n                       is_valid_rw_addr(data_list[j + 5]) or \\\n                       is_valid_rw_addr(data_list[j + 6]):\n                        continue\n\n                # check ops\n                if is_64bit():\n                    if not is_valid_rw_addr(data_list[j + 5]):\n                        continue\n                else:\n                    if not is_valid_rw_addr(data_list[j + 7]):\n                        continue\n            else:\n                # check uuid\n                if is_64bit():\n                    if is_valid_rw_addr(data_list[j + 0]) or \\\n                       is_valid_rw_addr(data_list[j + 1]):\n                        continue\n                else:\n                    if is_valid_rw_addr(data_list[j + 0]) or \\\n                       is_valid_rw_addr(data_list[j + 1]) or \\\n                       is_valid_rw_addr(data_list[j + 2]) or \\\n                       is_valid_rw_addr(data_list[j + 3]):\n                        continue\n\n                # check ops\n                if is_64bit():\n                    if not is_valid_rw_addr(data_list[j + 2]):\n                        continue\n                else:\n                    if not is_valid_rw_addr(data_list[j + 4]):\n                        continue\n\n                # check flags\n                if is_64bit():\n                    if is_valid_rw_addr(data_list[j + 3]):\n                        continue\n                else:\n                    if is_valid_rw_addr(data_list[j + 5]):\n                        continue\n\n            candidate_head.append(addr)\n\n        if len(candidate_head) == 0:\n            err(\"Could not find &tee_ctxes\")\n        elif len(candidate_head) > 1:\n            warn(\"Found multiple canddiate for &tee_ctxes\")\n        return candidate_head\n\n    def get_flags_str(self, flags_value):\n        flags_dic = {\n            0x0000_1000: \"TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE\",\n            0x0000_0800: \"TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT\",\n            0x0000_0400: \"TA_FLAG_DEVICE_ENUM_SUPP\",\n            0x0000_0200: \"TA_FLAG_DEVICE_ENUM\",\n            0x0000_0100: \"TA_FLAG_CONCURRENT\",\n            0x0000_0080: \"TA_FLAG_CACHE_MAINTENANCE\",\n            0x0000_0040: \"TA_FLAG_REMAP_SUPPORT\",\n            0x0000_0020: \"TA_FLAG_SECURE_DATA_PATH\",\n            0x0000_0010: \"TA_FLAG_INSTANCE_KEEP_ALIVE\",\n            0x0000_0008: \"TA_FLAG_MULTI_SESSION\",\n            0x0000_0004: \"TA_FLAG_SINGLE_INSTANCE\",\n            0x0000_0002: \"TA_FLAG_EXEC_DDR\",\n            0x0000_0001: \"TA_FLAG_USER_MODE\",\n        }\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n\n        flags_str = \" | \".join(flags)\n        if flags_str == \"\":\n            flags_str = \"none\"\n        return flags_str.replace(\"TA_FLAG_\", \"\")\n\n    def dump_service(self, data, virt_start, heads):\n        import uuid\n\n        def is_valid_rw_addr(addr):\n            return virt_start <= addr < virt_start + len(data)\n\n        def read_int_from_memory(addr):\n            if not is_valid_rw_addr(addr):\n                return None\n            index = (addr - virt_start) // current_arch.ptrsize\n            return data_list[index]\n\n        if not self.args.for_old_version:\n            offsetof_flags = 0\n            offsetof_link = offsetof_flags + current_arch.ptrsize\n            offsetof_uuid = offsetof_link + current_arch.ptrsize * 2\n            offsetof_ops = offsetof_uuid + 16\n            offsetof_ref_count = offsetof_ops + 4 * 2\n        else:\n            offsetof_uuid = 0\n            offsetof_ops = offsetof_uuid + 16\n            offsetof_flags = offsetof_ops + current_arch.ptrsize\n            offsetof_link = offsetof_flags + current_arch.ptrsize\n            offsetof_ref_count = offsetof_link + current_arch.ptrsize * 2 + 4 * 2\n\n        data_list = slice_unpack(data, current_arch.ptrsize)\n        for head in heads:\n            self.out.append(titlify(\"&tee_ctxes: {:#x}\".format(head)))\n\n            taa_ctx_list = []\n            current = read_int_from_memory(head)\n            while current:\n                d = {}\n                # addr\n                d[\"addr\"] = current\n                # uuid\n                d[\"raw_uuid\"] = data[current + offsetof_uuid - virt_start:][:16]\n                d[\"uuid_str\"] = str(uuid.UUID(bytes_le=d[\"raw_uuid\"]))\n                d[\"hint\"] = self.uuid_hint.get(d[\"uuid_str\"], \"???\")\n                # flags\n                d[\"flags\"] = read_int_from_memory(current + offsetof_flags)\n                d[\"flags_string\"] = \"(\" + self.get_flags_str(d[\"flags\"]) + \")\"\n                # ops\n                d[\"ops\"] = read_int_from_memory(current + offsetof_ops)\n                # ref_count\n                d[\"ref_count\"] = read_int_from_memory(current + offsetof_ref_count) & 0xffff_ffff\n                # append\n                Ctx = collections.namedtuple(\"Ctx\", d.keys())\n                taa_ctx_list.append(Ctx(*d.values()))\n                # goto next\n                current = read_int_from_memory(current + offsetof_link)\n\n            width = max([len(taa.hint) for taa in taa_ctx_list] + [0])\n            fmt = \"{:10s}  {:36s}  {:{:d}s}  {:10s}  {:10s}  {:s}\"\n            legend = [\"tee_ta_ctx\", \"uuid\", \"hint\", width, \"ops\", \"ref_count\", \"flags\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            for ctx in taa_ctx_list:\n                # dump\n                self.out.append(\"{:#010x}  {:36s}  {:{:d}s}  {:#010x}  {:#010x}  {:#010x} {:s}\".format(\n                    ctx.addr, ctx.uuid_str, ctx.hint, width,\n                    ctx.ops, ctx.ref_count,\n                    ctx.flags, ctx.flags_string,\n                ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        maps = PageMap.get_page_maps_by_pagewalk(\"pagewalk --optee --quiet --no-pager --disable-color\").splitlines()\n        if not maps:\n            err(\"Could not find memory maps\")\n            return\n\n        for m in maps:\n            s = m.split(None, 3)\n            if len(s) != 4:\n                continue\n            virt_range, phys_range, size, hint = s\n            if \"TEE-OS .data / stack\" not in hint:\n                continue\n            virt_start = int(virt_range.split(\"-\")[0], 16)\n            phys_start = int(phys_range.split(\"-\")[0], 16)\n            size = int(size, 16)\n            break\n        else:\n            err(\"Could not find memory maps\")\n            return\n\n        self.out = []\n        data = read_physmem(phys_start, size)\n        list_heads = self.find_list_head(data, virt_start)\n        if not list_heads:\n            if not args.for_old_version:\n                info(\"Trying with --for-old-version...\")\n                gdb.execute(\"optee-ta-dump memory --for-old-version\")\n            return\n\n        self.dump_service(data, virt_start, list_heads)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass OpteeTaDumpDirectoryCommand(OpteeTaDumpCommand):\n    \"\"\"Dump the OPTEE-Trusted-App list from host directory.\"\"\"\n\n    _cmdline_ = \"optee-ta-dump dir\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"host_dir\", metavar=\"HOST_DIR\",\n                        help=\"The host directory where you extracted the guest's /lib/optee_armtz/.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def get_ta_info_single(self, file_path, first_offset):\n        import uuid\n\n        IMG_TYPE = {0: \"LegacyTA\", 1: \"BootstrapTA\", 2: \"EncryptedTA\", 3: \"Subkey\"}\n        ALGOS = {\n            0x7000_4830: \"TEE_ALG_RSASSA_PKCS1_V1_5_SHA256\",\n            0x7041_4930: \"TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256\",\n            0x4000_0810: \"TEE_ALG_AES_GCM\",\n        }\n\n        d = {}\n        with open(file_path, \"rb\") as f:\n            f.seek(first_offset)\n\n            # struct shdr\n            magic = u32(f.read(4))\n            if magic != 0x4F545348:\n                return None\n            img_type = u32(f.read(4))\n            img_size = u32(f.read(4))\n            algo = u32(f.read(4))\n            hash_size = u16(f.read(2))\n            sig_size = u16(f.read(2))\n            d.update({\n                \"magic\": magic,\n                \"img_type\": (img_type, IMG_TYPE.get(img_type, \"Unknown\")),\n                \"img_size\": (img_size, GefUtil.get_size_str(img_size, enable_color=False)),\n                \"algo\": (algo, ALGOS.get(algo, f\"unknown-{algo:#x}\")),\n                \"hash_size\": hash_size,\n                \"sig_size\": sig_size,\n            })\n            f.seek(hash_size + sig_size, 1)\n\n            # sub header\n            if img_type == 0:\n                pass\n\n            elif img_type == 1:\n                # struct shdr_bootstrap_ta\n                raw_uuid = f.read(16)\n                ta_ver = u32(f.read(4))\n                d[\"bootstrap_uuid\"] = str(uuid.UUID(bytes=raw_uuid))\n                d[\"bootstrap_version\"] = ta_ver\n\n            elif img_type == 2:\n                # struct shdr_encrypted_ta\n                enc_algo = u32(f.read(4))\n                flags = u32(f.read(4))\n                iv_sz = u16(f.read(2))\n                tag_sz = u16(f.read(2))\n                iv = f.read(iv_sz)\n                tag = f.read(tag_sz)\n                d.update({\n                    \"enc_algo\": (enc_algo, ALGOS.get(enc_algo, f\"unknown-{enc_algo:#x}\")),\n                    \"enc_flags\": flags,\n                    \"iv_len\": iv_sz,\n                    \"tag_len\": tag_sz,\n                    \"iv_hex\": iv.hex(),\n                    \"tag_hex\": tag.hex(),\n                })\n\n            elif img_type == 3:\n                # struct shdr_subkey\n                raw_uuid = f.read(16)\n                name_sz = u32(f.read(4))\n                subk_version = u32(f.read(4))\n                max_depth = u32(f.read(4))\n                sk_algo = u32(f.read(4))\n                attr_cnt = u32(f.read(4))\n                f.seek(img_size - len(raw_uuid) - 4 * 5, 1)\n                name = f.read(name_sz).decode(errors=\"ignore\") if name_sz else \"\"\n                d.update({\n                    \"subkey_uuid\": str(uuid.UUID(bytes=raw_uuid)),\n                    \"subkey_name_size\": name_sz,\n                    \"subkey_version\": subk_version,\n                    \"subkey_max_depth\": max_depth,\n                    \"subkey_algo\": (sk_algo, ALGOS.get(sk_algo, f\"unknown-0x{sk_algo:x}\")),\n                    \"subkey_attr_count\": attr_cnt,\n                    \"next_name\": name.rstrip(\"\\0\"),\n                })\n\n            processed_size = f.tell()\n\n        TAInfo = collections.namedtuple(\"TAInfo\", d.keys())\n        return TAInfo(*d.values()), processed_size\n\n    def get_ta_info(self, file_path):\n        filesize = os.path.getsize(file_path)\n        processed_size = 0\n        ta_list = []\n        while processed_size < filesize:\n            ret = self.get_ta_info_single(file_path, processed_size)\n            if ret is None:\n                break\n            ta_info, processed_size = ret\n            ta_list.append(ta_info)\n        return ta_list\n\n    def dump_directory(self):\n        fmt = \"{:39s}  {:11s}  {:8s}  {:s}\"\n        legend = [\"filename\", \"TA type\", \"size\", \"hint\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        for filepath in GefUtil.walk(self.args.host_dir):\n            filename = os.path.basename(filepath)\n            r = re.match(\n                r\"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\.ta\",\n                filename,\n            )\n            if not r:\n                continue\n\n            # uuid -> hint\n            uuid = filename[:-3]\n            hint = self.uuid_hint.get(uuid, \"???\")\n\n            # other info\n            ta_list = self.get_ta_info(filepath)\n            if not ta_list:\n                self.out.append(\"{:39s}  {:11s}  {:8s}  {:s}\".format(filename, \"???\", \"???\", hint))\n                continue\n\n            # dump\n            self.out.append(\"{:39s}  {:11s}  {:8s}  {:s}\".format(\n                filename, ta_list[0].img_type[1], ta_list[0].img_size[1], hint,\n            ))\n            if self.args.verbose:\n                for ta_info in ta_list:\n                    for k, v in ta_info._asdict().items():\n                        if isinstance(v, tuple):\n                            self.out.append(\"  {:20s}: {:#x} ({:s})\".format(k, v[0], v[1]))\n                        elif isinstance(v, int):\n                            self.out.append(\"  {:20s}: {:#x}\".format(k, v))\n                        else:\n                            self.out.append(\"  {:20s}: {:s}\".format(k, v))\n                    self.out.append(\"\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if not os.path.isdir(args.host_dir):\n            err(\"Could not find directory\")\n            return\n\n        self.out = []\n        self.dump_directory()\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass OpteeShmListCommand(GenericCommand, BufferingOutput):\n    \"\"\"List dynamic shared-memory buffers currently registered in OP-TEE (for OP-TEE v4.3.0~).\"\"\"\n\n    _cmdline_ = \"optee-shm-list\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def find_reg_shm_list(self, data, virt_start):\n\n        def is_valid_rw_addr(addr):\n            return virt_start <= addr < virt_start + len(data)\n\n        def read_int_from_memory(addr):\n            if not is_valid_rw_addr(addr):\n                return None\n            index = (addr - virt_start) // current_arch.ptrsize\n            return data_list[index]\n\n        def is_slist_head(addr, head_next, offset):\n            current = head_next\n            seen = [current]\n            while True:\n                current_next = read_int_from_memory(current + offset)\n                if current_next is None:\n                    return False\n\n                if current_next == 0:\n                    return True\n\n                if current_next in seen:\n                    return False\n                seen.append(current)\n\n                current = current_next\n            return False\n\n        \"\"\"\n        struct list { // SLIST_ENTRY\n            struct list  *next;\n        }\n\n        [OP-TEE OS v4.3.0~]\n        struct mobj_reg_shm {\n            struct mobj {\n                const struct mobj_ops *ops;\n                size_t size;\n                size_t phys_granule;\n                struct refcount {\n                    unsigned int val;\n                } refc;\n            } mobj;\n            SLIST_ENTRY(mobj_reg_shm) next;\n            uint64_t cookie;\n            tee_mm_entry_t *mm;\n            paddr_t page_offset;\n            struct refcount mapcount;\n            bool guarded;\n            bool releasing;\n            bool release_frees;\n            paddr_t pages[];\n        };\n        \"\"\"\n\n        offsetof_ops = 0\n        offsetof_size = offsetof_ops + current_arch.ptrsize\n        offsetof_refc = offsetof_size + current_arch.ptrsize * 2\n        offsetof_next = offsetof_refc + current_arch.ptrsize\n        offsetof_cookie = offsetof_next + 8 # with pad\n        offsetof_mm = offsetof_cookie + 8\n        offsetof_page_offset = offsetof_mm + current_arch.ptrsize\n        offsetof_pages = offsetof_page_offset + current_arch.ptrsize + 4 + 4 # 4, 4 = map_count, bool*3\n\n        candidate_head = []\n        data_list = slice_unpack(data, current_arch.ptrsize)\n        for i in range(len(data_list) - 1):\n            # check if head\n            head_addr = virt_start + current_arch.ptrsize * i\n            next_value = data_list[i]\n            if not is_slist_head(head_addr, next_value, offsetof_next):\n                continue\n\n            current = next_value\n            seen = []\n            entries = []\n            found = True\n            while current:\n                if not is_valid_rw_addr(current):\n                    found = False\n                    break\n                if current in seen:\n                    found = False\n                    break\n                ops = read_int_from_memory(current + offsetof_ops)\n                size = read_int_from_memory(current + offsetof_size)\n                refc = read_int_from_memory(current + offsetof_refc)\n                next_ = read_int_from_memory(current + offsetof_next)\n                cookie = read_int_from_memory(current + offsetof_cookie)\n                mm = read_int_from_memory(current + offsetof_mm)\n                page_offset = read_int_from_memory(current + offsetof_page_offset)\n                seen.append(current)\n\n                # check ops\n                if is_valid_rw_addr(ops): # r-x\n                    found = False\n                    break\n                # check size\n                if is_valid_rw_addr(size):\n                    found = False\n                    break\n                # check size + page_offset\n                if (size + page_offset) % get_pagesize():\n                    found = False\n                    break\n                # check refc\n                if is_valid_rw_addr(refc):\n                    found = False\n                    break\n                if refc == 0 or refc >= 0x100:\n                    found = False\n                    break\n                # check cookie\n                if is_64bit():\n                    if cookie & 0xffff_0000_0000_0000 != 0xffff_0000_0000_0000:\n                        found = False\n                        break\n                # check mm\n                if mm and not is_valid_rw_addr(mm): # mm == 0 is ok\n                    found = False\n                    break\n                # check pages\n                pages = []\n                for j in range((size + page_offset) // get_pagesize()):\n                    p = read_int_from_memory(current + offsetof_pages + current_arch.ptrsize * j)\n                    if p & get_pagesize_mask_low():\n                        found = False\n                        break\n                    pages.append(p)\n                if not found:\n                    break\n\n                # already parsed\n                if len(seen) == 1: # first element\n                    for _, ents in candidate_head:\n                        if current in [e[0] for e in ents]:\n                            found = False\n                            break\n                    if not found:\n                        break\n\n                # add entry\n                entries.append([current, ops, size, refc, cookie, mm, page_offset, pages])\n                # goto next\n                current = next_\n\n            if found:\n                candidate_head.append([head_addr, entries])\n\n        if len(candidate_head) == 0:\n            err(\"Could not find &tee_ctxes\")\n        elif len(candidate_head) > 1:\n            warn(\"Found multiple canddiate for &reg_shm_list\")\n        return candidate_head\n\n    def dump_list(self, list_heads):\n        for head, entries in list_heads:\n            self.out.append(titlify(\"&reg_shm_list: {:#x}\".format(head)))\n            fmt = \"{:12s}  {:10s}  {:10s}  {:10s}  {:18s}  {:10s}  {:11s}  {:s}\"\n            legend = [\"mobj_reg_shm\", \"ops\", \"size\", \"refc\", \"cookie\", \"mm\", \"page_offset\", \"pages (phys)\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n            for addr, ops, size, refc, cookie, mm, page_offset, pages in entries:\n                pages_str = []\n                if pages:\n                    start = end = pages[0]\n                    for addr in pages[1:]:\n                        if addr == end + get_pagesize():\n                            end = addr\n                        else:\n                            pages_str.append(\"{:#x}-{:#x}\".format(start, end + get_pagesize()))\n                            start = end = addr\n                    pages_str.append(\"{:#x}-{:#x}\".format(start, end + get_pagesize()))\n\n                self.out.append(\n                    \"{:#010x}    {:#010x}  {:#010x}  {:#010x}  {:#018x}  {:#010x}  {:#010x}   {:s}\".format(\n                    addr, ops, size, refc, cookie, mm, page_offset, \",\".join(pages_str),\n                ))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        maps = PageMap.get_page_maps_by_pagewalk(\"pagewalk --optee --quiet --no-pager --disable-color\").splitlines()\n        if not maps:\n            err(\"Could not find memory maps\")\n            return\n\n        for m in maps:\n            s = m.split(None, 3)\n            if len(s) != 4:\n                continue\n            virt_range, phys_range, size, hint = s\n            if \"TEE-OS .data / stack\" not in hint:\n                continue\n            virt_start = int(virt_range.split(\"-\")[0], 16)\n            phys_start = int(phys_range.split(\"-\")[0], 16)\n            size = int(size, 16)\n            break\n        else:\n            err(\"Could not find memory maps\")\n            return\n\n        data = read_physmem(phys_start, size)\n        parsed_list_heads = self.find_reg_shm_list(data, virt_start)\n        if not parsed_list_heads:\n            err(\"Could not find reg_shm_list\")\n            return\n\n        self.out = []\n        self.dump_list(parsed_list_heads)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass OpteeBgetDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump bget allocator of OPTEE-Trusted-App.\"\"\"\n\n    _cmdline_ = \"optee-bget-dump\"\n    _category_ = \"06-j. Qemu-system/KGDB Cooperation - TrustZone\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    parser.add_argument(\"-m\", \"--malloc_ctx\", metavar=\"OFFSET_malloc_ctx\", type=AddressUtil.parse_address,\n                        help=\"The offset of `malloc_ctx` at OPTEE-TA.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"verbose output.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x2a408\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Simplified heap structure:\",\n        \"\",\n        \"+-malloc_ctx-------------------+         +-freed chunk------------+\",\n        \"| bufsize prevfree             |<--+ +-->| bufsize prevfree       |= 0 (if upper chunk is used)  +--> ...\",\n        \"| bufsize bsize                |   | |   | bufsize bsize          |= the size of this chunk      |\",\n        \"| struct bfhead *flink         |-----+   | struct bfhead *flink   |------------------------------+\",\n        \"| struct bfhead *blink         |   +-----| struct bfhead *blink   |\",\n        \"| (bufsize totalloc)           |         |                        |\",\n        \"| (long numget)                |         |                        |\",\n        \"| (long numrel)                |         |                        |\",\n        \"| (long numpblk)               |         +-used chunk-------------+\",\n        \"| (long numpget)               |         | bufsize prevfree       |= the size of upper chunk (if upper chunk is freed)\",\n        \"| (long numprel)               |         | bufsize bsize          |= the size of this chunk (negative number)\",\n        \"| (long numdget)               |         | uchar user_data[bsize] |\",\n        \"| (long numdrel)               |         |                        |\",\n        \"| (func_ptr compfcn)           |         |                        |\",\n        \"| (func_ptr acqfcn)            |         +------------------------+\",\n        \"| (func_ptr relfcn)            |\",\n        \"| (bufsize exp_incr)           |\",\n        \"| (bufsize pool_len)           |\",\n        \"| struct malloc_pool* pool     |\",\n        \"| size_t pool_len              |\",\n        \"| (struct malloc_stats mstats) |\",\n        \"+------------------------------+\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def is_readable_virt_memory(self, addr):\n        if is_arm32():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk -S --quiet --no-pager --disable-color\")\n            res = sorted(set(res.splitlines()))\n            res = list(filter(lambda line: \"PL0/RW-\" in line, res))\n        elif is_arm64():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk 1 --quiet --no-pager --disable-color\")\n            res = sorted(set(res.splitlines()))\n            res = list(filter(lambda line: \"EL0/RW-\" in line, res))\n        for line in res:\n            vrange, prange, *_ = line.split()\n            vstart, vend = [int(x, 16) for x in vrange.split(\"-\")]\n            pstart, pend = [int(x, 16) for x in prange.split(\"-\")]\n            if vstart <= addr < vend:\n                return True\n        return False\n\n    def get_ta_rw_address(self, ta_loaded_rx_end):\n        if is_arm32():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk -S --quiet --no-pager --disable-color\")\n            res = sorted(set(res.splitlines()))\n        elif is_arm64():\n            res = PageMap.get_page_maps_by_pagewalk(\"pagewalk 1 --quiet --no-pager --disable-color\")\n            res = sorted(set(res.splitlines()))\n        for line in res:\n            if not re.search(\"[PE]L1/RW\", line):\n                continue\n            vrange, prange, *_ = line.split()\n            vstart, vend = [int(x, 16) for x in vrange.split(\"-\")]\n            pstart, pend = [int(x, 16) for x in prange.split(\"-\")]\n            if vstart == ta_loaded_rx_end:\n                return (vstart, vend, pstart, pend)\n        return None\n\n    def get_malloc_ctx(self, ta_rw_address_map):\n        vstart = ta_rw_address_map[0]\n        vend = ta_rw_address_map[1]\n        data = read_memory(vstart, vend - vstart)\n        data = slice_unpack(data, current_arch.ptrsize)\n\n        candidate = []\n        for i in range(len(data) - 3):\n            if data[i] != 0 or data[i + 1] != 0: # should be 0\n                continue\n            if not is_valid_addr(data[i + 2]) or not is_valid_addr(data[i + 3]): # should be flink, blink\n                continue\n\n            addr = vstart + current_arch.ptrsize * i\n\n            flink_blink = read_int_from_memory(data[i + 2] + current_arch.ptrsize * 3)\n            blink_flink = read_int_from_memory(data[i + 3] + current_arch.ptrsize * 2)\n            if flink_blink != addr or blink_flink != addr:\n                continue\n\n            link_list_count = 1\n            flink_cur = data[i + 2]\n            blink_cur = data[i + 3]\n            flink_seen = []\n            blink_seen = []\n            while True:\n                if flink_cur in flink_seen:\n                    break\n                if blink_cur in blink_seen:\n                    break\n                flink_seen.append(flink_cur)\n                blink_seen.append(blink_cur)\n                try:\n                    flink_cur = read_int_from_memory(flink_cur + current_arch.ptrsize * 2)\n                    blink_cur = read_int_from_memory(blink_cur + current_arch.ptrsize * 3)\n                except gdb.MemoryError:\n                    link_list_count = -1\n                    break\n                link_list_count += 1\n\n            candidate.append((link_list_count, addr))\n\n        if len(candidate) == 0:\n            return None\n        return sorted(candidate, reverse=True)[0][1] # maybe the longest flink is malloc_ctx\n\n    def parse_flink(self, head):\n        current = head\n        flinks = []\n        seen = [current]\n        while True:\n            try:\n                prevfree = read_int_from_memory(current + current_arch.ptrsize * 0)\n                bsize = read_int_from_memory(current + current_arch.ptrsize * 1)\n                flink = read_int_from_memory(current + current_arch.ptrsize * 2)\n                blink = read_int_from_memory(current + current_arch.ptrsize * 3)\n                next_prevfree = read_int_from_memory(current + bsize)\n                next_bsize = read_int_from_memory(current + bsize + current_arch.ptrsize)\n            except gdb.MemoryError:\n                flinks.append(\"memory corrupted\")\n                break\n            if flink % 8 or blink % 8 or bsize % 8 or next_prevfree % 8 or next_bsize % 8:\n                flinks.append(\"unaligned corrupted\")\n                break\n            chunk = {\n                \"addr\": current, \"prevfree\": prevfree, \"bsize\": bsize, \"flink\": flink, \"blink\": blink,\n                \"next_prevfree\": next_prevfree, \"next_bsize\": next_bsize,\n            }\n            Chunk = collections.namedtuple(\"Chunk\", chunk.keys())\n            flinks.append(Chunk(*chunk.values()))\n            if flink == head:\n                break\n            if flink in seen[1:]:\n                flinks.append(\"loop detected\")\n                break\n            seen.append(current)\n            current = flink\n        return flinks\n\n    def parse_blink(self, head):\n        current = head\n        blinks = []\n        seen = [current]\n        while True:\n            try:\n                prevfree = read_int_from_memory(current + current_arch.ptrsize * 0)\n                bsize = read_int_from_memory(current + current_arch.ptrsize * 1)\n                flink = read_int_from_memory(current + current_arch.ptrsize * 2)\n                blink = read_int_from_memory(current + current_arch.ptrsize * 3)\n                next_prevfree = read_int_from_memory(current + bsize)\n                next_bsize = read_int_from_memory(current + bsize + current_arch.ptrsize)\n            except gdb.MemoryError:\n                blinks.append(\"memory corrupted\")\n                break\n            if flink % 8 or blink % 8 or bsize % 8 or next_prevfree % 8 or next_bsize % 8:\n                blinks.append(\"unaligned corrupted\")\n                break\n            chunk = {\n                \"addr\": current, \"prevfree\": prevfree, \"bsize\": bsize, \"flink\": flink, \"blink\": blink,\n                \"next_prevfree\": next_prevfree, \"next_bsize\": next_bsize,\n            }\n            Chunk = collections.namedtuple(\"Chunk\", chunk.keys())\n            blinks.append(Chunk(*chunk.values()))\n            if blink == head:\n                break\n            if blink in seen[1:]:\n                blinks.append(\"loop detected\")\n                break\n            seen.append(current)\n            current = blink\n        return blinks\n\n    def parse_malloc_ctx(self, malloc_ctx_addr):\n        malloc_ctx = {}\n        malloc_ctx[\"addr\"] = current = malloc_ctx_addr\n\n        malloc_ctx[\"prevfree\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_ctx[\"bsize\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n        malloc_ctx[\"flink\"] = read_int_from_memory(current)\n        malloc_ctx[\"flink_list\"] = self.parse_flink(malloc_ctx[\"flink\"])\n        current += current_arch.ptrsize\n        malloc_ctx[\"blink\"] = read_int_from_memory(current)\n        malloc_ctx[\"blink_list\"] = self.parse_blink(malloc_ctx[\"blink\"])\n        current += current_arch.ptrsize\n\n        # search for pool\n        for _ in range(14):\n            pool_candidate = read_int_from_memory(current)\n            current += current_arch.ptrsize\n            if self.is_readable_virt_memory(pool_candidate):\n                malloc_ctx[\"pool\"] = pool_candidate\n                break\n        else:\n            err(\"Could not find malloc_ctx->pool\")\n            return None\n\n        malloc_ctx[\"pool_len\"] = read_int_from_memory(current)\n        current += current_arch.ptrsize\n\n        malloc_ctx[\"pool_list\"] = []\n        for i in range(malloc_ctx[\"pool_len\"]):\n            buf = read_int_from_memory(malloc_ctx[\"pool\"] + (i * 2) * current_arch.ptrsize)\n            size = read_int_from_memory(malloc_ctx[\"pool\"] + (i * 2 + 1) * current_arch.ptrsize)\n            pool = {\"buf\": buf, \"len\": size}\n            Pool = collections.namedtuple(\"Pool\", pool.keys())\n            malloc_ctx[\"pool_list\"].append(Pool(*pool.values()))\n\n        MallocCtx = collections.namedtuple(\"MallocCtx\", malloc_ctx.keys())\n        return MallocCtx(*malloc_ctx.values())\n\n    def dump_malloc_ctx(self, malloc_ctx):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n\n        self.out.append(titlify(\"malloc_ctx @ {:#x}\".format(malloc_ctx.addr)))\n        self.out.append(\"prevfree: {:#x}\".format(malloc_ctx.prevfree))\n        self.out.append(\"bsize:    {:#x}\".format(malloc_ctx.bsize))\n        self.out.append(\"flink:    {:#x}\".format(malloc_ctx.flink))\n        for chunk in malloc_ctx.flink_list:\n            if isinstance(chunk, str):\n                self.out.append(\" -> {:s}\".format(Color.colorify(chunk, corrupted_msg_color)))\n            else:\n                fmt = \" -> {:s}: prevfree:{:#x} bsize:{:s} flink:{:#010x} blink:{:#010x}\"\n                fmt += \" next_prevfree:{:#010x} next_bsize:{:#010x} (={:#010x})\"\n                self.out.append(fmt.format(\n                    Color.colorify(\"{:#010x}\".format(chunk.addr), freed_address_color),\n                    chunk.prevfree,\n                    Color.colorify(\"{:#010x}\".format(chunk.bsize), chunk_size_color),\n                    chunk.flink, chunk.blink,\n                    chunk.next_prevfree,\n                    chunk.next_bsize,\n                    (-chunk.next_bsize) & 0xffff_ffff,\n                ))\n        self.out.append(\"blink:    {:#x}\".format(malloc_ctx.blink))\n        for chunk in malloc_ctx.blink_list:\n            if isinstance(chunk, str):\n                self.out.append(\" -> {:s}\".format(Color.colorify(chunk, corrupted_msg_color)))\n            else:\n                fmt = \" -> {:s}: prevfree:{:#x} bsize:{:s} flink:{:#010x} blink:{:#010x}\"\n                fmt += \" next_prevfree:{:#010x} next_bsize:{:#010x} (={:#010x})\"\n                self.out.append(fmt.format(\n                    Color.colorify(\"{:#010x}\".format(chunk.addr), freed_address_color),\n                    chunk.prevfree,\n                    Color.colorify(\"{:#010x}\".format(chunk.bsize), chunk_size_color),\n                    chunk.flink,\n                    chunk.blink,\n                    chunk.next_prevfree,\n                    chunk.next_bsize,\n                    (-chunk.next_bsize) & 0xffff_ffff,\n                ))\n        self.out.append(\"pool:     {:#x}\".format(malloc_ctx.pool))\n        self.out.append(\"pool_len: {:#x}\".format(malloc_ctx.pool_len))\n\n        for i in range(malloc_ctx.pool_len):\n            pool = malloc_ctx.pool_list[i]\n            self.out.append(\"  pool[{:d}]  buf:{:#x}  size:{:#x}\".format(i, pool.buf, pool.len))\n        return\n\n    def dump_chunk_list(self, malloc_ctx):\n        freed_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_freed\")\n        used_address_color = Config.get_gef_setting(\"theme.heap_chunk_address_used\")\n        corrupted_msg_color = Config.get_gef_setting(\"theme.heap_corrupted_msg\")\n        chunk_size_color = Config.get_gef_setting(\"theme.heap_chunk_size\")\n        chunk_used_color = Config.get_gef_setting(\"theme.heap_chunk_used\")\n        chunk_freed_color = Config.get_gef_setting(\"theme.heap_chunk_freed\")\n\n        for i in range(malloc_ctx.pool_len):\n            pool = malloc_ctx.pool_list[i]\n            pool_start = pool.buf\n            pool_end = pool.buf + pool.len\n            self.out.append(titlify(\"pool[{:d}] @ {:#x} - {:#x}\".format(i, pool_start, pool_end)))\n\n            chunk = pool_start\n            seen = []\n            while chunk < pool_end:\n                if chunk in seen:\n                    self.out.append(Color.colorify(\"loop detected\", corrupted_msg_color))\n                    break\n                seen.append(chunk)\n                try:\n                    prevfree = read_int_from_memory(chunk + current_arch.ptrsize * 0)\n                    bsize = read_int_from_memory(chunk + current_arch.ptrsize * 1)\n                    flink = read_int_from_memory(chunk + current_arch.ptrsize * 2)\n                    blink = read_int_from_memory(chunk + current_arch.ptrsize * 3)\n                except gdb.MemoryError:\n                    self.out.append(Color.colorify(\"unaligned orrupted\", corrupted_msg_color))\n                    break\n                bsize_inv = (-bsize) & 0xffff_ffff\n                if bsize_inv < 0x8000_0000: # used\n                    self.out.append(\"{:s} {:s}: prevfree:{:#010x} bsize:{:#010x} ({:s})\".format(\n                        Color.colorify(\"used\", chunk_used_color),\n                        Color.colorify(\"{:#010x}\".format(chunk), used_address_color),\n                        prevfree,\n                        bsize,\n                        Color.colorify(\"{:#010x}\".format(bsize_inv), chunk_size_color),\n                    ))\n                    chunk += bsize_inv\n                else: # freed\n                    self.out.append(\n                        \"{:s} {:s}: prevfree:{:#010x} bsize:{:s}              flink:{:#010x} blink:{:#010x}\".format(\n                            Color.colorify(\"free\", chunk_freed_color),\n                            Color.colorify(\"{:#010x}\".format(chunk), freed_address_color),\n                            prevfree,\n                            Color.colorify(\"{:#010x}\".format(bsize), chunk_size_color),\n                            flink, blink,\n                        ),\n                    )\n                    chunk += bsize\n                if chunk % 8:\n                    self.out.append(Color.colorify(\"unaligned orrupted\", corrupted_msg_color))\n                    break\n            return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.out = []\n\n        ta_address_map = OpteeThreadEnterUserModeBreakpoint.get_ta_loaded_address()\n        if ta_address_map is None:\n            err(\"Could not find TA address\")\n            return\n\n        ta_address = ta_address_map[0]\n        self.verbose_info(\"TA loaded address (RX): {:#x} - {:#x}\".format(ta_address_map[0], ta_address_map[1]))\n\n        if args.malloc_ctx is None:\n            ta_rw_address_map = self.get_ta_rw_address(ta_address_map[1])\n            if ta_rw_address_map is None:\n                err(\"Could not find TA rw address\")\n                return\n            self.verbose_info(\"TA loaded address (RW): {:#x} - {:#x}\".format(ta_rw_address_map[0], ta_rw_address_map[1]))\n            malloc_ctx_addr = self.get_malloc_ctx(ta_rw_address_map)\n            if malloc_ctx_addr is None:\n                err(\"Could not find malloc_ctx\")\n                return\n        else:\n            self.verbose_info(\"The offset of malloc_ctx: {:#x}\".format(args.malloc_ctx))\n            malloc_ctx_addr = ta_address + args.malloc_ctx\n\n        self.verbose_info(\"malloc_ctx: {:#x}\".format(malloc_ctx_addr))\n\n        malloc_ctx = self.parse_malloc_ctx(malloc_ctx_addr)\n        if malloc_ctx is None:\n            err(\"Failed to parse\")\n            return\n\n        self.dump_malloc_ctx(malloc_ctx)\n        self.dump_chunk_list(malloc_ctx)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass CpuidCommand(GenericCommand, BufferingOutput):\n    \"\"\"Get cpuid result.\"\"\"\n\n    _cmdline_ = \"cpuid\"\n    _category_ = \"04-a. Register - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Disable `-enable-kvm` option for qemu-system.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def execute_cpuid(self, num, subnum=0):\n        codes = [b\"\\x0f\\xa2\"] # cpuid\n        if is_x86_64():\n            regs = {\"$rax\": num, \"$rcx\": subnum}\n        else:\n            regs = {\"$eax\": num, \"$ecx\": subnum}\n        ret = ExecAsm(codes, regs=regs).exec_code()\n\n        if is_x86_64():\n            eax = ret[\"reg\"][\"$rax\"] & 0xffff_ffff\n            ebx = ret[\"reg\"][\"$rbx\"] & 0xffff_ffff\n            ecx = ret[\"reg\"][\"$rcx\"] & 0xffff_ffff\n            edx = ret[\"reg\"][\"$rdx\"] & 0xffff_ffff\n        else:\n            eax = ret[\"reg\"][\"$eax\"]\n            ebx = ret[\"reg\"][\"$ebx\"]\n            ecx = ret[\"reg\"][\"$ecx\"]\n            edx = ret[\"reg\"][\"$edx\"]\n        return eax, ebx, ecx, edx\n\n    def make_out(self, id, subid, eax, ebx, ecx, edx):\n        if eax == ebx == ecx == edx == 0:\n            return\n\n        def o(msg):\n            self.out.append(msg)\n            return\n\n        if subid is None:\n            o(titlify(\"cpuid (eax={:#x})\".format(id)))\n        else:\n            o(titlify(\"cpuid (eax={:#x}, ecx={:#x})\".format(id, subid)))\n        o(Color.colorify(\"eax={:#x}, ebx={:#x}, ecx={:#x}, edx={:#x}\".format(eax, ebx, ecx, edx), \"bold yellow\"))\n\n        def c(reg, shift, mask, msg):\n            val = (reg >> shift) & mask\n            msg = \"        \" + msg + \" (={:#x})\".format(val)\n            if val:\n                return Color.boldify(msg)\n            else:\n                return msg\n\n        if id == 0:\n            vid = String.bytes2str(p32(ebx) + p32(edx) + p32(ecx))\n            o(\"eax: Maximum Input Value for Basic CPUID Information\")\n            o(\"ebx+edx+ecx: Vendor ID (={!r})\".format(vid))\n        elif id == 1:\n            o(\"eax: Version Information\")\n            o(c(eax,  0, 0xf,         \"EAX  3- 0: Stepping ID\"))\n            o(c(eax,  4, 0xf,         \"EAX  7- 4: Model Number\"))\n            o(c(eax,  8, 0xf,         \"EAX 11- 8: Family Code\"))\n            o(c(eax, 12, 0b11,        \"EAX 13-12: Processor Type\"))\n            o(c(eax, 14, 0b11,        \"EAX 15-14: Reserved\"))\n            o(c(eax, 16, 0xf,         \"EAX 19-16: Extended Model\"))\n            o(c(eax, 20, 0xff,        \"EAX 27-20: Extended Family\"))\n            o(c(eax, 28, 0xf,         \"EAX 31-28: Reserved\"))\n            o(\"ebx: Additional Information\")\n            o(c(ebx,  0, 0xff,        \"EBX  7- 0: Brand Index\"))\n            o(c(ebx,  8, 0xff,        \"EBX 15- 8: CLFLUSH line size\"))\n            o(c(ebx, 16, 0xff,        \"EBX 23-16: The number of logical processors\"))\n            o(c(ebx, 24, 0xff,        \"EBX 31-24: Initial APIC ID\"))\n            o(\"edx,ecx: Feature Information\")\n            o(c(edx,  0, 1,           \"EDX     0: FPU (Floating Point Unit on-chip)\"))\n            o(c(edx,  1, 1,           \"EDX     1: VME (Virtual 8086 Mode Enhancements)\"))\n            o(c(edx,  2, 1,           \"EDX     2: DE (Debugging Extensions)\"))\n            o(c(edx,  3, 1,           \"EDX     3: PSE (Page Size Extension)\"))\n            o(c(edx,  4, 1,           \"EDX     4: TSC (Time Stamp Counter)\"))\n            o(c(edx,  5, 1,           \"EDX     5: MSR (Model Specific Registers RDMSR and WRMSR instructions)\"))\n            o(c(edx,  6, 1,           \"EDX     6: PAE (Physical Address Extension)\"))\n            o(c(edx,  7, 1,           \"EDX     7: MCE (Machine Check Exception)\"))\n            o(c(edx,  8, 1,           \"EDX     8: CX8 (CMPXCHG8B instruction)\"))\n            o(c(edx,  9, 1,           \"EDX     9: APIC (APIC on-chip)\"))\n            o(c(edx, 10, 1,           \"EDX    10: Reserved\"))\n            o(c(edx, 11, 1,           \"EDX    11: SEP (SYSENTER and SYSEXIT instructions)\"))\n            o(c(edx, 12, 1,           \"EDX    12: MTRR (Memory Type Range Registers)\"))\n            o(c(edx, 13, 1,           \"EDX    13: PGE (Page Global Bit)\"))\n            o(c(edx, 14, 1,           \"EDX    14: MCA (Machine Check Architecture)\"))\n            o(c(edx, 15, 1,           \"EDX    15: CMOV (Conditional Move instructions)\"))\n            o(c(edx, 16, 1,           \"EDX    16: PAT (Page Attribute Table)\"))\n            o(c(edx, 17, 1,           \"EDX    17: PSE-36 (36-Bit Page Size Extension)\"))\n            o(c(edx, 18, 1,           \"EDX    18: PSN (Processor Serial Number)\"))\n            o(c(edx, 19, 1,           \"EDX    19: CLFSH (CLFLUSH instruction)\"))\n            o(c(edx, 20, 1,           \"EDX    20: Reserved\"))\n            o(c(edx, 21, 1,           \"EDX    21: DS (Debug Store)\"))\n            o(c(edx, 22, 1,           \"EDX    22: ACPI (Thermal Monitor and Software Controlled Clock Facilities)\"))\n            o(c(edx, 23, 1,           \"EDX    23: MMX (Intel MMX technology)\"))\n            o(c(edx, 24, 1,           \"EDX    24: FXSR (FXSAVE and FXRSTOR instructions)\"))\n            o(c(edx, 25, 1,           \"EDX    25: SSE (Streaming SIMD Extension)\"))\n            o(c(edx, 26, 1,           \"EDX    26: SSE2 (STreaming SIMD Extension 2)\"))\n            o(c(edx, 27, 1,           \"EDX    27: SS (Self Snoop)\"))\n            o(c(edx, 28, 1,           \"EDX    28: HTT (Max APIC IDs reserved field is Valid)\"))\n            o(c(edx, 29, 1,           \"EDX    29: TM (Thermal Monitor)\"))\n            o(c(edx, 30, 1,           \"EDX    30: Reserved\"))\n            o(c(edx, 31, 1,           \"EDX    31: PBE (Pending Break Enable)\"))\n            o(c(ecx,  0, 1,           \"ECX     0: SSE3 (Streaming SIMD Extensions 3)\"))\n            o(c(ecx,  1, 1,           \"ECX     1: PCLMULQDQ (PCLMULQDQ instruction)\"))\n            o(c(ecx,  2, 1,           \"ECX     2: DTES64 (64-bit DS Area)\"))\n            o(c(ecx,  3, 1,           \"ECX     3: MONITOR (MONITOR/MWAIT instruction)\"))\n            o(c(ecx,  4, 1,           \"ECX     4: DS-CPL (CPL Qualified Debug Store)\"))\n            o(c(ecx,  5, 1,           \"ECX     5: VMX (Intel VT (Virtual Machine eXtensions))\"))\n            o(c(ecx,  6, 1,           \"ECX     6: SMX (Safer Mode eXtensions)\"))\n            o(c(ecx,  7, 1,           \"ECX     7: EIST (Enhanced Intel SpeedStep Technology)\"))\n            o(c(ecx,  8, 1,           \"ECX     8: TM2 (Thermal Monitor 2)\"))\n            o(c(ecx,  9, 1,           \"ECX     9: SSSE3 (Supplemental Streaming SIMD Extensions 3)\"))\n            o(c(ecx, 10, 1,           \"ECX    10: CNXT-ID (L1 Context ID)\"))\n            o(c(ecx, 11, 1,           \"ECX    11: SDBG (IA32_DEBUG_INTERFACE MSR for silicon debug)\"))\n            o(c(ecx, 12, 1,           \"ECX    12: FMA (FMA extensions using YMM state)\"))\n            o(c(ecx, 13, 1,           \"ECX    13: CMPXCHG16B (CMPXCHG16B instruction)\"))\n            o(c(ecx, 14, 1,           \"ECX    14: xTPR (xTPR update control)\"))\n            o(c(ecx, 15, 1,           \"ECX    15: PDCM (Perfmon and Debug Capability MSR)\"))\n            o(c(ecx, 16, 1,           \"ECX    16: Reserved\"))\n            o(c(ecx, 17, 1,           \"ECX    17: PCID (Process-Context IDentifiers)\"))\n            o(c(ecx, 18, 1,           \"ECX    18: DCA (Direct Cache Access)\"))\n            o(c(ecx, 19, 1,           \"ECX    19: SSE4_1 (Streaming SIMD Extensions 4.1)\"))\n            o(c(ecx, 20, 1,           \"ECX    20: SSE4_2 (Streaming SIMD Extensions 4.2)\"))\n            o(c(ecx, 21, 1,           \"ECX    21: x2APIC\"))\n            o(c(ecx, 22, 1,           \"ECX    22: MOVBE (MOVBE instruction)\"))\n            o(c(ecx, 23, 1,           \"ECX    23: POPCNT (POPulation CouNt instruction)\"))\n            o(c(ecx, 24, 1,           \"ECX    24: TSC-Deadline\"))\n            o(c(ecx, 25, 1,           \"ECX    25: AESNI (AESNI Instruction)\"))\n            o(c(ecx, 26, 1,           \"ECX    26: XSAVE (XSAVE instruction)\"))\n            o(c(ecx, 27, 1,           \"ECX    27: OSXSAVE (OSXSAVE instruction)\"))\n            o(c(ecx, 28, 1,           \"ECX    28: AVX (Intel Advanced Vector eXtensions)\"))\n            o(c(ecx, 29, 1,           \"ECX    29: F16C (16-bit Floating-point Conversion instructions)\"))\n            o(c(ecx, 30, 1,           \"ECX    30: RDRAND (RDRAND instruction)\"))\n            o(c(ecx, 31, 1,           \"ECX    31: RAZ (Reserved for use by hypervisor to indicate guest status)\"))\n        elif id == 2:\n            o(\"Cache and TLB Information\")\n        elif id == 3:\n            o(\"eax,ebx: Reserved\")\n            o(\"edx+ecx: Processor Serial Number\")\n        elif id == 4:\n            o(\"Information of cache configuration descriptor\")\n        elif id == 5:\n            o(\"Information of MONITOR/MWAIT\")\n        elif id == 6:\n            o(\"Information of power management\")\n            o(c(eax,  0, 1,           \"EAX     0: Digital temperature sensor\"))\n            o(c(eax,  1, 1,           \"EAX     1: Intel Turbo Boost Technology\"))\n            o(c(eax,  2, 1,           \"EAX     2: ARAT (Always Running APIC Timer)\"))\n            o(c(eax,  3, 1,           \"EAX     3: Reserved\"))\n            o(c(eax,  4, 1,           \"EAX     4: Power limit notification controls\"))\n            o(c(eax,  5, 1,           \"EAX     5: Clock modulation duty cycle extensions\"))\n            o(c(eax,  6, 1,           \"EAX     6: Package thermal management\"))\n            o(c(eax,  7, 1,           \"EAX     7: Hardware-managed P-state base support (HWP)\"))\n            o(c(eax,  8, 1,           \"EAX     8: HWP notification interrupt enable MSR\"))\n            o(c(eax,  9, 1,           \"EAX     9: HWP activity window MSR\"))\n            o(c(eax, 10, 1,           \"EAX    10: HWP energy/performance preference MSR\"))\n            o(c(eax, 11, 1,           \"EAX    11: HWP package level request MSR\"))\n            o(c(eax, 12, 1,           \"EAX    12: Reserved\"))\n            o(c(eax, 13, 1,           \"EAX    13: HDC (Hardware Duty Cycle programming)\"))\n            o(c(eax, 14, 1,           \"EAX    14: Intel Turbo Boost Max Technology 3.0\"))\n            o(c(eax, 15, 1,           \"EAX    15: HWP Capabilities, Highest Performance change\"))\n            o(c(eax, 16, 1,           \"EAX    16: HWP PECI override\"))\n            o(c(eax, 17, 1,           \"EAX    17: Flexible HWP\"))\n            o(c(eax, 18, 1,           \"EAX    18: Fast access mode for IA32_HWP_REQUEST MSR\"))\n            o(c(eax, 19, 1,           \"EAX    19: Hardware feedback MSRs\"))\n            o(c(eax, 20, 1,           \"EAX    20: Ignoring Idle Logical Processor HWP request\"))\n            o(c(eax, 21, 1,           \"EAX    21: Reserved\"))\n            o(c(eax, 22, 1,           \"EAX    22: Reserved\"))\n            o(c(eax, 23, 1,           \"EAX    23: Enhanced hardware feedback MSRs\"))\n            o(c(eax, 24, 0x7f,        \"EAX 30-24: Reserved\"))\n            o(c(eax, 31, 1,           \"EAX    31: IP payloads are LIP\"))\n            o(c(ebx,  0, 0xf,         \"EBX  3- 0: Number of interrupted thresholds of digital temperature sensor\"))\n            o(c(ebx,  4, 0xfff_ffff,  \"EBX 31- 4: Reserved\"))\n            o(c(ecx,  0, 1,           \"ECX     0: Hardware Coordination Feedback Capability (APERF and MPERF)\"))\n            o(c(ecx,  1, 1,           \"ECX     1: Reserved\"))\n            o(c(ecx,  2, 1,           \"ECX     2: Reserved\"))\n            o(c(ecx,  3, 1,           \"ECX     3: Performance-energy bias preference\"))\n            o(c(ecx,  4, 0xfff_ffff,  \"ECX 31- 4: Reserved\"))\n            o(c(edx,  0, 1,           \"EDX     0: Performance feature report\"))\n            o(c(edx,  1, 1,           \"EDX     1: Energy efficiency capacity report\"))\n            o(c(edx,  2, 0x3f,        \"EDX  7- 2: Reserved\"))\n            o(c(edx,  8, 0xf,         \"EDX 11- 8: The size of the hardware feedback interface structure\"))\n            o(c(edx, 12, 0xf,         \"EDX 15-12: Reserved\"))\n            o(c(edx, 16, 0xffff,      \"EDX 31-16: Index of rows for the hardware feedback interface structure\"))\n        elif id == 7 and subid == 0:\n            o(\"eax: Maximum Input Value for Extended CPUID Information\")\n            o(\"ebx,edx,edx: Extended Feature Information\")\n            o(c(ebx,  0, 1,           \"EBX     0: FSGSBASE (FSGSBASE instructions)\"))\n            o(c(ebx,  1, 1,           \"EBX     1: TSC_ADJUST (IA32_TSC_ADJUST MSR supported)\"))\n            o(c(ebx,  2, 1,           \"EBX     2: SGX (Software Guard Extensions)\"))\n            o(c(ebx,  3, 1,           \"EBX     3: BMI1 (Bit Manipulation Instructions)\"))\n            o(c(ebx,  4, 1,           \"EBX     4: HLE (Hardware Lock Elision)\"))\n            o(c(ebx,  5, 1,           \"EBX     5: AVX2 (Advanced Vector Extensions 2.0)\"))\n            o(c(ebx,  6, 1,           \"EBX     6: FDP_EXCPTN_ONLY (x87 FPU Data Pointer updated only on x87 Exceptions)\"))\n            o(c(ebx,  7, 1,           \"EBX     7: SMEP (Supervisor Mode Execution Protection)\"))\n            o(c(ebx,  8, 1,           \"EBX     8: BMI2 (Bit Manipulation Instructions 2)\"))\n            o(c(ebx,  9, 1,           \"EBX     9: ERMS (Enhanced REP MOVSB/STOSB)\"))\n            o(c(ebx, 10, 1,           \"EBX    10: INVPCID (INVPCID instruction)\"))\n            o(c(ebx, 11, 1,           \"EBX    11: RTM (Restricted Transactional Memory)\"))\n            o(c(ebx, 12, 1,           \"EBX    12: PQM (Platform QoS Monitoring)\"))\n            o(c(ebx, 13, 1,           \"EBX    13: x87 FPU CS and DS deprecated\"))\n            o(c(ebx, 14, 1,           \"EBX    14: MPX (Memory Protection eXtensions)\"))\n            o(c(ebx, 15, 1,           \"EBX    15: PQE (Platform QoS Enforcement)\"))\n            o(c(ebx, 16, 1,           \"EBX    16: AVX512F (AVX512 Foundation)\"))\n            o(c(ebx, 17, 1,           \"EBX    17: AVX512DQ (AVX512 Double/Quadword instructions)\"))\n            o(c(ebx, 18, 1,           \"EBX    18: RDSEED (RDSEED instruction)\"))\n            o(c(ebx, 19, 1,           \"EBX    19: ADX (Multi-Precision Add-Carry instruction eXtensions)\"))\n            o(c(ebx, 20, 1,           \"EBX    20: SMAP (Supervisor Mode Access Prevention)\"))\n            o(c(ebx, 21, 1,           \"EBX    21: AVX512IFMA (AVX512 Integer FMA instructions)\"))\n            o(c(ebx, 22, 1,           \"EBX    22: (Intel) PCOMMIT (Persistent Commit instruction)\"))\n            o(c(ebx, 22, 1,           \"EBX    22: (AMD) RDPID (RDPID instruction and TSC_AUX MSR iupport)\"))\n            o(c(ebx, 23, 1,           \"EBX    23: CLFLUSHOPT (CLFLUSHOPT instruction)\"))\n            o(c(ebx, 24, 1,           \"EBX    24: CLWB (Cache Line Write-Back instruction)\"))\n            o(c(ebx, 25, 1,           \"EBX    25: PT (Intel Processor Trace)\"))\n            o(c(ebx, 26, 1,           \"EBX    26: AVX512PF (AVX512 Prefetch instructions)\"))\n            o(c(ebx, 27, 1,           \"EBX    27: AVX512ER (AVX512 Exponent/Reciprocal instructions)\"))\n            o(c(ebx, 28, 1,           \"EBX    28: AVX512CD (AVX512 Conflict Detection instructions)\"))\n            o(c(ebx, 29, 1,           \"EBX    29: SHA (SHA-1/SHA-256 instructions)\"))\n            o(c(ebx, 30, 1,           \"EBX    30: AVX512BW (AVX512 Byte/Word instructions)\"))\n            o(c(ebx, 31, 1,           \"EBX    31: AVX512VL (AVX512 Vector Length Extensions)\"))\n            o(c(ecx,  0, 1,           \"ECX     0: PREFETCHWT1 (PREFETCHWT1 instruction)\"))\n            o(c(ecx,  1, 1,           \"ECX     1: AVX512VBMI (AVX512 Vector Byte Manipulation Instructions)\"))\n            o(c(ecx,  2, 1,           \"ECX     2: UMIP (User Mode Instruction Prevention)\"))\n            o(c(ecx,  3, 1,           \"ECX     3: PKU (Protection Keys for User-mode pages)\"))\n            o(c(ecx,  4, 1,           \"ECX     4: OSPKE (OS has Enabled Protection Keys)\"))\n            o(c(ecx,  5, 1,           \"ECX     5: WAITPKG (Wait and Pause Enhancements)\"))\n            o(c(ecx,  6, 1,           \"ECX     6: AVX512VBMI2 (AVX512 Vector Byte Manipulation Instructions 2)\"))\n            o(c(ecx,  7, 1,           \"ECX     7: CET_SS (CET shadow stack)\"))\n            o(c(ecx,  8, 1,           \"ECX     8: GFNI (Galois Field NI / Galois Field Affine Transformation)\"))\n            o(c(ecx,  9, 1,           \"ECX     9: VAES (VEX-encoded AES-NI)\"))\n            o(c(ecx, 10, 1,           \"ECX    10: VPCL (VEX-encoded PCLMUL)\"))\n            o(c(ecx, 11, 1,           \"ECX    11: AVX512VNNI (AVX512 Vector Neural Network Instructions)\"))\n            o(c(ecx, 12, 1,           \"ECX    12: AVX512BITALG (AVX512 Bitwise Algorithms)\"))\n            o(c(ecx, 13, 1,           \"ECX    13: TME_EN (Total Memory Encryption)\"))\n            o(c(ecx, 14, 1,           \"ECX    14: AVX512 VPOPCNTDQ\"))\n            o(c(ecx, 15, 1,           \"ECX    15: Reserved\"))\n            o(c(ecx, 16, 1,           \"ECX    16: LA57 (5-Level paging)\"))\n            o(c(ecx, 17, 0x1f,        \"ECX 21-17: MAWAU (MPX Address-Width Adjust for CPL=3)\"))\n            o(c(ecx, 22, 1,           \"ECX    22: RDPID (Read Processor ID)\"))\n            o(c(ecx, 23, 1,           \"ECX    23: KL (Key Locker)\"))\n            o(c(ecx, 24, 1,           \"ECX    24: Reserved\"))\n            o(c(ecx, 25, 1,           \"ECX    25: CLDEMOTE (Cache Line Demote)\"))\n            o(c(ecx, 26, 1,           \"ECX    26: Reserved\"))\n            o(c(ecx, 27, 1,           \"ECX    27: MOVDIRI (32-bit Direct Stores)\"))\n            o(c(ecx, 28, 1,           \"ECX    28: MOVDIRI64B (64-bit Direct Stores)\"))\n            o(c(ecx, 29, 1,           \"ECX    29: ENQCMD (ENQueue Stores)\"))\n            o(c(ecx, 30, 1,           \"ECX    30: SGX_LC (SGX Launch Configuration)\"))\n            o(c(ecx, 31, 1,           \"ECX    31: PKS (Protection Keys for Supervisor-mode pages)\"))\n            o(c(edx,  0, 1,           \"EDX     0: Reserved\"))\n            o(c(edx,  1, 1,           \"EDX     1: Reserved\"))\n            o(c(edx,  2, 1,           \"EDX     2: AVX512_4VNNIW\"))\n            o(c(edx,  3, 1,           \"EDX     3: AVX512_4FMAPS\"))\n            o(c(edx,  4, 1,           \"EDX     4: Fast Short REP MOV\"))\n            o(c(edx,  5, 1,           \"EDX     5: UINTR (User Interrupts)\"))\n            o(c(edx,  6, 1,           \"EDX     6: Reserved\"))\n            o(c(edx,  7, 1,           \"EDX     7: Reserved\"))\n            o(c(edx,  8, 1,           \"EDX     8: AVX512_VP2INTERSECT\"))\n            o(c(edx,  9, 1,           \"EDX     9: Reserved\"))\n            o(c(edx, 10, 1,           \"EDX    10: MD_CLEAR\"))\n            o(c(edx, 11, 1,           \"EDX    11: Reserved\"))\n            o(c(edx, 12, 1,           \"EDX    12: Reserved\"))\n            o(c(edx, 13, 1,           \"EDX    13: TSX force abort MSR\"))\n            o(c(edx, 14, 1,           \"EDX    14: SERIALIZE\"))\n            o(c(edx, 15, 1,           \"EDX    15: Hybrid\"))\n            o(c(edx, 16, 1,           \"EDX    16: TSX suspend load address tracking\"))\n            o(c(edx, 17, 1,           \"EDX    17: Reserved\"))\n            o(c(edx, 18, 1,           \"EDX    18: PCONFIG\"))\n            o(c(edx, 19, 1,           \"EDX    19: Reserved\"))\n            o(c(edx, 20, 1,           \"EDX    20: CET_IBT (CET Indirect Branch Tracking)\"))\n            o(c(edx, 21, 1,           \"EDX    21: Reserved\"))\n            o(c(edx, 22, 1,           \"EDX    22: AMX-BF16 (Tile computation on bfloat16)\"))\n            o(c(edx, 23, 1,           \"EDX    23: AVX512FP16\"))\n            o(c(edx, 24, 1,           \"EDX    24: AMX-TILE (Tile architecture)\"))\n            o(c(edx, 25, 1,           \"EDX    25: AMX-INT8 (Tile computation on 8-bit integers)\"))\n            o(c(edx, 26, 1,           \"EDX    26: IBRS/IBPB (Indirect Branch Restricted Speculation/Predictor Barrier)\"))\n            o(c(edx, 27, 1,           \"EDX    27: STIBP (Single Thread Indirect Branch Predictors)\"))\n            o(c(edx, 28, 1,           \"EDX    28: L1D_FLUSH (L1 Data Cache Flush)\"))\n            o(c(edx, 29, 1,           \"EDX    29: IA32_ARCH_CAPABILITIES MSR\"))\n            o(c(edx, 30, 1,           \"EDX    30: IA32_CORE_CAPABILITIES MSR\"))\n            o(c(edx, 31, 1,           \"EDX    31: SSBD (Speculative Store Bypass Disable)\"))\n        elif id == 7 and subid != 0:\n            o(\"ebx,edx,edx: Extended Feature Information\")\n        elif id == 8:\n            o(\"Reserved\")\n        elif id == 9:\n            o(\"eax: PLATFORM_DCA_CAP MSR\")\n            o(\"ebx,ecx,edx: Reserved\")\n        elif id == 10:\n            o(\"DCA parameters\")\n            o(c(eax,  0, 0xff,        \"EAX  7- 0: Revision\"))\n            o(c(eax,  8, 0xff,        \"EAX 15- 8: Number of PeMo counters per logical processor\"))\n            o(c(eax, 16, 0xff,        \"EAX 23-16: Bit width of PeMo counter\"))\n            o(c(eax, 24, 0xff,        \"EAX 31-24: EBX bit vector length\"))\n            o(c(ebx,  0, 1,           \"EBX     0: Core cycles event unavailable\"))\n            o(c(ebx,  1, 1,           \"EBX     1: Instructions retired event unavailable\"))\n            o(c(ebx,  2, 1,           \"EBX     2: Reference cycles event unavailable\"))\n            o(c(ebx,  3, 1,           \"EBX     3: Last level cache references event unavailable\"))\n            o(c(ebx,  4, 1,           \"EBX     4: Last level cache misses event unavailable\"))\n            o(c(ebx,  5, 1,           \"EBX     5: Branch instructions retired event unavailable\"))\n            o(c(ebx,  6, 1,           \"EBX     6: Branch mispredicts retired event unavailable\"))\n            o(c(ebx,  7, 0x1ff_ffff,  \"EBX 31- 7: Reserved\"))\n            o(c(ecx,  0, 0xffff_ffff, \"ECX 31- 0: Reserved\"))\n            o(c(edx,  0, 0x1f,        \"EDX  4- 0: Number of fixed function PeMo counters\"))\n            o(c(edx,  5, 0xff,        \"EDX 12- 5: Bit width of fixed function PeMo counter\"))\n            o(c(edx, 13, 1,           \"EDX    13: Reserved\"))\n            o(c(edx, 14, 1,           \"EDX    14: Reserved\"))\n            o(c(edx, 15, 1,           \"EDX    15: AnyThread deprecation\"))\n            o(c(edx, 16, 0xffff,      \"EDX 31-16: Reserved\"))\n        elif id == 11:\n            o(\"Information of topology enumeration\")\n        elif id == 12:\n            o(\"Reserved\")\n        elif id == 13:\n            if subid == 0:\n                m = \"main\"\n            elif subid == 1:\n                m = \"sub\"\n            else:\n                m = \"XCR0.{:d}\".format(subid)\n            o(\"Information of extended state enumeration ({:s})\".format(m))\n        elif id in [15, 16]:\n            o(\"Intel Resource Director Technology (Intel RDT), Cache, Memory Bandwidth Allocation Enumeration\")\n        elif id == 18:\n            o(\"Information of Intel SGX\")\n        elif id == 20:\n            o(\"Information of Intel Processor Trace Enumeration\")\n            o(c(ebx,  0, 1,           \"EBX     0: CR3 filtering\"))\n            o(c(ebx,  1, 1,           \"EBX     1: Configurable PSB, Cycle-Accurate Mode\"))\n            o(c(ebx,  2, 1,           \"EBX     2: Filtering preserved across warm reset\"))\n            o(c(ebx,  3, 1,           \"EBX     3: MTC timing packet, suppression of COFI-based packets\"))\n            o(c(ebx,  4, 1,           \"EBX     4: PTWRITE\"))\n            o(c(ebx,  5, 1,           \"EBX     5: Power Event Trace\"))\n            o(c(ebx,  6, 1,           \"EBX     6: PSB and PMI preservation MSRs\"))\n            o(c(ebx,  7, 0x1ff_ffff,  \"EBX 31- 7: Reserved\"))\n            o(c(ecx,  0, 1,           \"ECX     0: ToPA output scheme\"))\n            o(c(ecx,  1, 1,           \"ECX     1: ToPA tables hold multiple output entries\"))\n            o(c(ecx,  2, 1,           \"ECX     2: Single-range output scheme\"))\n            o(c(ecx,  3, 1,           \"ECX     3: Trace Transport output support\"))\n            o(c(ecx,  4, 0x7ff_ffff,  \"ECX 30- 4: Reserved\"))\n            o(c(ecx, 31, 1,           \"ECX    31: IP payloads are LIP\"))\n        elif id == 21:\n            o(\"TSC and Nominal Core Crystal Clock\")\n        elif id == 22:\n            o(\"Information of CPU frequency\")\n            o(c(eax,  0, 0xffff,      \"EAX 15- 0: Processor Base Frequency (MHz)\"))\n            o(c(eax, 16, 0xffff,      \"EAX 31-16: Reserved\"))\n            o(c(ebx,  0, 0xffff,      \"EBX 15- 0: Maximum Frequency (MHz)\"))\n            o(c(ebx, 16, 0xffff,      \"EBX 31-16: Reserved\"))\n            o(c(ecx,  0, 0xffff,      \"ECX 15- 0: Bus (Reference) Frequency (MHz)\"))\n            o(c(ecx, 16, 0xffff,      \"ECX 31-16: Reserved\"))\n            o(c(edx,  0, 0xffff_ffff, \"EDX 31- 0: Reserved\"))\n        elif id == 23:\n            o(\"Information of System-On-Chip Vendor Attribute Enumeration\")\n        elif id == 24:\n            o(\"Information of Deterministic Address Translation Parameters\")\n        elif id == 26:\n            o(\"Information of Hybrid Information Enumeration\")\n        elif id == 31:\n            o(\"Information of V2 Extended Topology Enumeration\")\n        elif id == 0x4000_0000:\n            vid = String.bytes2str(p32(ebx) + p32(ecx) + p32(edx))\n            o(\"eax: Maximum Input Value for Hypervisor Function CPUID Information\")\n            o(\"ebx+ecx+edx: Hypervisor Brand String (={!r})\".format(vid))\n        elif id == 0x4000_0001:\n            o(\"Hypervisor\")\n            o(c(eax,  0, 1,           \"EAX     0: Clocksource\"))\n            o(c(eax,  1, 1,           \"EAX     1: NOP IO Delay\"))\n            o(c(eax,  2, 1,           \"EAX     2: MMU Op\"))\n            o(c(eax,  3, 1,           \"EAX     3: Clocksource 2\"))\n            o(c(eax,  4, 1,           \"EAX     4: Async PF\"))\n            o(c(eax,  5, 1,           \"EAX     5: Steal Time\"))\n            o(c(eax,  6, 1,           \"EAX     6: PV EOI\"))\n            o(c(eax,  7, 1,           \"EAX     7: PV UNHALT\"))\n            o(c(eax,  8, 1,           \"EAX     8: Reserved\"))\n            o(c(eax,  9, 1,           \"EAX     9: PV TLB flush\"))\n            o(c(eax, 10, 1,           \"EAX    10: PV async PF VMEXIT\"))\n            o(c(eax, 11, 1,           \"EAX    11: PV send IPI\"))\n            o(c(eax, 12, 1,           \"EAX    12: PV poll control\"))\n            o(c(eax, 13, 1,           \"EAX    13: PV sched yield\"))\n            o(c(eax, 14, 1,           \"EAX    14: Async PF INT\"))\n            o(c(eax, 15, 1,           \"EAX    15: MSI extended destination ID\"))\n            o(c(eax, 16, 1,           \"EAX    16: Hypercall map GPA range\"))\n            o(c(eax, 17, 1,           \"EAX    17: Hypercall map GPA range\"))\n            o(c(eax, 18, 1,           \"EAX    18: Migration control\"))\n            o(c(eax, 19, 0x3f,        \"EAX 24-19: Reserved\"))\n            o(c(eax, 25, 1,           \"EAX    25: Clocksource Stable\"))\n            o(c(eax, 26, 0x3f,        \"EAX 31-26: Reserved\"))\n            o(c(edx,  0, 1,           \"EDX     0: vCPUs realtime, never preempted\"))\n            o(c(edx,  1, 0x7fff_ffff, \"EDX 31- 1: Reserved\"))\n        elif id == 0x4000_0003:\n            o(\"Hypervisor\")\n            o(c(eax,  0, 1,           \"EAX     0: VP_RUNTIME\"))\n            o(c(eax,  1, 1,           \"EAX     1: TIME_REF_COUNT\"))\n            o(c(eax,  2, 1,           \"EAX     2: Basic SynIC MSRs\"))\n            o(c(eax,  3, 1,           \"EAX     3: Synthetic Timer\"))\n            o(c(eax,  4, 1,           \"EAX     4: APIC access\"))\n            o(c(eax,  5, 1,           \"EAX     5: Hypercall MSRs\"))\n            o(c(eax,  6, 1,           \"EAX     6: VP Index MSR\"))\n            o(c(eax,  7, 1,           \"EAX     7: System Reset MSR\"))\n            o(c(eax,  8, 1,           \"EAX     8: Access stats MSRs\"))\n            o(c(eax,  9, 1,           \"EAX     9: Reference TSC\"))\n            o(c(eax, 10, 1,           \"EAX    10: Guest Idle MSR\"))\n            o(c(eax, 11, 1,           \"EAX    11: Timer Frequency MSRs\"))\n            o(c(eax, 12, 1,           \"EAX    12: Debug MSRs\"))\n            o(c(eax, 13, 1,           \"EAX    13: Reenlightenment controls\"))\n            o(c(eax, 14, 0x3_ffff,    \"EAX 31-14: Reserved\"))\n            o(c(ebx,  0, 1,           \"EBX     0: CreatePartitions\"))\n            o(c(ebx,  1, 1,           \"EBX     1: AccessPartitionId\"))\n            o(c(ebx,  2, 1,           \"EBX     2: AccessMemoryPool\"))\n            o(c(ebx,  3, 1,           \"EBX     3: AdjustMemoryBuffers\"))\n            o(c(ebx,  4, 1,           \"EBX     4: PostMessages\"))\n            o(c(ebx,  5, 1,           \"EBX     5: SignalEvents\"))\n            o(c(ebx,  6, 1,           \"EBX     6: CreatePort\"))\n            o(c(ebx,  7, 1,           \"EBX     7: ConnectPort\"))\n            o(c(ebx,  8, 1,           \"EBX     8: AccessStats\"))\n            o(c(ebx,  9, 1,           \"EBX     9: Reserved\"))\n            o(c(ebx, 10, 1,           \"EBX    10: Reserved\"))\n            o(c(ebx, 11, 1,           \"EBX    11: Debugging\"))\n            o(c(ebx, 12, 1,           \"EBX    12: CpuManagement\"))\n            o(c(ebx, 13, 1,           \"EBX    13: ConfigureProfiler\"))\n            o(c(ebx, 14, 1,           \"EBX    14: EnableExpandedStackwalking\"))\n            o(c(ebx, 15, 1,           \"EBX    15: Reserved\"))\n            o(c(ebx, 16, 1,           \"EBX    16: AccessVSM\"))\n            o(c(ebx, 17, 1,           \"EBX    17: AccessVpRegisters\"))\n            o(c(ebx, 18, 1,           \"EBX    18: Reserved\"))\n            o(c(ebx, 19, 1,           \"EBX    19: Reserved\"))\n            o(c(ebx, 20, 1,           \"EBX    20: EnableExtendedHypercalls\"))\n            o(c(ebx, 21, 1,           \"EBX    21: StartVirtualProcessor\"))\n            o(c(ebx, 22, 0x3ff,       \"EBX 31-22: Reserved\"))\n            o(c(edx,  0, 1,           \"EDX     0: MWAIT instruction support (deprecated)\"))\n            o(c(edx,  1, 1,           \"EDX     1: Guest debugging support\"))\n            o(c(edx,  2, 1,           \"EDX     2: Performance Monitor support\"))\n            o(c(edx,  3, 1,           \"EDX     3: Physical CPU dynamic partitioning event support\"))\n            o(c(edx,  4, 1,           \"EDX     4: Hypercall input params via XMM registers\"))\n            o(c(edx,  5, 1,           \"EDX     5: Virtual guest idle state support\"))\n            o(c(edx,  6, 1,           \"EDX     6: Hypervisor sleep state support\"))\n            o(c(edx,  7, 1,           \"EDX     7: NUMA distance query support\"))\n            o(c(edx,  8, 1,           \"EDX     8: Timer frequency details available\"))\n            o(c(edx,  9, 1,           \"EDX     9: Synthetic machine check injection support\"))\n            o(c(edx, 10, 1,           \"EDX    10: Guest crash MSR support\"))\n            o(c(edx, 11, 1,           \"EDX    11: Debug MSR support\"))\n            o(c(edx, 12, 1,           \"EDX    12: NPIEP support\"))\n            o(c(edx, 13, 1,           \"EDX    13: Hypervisor disable support\"))\n            o(c(edx, 14, 1,           \"EDX    14: Extended GVA ranges for flush virtual address list available\"))\n            o(c(edx, 15, 1,           \"EDX    15: Hypercall output via XMM registers\"))\n            o(c(edx, 16, 1,           \"EDX    16: Virtual guest idle state\"))\n            o(c(edx, 17, 1,           \"EDX    17: Soft interrupt polling mode available\"))\n            o(c(edx, 18, 1,           \"EDX    18: Hypercall MSR lock available\"))\n            o(c(edx, 19, 1,           \"EDX    19: Direct synthetic timers support\"))\n            o(c(edx, 20, 1,           \"EDX    20: PAT register available for VSM\"))\n            o(c(edx, 21, 1,           \"EDX    21: BNDCFGS register available for VSM\"))\n            o(c(edx, 22, 1,           \"EDX    22: Reserved\"))\n            o(c(edx, 23, 1,           \"EDX    23: Synthetic time unhalted timer\"))\n            o(c(edx, 24, 1,           \"EDX    24: Reserved\"))\n            o(c(edx, 25, 1,           \"EDX    25: Reserved\"))\n            o(c(edx, 26, 1,           \"EDX    26: Intel Last Branch Record (LBR) feature\"))\n            o(c(edx, 27, 1,           \"EDX 31-27: Reserved\"))\n        elif id == 0x4000_0004:\n            o(\"Hypervisor implementation recommendations\")\n            o(c(eax,  0, 1,           \"EAX     0: Hypercall for address space switches\"))\n            o(c(eax,  1, 1,           \"EAX     1: Hypercall for local TLB flushes\"))\n            o(c(eax,  2, 1,           \"EAX     2: Hypercall for remote TLB flushes\"))\n            o(c(eax,  3, 1,           \"EAX     3: MSRs for accessing APIC registers\"))\n            o(c(eax,  4, 1,           \"EAX     4: Hypervisor MSR for system RESET\"))\n            o(c(eax,  5, 1,           \"EAX     5: Relaxed timing\"))\n            o(c(eax,  6, 1,           \"EAX     6: DMA remapping\"))\n            o(c(eax,  7, 1,           \"EAX     7: Interrupt remapping\"))\n            o(c(eax,  8, 1,           \"EAX     8: x2APIC MSRs\"))\n            o(c(eax,  9, 1,           \"EAX     9: Deprecating AutoEOI\"))\n            o(c(eax, 10, 1,           \"EAX    10: Hypercall for SyntheticClusterIpi\"))\n            o(c(eax, 11, 1,           \"EAX    11: Interface ExProcessorMasks\"))\n            o(c(eax, 12, 1,           \"EAX    12: Nested Hyper-V partition\"))\n            o(c(eax, 13, 1,           \"EAX    13: INT for MBEC system calls\"))\n            o(c(eax, 14, 1,           \"EAX    14: Enlightenment VMCS interface\"))\n            o(c(eax, 15, 1,           \"EAX    15: Synced timeline\"))\n            o(c(eax, 16, 1,           \"EAX    16: Reserved\"))\n            o(c(eax, 17, 1,           \"EAX    17: Direct local flush entire\"))\n            o(c(eax, 18, 1,           \"EAX    18: No architectural core sharing\"))\n            o(c(eax, 19, 0x1fff,      \"EAX 31-19: Reserved\"))\n        elif id == 0x4000_0006:\n            o(\"Hypervisor hardware features enable\")\n            o(c(eax,  0, 1,           \"EAX     0: APIC overlay assist\"))\n            o(c(eax,  1, 1,           \"EAX     1: MSR bitmaps\"))\n            o(c(eax,  2, 1,           \"EAX     2: Architectural performance counters\"))\n            o(c(eax,  3, 1,           \"EAX     3: Second-level address translation\"))\n            o(c(eax,  4, 1,           \"EAX     4: DMA remapping\"))\n            o(c(eax,  5, 1,           \"EAX     5: Interrupt remapping\"))\n            o(c(eax,  6, 1,           \"EAX     6: Memory patrol scrubber\"))\n            o(c(eax,  7, 1,           \"EAX     7: DMA protection\"))\n            o(c(eax,  8, 1,           \"EAX     8: HPET\"))\n            o(c(eax,  9, 1,           \"EAX     9: Volatile synthetic timers\"))\n            o(c(eax, 10, 0x3f_ffff,   \"EAX 31-10: Reserved\"))\n        elif id == 0x4000_0007:\n            o(\"Hypervisor CPU management features\")\n            o(c(eax,  0, 1,           \"EAX     0: Start logical processor\"))\n            o(c(eax,  1, 1,           \"EAX     1: Create root virtual processor\"))\n            o(c(eax,  2, 1,           \"EAX     2: Performance counter sync\"))\n            o(c(eax,  3, 0x1fff_ffff, \"EAX 31- 3: Reserved\"))\n            o(c(ebx,  0, 1,           \"EBX     0: Processor power management\"))\n            o(c(ebx,  1, 1,           \"EBX     1: MWAIT idle states\"))\n            o(c(ebx,  2, 1,           \"EBX     2: Logical processor idling\"))\n            o(c(ebx,  3, 0x1fff_ffff, \"EBX 31- 3: Reserved\"))\n            o(c(ecx,  0, 1,           \"ECX     0: Remap guest uncached\"))\n            o(c(ecx,  1, 0x7fff_ffff, \"ECX 31- 1: Reserved\"))\n        elif id == 0x4000_0008:\n            o(\"Hypervisor shared virtual memory (SVM) features\")\n            o(c(eax,  0, 1,           \"EAX     0: SVM (Shared Virtual Memory)\"))\n            o(c(eax,  1, 0x7fff_ffff, \"EAX 31- 1: Reserved\"))\n        elif id == 0x4000_0009:\n            o(\"Nested hypervisor feature identification\")\n            o(c(eax,  0, 1,           \"EAX     0: Reserved\"))\n            o(c(eax,  1, 1,           \"EAX     1: Reserved\"))\n            o(c(eax,  2, 1,           \"EAX     2: Synthetic Timer\"))\n            o(c(eax,  3, 1,           \"EAX     3: Reserved\"))\n            o(c(eax,  4, 1,           \"EAX     4: Interrupt control registers\"))\n            o(c(eax,  5, 1,           \"EAX     5: Hypercall MSRs\"))\n            o(c(eax,  6, 1,           \"EAX     6: VP index MSR\"))\n            o(c(eax,  7, 0x1f,        \"EAX 11- 7: Reserved\"))\n            o(c(eax, 12, 1,           \"EAX    12: Reenlightenment controls\"))\n            o(c(eax, 13, 0x7_ffff,    \"EAX 31-13: Reserved\"))\n            o(c(edx,  0, 0xf,         \"EDX  3- 0: Reserved\"))\n            o(c(eax,  4, 1,           \"EDX     4: Hypercall input params via XMM registers\"))\n            o(c(edx,  5, 0x3ff,       \"EDX 14- 5: Reserved\"))\n            o(c(edx, 15, 1,           \"EDX    15: Hypercall output via XMM registers\"))\n            o(c(edx, 16, 1,           \"EDX    16: Reserved\"))\n            o(c(edx, 17, 1,           \"EDX    17: Soft interrupt polling mode available\"))\n            o(c(edx, 18, 0x3fff,      \"EDX 31-18: Reserved\"))\n        elif id == 0x4000_000a:\n            o(\"Nested hypervisor feature identification\")\n            o(c(eax,  0, 0x1_ffff,    \"EAX 16- 0: Reserved\"))\n            o(c(eax, 17, 1,           \"EAX    17: Direct virtual flush hypercalls\"))\n            o(c(eax, 18, 1,           \"EAX    18: Flush GPA space and list hypercalls\"))\n            o(c(eax, 19, 1,           \"EAX    19: Enlightened MSR bitmaps\"))\n            o(c(eax, 20, 1,           \"EAX    20: Combining virtualization exceptions in page fault exception class\"))\n            o(c(eax, 21, 0x7ff,       \"EAX 31-21: Reserved\"))\n        elif id == 0x4000_0010:\n            o(\"Hypervisor timing information\")\n            o(\"eax: (Virtual) TSC frequency in kHz\")\n            o(\"ebx: (Virtual) Bus (local apic timer) frequency in kHz\")\n            o(\"ecx,edx: Reserved\")\n        elif id == 0x8000_0000:\n            o(\"eax: Maximum Input Value for Extended Function CPUID Information\")\n            o(\"ebx,ecx,edx: Reserved\")\n        elif id == 0x8000_0001:\n            o(\"eax,ebx: Extended Processor Signature\")\n            o(\"edx,ecx: Extended Processor Feature\")\n            o(c(edx,  0, 1,           \"EDX     0: FPU (Floating Point Unit on-chip)\"))\n            o(c(edx,  1, 1,           \"EDX     1: VME (Virtual 8086 Mode Enhancements)\"))\n            o(c(edx,  2, 1,           \"EDX     2: DE (Debugging Extensions)\"))\n            o(c(edx,  3, 1,           \"EDX     3: PSE (Page Size Extension)\"))\n            o(c(edx,  4, 1,           \"EDX     4: TSC (Time Stamp Counter)\"))\n            o(c(edx,  5, 1,           \"EDX     5: MSR (Model Specific Registers RDMSR and WRMSR instructions)\"))\n            o(c(edx,  6, 1,           \"EDX     6: PAE (Physical Address Extension)\"))\n            o(c(edx,  7, 1,           \"EDX     7: MCE (Machine Check Exception)\"))\n            o(c(edx,  8, 1,           \"EDX     8: CX8 (CMPXCHG8B instruction)\"))\n            o(c(edx,  9, 1,           \"EDX     9: APIC (APIC on-chip)\"))\n            o(c(edx, 10, 1,           \"EDX    10: Reserved\"))\n            o(c(edx, 11, 1,           \"EDX    11: (Intel) SEP (SYSENTER and SYSEXIT instructions)\"))\n            o(c(edx, 11, 1,           \"EDX    11: (AMD) SYSCALL (SYSCALL and SYSRET instructions)\"))\n            o(c(edx, 12, 1,           \"EDX    12: MTRR (Memory Type Range Registers)\"))\n            o(c(edx, 13, 1,           \"EDX    13: PGE (Page Global Bit)\"))\n            o(c(edx, 14, 1,           \"EDX    14: MCA (Machine Check Architecture)\"))\n            o(c(edx, 15, 1,           \"EDX    15: CMOV (Conditional MOVe instructions)\"))\n            o(c(edx, 16, 1,           \"EDX    16: PAT (Page Attribute Table)\"))\n            o(c(edx, 17, 1,           \"EDX    17: PSE-36 (36-Bit Page Size Extension)\"))\n            o(c(edx, 18, 1,           \"EDX    18: Reserved\"))\n            o(c(edx, 19, 1,           \"EDX    19: MP (MultiProcessing capable)\"))\n            o(c(edx, 20, 1,           \"EDX    20: (Intel) XD (No-execute page protection)\"))\n            o(c(edx, 20, 1,           \"EDX    20: (AMD) NX (No-execute page protection)\"))\n            o(c(edx, 21, 1,           \"EDX    21: Reserved\"))\n            o(c(edx, 22, 1,           \"EDX    22: MMX+ (MMX instruction extensions)\"))\n            o(c(edx, 23, 1,           \"EDX    23: MMX (Intel MMX technology)\"))\n            o(c(edx, 24, 1,           \"EDX    24: FXSR (FXSAVE and FXRSTOR instructions)\"))\n            o(c(edx, 25, 1,           \"EDX    25: FFXSR (Fast FXSAVE/FXRSTOR)\"))\n            o(c(edx, 26, 1,           \"EDX    26: P1GB (1GB Page support)\"))\n            o(c(edx, 27, 1,           \"EDX    27: RDTSCP (RDTSCP instruction)\"))\n            o(c(edx, 28, 1,           \"EDX    28: Reserved\"))\n            o(c(edx, 29, 1,           \"EDX    29: LM (Long Mode (EM64T))\"))\n            o(c(edx, 30, 1,           \"EDX    30: 3DNow!+ (3DNow! extended)\"))\n            o(c(edx, 31, 1,           \"EDX    31: 3DNow! (3DNow! instructions)\"))\n            o(c(ecx,  0, 1,           \"ECX     0: LAHF (LAHF/SAHF supported in 64-bit mode)\"))\n            o(c(ecx,  1, 1,           \"ECX     1: CMPL (Core Multi-Processing Legacy mode)\"))\n            o(c(ecx,  2, 1,           \"ECX     2: SVM (Secure Virtual Machine)\"))\n            o(c(ecx,  3, 1,           \"ECX     3: EAS (Extended APIC Space)\"))\n            o(c(ecx,  4, 1,           \"ECX     4: AMC8 (AltMovCr8; LOCK MOV CR0 means MOV CR8)\"))\n            o(c(ecx,  5, 1,           \"ECX     5: ABM (Advanced Bit Manipulation; LZCNT instruction)\"))\n            o(c(ecx,  6, 1,           \"ECX     6: SSE4A (SSE4A instructions)\"))\n            o(c(ecx,  7, 1,           \"ECX     7: MASSE (Mis-Aligned SSE Support)\"))\n            o(c(ecx,  8, 1,           \"ECX     8: PREFETCH (3DNow! PREFETCH/PREFETCHHW instructions)\"))\n            o(c(ecx,  9, 1,           \"ECX     9: OSVW (OS-Visible Workaround)\"))\n            o(c(ecx, 10, 1,           \"ECX    10: IBS (Instruction-Based Sampling)\"))\n            o(c(ecx, 11, 1,           \"ECX    11: XOP (eXtended OPeration)\"))\n            o(c(ecx, 12, 1,           \"ECX    12: SKINIT (SKINIT/STGI instructions)\"))\n            o(c(ecx, 13, 1,           \"ECX    13: WDT (WatchDog Timer)\"))\n            o(c(ecx, 14, 1,           \"ECX    14: Reserved\"))\n            o(c(ecx, 15, 1,           \"ECX    15: LWP (Light Weight Profiling)\"))\n            o(c(ecx, 16, 1,           \"ECX    16: FMA4 (4-operands FMA instructions)\"))\n            o(c(ecx, 17, 1,           \"ECX    17: TCE (Translation Cache Extension)\"))\n            o(c(ecx, 18, 1,           \"ECX    18: Reserved\"))\n            o(c(ecx, 19, 1,           \"ECX    19: MSR (Node ID MSR\"))\n            o(c(ecx, 20, 1,           \"ECX    20: Reserved\"))\n            o(c(ecx, 21, 1,           \"ECX    21: TBM (Trailing Bit Manipulation instructions)\"))\n            o(c(ecx, 22, 1,           \"ECX    22: TOPOEXT (TOPology EXTensions)\"))\n            o(c(ecx, 23, 1,           \"ECX    23: PERFCTR_CORE (CORE PERFormance CounTeR extensions)\"))\n            o(c(ecx, 24, 1,           \"ECX    24: PERFCTR_NB (NB PERFormance CounTeR extensions\"))\n            o(c(ecx, 25, 1,           \"ECX    25: Streaming performance monitor architecture\"))\n            o(c(ecx, 26, 1,           \"ECX    26: DBX (Data breakpoint eXtensions)\"))\n            o(c(ecx, 27, 1,           \"ECX    27: PERFTSC (PERFormance Time Stamp Counter)\"))\n            o(c(ecx, 28, 1,           \"ECX    28: PERFCTR_L2 (L2 PERFormance CounTeR extensions)\"))\n            o(c(ecx, 29, 1,           \"ECX    29: MONITORX/MWAITX instructions\"))\n            o(c(ecx, 30, 1,           \"ECX    30: Address mask extension for instruction breakpoint\"))\n            o(c(ecx, 31, 1,           \"ECX    31: Reserved\"))\n        elif id in [0x8000_0002, 0x8000_0003, 0x8000_0004]:\n            vid = String.bytes2str(p32(eax) + p32(ebx) + p32(ecx) + p32(edx))\n            o(\"eax+ebx+ecx+edx: Processor Brand String (={!r})\".format(vid))\n        elif id == 0x8000_0005:\n            o(\"L1 Cache Information\")\n            o(\"eax: 4/2 MB L1 TLB configuration descriptor\")\n            o(\"ebx: 4 KB L1 TLB configuration descriptor\")\n            o(\"ecx: data L1 cache configuration descriptor\")\n            o(\"edx: code L1 cache configuration descriptor\")\n        elif id == 0x8000_0006:\n            o(\"L2/L3 Cache Information\")\n            o(\"eax: 4/2 MB L2 TLB configuration descriptor\")\n            o(\"ebx: 4 KB L2 TLB configuration descriptor\")\n            o(\"ecx: unified L2 cache configuration descriptor\")\n            o(\"edx: unified L3 cache configuration descriptor\")\n        elif id == 0x8000_0007:\n            o(\"ebx: RAS Capabilities\")\n            o(c(ebx,  0, 1,           \"EBX     0: MCA overflow recovery\"))\n            o(c(ebx,  1, 1,           \"EBX     1: Software uncorrectable error containment and recovery\"))\n            o(c(ebx,  2, 1,           \"EBX     2: HWA (HardWare Assert)\"))\n            o(c(ebx,  3, 1,           \"EBX     3: Scalable MCA\"))\n            o(c(ebx,  4, 1,           \"EBX     4: PFEH (Platform First Error Handling)\"))\n            o(c(ebx,  5, 0x7ff_ffff,  \"EBX 31- 5: Reserved\"))\n            o(\"edx: Advanced Power Management information\")\n            o(c(edx,  0, 1,           \"EDX     0: TS (Temperature Sensor)\"))\n            o(c(edx,  1, 1,           \"EDX     1: FID (Frequency ID control)\"))\n            o(c(edx,  2, 1,           \"EDX     2: VID (Voltage ID control)\"))\n            o(c(edx,  3, 1,           \"EDX     3: TTP (Thermal Trip)\"))\n            o(c(edx,  4, 1,           \"EDX     4: TM (Thermal Monitoring)\"))\n            o(c(edx,  5, 1,           \"EDX     5: STC (Software Thermal Control)\"))\n            o(c(edx,  6, 1,           \"EDX     6: MUL (100MHz Multiplier steps)\"))\n            o(c(edx,  7, 1,           \"EDX     7: HWPS (HardWare P-State control)\"))\n            o(c(edx,  8, 1,           \"EDX     8: ITSC (Invariant TSC)\"))\n            o(c(edx,  9, 1,           \"EDX     9: Core performance boost\"))\n            o(c(edx, 10, 1,           \"EDX    10: Read-only effective frequency interface\"))\n            o(c(edx, 11, 1,           \"EDX    11: Processor feedback interface\"))\n            o(c(edx, 12, 1,           \"EDX    12: Core power reporting\"))\n            o(c(edx, 13, 1,           \"EDX    13: Connected standby\"))\n            o(c(edx, 14, 1,           \"EDX    14: RAPL (Running Average Power Limit)\"))\n            o(c(edx, 15, 0x1_ffff,    \"EAX 31-15: Reserved\"))\n        elif id == 0x8000_0008:\n            o(\"eax: Extended Address Length Information\")\n            o(c(eax,  0, 0xff,        \"EAX  7- 0: Physical address length\"))\n            o(c(eax,  8, 0xff,        \"EAX 15- 8: Linear address length\"))\n            o(c(eax, 16, 0xff,        \"EAX 23-16: Guest physical address length\"))\n            o(c(eax, 24, 0xff,        \"EAX 31-24: Reserved\"))\n            o(\"ebx: Extended Feature Extensions ID\")\n            o(c(ebx,  0, 1,           \"EBX     0: CLZERO (CLZERO instruction)\"))\n            o(c(ebx,  1, 1,           \"EBX     1: IRPerf (Instructions Retired count support)\"))\n            o(c(ebx,  2, 1,           \"EBX     2: XSAVE always saves/restores error pointers\"))\n            o(c(ebx,  3, 1,           \"EBX     3: INVLPGB and TLBSYNC instruction\"))\n            o(c(ebx,  4, 1,           \"EBX     4: RDPRU (RDPRU instruction)\"))\n            o(c(ebx,  5, 1,           \"EBX     5: Reserved\"))\n            o(c(ebx,  6, 1,           \"EBX     6: MBE (Memory Bandwidth Enforcement)\"))\n            o(c(ebx,  7, 1,           \"EBX     7: Reserved\"))\n            o(c(ebx,  8, 1,           \"EBX     8: MCOMMIT (MCOMMIT instruction)\"))\n            o(c(ebx,  9, 1,           \"EBX     9: WBNOINVD (Write Back and do NOt INValiDate cache)\"))\n            o(c(ebx, 10, 1,           \"EBX    10: LBR extensions\"))\n            o(c(ebx, 11, 1,           \"EBX    11: Reserved\"))\n            o(c(ebx, 12, 1,           \"EBX    12: IBPB (Indirect Branch Prediction Barrier)\"))\n            o(c(ebx, 13, 1,           \"EBX    13: WBINVD (Write Back and INValiDate cache)\"))\n            o(c(ebx, 14, 1,           \"EBX    14: IBRS (Indirect Branch Restricted Speculation)\"))\n            o(c(ebx, 15, 1,           \"EBX    15: STIBP (Single Thread Indirect Branch Predictor)\"))\n            o(c(ebx, 16, 1,           \"EBX    16: Reserved\"))\n            o(c(ebx, 17, 1,           \"EBX    17: STIBP always on\"))\n            o(c(ebx, 18, 1,           \"EBX    18: IBRS preferred over software solution\"))\n            o(c(ebx, 19, 1,           \"EBX    19: IBRS provides Same Mode Protection\"))\n            o(c(ebx, 20, 1,           \"EBX    20: EFER.LMLSE is unsupported\"))\n            o(c(ebx, 21, 1,           \"EBX    21: INVLPGB for guest nested translations\"))\n            o(c(ebx, 22, 1,           \"EBX    22: Reserved\"))\n            o(c(ebx, 23, 1,           \"EBX    23: PPIN (Protected Processor Inventory Number)\"))\n            o(c(ebx, 24, 1,           \"EBX    24: SSBD (Speculative Store Bypass Disable)\"))\n            o(c(ebx, 25, 1,           \"EBX    25: VIRT_SPEC_CTL\"))\n            o(c(ebx, 26, 1,           \"EBX    26: SSBD no longer needed\"))\n            o(c(ebx, 27, 1,           \"EBX    27: CPPC (Collaborative Processor Performance Control)\"))\n            o(c(ebx, 28, 1,           \"EBX    28: PSFD (Predictive Store Forward Disable)\"))\n            o(c(ebx, 29, 1,           \"EBX    29: Reserved\"))\n            o(c(ebx, 30, 1,           \"EBX    30: Reserved\"))\n            o(c(ebx, 31, 1,           \"EBX    31: Reserved\"))\n            o(\"ecx: Extended Core Information\")\n            o(c(ecx,  0, 0xff,        \"ECX  7- 0: Number of cores per (number of dies-1)\"))\n            o(c(ecx,  8, 0xf,         \"ECX 11- 8: Reserved\"))\n            o(c(ecx, 12, 0xf,         \"ECX 15-12: Number of LSBs in APIC ID that indicate core ID\"))\n            o(c(ecx, 16, 0xffff,      \"ECX 31-16: Reserved\"))\n        elif id == 0x8000_000a:\n            o(\"SVM Revision and Feature Identification\")\n            o(c(edx,  0, 1,           \"EDX     0: Nested paging\"))\n            o(c(edx,  1, 1,           \"EDX     1: LBR virtualization\"))\n            o(c(edx,  2, 1,           \"EDX     2: SVM lock\"))\n            o(c(edx,  3, 1,           \"EDX     3: NRIP save\"))\n            o(c(edx,  4, 1,           \"EDX     4: MSR-based TSC rate control\"))\n            o(c(edx,  5, 1,           \"EDX     5: VMCB clean bits\"))\n            o(c(edx,  6, 1,           \"EDX     6: Flush by ASID\"))\n            o(c(edx,  7, 1,           \"EDX     7: Decode assists\"))\n            o(c(edx,  8, 1,           \"EDX     8: Reserved\"))\n            o(c(edx,  9, 1,           \"EDX     9: Reserved\"))\n            o(c(edx, 10, 1,           \"EDX    10: Pause intercept filter\"))\n            o(c(edx, 11, 1,           \"EDX    11: Encrypted micro-code patch\"))\n            o(c(edx, 12, 1,           \"EDX    12: PAUSE filter threshold\"))\n            o(c(edx, 13, 1,           \"EDX    13: AMD virtual interrupt controller\"))\n            o(c(edx, 14, 1,           \"EDX    14: Reserved\"))\n            o(c(edx, 15, 1,           \"EDX    15: Virtualized VMLOAD/VMSAVE\"))\n            o(c(edx, 16, 1,           \"EDX    16: Virtualized GIF\"))\n            o(c(edx, 17, 1,           \"EDX    17: GMET (Guest Mode Execution Trap\"))\n            o(c(edx, 18, 1,           \"EDX    18: Reserved\"))\n            o(c(edx, 19, 1,           \"EDX    19: SVM supervisor shadow stack restrictions\"))\n            o(c(edx, 20, 1,           \"EDX    20: SPEC_CTRL virtualization\"))\n            o(c(edx, 21, 1,           \"EDX    21: Reserved\"))\n            o(c(edx, 22, 1,           \"EDX    22: Reserved\"))\n            o(c(edx, 23, 1,           \"EDX    23: Host MCE override\"))\n            o(c(edx, 24, 1,           \"EDX    24: INVLPGB/TLBSYNC hypervisor enable\"))\n            o(c(edx, 25, 0x7f,        \"EDX 31-25: Reserved\"))\n        elif id == 0x8000_0019:\n            o(\"TLB Configuration Descriptors\")\n        elif id == 0x8000_001a:\n            o(\"Performance Optimization Identifiers\")\n            o(c(eax,  0, 1,           \"EAX     0: FP128 (128-bit SSE full-width pipelines)\"))\n            o(c(eax,  1, 1,           \"EAX     1: MOVU (Efficient MOVU SSE instructions)\"))\n            o(c(eax,  2, 1,           \"EAX     2: FP256 (256-bit AVX full-width pipelines)\"))\n            o(c(eax,  3, 0x1fff_ffff, \"EAX 31- 3: Reserved\"))\n        elif id == 0x8000_001b:\n            o(\"Instruction Based Sampling Identifiers\")\n            o(c(eax,  0, 1,           \"EAX     0: IBSFFV (IBS Feature Flags Valid)\"))\n            o(c(eax,  1, 1,           \"EAX     1: FetchSam (IBS Fetch Sampling)\"))\n            o(c(eax,  2, 1,           \"EAX     2: OpSam (IBS Execution Sampling)\"))\n            o(c(eax,  3, 1,           \"EAX     3: RdWrOpCnt (Read/write of Op Counter)\"))\n            o(c(eax,  4, 1,           \"EAX     4: OpCnt (Op Counting mode)\"))\n            o(c(eax,  5, 1,           \"EAX     5: BrnTrgt (Branch Target address reporting)\"))\n            o(c(eax,  6, 1,           \"EAX     6: OpCntExt (IBS op cur/max count extended by 7 bits)\"))\n            o(c(eax,  7, 1,           \"EAX     7: RipInvalidChk (IBS RIP invalid indication)\"))\n            o(c(eax,  8, 1,           \"EAX     8: OpBrnFuse (IBS fused Branch micro-op indication)\"))\n            o(c(eax,  9, 1,           \"EAX     9: IbsFetchCtlExtd (IBS Fetch Control Extended MSR)\"))\n            o(c(eax, 10, 1,           \"EAX    10: IbsOpData4 (IBS Op Data 4 MSR)\"))\n            o(c(eax, 11, 0x1f_ffff,   \"EAX 31-11: Reserved\"))\n        elif id == 0x8fff_ffff:\n            vid = String.bytes2str(p32(eax) + p32(ebx) + p32(ecx) + p32(edx))\n            o(\"eax+ebx+ecx+edx: Easter egg (={!r})\".format(vid))\n        elif id == 0xc000_0000:\n            o(\"eax: Maximum Input Value for Extended Function CPUID Information\")\n            o(\"ebx,ecx,edx: Reserved\")\n        elif id == 0xc000_0001:\n            o(\"Centaur features\")\n            o(c(edx,  0, 1,           \"EDX     0: AIS (Alternate Instruction Set available)\"))\n            o(c(edx,  1, 1,           \"EDX     1: AIS_EN (Alternate Instruction Set ENabled)\"))\n            o(c(edx,  2, 1,           \"EDX     2: RNG (Random Number Generator available)\"))\n            o(c(edx,  3, 1,           \"EDX     3: RNG_EN (Random Number Generator ENabled)\"))\n            o(c(edx,  4, 1,           \"EDX     4: LH (LongHaul MSR 0000_110Ah)\"))\n            o(c(edx,  5, 1,           \"EDX     5: FEMMS\"))\n            o(c(edx,  6, 1,           \"EDX     6: ACE (Advanced Cryptography Engine available)\"))\n            o(c(edx,  7, 1,           \"EDX     7: ACE_EN (Advanced Cryptography Engine Enabled)\"))\n            o(c(edx,  8, 1,           \"EDX     8: ACE2 (Montgomery Multiplier and Hash Engine available)\"))\n            o(c(edx,  9, 1,           \"EDX     9: ACE2_EN (Montgomery Multiplier and Hash Engine Enabled)\"))\n            o(c(edx, 10, 1,           \"EDX    10: PHE (Padlock Hash Engine available)\"))\n            o(c(edx, 11, 1,           \"EDX    11: PHE_EN (Padlock Hash Engine ENabled)\"))\n            o(c(edx, 12, 1,           \"EDX    12: PMM (Padlock Montgomery Multiplier available)\"))\n            o(c(edx, 13, 1,           \"EDX    13: PMM_EN (Padlock Montgomery Multiplier ENabled)\"))\n            o(c(edx, 14, 0x3_ffff,    \"EAX 31-14: Reserved\"))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        self.out = []\n\n        # Basic Information\n        eax, _, _, _ = self.execute_cpuid(0)\n        valid_max_cpuid = min(eax, 0x20)\n\n        for id in range(valid_max_cpuid + 1):\n            if id == 4:\n                for subid in range(3):\n                    eax, ebx, ecx, edx = self.execute_cpuid(id, subid)\n                    self.make_out(id, subid, eax, ebx, ecx, edx)\n            elif id == 7:\n                eax, _, _, _ = self.execute_cpuid(id, 0)\n                for subid in range(eax + 1):\n                    eax, ebx, ecx, edx = self.execute_cpuid(id, subid)\n                    self.make_out(id, subid, eax, ebx, ecx, edx)\n            elif id == 13:\n                for subid in range(63):\n                    eax, ebx, ecx, edx = self.execute_cpuid(id, subid)\n                    self.make_out(id, subid, eax, ebx, ecx, edx)\n            elif id in [16, 18, 19, 20, 23, 24, 26, 31]:\n                eax, ebx, ecx, edx = self.execute_cpuid(id, 0)\n                self.make_out(id, 0, eax, ebx, ecx, edx)\n            else:\n                eax, ebx, ecx, edx = self.execute_cpuid(id)\n                self.make_out(id, None, eax, ebx, ecx, edx)\n\n        # Hypervisor Information\n        valid_max_cpuid, _, _, _ = self.execute_cpuid(0x4000_0000)\n        for id in range(0x4000_0000, valid_max_cpuid + 1):\n            eax, ebx, ecx, edx = self.execute_cpuid(id)\n            self.make_out(id, None, eax, ebx, ecx, edx)\n\n        # Extended Information\n        valid_max_cpuid, _, _, _ = self.execute_cpuid(0x8000_0000)\n        for id in range(0x8000_0000, valid_max_cpuid + 1):\n            eax, ebx, ecx, edx = self.execute_cpuid(id)\n            self.make_out(id, None, eax, ebx, ecx, edx)\n        for id in [0x8fff_ffff]:\n            eax, ebx, ecx, edx = self.execute_cpuid(id)\n            self.make_out(id, None, eax, ebx, ecx, edx)\n\n        # Transmeta Specific Information\n        valid_max_cpuid, _, _, _ = self.execute_cpuid(0x8086_0000)\n        for id in range(0x8086_0000, valid_max_cpuid + 1):\n            eax, ebx, ecx, edx = self.execute_cpuid(id)\n            self.make_out(id, None, eax, ebx, ecx, edx)\n\n        # Centaur(VIA) Specific Information\n        valid_max_cpuid, _, _, _ = self.execute_cpuid(0xc000_0000)\n        for id in range(0xc000_0000, valid_max_cpuid + 1):\n            eax, ebx, ecx, edx = self.execute_cpuid(id)\n            self.make_out(id, None, eax, ebx, ecx, edx)\n\n        self.print_output()\n        return\n\n\n@register_command\nclass MsrCommand(GenericCommand):\n    \"\"\"Read or write MSR value.\"\"\"\n\n    _cmdline_ = \"msr\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"msr_target\", metavar=\"MSR_NAME|MSR_CONST\", nargs=\"?\",\n                        help=\"the MSR name or constant to know the value.\")\n    parser.add_argument(\"msr_value\", metavar=\"MSR_VALUE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the MSR value to update.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}                   # show frequently used MSRs\",\n        \"{0:s} 0xc0000080        # read msr\",\n        \"{0:s} MSR_EFER          # another valid format\",\n        \"{0:s} 0xc0000080 0xd01  # write msr\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Disable`-enable-kvm` option for qemu-system.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    msr_table = [\n        # frequently used x86-64 MSRs\n        [\"MSR_EFER\",              0xc000_0080, \"Extended feature register\"],\n        [\"MSR_STAR\",              0xc000_0081, \"Legacy mode SYSCALL target\"],\n        [\"MSR_LSTAR\",             0xc000_0082, \"Long mode SYSCALL target\"],\n        [\"MSR_CSTAR\",             0xc000_0083, \"Compat mode SYSCALL target\"],\n        [\"MSR_SYSCALL_MASK\",      0xc000_0084, \"EFLAGS mask for syscall\"],\n        [\"MSR_FS_BASE\",           0xc000_0100, \"64bit FS base\"],\n        [\"MSR_GS_BASE\",           0xc000_0101, \"64bit GS base\"],\n        [\"MSR_KERNEL_GS_BASE\",    0xc000_0102, \"SwapGS GS shadow\"],\n        [\"MSR_TSC_AUX\",           0xc000_0103, \"Auxiliary TSC\"],\n        # x86-32 and x86-64\n        [\"MSR_IA32_SYSENTER_CS\",  0x0000_0174, \"Sysenter CS\"],\n        [\"MSR_IA32_SYSENTER_ESP\", 0x0000_0175, \"Sysenter ESP\"],\n        [\"MSR_IA32_SYSENTER_EIP\", 0x0000_0176, \"Sysenter EIP\"],\n        [\"MSR_IA32_U_CET\",        0x0000_06a0, \"User mode CET\"],\n        [\"MSR_IA32_S_CET\",        0x0000_06a2, \"Kernel mode CET\"],\n        [\"MSR_IA32_PL0_SSP\",      0x0000_06a4, \"Ring-0 shadow stack pointer\"],\n        [\"MSR_IA32_PL1_SSP\",      0x0000_06a5, \"Ring-1 shadow stack pointer\"],\n        [\"MSR_IA32_PL2_SSP\",      0x0000_06a6, \"Ring-2 shadow stack pointer\"],\n        [\"MSR_IA32_PL3_SSP\",      0x0000_06a7, \"Ring-3 shadow stack pointer\"],\n        [\"MSR_IA32_INT_SSP_TAB\",  0x0000_06a8, \"Exception shadow stack table\"],\n    ]\n\n    def lookup_name2const(self, target_name):\n        for name, const, _desc in self.msr_table:\n            if name == target_name:\n                return const\n        try:\n            return int(target_name, 0)\n        except ValueError:\n            return None\n\n    def lookup_const2name(self, target_const):\n        for name, const, _desc in self.msr_table:\n            if const == target_const:\n                return name\n        return \"Unknown\"\n\n    def print_const_table(self):\n        gef_print(titlify(\"MSR table (frequently used only)\"))\n        fmt = \"{:30s}  {:10s}  {:30s}  {:s}\"\n        legend = [\"Name\", \"Const\", \"Description\", \"Value\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        for name, const, desc in self.msr_table:\n            value = MsrCommand.read_msr(const)\n            if value is None:\n                gef_print(\"{:30s}  {:#010x}  {:30s}  {!s}\".format(\n                    name, const, desc, None,\n                ))\n                continue\n\n            sym = \"\"\n            if is_valid_addr(value):\n                sym = Symbol.get_symbol_string(value)\n\n            gef_print(\"{:30s}  {:#010x}  {:30s}  {:s}{:s}\".format(\n                name, const, desc, AddressUtil.format_address(value), sym,\n            ))\n\n        info(\"See more info: https://elixir.bootlin.com/linux/latest/source/arch/x86/include/asm/msr-index.h\")\n        return\n\n    @staticmethod\n    def read_msr(const):\n        codes = [b\"\\x0f\\x32\"] # rdmsr\n        if is_x86_64():\n            regs = {\"$rcx\": const}\n        else:\n            regs = {\"$ecx\": const}\n        ret = ExecAsm(codes, regs=regs).exec_code()\n\n        if ret is None:\n            return None\n\n        if is_x86_64():\n            edx = ret[\"reg\"][\"$rdx\"] & 0xffff_ffff\n            eax = ret[\"reg\"][\"$rax\"] & 0xffff_ffff\n        else:\n            edx = ret[\"reg\"][\"$edx\"]\n            eax = ret[\"reg\"][\"$eax\"]\n        return ((edx << 32) | eax) & 0xffff_ffff_ffff_ffff\n\n    @staticmethod\n    def write_msr(const, value):\n        codes = [b\"\\x0f\\x30\"] # wrmsr\n        if is_x86_64():\n            regs = {\"$rcx\": const, \"$rdx\": value >> 32, \"$rax\": value & 0xffff_ffff}\n        else:\n            regs = {\"$ecx\": const, \"$edx\": value >> 32, \"$eax\": value & 0xffff_ffff}\n        ret = ExecAsm(codes, regs=regs).exec_code()\n        return bool(ret)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @only_if_in_kernel\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        # list\n        if args.msr_target is None and args.msr_value is None:\n            self.print_const_table()\n            return\n\n        # search for const table\n        const = self.lookup_name2const(args.msr_target)\n        if const is None:\n            self.usage()\n            return\n\n        if args.msr_value is None:\n            # exec rdmsr\n            value = MsrCommand.read_msr(const)\n            if value is None:\n                err(\"Failed to read\")\n                return\n            name = self.lookup_const2name(const)\n            if args.quiet:\n                gef_print(\"{:s}\".format(AddressUtil.format_address(value)))\n            else:\n                gef_print(\"{:s} ({:#x}): {:s}\".format(name, const, AddressUtil.format_address(value)))\n\n        else:\n            # exec wrmsr\n            ret = MsrCommand.write_msr(const, args.msr_value)\n            if ret:\n                info(\"Success to write\")\n            else:\n                err(\"Failed to write\")\n        return\n\n\n@register_command\nclass CetCommand(GenericCommand):\n    \"\"\"Display Intel CET settings.\"\"\"\n\n    _cmdline_ = \"cet\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    U_S_COMMON_BITS = {\n        \"SH_STK_EN\": 0,    # Shadow Stack enable\n        \"WR_SHSTK_EN\": 1,  # WRSS{D,Q}W enable\n        \"ENDBR_EN\": 2,     # IBT enable\n        \"LEG_IW_EN\": 3,    # Legacy indirect-write compat\n        \"NO_TRACK_EN\": 4,  # No-track prefix enable\n        \"SUPPRESS_DIS\": 5, # Suppress disable\n        # 6..9 reserved\n        \"SUPPRESS\": 10,    # IBT suppression state\n        \"TRACKER\": 11,     # TRACKER state bit-field (0:IDLE, 1:WAIT_FOR_ENDBRANCH)\n        # 12..63 EB_LEG_BITMAP_BASE (bitmap base, <<12)\n    }\n\n    TRACKER_STATES = {0: \"IDLE\", 1: \"WAIT_FOR_ENDBRANCH\"}\n\n    def decode_cet_bits(self, val):\n        if val is None:\n            return None\n        d = {}\n        for name, bit in self.U_S_COMMON_BITS.items():\n            d[name] = (val >> bit) & 1\n        tracker = (val >> 11) & 0x1\n        d[\"TRACKER\"] = \"{:d} ({:s})\".format(d[\"TRACKER\"], self.TRACKER_STATES[tracker])\n        d[\"EB_LEG_BITMAP_BASE\"] = AddressUtil.format_address(val & ~0xfff)\n        return d\n\n    def print_cet_bits(self, title, d):\n        gef_print(titlify(title))\n        for k, v in d.items():\n            if k in [\"TRACKER\", \"EB_LEG_BITMAP_BASE\"]:\n                gef_print(\"{:20s} : {:s}\".format(k, v))\n            else:\n                gef_print(\"{:20s} : {:x}\".format(k, v))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @only_if_in_kernel\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        cr4 = get_register(\"cr4\", use_monitor=True)\n        gef_print(titlify(\"CET summary\"))\n        if cr4 is not None:\n            cet_master = (cr4 >> 23) & 1\n            gef_print(\"CR4 = {:#x} (CR4.CET = {:#x})\".format(cr4, cet_master))\n        else:\n            gef_print(\"CR4 = N/A\")\n\n        IA32_U_CET = MsrCommand.read_msr(0x6a0)\n        ud = self.decode_cet_bits(IA32_U_CET)\n        if ud is not None:\n            self.print_cet_bits(\"IA32_U_CET ({:#x})\".format(IA32_U_CET), ud)\n        else:\n            gef_print(\"IA_32_U_CET = N/A\")\n\n        IA32_S_CET = MsrCommand.read_msr(0x6a2)\n        sd = self.decode_cet_bits(IA32_S_CET)\n        if sd is not None:\n            self.print_cet_bits(\"IA32_S_CET ({:#x})\".format(IA32_S_CET), ud)\n        else:\n            gef_print(\"IA_32_U_CET = N/A\")\n\n        IA32_PL0_SSP = MsrCommand.read_msr(0x6a4)\n        IA32_PL1_SSP = MsrCommand.read_msr(0x6a5)\n        IA32_PL2_SSP = MsrCommand.read_msr(0x6a6)\n        IA32_PL3_SSP = MsrCommand.read_msr(0x6a7)\n        IA32_INT_SSP_TAB = MsrCommand.read_msr(0x6a8)\n        gef_print(titlify(\"SSP MSRs\"))\n        gef_print(\"PL0_SSP = {:s}\".format(AddressUtil.format_address(IA32_PL0_SSP)))\n        gef_print(\"PL1_SSP = {:s}\".format(AddressUtil.format_address(IA32_PL1_SSP)))\n        gef_print(\"PL2_SSP = {:s}\".format(AddressUtil.format_address(IA32_PL2_SSP)))\n        gef_print(\"PL3_SSP = {:s}\".format(AddressUtil.format_address(IA32_PL3_SSP)))\n        gef_print(\"IA32_INTERRUPT_SSP_TABLE_ADDR = {:s}\".format(AddressUtil.format_address(IA32_INT_SSP_TAB)))\n        return\n\n\n@register_command\nclass MteTagsCommand(GenericCommand):\n    \"\"\"Display the MTE tag for the specified address (ARM64 only).\"\"\"\n\n    _cmdline_ = \"mte-tags\"\n    _category_ = \"02-f. Process Information - Security\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the start address to display the MTE tag.\")\n    parser.add_argument(\"count\", metavar=\"COUNT\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"repeat count for MTE tag displaying (every 16 bytes).\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"rr\",))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        auxv = Auxv.get_auxiliary_values()\n        HWCAP2_MTE = 1 << 18\n        if auxv and \"AT_HWCAP2\" in auxv and (auxv[\"AT_HWCAP2\"] & HWCAP2_MTE) == 0:\n            err(\"MTE is unsupported\")\n            return\n\n        codes = [b\"\\x00\\x00\\x60\\xD9\"] # ldg x0, [x0]\n        count = args.count or 1\n        for i in range(count):\n            address = args.address + 16 * i\n            if not is_valid_addr(address):\n                break\n            ret = ExecAsm(codes, regs={\"$x0\": address}).exec_code()\n            tag = (ret[\"reg\"][\"$x0\"] >> 56) & 0xff\n            gef_print(\"{!s}: {:#04x} ({:#018x})\".format(ProcessMap.lookup_address(address), tag, tag << 56))\n        return\n\n\n@register_command\nclass PacKeysCommand(GenericCommand):\n    \"\"\"Pretty-print PAC keys from qemu registers (ARM64 only).\"\"\"\n\n    _cmdline_ = \"pac-keys\"\n    _category_ = \"04-a. Register - View\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        for keyname in [\"APIA\", \"APIB\", \"APDA\", \"APDB\", \"APGA\"]:\n            try:\n                lo = get_register(\"{:s}KEYLO_EL1\".format(keyname))\n                hi = get_register(\"{:s}KEYHI_EL1\".format(keyname))\n                bs = \" \".join(slicer(p64(lo).hex() + p64(hi).hex(), 2))\n                gef_print(\"{:s}KEY: {:#018x} {:#018x} ({:s})\".format(keyname, hi, lo, bs))\n            except Exception:\n                err(\"Failed to get the value of PAC keys\")\n                break\n        return\n\n\n@register_command\nclass VBARCommand(GenericCommand, BufferingOutput):\n    \"\"\"Pretty-print ARM/ARM64 vector table.\"\"\"\n\n    _cmdline_ = \"vbar\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--address\", type=AddressUtil.parse_address, help=\"the vector address.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"display all instructions (for ARM64).\")\n    _syntax_ = parser.format_help()\n\n    A32_VECTOR_NAMES = [\n        (0x00, 0x04, \"Reset\"),\n        (0x04, 0x04, \"Undefined Instruction\"),\n        (0x08, 0x04, \"Supervisor Call\"),\n        (0x0c, 0x04, \"Prefetch Abort\"),\n        (0x10, 0x04, \"Data Abort\"),\n        (0x14, 0x04, \"Reserved\"),\n        (0x18, 0x04, \"IRQ Interrupt\"),\n        (0x1c, 0x04, \"FIQ Interrupt\"),\n    ]\n\n    A64_VECTOR_NAMES = [\n        (0x000, 0x80, \"Current EL (SP0)   - Synchronous\"),\n        (0x080, 0x80, \"Current EL (SP0)   - IRQ/vIRQ\"),\n        (0x100, 0x80, \"Current EL (SP0)   - FIQ/vFIQ\"),\n        (0x180, 0x80, \"Current EL (SP0)   - SError/vSError\"),\n        (0x200, 0x80, \"Current EL (SPx)   - Synchronous\"),\n        (0x280, 0x80, \"Current EL (SPx)   - IRQ/vIRQ\"),\n        (0x300, 0x80, \"Current EL (SPx)   - FIQ/vFIQ\"),\n        (0x380, 0x80, \"Current EL (SPx)   - SError/vSError\"),\n        (0x400, 0x80, \"Lower EL (AArch64) - Synchronous\"),\n        (0x480, 0x80, \"Lower EL (AArch64) - IRQ/vIRQ\"),\n        (0x500, 0x80, \"Lower EL (AArch64) - FIQ/vFIQ\"),\n        (0x580, 0x80, \"Lower EL (AArch64) - SError/vSError\"),\n        (0x600, 0x80, \"Lower EL (AArch32) - Synchronous\"),\n        (0x680, 0x80, \"Lower EL (AArch32) - IRQ/vIRQ\"),\n        (0x700, 0x80, \"Lower EL (AArch32) - FIQ/vFIQ\"),\n        (0x780, 0x80, \"Lower EL (AArch32) - SError/vSError\"),\n    ]\n\n    def get_vbar_arm32(self):\n        if self.args.address is not None:\n            vbars = [(\"User specified\", self.args.address)]\n            return vbars\n\n        vbars = []\n\n        # VBAR\n        sctlr = get_register(\"$SCTLR\") or get_register(\"$SCTLR_EL1\")\n        if (sctlr >> 13) & 1:\n            vbars.append((\"$VBAR ($SCTLR.V==1)\", 0xffff_0000)) # default\n        else:\n            vbar = get_register(\"$VBAR\") or get_register(\"$VBAR_EL1\")\n            vbars.append((\"$VBAR ($SCTLR.V==0)\", vbar))\n\n        # VBAR_S\n        sctlr_s = get_register(\"$SCTLR_S\") or get_register(\"$SCTLR_EL1_S\")\n        if sctlr_s is not None:\n            if (sctlr_s >> 13) & 1:\n                vbars.append((\"$VBAR_S ($SCTLR_S.V==1)\", 0xffff_0000)) # default\n            else:\n                vbar = get_register(\"$VBAR_S\") or get_register(\"$VBAR_EL1_S\")\n                vbars.append((\"$VBAR_S ($SCTLR_S.V==0)\", vbar))\n        return vbars\n\n    def dump_vbar_arm32(self):\n        vbars = self.get_vbar_arm32()\n        max_width = max(len(x[2]) for x in self.A32_VECTOR_NAMES)\n\n        for regname, vbar in vbars:\n            self.out.append(titlify(regname))\n\n            # address check\n            if \"$VBAR_S\" in regname and not is_in_secure():\n                vbar_phys = XSecureMemAddrCommand.v2p_secure(vbar)\n                if vbar_phys is None:\n                    self.err_add_out(\"Invalid VBAR address: {:#x}\".format(vbar))\n                    continue\n            else:\n                if not is_valid_addr(vbar):\n                    if vbar is None:\n                        self.err_add_out(\"Invalid VBAR address: None\")\n                    else:\n                        self.err_add_out(\"Invalid VBAR address: {:#x}\".format(vbar))\n                    continue\n\n            # read each entry\n            for ofs, _sz, s in self.A32_VECTOR_NAMES:\n                s = Color.colorify(s.ljust(max_width), \"bold\")\n                if \"$VBAR_S\" in regname and not is_in_secure():\n                    try:\n                        code = read_physmem(vbar_phys + ofs, 4)\n                    except gdb.MemoryError:\n                        self.out.append(\"[{:+#05x}] {:s}: {:s}\".format(ofs, s, \"Memory access error\"))\n                        continue\n                    try:\n                        insn_str = gdb.execute(\"pdisas {:#x} code={:s} -l 1\".format(vbar + ofs, code.hex()), to_string=True)\n                        insn_str = insn_str.replace(\"            \", \"\")\n                    except gdb.error:\n                        self.out.append(\"[{:+#05x}] {:s}: {:s}\".format(ofs, s, \"Capstone not found\"))\n                        continue\n                else:\n                    try:\n                        insn = get_insn(vbar + ofs)\n                    except gdb.MemoryError:\n                        self.out.append(\"[{:+#05x}] {:s}: {:s}\".format(ofs, s, \"Memory access error\"))\n                        continue\n                    insn_str = insn.colored_text(4)\n                self.out.append(\"[{:+#05x}] {:s}: {:s}\".format(ofs, s, insn_str.strip()))\n        return\n\n    def get_vbar_arm64(self):\n        if self.args.address is not None:\n            vbars = [(\"User specified\", self.args.address)]\n            return vbars\n\n        vbars = []\n\n        # VBAR\n        vbar = get_register(\"$VBAR\") or get_register(\"$VBAR_EL1\")\n        vbars.append((\"$VBAR\", vbar))\n\n        # VBAR_EL2\n        vbar = get_register(\"$VBAR_EL2\")\n        vbars.append((\"$VBAR_EL2\", vbar))\n\n        # VBAR_EL3\n        vbar = get_register(\"$VBAR_EL3\")\n        vbars.append((\"$VBAR_EL3\", vbar))\n        return vbars\n\n    def dump_vbar_arm64(self):\n        vbars = self.get_vbar_arm64()\n        max_width = max(len(x[2]) for x in self.A64_VECTOR_NAMES)\n\n        def get_EL():\n            CPSR = get_register(\"$cpsr\") & 0xffff_ffff\n            return (CPSR >> 2) & 0b11\n\n        base_EL = get_EL()\n\n        for regname, vbar in vbars:\n            self.out.append(titlify(regname))\n\n            # switch EL\n            if regname == \"$VBAR\" and base_EL != 1:\n                gdb.execute(\"switch-el 1\", to_string=True)\n            elif regname == \"$VBAR_EL2\" and base_EL != 2:\n                gdb.execute(\"switch-el 2\", to_string=True)\n            elif regname == \"$VBAR_EL3\" and base_EL != 3:\n                gdb.execute(\"switch-el 3\", to_string=True)\n            else:\n                gdb.execute(\"switch-el {:d}\".format(base_EL), to_string=True)\n\n            # address check\n            if not is_valid_addr(vbar):\n                if vbar is None:\n                    self.err_add_out(\"Invalid VBAR address: None\")\n                else:\n                    self.err_add_out(\"Invalid VBAR address: {:#x}\".format(vbar))\n                continue\n\n            # read each entry\n            for ofs, sz, s in self.A64_VECTOR_NAMES:\n                if self.args.verbose:\n                    # full\n                    pos = 0\n                    while pos < sz:\n                        insn = get_insn(vbar + ofs + pos)\n                        insn_str = insn.colored_text(4)\n                        if pos == 0:\n                            s = Color.colorify(s.ljust(max_width), \"bold\")\n                            self.out.append(\"[{:+#06x}] {:s}: {:s}\".format(ofs, s, insn_str))\n                        else:\n                            s = \" \" * max_width\n                            self.out.append(\"{:8s} {:s}: {:s}\".format(\"\", s, insn_str))\n                        pos += insn.size\n                else:\n                    # compact\n                    insn = get_insn(vbar + ofs)\n                    insn_str = insn.colored_text(4)\n                    s = Color.colorify(s.ljust(max_width), \"bold\")\n                    self.out.append(\"[{:+#06x}] {:s}: {:s}\".format(ofs, s, insn_str))\n\n        # revert\n        gdb.execute(\"switch-el {:d}\".format(base_EL), to_string=True)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.out = []\n        if is_arm32():\n            self.dump_vbar_arm32()\n        elif is_arm64():\n            self.dump_vbar_arm64()\n        self.print_output(check_terminal_size=True)\n        return\n\n\nclass BitInfo:\n    \"\"\"Printing various bit information of the register.\"\"\"\n\n    def __init__(self, name, register_bit=None, bit_info=(), desc=None):\n        self.name = name\n        if register_bit is None:\n            self.register_bit = current_arch.ptrsize * 8\n        else:\n            self.register_bit = register_bit\n        self.description = desc\n\n        # bit_info: [[bits, short_name, short_description, long_description], ...]\n        self.bit_info = bit_info\n        return\n\n    @staticmethod\n    def bits_split(x, bits):\n        # split by 4bits. e.g., 0bXXYYYY -> 0b00XX_YYYY\n        out = \"\"\n        for i in range(bits):\n            if x & (1 << i):\n                out = \"1\" + out\n            else:\n                out = \"0\" + out\n            if i % 4 == 3:\n                out = \"_\" + out\n        return \"0b\" + out[1:]\n\n    def print_value(self, regval, split=False):\n        regname = Color.colorify(self.name, \"bold red\")\n        value_str = Color.colorify_hex(regval, \"bold yellow\")\n        if split:\n            bit_split_str = BitInfo.bits_split(regval, self.register_bit)\n            value_str += Color.colorify(\" (={:s})\".format(bit_split_str), \"bold yellow\")\n        self.out.append(\"{:s} = {:s}\".format(regname, value_str))\n        return\n\n    def print_description(self):\n        if self.description:\n            self.out.append(Color.boldify(self.description))\n        return\n\n    def print_bitinfo(self, regval):\n        # preprocess\n        max_width_bits = 2 # default\n        max_width_sym = 0\n        max_width_val = 0\n        bit_range_strs = []\n        bit_values = []\n        for bits, sym, *_ in self.bit_info:\n            if isinstance(bits, range):\n                bits = list(bits)\n\n            # search for max width for bit_ragne_string\n            if isinstance(bits, int):\n                b = \"{:d}\".format(bits)\n                bit_range_strs.append(b)\n            else:\n                # e.g., [11, 12, 0, 1, 2, 10] -> [0, 1, 2, 10, 11, 12]\n                bits = sorted(bits)\n                # e.g., [0, 1, 2, 10, 11, 12] -> [[0, 1, 2], [10, 11, 12]]\n                gen = itertools.groupby(bits, key=lambda n, c=itertools.count(): n - next(c)) # noqa: B008\n                gr_bits = [list(g) for _, g in gen]\n\n                tmp = []\n                for gb in gr_bits:\n                    if len(gb) == 1:\n                        tmp.append(\"{:d}\".format(gb[0]))\n                    else:\n                        tmp.append(\"{:d}-{:d}\".format(gb[-1], gb[0]))\n                bit_str = \",\".join(tmp[::-1])\n                bit_range_strs.append(bit_str)\n                max_width_bits = max(max_width_bits, len(bit_str))\n\n            # search for max width for sym\n            if sym:\n                max_width_sym = max(max_width_sym, len(sym))\n\n            # search for max width for val\n            if isinstance(bits, int):\n                val = (regval & (1 << bits)) >> bits\n                bit_values.append(val)\n            else:\n                val = 0\n                for i, x in enumerate(bits):\n                    val |= (regval & (1 << x)) >> (x - i)\n                bit_values.append(val)\n            max_width_val = max(max_width_val, len(\"{:#x}\".format(val)))\n\n        # here, preprocess is finieshed.\n        # - max_width_bits\n        # - max_width_sym\n        # - max_width_val\n        # - bit_range_strs # e.g., [\"0\", \"4-1\", \"8-7,5\"]\n        # - bit_values     # e.g., [0b1, 0b1111, 0b1101]\n\n        # actual perform\n        for i, (_, sym, *desc) in enumerate(self.bit_info):\n            b = bit_range_strs[i]\n            val = bit_values[i]\n\n            msg = \"bit{:>{:d}s}: \".format(b, max_width_bits)\n\n            if val:\n                msg += Color.boldify(\"{:>#{:d}x} \".format(val, max_width_val))\n            else:\n                msg += \"{:>#{:d}x} \".format(val, max_width_val)\n\n            if sym is not None:\n                msg += \"{:{:d}s}  \".format(sym, max_width_sym)\n\n            if len(desc) == 1:\n                # short description only\n                if desc[0]:\n                    msg += desc[0]\n\n            elif len(desc) >= 2:\n                # short description and long description\n                if desc[0]:\n                    msg += desc[0] + \"; \"\n                msg += \"; \".join(desc[1:])\n\n            self.out.append(msg)\n        return\n\n    def make_out(self, regval, split=False):\n        self.out = []\n        self.print_value(regval, split)\n        self.print_description()\n        self.print_bitinfo(regval)\n        return self.out\n\n    def print(self, regval, split=False):\n        self.make_out(regval, split)\n        if self.out:\n            gef_print(\"\\n\".join(self.out))\n        return\n\n\n@register_command\nclass QemuRegistersCommand(GenericCommand, BufferingOutput):\n    \"\"\"Get registers via qemu-monitor and show the detail of x64/x86 system registers.\"\"\"\n\n    _cmdline_ = \"qreg\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"also display detailed bit information.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def qregisters_x86_x64(self):\n        red = lambda x: Color.colorify(x, \"bold red\")\n        yellow = lambda x: Color.colorify(x, \"bold yellow\")\n\n        # CR0\n        self.out.append(titlify(\"CR0 (Control Register 0)\"))\n        desc = \"It contains system control flags that control operating mode and states of the processor\"\n        bit_info = [\n            [31, \"PG\", \"Paging\",\n             \"If 1, enable paging and use CR3 register, else disable paging\"],\n            [30, \"CD\", \"Cache disable\",\n             \"If 1, disable the memory cache globally\"],\n            [29, \"NW\", \"Not-write through\",\n             \"If 1, disable write-through caching globally\"],\n            [18, \"AM\", \"Alignment mask\",\n             \"If 1, alignment check enabled when EFLAGS.AC==1 and Ring-3\"],\n            [16, \"WP\", \"Write protect\",\n             \"If 1, the CPU can't write to read-only pages when Ring-0\"],\n            [5, \"NE\", \"Numeric error\",\n             \"If 1, enable internal x87 FPU error reporting, else enable PC style x87 error detection\"],\n            [4, \"ET\", \"Extension type\",\n             \"x64: always 1. i386: if 1, x87 DX math coprosessor instructions is supported\"],\n            [3, \"TS\", \"Task switched\",\n             \"If 1, allow the saving x87 task context upon a task switch only after x87 instruction used\"],\n            [2, \"EM\", \"Emulation\",\n             \"If 1, no x87 FPU present, else x87 FPU present\"],\n            [1, \"MP\", \"Monitor co-processor\",\n             \"If 1, WAIT/FWAIT instructions generate #NM exception when CR0.TS\"],\n            [0, \"PE\", \"Protected mode enable\",\n             \"If 1, system is in protected mode, else system is in real mode\"],\n        ]\n        cr0 = get_register(\"cr0\", use_monitor=True)\n        self.out.extend(BitInfo(\"CR0\", 32, bit_info, desc).make_out(cr0))\n\n        # CR1\n        self.out.append(titlify(\"CR1 (Control Register 1)\"))\n        self.out.append(\"Reserved\")\n\n        # CR2\n        self.out.append(titlify(\"CR2 (Control Register 2)\"))\n        desc = \"When page fault, the address attempted to access is stored (PFLA: Page Fault Linear Address)\"\n        cr2 = get_register(\"cr2\", use_monitor=True)\n        self.out.extend(BitInfo(\"CR2\", desc=desc).make_out(cr2))\n\n        # CR3\n        self.out.append(titlify(\"CR3 (Control Register 3)\"))\n        desc = \"It contains the physical address of the base of the paging-structure hierarchy and two flags\"\n        bit_info = [\n            [62, \"LAM_U48\", \"User LAM48 enable\",\n             \"If 1 and CR3.LAM_U57 is 0, enables LAM48 (masking of linear-address bits 62:48) for user pointers\"],\n            [61, \"LAM_U57\", \"User LAM57 enable\",\n            \"If 1, enables LAM57 (masking of linear-address bits 62:57) for user pointers; overrides CR3.LAM_U48\"],\n            [range(12, 32), None, None,\n             \"Base of page directory base, typically it points to PML4T if 4-level paging\"],\n            [range(0, 12), None, None,\n             \"Process context identifier when CR4.PCIDE=1\"],\n            [4, \"PCD\", \"Page-level Cache Disable\",\n             \"If 1, disable Page-Directory itself caching when CR4.PCIDE=0\"],\n            [3, \"PWT\", \"Page-level Write-Through\",\n             \"If 1, enable write through Page-Directory itself caching when CR4.PCIDE=0\"],\n        ]\n        cr3 = get_register(\"cr3\", use_monitor=True)\n        self.out.extend(BitInfo(\"CR3\", bit_info=bit_info, desc=desc).make_out(cr3))\n\n        # CR4\n        self.out.append(titlify(\"CR4 (Control Register 4)\"))\n        desc = \"It contains flags that architectural extensions, indicate OS or executive support\"\n        bit_info = [\n            [28, \"LAM_SUP\", \"Supervisor LAM enable\",\n             \"If 1, enables LAM for supervisor pointers (kernel addresses)\"],\n            [27, \"LASS\", \"Linear-address-space Separation\",\n             \"If 1, enables LASS (linear-address-space separation)\"],\n            [25, \"UINTR\", \"Enable user-mode inter-processor interrupts\",\n             \"If 1, enable User-Interrupt Delivery\"],\n            [24, \"PKS\", \"Enable protection keys for supervisor-mode pages\",\n             \"If 1, enable PKS\"],\n            [23, \"CET\", \"Control-flow Enforcement Technology\",\n             \"If 1, enable CET\"],\n            [22, \"PKE\", \"Protection Key Enable\",\n             \"If 1, enable PKE\"],\n            [21, \"SMAP\", \"Supervisor Mode Access Protection Enable\",\n             \"If 1, access of data in a higher ring generates a fault\"],\n            [20, \"SMEP\", \"Supervisor Mode Execution Protection Enable\",\n             \"If 1, execution of code in a higher ring generates a fault\"],\n            [19, \"KL\", \"Key-Locker Enable\",\n             \"If 1, enable LOADIWKEY\"],\n            [18, \"OSXSAVE\", \"Enable XSAVE and Processor Extended States\",\n             \"If 1, enable XSAVE/XSAVEC/XSAVEOPT/XSAVES/XRSTOR/XRSTORS/XSETBV/XGETBV\"],\n            [17, \"PCIDE\", \"PCID Enable\",\n             \"If 1, enable process-context identifiers (PCIDs)\"],\n            [16, \"FSGSBASE\", \"FSGSBASE Enable\",\n             \"If 1, enable RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE\"],\n            [14, \"SMXE\", \"Safer Mode Extensions Enable\",\n             \"If 1, enable Trusted Execution Technology (TXT)\"],\n            [13, \"VMXE\", \"Virtual Machine Extensions Enable\",\n             \"If 1, enable Intel VT-x x86 virtualization\"],\n            [12, \"LA57\", \"57bit linear addresses\",\n             \"If 1, enable 5-Level Paging\"],\n            [11, \"UMIP\", \"User-Mode Instruction Prevention\",\n             \"If 1, SGDT/SIDT/SLDT/SMSW/STR instructions can only be executed in ring0\"],\n            [10, \"OSXMMEXCPT\", \"OS support for Unmasked SIMD FP Exceptions\",\n             \"If 1, enable unmasked SSE exceptions\"],\n            [9, \"OSFXSR\", \"OS support for FXSAVE/FXRSTOR\",\n             \"If 1, enable SSE instructions and fast FPU save & restore\"],\n            [8, \"PCE\", \"Performance-Monitoring Counter enable\",\n             \"If 1, RDPMC instruction can be executed at any privilege level\"],\n            [7, \"PGE\", \"Page Global Enabled\",\n             \"If 1, address translations (PDE or PTE records) may be shared between address spaces\"],\n            [6, \"MCE\", \"Machine Check Exception\",\n             \"If 1, enable machine check interrupts to occur\"],\n            [5, \"PAE\", \"Physical Address Extension\",\n             \"If 1, changes page table layout to translate 32bit virtaddr into 36bit physaddr\"],\n            [4, \"PSE\", \"Page Size Extension\",\n             \"If 1, page size is 4MB, else 4KB, this bit is ignored when PAE or x86-64 long mode\"],\n            [3, \"DE\", \"Debugging Extensions\",\n             \"If 1, enable debug register based breaks on I/O space access\"],\n            [2, \"TSD\", \"Time Stamp Disable\",\n             \"If 1, RDTSC instruction can only be executed in ring0\"],\n            [1, \"PVI\", \"Protected-mode Virtual Interrupts\",\n             \"If 1, enable support for the virtual interrupt flag (VIF) in protected mode\"],\n            [0, \"VME\", \"Virtual 8086 Mode Extensions\",\n             \"If 1, enable support for the virtual interrupt flag (VIF) in virtual-8086 mode\"],\n        ]\n        cr4 = get_register(\"cr4\", use_monitor=True)\n        self.out.extend(BitInfo(\"CR4\", bit_info=bit_info, desc=desc).make_out(cr4))\n\n        # CR8\n        self.out.append(titlify(\"CR8 (Control Register 8)\"))\n        desc = \"Contain task priority level\"\n        bit_info = [\n            [range(0, 4), \"TPL\", \"Task Priority Class\"],\n        ]\n        cr8 = get_register(\"cr8\", use_monitor=True)\n        if cr8 is not None: # only access x86 64-bit mode\n            self.out.extend(BitInfo(\"CR8\", bit_info=bit_info, desc=desc).make_out(cr8))\n\n        # XCR0\n        # QEMU's monitor does not currently support displaying XCR0. Therefore, this code will not be executed.\n        self.out.append(titlify(\"XCR0 (Extended Control Register 0)\"))\n        desc = \"Contain task priority level\"\n        bit_info = [\n            [19, \"APX\", \"Intel APX\",\n             \"Enables Intel APX; EGPR (R16-R31) state is managed via XSAVE\"],\n            [18, \"AMX_TILEDATA\", \"Intel AMX tile data\",\n             \"Enables XSAVE-managed AMX tile data state (requires XCR0[18:17]=0b11 for AMX instructions)\"],\n            [17, \"AMX_TILECFG\", \"Intel AMX tile config\",\n             \"Enables XSAVE-managed AMX tile config state (requires XCR0[18:17]=0b11 for AMX instructions)\"],\n            [9, \"PKRU\", \"Protection Keys\",\n             \"Enables XSAVE-managed PKRU state\"],\n            [7, \"HI16_ZMM\", \"AVX-512 ZMM16-31\",\n             \"Enables XSAVE-managed upper ZMM registers ZMM16-ZMM31\"],\n            [6, \"ZMM_HI256\", \"AVX-512 upper halves\",\n             \"Enables XSAVE-managed upper 256 bits of ZMM0-ZMM15\"],\n            [5, \"OPMASK\", \"AVX-512 opmask\",\n             \"Enables XSAVE-managed opmask registers k0-k7\"],\n            [4, \"BNDCSR\", \"MPX bounds config/status\",\n             \"Enables XSAVE-managed BNDCFGU and BNDSTATUS (MPX)\"],\n            [3, \"BNDREG\", \"MPX bounds registers\",\n             \"Enables XSAVE-managed BND0-BND3 registers (MPX)\"],\n            [2, \"AVX\", \"AVX YMM state\",\n             \"Enables XSAVE-managed YMM state (requires SSE enabled)\"],\n            [1, \"SSE\", \"SSE XMM/MXCSR state\",\n             \"Enables XSAVE-managed XMM registers and MXCSR\"],\n            [0, \"X87\", \"x87 FPU/MMX state\",\n             \"x87 FPU/MMX state (architecturally required)\"],\n        ]\n        xcr0 = get_register(\"xcr0\", use_monitor=True)\n        if xcr0 is not None:\n            self.out.extend(BitInfo(\"XCR0\", bit_info=bit_info, desc=desc).make_out(xcr0))\n\n        # DR0-DR3\n        self.out.append(titlify(\"DR0-DR3 (Debug Address Register 0-3)\"))\n        desc = \"Contain linear addresses of up to 4 HW breakpoints. If paging is enabled, they are translated to physical addresses\"\n        dr0 = get_register(\"dr0\", use_monitor=True)\n        dr1 = get_register(\"dr1\", use_monitor=True)\n        dr2 = get_register(\"dr2\", use_monitor=True)\n        dr3 = get_register(\"dr3\", use_monitor=True)\n        self.out.extend(BitInfo(\"DR0\").make_out(dr0))\n        self.out.extend(BitInfo(\"DR1\").make_out(dr1))\n        self.out.extend(BitInfo(\"DR2\").make_out(dr2))\n        self.out.extend(BitInfo(\"DR3\", desc=desc).make_out(dr3))\n\n        # DR4-DR5\n        self.out.append(titlify(\"DR4-DR5 (Debug Register 4-5)\"))\n        self.out.append(\"Reserved\")\n\n        # DR6\n        self.out.append(titlify(\"DR6 (Debug Status Register 6)\"))\n        desc = \"It permits the debugger to determine which debug conditions have occurred\"\n        bit_info = [\n            [16, \"RTM\", \"restricted transactional memory\",\n             \"If 0, the debug exception or breakpoint exception occurred inside an RTM region\"],\n            [15, \"BT\", \"task switch\",\n             \"If 1, the debug instruction resulted from a task switch where TSS.T of target task was set\"],\n            [14, \"BS\", \"single step\",\n             \"If 1, the debug exception was triggered by the single-step execution mode (enabled with EFLAGS.TF)\"],\n            [13, \"BD\", \"debug register access detected\",\n             \"If 1, the next instruction accesses one of the debug registers\"],\n            [3, \"B3\", \"breakpoint condition detected\",\n             \"If 1, breakpoint condition was met when a debug exception for DR3\"],\n            [2, \"B2\", \"breakpoint condition detected\",\n             \"If 1, breakpoint condition was met when a debug exception for DR2\"],\n            [1, \"B1\", \"breakpoint condition detected\",\n             \"If 1, breakpoint condition was met when a debug exception for DR1\"],\n            [0, \"B0\", \"breakpoint condition detected\",\n             \"If 1, breakpoint condition was met when a debug exception for DR0\"],\n        ]\n        dr6 = get_register(\"dr6\", use_monitor=True)\n        self.out.extend(BitInfo(\"DR6\", 32, bit_info, desc).make_out(dr6))\n\n        # DR7\n        self.out.append(titlify(\"DR7 (Debug Control Register 7)\"))\n        desc = \"A local breakpoint bit deactivates on hardware task switches, while a global does not\"\n        bit_info = [\n            [[30, 31], \"LEN3\", \"Size of DR3 breakpoint\"],\n            [[28, 29], \"R/W3\", \"Breakpoint conditions for DR3\"],\n            [[26, 27], \"LEN2\", \"Size of DR2 breakpoint\"],\n            [[24, 25], \"R/W2\", \"Breakpoint conditions for DR2\"],\n            [[22, 23], \"LEN1\", \"Size of DR1 breakpoint\"],\n            [[20, 21], \"R/W1\", \"Breakpoint conditions for DR1\"],\n            [[18, 19], \"LEN0\", \"Size of DR0 breakpoint\"],\n            [[16, 17], \"R/W0\", \"Breakpoint conditions for DR0\"],\n            [13, \"GD\", \"General Detect enable\"],\n            [11, \"RTM\", \"Restricted Transactional Memory\"],\n            [9, \"GE\", \"Global Exact breakpoint\"],\n            [8, \"LE\", \"Local Exact breakpoint\"],\n            [7, \"G3\", \"Global DR3 breakpoint\"],\n            [6, \"L3\", \"Local DR3 breakpoint\"],\n            [5, \"G2\", \"Global DR2 breakpoint\"],\n            [4, \"L2\", \"Local DR2 breakpoint\"],\n            [3, \"G1\", \"Global DR1 breakpoint\"],\n            [2, \"L1\", \"Local DR1 breakpoint\"],\n            [1, \"G0\", \"Global DR0 breakpoint\"],\n            [0, \"L0\", \"Local DR0 breakpoint\"],\n        ]\n        dr7 = get_register(\"dr7\", use_monitor=True)\n        self.out.extend(BitInfo(\"DR7\", bit_info=bit_info, desc=desc).make_out(dr7))\n\n        # EFER\n        self.out.append(titlify(\"EFER (Extended Feature Enable Register; MSR_EFER:0xc0000080)\"))\n        efer = get_register(\"efer\", use_monitor=True)\n        bit_info = [\n            [21, \"AIBRSE\", \"Automatic IBRS Enable\"],\n            [20, \"UAIE\", \"Upper Address Ignore Enable\"],\n            [18, \"INTWB\", \"Interruptible WBINVD/WBNOINVD Enable\"],\n            [17, \"MCOMMIT\", \"MCOMMIT instruction Enable\"],\n            [15, \"TCE\", \"Translation Cache Extension\"],\n            [14, \"FFXSR\", \"Fast FXSAVE/FXRSTOR\"],\n            [13, \"LMSLE\", \"Long Mode Segment Limit Enable\"],\n            [12, \"SVME\", \"Secure Virtual Machine Enable\"],\n            [11, \"NXE\", \"No-Execute Enable\"],\n            [10, \"LMA\", \"Long Mode Active\"],\n            [8, \"LME\", \"Long Mode Enable\"],\n            [4, \"L2D\", \"L2 Cache Disable\", \"only AMD K6\"],\n            [3, \"GEWBED\", \"Global EWBE# Disable\", \"only AMD K6\"],\n            [2, \"SEWBED\", \"Speculative EWBE# Disable\", \"only AMD K6\"],\n            [1, \"DPE\", \"Data Prefetch Enable\", \"only AMD K6\"],\n            [0, \"SCE\", \"System Call Extensions\"],\n        ]\n        self.out.extend(BitInfo(\"EFER\", bit_info=bit_info).make_out(efer))\n\n        # TR\n        res = gdb.execute(\"monitor info registers\", to_string=True)\n        self.out.append(titlify(\"TR (Task Register)\"))\n        tr = re.search(r\"TR\\s*=\\s*(\\S+) (\\S+) (\\S+) (\\S+)\", res)\n        trseg, base, limit, attr = [int(tr.group(i), 16) for i in range(1, 5)]\n        self.out.append(\"{:s} = {:s}\".format(red(\"TR\"), yellow(\"{:#x}\".format(trseg))))\n        self.out.append(\"seg: {:s}: segment selector for TSS (Task State Segment)\".format(\n            Color.boldify(\"{:#x} (rpl:{:d},ti:{:d},index:{:d})\".format(\n                trseg, trseg & 0b11, (trseg >> 2) & 1, trseg >> 3),\n            ),\n        ))\n        self.out.append(\"  base : {:s}: starting address of TSS\".format(\n            Color.colorify_hex(base, \"bold\"),\n        ))\n        self.out.append(\"  limit: {:s}: segment limit or fixed value(={:s})\".format(\n            Color.colorify_hex(limit, \"bold\"),\n            \"=__KERNEL_TSS_LIMIT x64:0x206f/x86:0x206b\",\n        ))\n        self.out.append(\"  attr : {:s}: attribute\".format(Color.colorify_hex(attr, \"bold\")))\n\n        # GDTR\n        self.out.append(titlify(\"GDTR (Global Descriptor Table Register)\"))\n        gdtr = re.search(r\"GDT\\s*=\\s*(\\S+) (\\S+)\", res)\n        base, limit = [int(gdtr.group(i), 16) for i in range(1, 3)]\n        self.out.append(\"{:s} = {:s}:{:s}\".format(\n            red(\"GDTR\"), yellow(\"{:#x}\".format(base)), yellow(\"{:#x}\".format(limit)),\n        ))\n        self.out.append(\"base : {:s}: starting address of GDT (Global Descriptor Table)\".format(\n            Color.colorify_hex(base, \"bold\"),\n        ))\n        self.out.append(\"limit: {:s}: (size of GDT) - 1\".format(\n            Color.colorify_hex(limit, \"bold\"),\n        ))\n\n        ret = gdb.execute(\"gdtinfo -q -n --only-gdt\", to_string=True)\n        self.out.append(ret.rstrip())\n\n        # IDTR\n        self.out.append(titlify(\"IDTR (Interrupt Descriptor Table Register)\"))\n        idtr = re.search(r\"IDT\\s*=\\s*(\\S+) (\\S+)\", res)\n        base, limit = [int(idtr.group(i), 16) for i in range(1, 3)]\n        self.out.append(\"{:s} = {:s}:{:s}\".format(\n            red(\"IDTR\"), yellow(\"{:#x}\".format(base)), yellow(\"{:#x}\".format(limit)),\n        ))\n        self.out.append(\"base : {:s}: starting address of IDT (Interrupt Descriptor Table)\".format(\n            Color.colorify_hex(base, \"bold\"),\n        ))\n        self.out.append(\"limit: {:s}: (size of IDT) - 1\".format(\n            Color.colorify_hex(limit, \"bold\"),\n        ))\n\n        ret = gdb.execute(\"idtinfo -q -n\", to_string=True)\n        self.out.append(ret.rstrip())\n\n        # LDTR\n        self.out.append(titlify(\"LDTR (Local Descriptor Table Register)\"))\n        ldtr = re.search(r\"LDT\\s*=\\s*(\\S+) (\\S+) (\\S+) (\\S+)\", res)\n        seg, base, limit, attr = [int(ldtr.group(i), 16) for i in range(1, 5)]\n        self.out.append(\"{:s} = {:s}\".format(red(\"LDTR\"), yellow(\"{:#x}\".format(seg))))\n        self.out.append(\"seg: {:s}: segment selector for LDT (Local Descriptor Table)\".format(\n            Color.boldify(\"{:#x} (rpl:{:d},ti:{:d},index:{:d})\".format(\n                seg, seg & 0b11, (seg >> 2) & 1, seg >> 3),\n            ),\n        ))\n        self.out.append(\"  base : {:s}: starting address of LDT\".format(\n            Color.colorify_hex(base, \"bold\"),\n        ))\n        self.out.append(\"  limit: {:s}: segment limit\".format(\n            Color.colorify_hex(limit, \"bold\"),\n        ))\n        self.out.append(\"  attr : {:s}: attribute\".format(\n            Color.colorify_hex(attr, \"bold\"),\n        ))\n\n        ret = gdb.execute(\"gdtinfo -q -n --only-ldt\", to_string=True)\n        self.out.append(ret.rstrip())\n        return\n\n    def qregisters(self):\n        res = gdb.execute(\"monitor info registers\", to_string=True).strip()\n        self.out.append(titlify(\"info registers\"))\n        for line in res.splitlines():\n            self.out.append(line)\n\n        if is_x86():\n            if not self.args.verbose:\n                self.info_add_out(\"use `-v` for print Additional info\")\n            else:\n                self.info_add_out(\"Additional info\")\n                self.qregisters_x86_x64()\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    def do_invoke(self, args):\n        self.out = []\n        self.qregisters()\n        self.print_output()\n        return\n\n\nclass PageMap:\n    \"\"\"A collection of utility functions that are related to memory map from page tables.\"\"\"\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_page_maps_by_pagewalk(command):\n        if is_kgdb():\n            info(\"Start `pagewalk`\")\n        res = gdb.execute(command, to_string=True)\n        if 'Exception raised' in res:\n            gef_print(res)\n        return res\n\n    @staticmethod\n    @Cache.cache_until_next\n    def get_page_maps_arm64_optee_secure_memory(verbose=False):\n        # heuristic search of qemu-system memory\n        sm = QemuMonitor.get_secure_memory_map(verbose)\n        if sm is None:\n            err(\"Could not find secure memory maps\")\n            return None\n        data = XSecureMemAddrCommand.read_secure_memory(sm, 0x0, sm.size, verbose)\n        data_list = slice_unpack(data, 8)\n\n        \"\"\"\n        enum teecore_memtypes {\n            MEM_AREA_TEE_RAM = 1,\n            MEM_AREA_TEE_RAM_RX,\n            MEM_AREA_TEE_RAM_RO,\n            MEM_AREA_TEE_RAM_RW,\n            MEM_AREA_INIT_RAM_RO,\n            MEM_AREA_INIT_RAM_RX,\n            MEM_AREA_NEX_RAM_RO,\n            MEM_AREA_NEX_RAM_RW,\n            MEM_AREA_NEX_DYN_VASPACE,\n            MEM_AREA_TEE_DYN_VASPACE,\n            MEM_AREA_TEE_COHERENT,\n            MEM_AREA_TEE_ASAN,\n            MEM_AREA_IDENTITY_MAP_RX,\n            MEM_AREA_NSEC_SHM,\n            MEM_AREA_NEX_NSEC_SHM,\n            MEM_AREA_RAM_NSEC,\n            MEM_AREA_RAM_SEC,\n            MEM_AREA_ROM_SEC,\n            MEM_AREA_IO_NSEC,\n            MEM_AREA_IO_SEC,\n            MEM_AREA_EXT_DT,\n            MEM_AREA_MANIFEST_DT,\n            MEM_AREA_TRANSFER_LIST,\n            MEM_AREA_RES_VASPACE,\n            MEM_AREA_SHM_VASPACE,\n            MEM_AREA_TS_VASPACE,\n            MEM_AREA_PAGER_VASPACE,\n            MEM_AREA_SDP_MEM,\n            MEM_AREA_DDR_OVERALL,\n            MEM_AREA_SEC_RAM_OVERALL,\n            MEM_AREA_MAXTYPE\n        };\n        struct tee_mmap_region {\n            unsigned int type; /* enum teecore_memtypes */\n            unsigned int region_size;\n            paddr_t pa;\n            vaddr_t va;\n            size_t size;\n            uint32_t attr; /* TEE_MATTR_* above */\n        };\n        \"\"\"\n        maps = []\n        old_i = -1\n        for i in range(len(data_list) - 4):\n            type_ = data_list[i] & 0xffff_ffff\n            region_size = (data_list[i] >> 32) & 0xffff_ffff\n            if type_ == 0 or 30 < type_: # enum teecore_memtypes\n                continue\n            if region_size & 0xfff or region_size < 0x1000 or 0xffff_f000 < region_size:\n                continue\n            pa, va, size, attr = data_list[i + 1:i + 5]\n            if pa & 0xfff or 0xffff_f000 < pa:\n                continue\n            if va & 0xfff or 0xffff_f000 < va:\n                continue\n            if size & 0xfff or size < 0x1000 or 0xffff_f000 < size:\n                continue\n            if len(maps) > 0 and old_i + 5 != i: # Judging continuity\n                continue\n            maps.append([va, va + size, pa, pa + size])\n            old_i = i\n        return maps\n\n    @staticmethod\n    def get_page_maps(FORCE_PREFIX_S, verbose=False):\n        if is_arm64():\n            if FORCE_PREFIX_S is True:\n                return PageMap.get_page_maps_arm64_optee_secure_memory(verbose) # already parsed\n            else:\n                res = PageMap.get_page_maps_by_pagewalk(\"pagewalk 1 --quiet --no-pager --no-merge --disable-color\")\n        else:\n            if FORCE_PREFIX_S is None:\n                res = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --no-merge --disable-color\")\n            elif FORCE_PREFIX_S is True:\n                res = PageMap.get_page_maps_by_pagewalk(\"pagewalk -S --quiet --no-pager --no-merge --disable-color\")\n            elif FORCE_PREFIX_S is False:\n                res = PageMap.get_page_maps_by_pagewalk(\"pagewalk -s --quiet --no-pager --no-merge --disable-color\")\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n        maps = []\n        for line in res:\n            vrange, prange, *_ = line.split()\n            vstart, vend = [int(x, 16) for x in vrange.split(\"-\")]\n            pstart, pend = [int(x, 16) for x in prange.split(\"-\")]\n            maps.append((vstart, vend, pstart, pend))\n        if maps == []:\n            if is_x86():\n                warn(\"Make sure you are in ring0 (=kernel mode)\")\n            elif is_arm32():\n                warn(\"Make sure you are in supervisor mode (=kernel mode)\")\n                warn(\"Make sure qemu 3.x or higher\")\n            elif is_arm64():\n                warn(\"Make sure you are in EL1 (=kernel mode)\")\n                warn(\"Make sure qemu 3.x or higher\")\n            return None\n        return maps\n\n    @staticmethod\n    def v2p_from_map(address, maps):\n        for vstart, vend, pstart, _pend in maps:\n            if vstart <= address < vend:\n                offset = address - vstart\n                paddr = pstart + offset\n                return paddr\n        return None\n\n    @staticmethod\n    def p2v_from_map(address, maps): # return list\n        vaddrs = []\n        for vstart, _vend, pstart, pend in maps:\n            if pstart <= address < pend:\n                offset = address - pstart\n                vaddr = vstart + offset\n                vaddrs.append(vaddr)\n        return vaddrs\n\n\n@register_command\nclass Virt2PhysCommand(GenericCommand):\n    \"\"\"Translate from virtual address to physical address.\"\"\"\n\n    _cmdline_ = \"v2p\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-S\", dest=\"force_secure\", action=\"store_true\",\n                       help=\"ARMv7: use TTBRn_ELm_S to parse start. ARMv8: heuristic search the memory of qemu-system.\")\n    group.add_argument(\"-s\", dest=\"force_normal\", action=\"store_true\",\n                       help=\"ARMv7/v8: use TTBRn_ELm to parse start.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the address of data to translate.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0xffffffff855041e0\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        FORCE_PREFIX_S = None\n        if is_arm32() or is_arm64():\n            if args.force_normal:\n                FORCE_PREFIX_S = False\n            elif args.force_secure:\n                FORCE_PREFIX_S = True\n\n        # do not use cache\n        maps = PageMap.get_page_maps(FORCE_PREFIX_S)\n        if maps is None:\n            return\n        paddr = PageMap.v2p_from_map(args.address, maps)\n        if paddr is not None:\n            gef_print(\"Virt: {:#x} -> Phys: {:#x}\".format(args.address, paddr))\n        return\n\n\n@register_command\nclass Phys2VirtCommand(GenericCommand):\n    \"\"\"Translate from physical address to virtual address.\"\"\"\n\n    _cmdline_ = \"p2v\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-S\", dest=\"force_secure\", action=\"store_true\",\n                       help=\"ARMv7: use TTBRn_ELm_S to parse start. ARMv8: heuristic search the memory of qemu-system.\")\n    group.add_argument(\"-s\", dest=\"force_normal\", action=\"store_true\",\n                       help=\"ARMv7/v8: use TTBRn_ELm to parse start.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the address of data to translate.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"verbose output (for arm64 secure memory).\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x55041e0\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        FORCE_PREFIX_S = None\n        if is_arm32() or is_arm64():\n            if args.force_normal:\n                FORCE_PREFIX_S = False\n            elif args.force_secure:\n                FORCE_PREFIX_S = True\n\n        # do not use cache\n        maps = PageMap.get_page_maps(FORCE_PREFIX_S, args.verbose)\n        if maps is None:\n            return\n\n        vaddrs = PageMap.p2v_from_map(args.address, maps)\n\n        if args.verbose:\n            loop_max = len(vaddrs)\n        else:\n            loop_max = min(len(vaddrs), 10)\n\n        if loop_max == 0:\n            gef_print(\"Not mapped as virt\")\n        else:\n            for i in range(loop_max):\n                gef_print(\"Phys: {:#x} -> Virt: {:#x}\".format(args.address, vaddrs[i]))\n            gef_print(\"Total {:d} results are found\".format(len(vaddrs)))\n        return\n\n\n@register_command\nclass PagewalkCommand(GenericCommand, BufferingOutput):\n    \"\"\"The base command to dump page tables.\"\"\"\n\n    _cmdline_ = \"pagewalk\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [\"pw\", \"ptdump\", \"pt\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"x64\")\n    subparsers.add_parser(\"x86\")\n    subparsers.add_parser(\"arm\")\n    subparsers.add_parser(\"arm64\")\n    subparsers.add_parser(\"riscv\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        return\n\n    def read_physmem_cache(self, paddr, size):\n        key = \"{:#x}_{:d}\".format(paddr, size)\n        if key in self.cache:\n            return self.cache[key]\n        out = read_physmem(paddr, size)\n        self.cache[key] = out\n        return out\n\n    # merge pages that points same phys page\n    def merge1(self, mappings):\n        # for example, there are 16 pages,\n        #    virt: 0xffffffff11107000 -> phys: 0xabcd000\n        #    virt: 0xffffffff11117000 -> phys: 0xabcd000\n        #    virt: 0xffffffff11127000 -> phys: 0xabcd000\n        #    ...\n        #    virt: 0xffffffff111d7000 -> phys: 0xabcd000\n        #    virt: 0xffffffff111e7000 -> phys: 0xabcd000\n        #    virt: 0xffffffff111f7000 -> phys: 0xabcd000\n        # they will be merged by \"*\". type is changed from int to string.\n        #    virt: \"0xffffffff111*7000\" -> phys: 0xabcd000\n\n        # group entries that refer to the same phys page\n        tmp = {}\n        for entry in mappings: # [virt_addr, phys_addr, page_size, page_count, flags]\n            va, other = entry[0], tuple(entry[1:])\n            if other not in tmp:\n                tmp[other] = []\n            tmp[other].append(va)\n\n        # internal merge function\n        def recursive_merge(d):\n            if d == {}:\n                return [\"\"]\n            out = []\n            if len(d) == 16:\n                tmp = list(d.values())\n                if tmp.count(tmp[0]) == 16:\n                    for vv in recursive_merge(tmp[0]):\n                        out.append(\"*\" + vv)\n                    return out\n            for k, v in d.items():\n                for vv in recursive_merge(v):\n                    out.append(k + vv)\n            return out\n\n        # merge if possible\n        merged_mappings = []\n        for other, va_array in tmp.items():\n            # usually go through this path\n            if len(va_array) < 16:\n                for va in va_array:\n                    merged_mappings.append([\"{:016x}\".format(va)] + list(other))\n                continue\n\n            # fast path for x64\n            if len(va_array) == 0x10000:\n                va_sorted = sorted([x >> 16 for x in va_array])\n                if va_sorted[0] + 0xffff == va_sorted[-1]:\n                    new_va_str = \"{:016x}\".format(va_array[0])\n                    new_va_str = new_va_str[:8] + \"****\" + new_va_str[12:]\n                    merged_mappings.append([new_va_str] + list(other))\n                    continue\n\n            # slow path\n            queue = [\"{:016x}\".format(x) for x in va_array]\n            # extract\n            dic = {}\n            for q in queue:\n                for i in range(16):\n                    dst = dic\n                    src = dic\n                    for j in range(i + 1):\n                        src = src.get(q[j], {})\n                        if j > 0:\n                            dst = dst.get(q[j - 1], {})\n                    dst[q[i]] = src\n\n            # merge\n            for d in recursive_merge(dic):\n                merged_mappings.append([d] + list(other))\n\n        # done\n        return sorted(merged_mappings)\n\n    # merge consecutive pages\n    def merge2(self, mappings):\n        merged_mappings = []\n        prev = None\n        for now in mappings: # [virt_addr_string, phys_addr, page_size, page_count, flags]\n            # specific case\n            if isinstance(now[0], str) and \"*\" in now[0]:\n                if prev:\n                    merged_mappings += [prev]\n                merged_mappings += [now]\n                prev = None\n                continue\n\n            # first loop case\n            if prev is None:\n                prev = now\n                continue\n\n            now_va = int(now[0], 16) if isinstance(now[0], str) else now[0]\n            prev_va = int(prev[0], 16) if isinstance(prev[0], str) else prev[0]\n            now_pa = int(now[1], 16) if isinstance(now[1], str) else now[1]\n            prev_pa = int(prev[1], 16) if isinstance(prev[1], str) else prev[1]\n            now_size = now[2]\n            prev_size = prev[2]\n            #now_cnt = now[3] # unused\n            prev_cnt = prev[3]\n            now_flags = now[4]\n            prev_flags = prev[4]\n\n            # check consecutiveness\n            if self.args.simple:\n                if prev_va + prev_size == now_va: # va consecutiveness\n                    if prev_flags == now_flags: # flags equivalence\n                        # ok, they are consecutive (at least virt_addr)\n                        prev[2] += now[2]\n                        # For simple mode, page_size is ignored.\n                        # so we use entry[2] as total_size instead of page_size.\n                        continue\n            else:\n                if prev_va + prev_size * prev_cnt == now_va: # va consecutiveness\n                    if prev_pa + prev_size * prev_cnt == now_pa: # pa consecutiveness\n                        if prev_size == now_size: # page_size equivalence\n                            if prev_flags == now_flags: # flags equivalence\n                                # ok, they are consecutive\n                                prev[3] += 1 # prev_page_cnt update\n                                continue\n\n            merged_mappings += [prev]\n            prev = now\n\n        if prev:\n            merged_mappings += [prev]\n\n        return merged_mappings\n\n    def vrange_filter(self, mappings):\n        filtered_mappings = []\n        for mapping in mappings:\n            va, _, size, cnt = mapping[:4]\n            if isinstance(va, str) and \"*\" in va:\n                start = int(va.replace(\"*\", \"0\"), 16)\n                end = int(va.replace(\"*\", \"f\"), 16)\n                for addr in self.vrange:\n                    if start <= addr < end + size * cnt:\n                        filtered_mappings.append(mapping)\n                        break\n            else:\n                if isinstance(va, str):\n                    va = int(va, 16)\n                for addr in self.vrange:\n                    if va <= addr < va + size * cnt:\n                        filtered_mappings.append(mapping)\n                        break\n        return sorted(filtered_mappings)\n\n    def prange_filter(self, mappings):\n        filtered_mappings = []\n        for mapping in mappings:\n            _, pa, size, cnt = mapping[:4]\n            if isinstance(pa, str):\n                pa = int(pa, 16)\n            for addr in self.args.prange:\n                if pa <= addr < pa + size * cnt:\n                    filtered_mappings.append(mapping)\n                    break\n        return sorted(filtered_mappings)\n\n    def format_entry(self, entry):\n        va, pa, size, cnt, flags = entry\n        if isinstance(va, str) and \"*\" in va:\n            vend = \"{:016x}\".format(int(va.replace(\"*\", \"0\"), 16) + size * cnt)\n            for pos in [x.span() for x in re.finditer(r\"\\*\", va)]:\n                vend = vend[:pos[0]] + \"*\" + vend[pos[1]:]\n            pend = pa + size * cnt\n            if self.args.simple:\n                text = \"0x{:16s}-0x{:16s}  {:37s}  {:<#12x} {:<11s} {:<6s} [{:s}]\".format(\n                    va, vend, \"-\", size, \"-\", \"-\", flags,\n                )\n            else:\n                text = \"0x{:16s}-0x{:16s}  {:#018x}-{:#018x}  {:<#12x} {:<#11x} {:<6d} [{:s}]\".format(\n                    va, vend, pa, pend, size * cnt, size, cnt, flags,\n                )\n        else:\n            if isinstance(va, str):\n                va = int(va, 16)\n            vend = va + size * cnt\n            pend = pa + size * cnt\n            if self.args.simple:\n                text = \"{:#018x}-{:#018x}  {:37s}  {:<#12x} {:<11s} {:<6s} [{:s}]\".format(\n                    va, vend, \"-\", size, \"-\", \"-\", flags,\n                )\n            else:\n                text = \"{:#018x}-{:#018x}  {:#018x}-{:#018x}  {:<#12x} {:<#11x} {:<6d} [{:s}]\".format(\n                    va, vend, pa, pend, size * cnt, size, cnt, flags,\n                )\n        return text\n\n    def merging(self):\n        self.mappings = sorted(self.mappings)\n\n        # merging\n        if self.args.no_merge:\n            pass\n        else:\n            if is_x86_64():\n                self.mappings = self.merge1(self.mappings)\n                self.quiet_info_add_out(\"PT Entry (merged similar pages that refer the same physpage): {:d}\".format(\n                    len(self.mappings),\n                ))\n            self.mappings = self.merge2(self.mappings)\n            self.quiet_info_add_out(\"PT Entry (merged consecutive pages): {:d}\".format(\n                len(self.mappings),\n            ))\n        return\n\n    def add_color(self, lines):\n        for i in range(len(lines)):\n            line = lines[i].split(None, 5)\n            if len(line) < 6:\n                continue\n            if is_x86() or is_riscv32() or is_riscv64():\n                if re.search(r\"^\\[R-- \", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_readonly\"))\n                elif re.search(r\"^\\[..X \", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_code\"))\n                elif re.search(r\"^\\[RW- \", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_writable\"))\n                if re.search(r\"^\\[RWX \", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_rwx\"))\n            elif is_arm32():\n                if re.search(r\"PL/R--\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_readonly\"))\n                elif re.search(r\"PL1/..X\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_code\"))\n                elif re.search(r\"PL1/RW-\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_writable\"))\n                if re.search(r\"PL1/RWX\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_rwx\"))\n            elif is_arm64():\n                if re.search(r\"EL[1-3]/R--\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_readonly\"))\n                elif re.search(r\"EL[1-3]/..X\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_code\"))\n                elif re.search(r\"EL[1-3]/RW-\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_writable\"))\n                if re.search(r\"EL[1-3]/RWX\", line[5]):\n                    lines[i] = Color.colorify(lines[i], Config.get_gef_setting(\"theme.address_rwx\"))\n        return lines\n\n    def make_out(self, mappings):\n        if mappings is None or len(mappings) == 0:\n            self.warn_add_out(\"No virtual mappings found\")\n            return\n\n        filtered_mappings = mappings.copy()\n\n        # filter by virtual address range\n        if self.vrange != []:\n            filtered_mappings = self.vrange_filter(filtered_mappings)\n            self.quiet_info_add_out(\"PT Entry (filtered by virtual address range): {:d}\".format(\n                len(filtered_mappings),\n            ))\n\n        # filter by physical address range\n        if self.args.prange != []:\n            filtered_mappings = self.prange_filter(filtered_mappings)\n            self.quiet_info_add_out(\"PT Entry (filtered by physical address range): {:d}\".format(\n                len(filtered_mappings),\n            ))\n\n        # create output\n        lines = []\n        for entry_info in filtered_mappings:\n            line = self.format_entry(entry_info)\n            lines.append(line)\n\n        # filter by keyword\n        if self.args.filter != []:\n            filtered_lines = []\n            for line in lines:\n                for re_pattern in self.args.filter:\n                    if re_pattern.search(line):\n                        filtered_lines.append(line)\n                        break\n            lines = filtered_lines\n            self.quiet_info_add_out(\"PT Entry (filtered by keyword): {:d}\".format(len(lines)))\n\n        # sort by phys\n        if self.args.sort_by_phys:\n            lines = sorted(lines, key=lambda x: x.split()[1])\n\n        # check how many result\n        if lines == []:\n            self.warn_add_out(\"Nothing to display\")\n            return\n\n        # add legend\n        self.out.append(titlify(\"Memory map\"))\n        fmt = \"{:37s}  {:37s}  {:12s} {:11s} {:6s} {:s}\"\n        legend = [\"Virtual address start-end\", \"Physical address start-end\", \"Total size\", \"Page size\", \"Count\", \"Flags\"]\n        self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n\n        # coloring\n        if not self.args.disable_color:\n            lines = self.add_color(lines)\n\n        # add out\n        self.out.extend(lines)\n        return\n\n    def is_not_trace_target(self, va_start, va_end):\n        if self.args.trace == []:\n            return False\n        for tr in self.args.trace:\n            if va_start <= tr and tr < va_end:\n                return False\n        return True\n\n    def is_not_filter_target(self, line):\n        if self.args.filter == []:\n            return False\n        for re_pattern in self.args.filter:\n            if re_pattern.search(line):\n                return False\n        return True\n\n    # Need not @parse_args because argparse can't stop interpreting options for pagewalk sub-command.\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"x86_16\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    def do_invoke(self, argv):\n        if is_x86_32() or is_x86_16():\n            gdb.execute(\"pagewalk x86 {}\".format(\" \".join(argv)))\n        elif is_x86_64():\n            gdb.execute(\"pagewalk x64 {}\".format(\" \".join(argv)))\n        elif is_arm32():\n            gdb.execute(\"pagewalk arm {}\".format(\" \".join(argv)))\n        elif is_arm64():\n            gdb.execute(\"pagewalk arm64 {}\".format(\" \".join(argv)))\n        elif is_riscv64() or is_riscv32():\n            gdb.execute(\"pagewalk riscv {}\".format(\" \".join(argv)))\n        return\n\n\n@register_command\nclass PagewalkRiscvCommand(PagewalkCommand):\n    \"\"\"Dump pagetable for riscv64/32.\"\"\"\n\n    _cmdline_ = \"pagewalk riscv\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [\"pagewalk riscv32\", \"pagewalk riscv64\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-L\", \"--print-each-level\", action=\"store_true\", help=\"show all level pagetables.\")\n    parser.add_argument(\"-N\", \"--no-merge\", action=\"store_true\",\n                        help=\"do not merge similar/consecutive address.\")\n    parser.add_argument(\"-P\", \"--sort-by-phys\", action=\"store_true\",\n                        help=\"sort by physical address.\")\n    parser.add_argument(\"-Q\", \"--simple\", action=\"store_true\",\n                        help=\"merge with ignoring physical address consecutivness.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", action=\"append\", type=re.compile, default=[],\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-v\", \"--vrange\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified virtual address.\")\n    parser.add_argument(\"-p\", \"--prange\", metavar=\"PADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified physical address.\")\n    parser.add_argument(\"-t\", \"--trace\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"show all level pagetables only associated specified address.\")\n    parser.add_argument(\"-D\", \"--disable-color\", action=\"store_true\", help=\"disable RWX colored output\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        self.mappings = None\n        return\n\n    def format_flags(self, flag_info):\n        flag_info_key = tuple(flag_info)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n\n        perm = \"\"\n        perm += [\"-\", \"R\"][\"R\" in flag_info]\n        perm += [\"-\", \"W\"][\"W\" in flag_info]\n        perm += [\"-\", \"X\"][\"X\" in flag_info]\n        if perm in [\"R--\", \"RW-\", \"--X\", \"R-X\", \"RWX\"]:\n            flags.append(perm)\n        else:\n            flags.append(\"???\")\n\n        if \"U\" in flag_info:\n            if self.sstatus_sum:\n                flags.append(\"USER+KERN\")\n            else:\n                flags.append(\"USER\")\n        else:\n            flags.append(\"KERN\")\n\n        if not self.args.simple:\n            if \"A\" in flag_info:\n                flags.append(\"ACCESSED\")\n            if \"D\" in flag_info:\n                flags.append(\"DIRTY\")\n            if \"G\" in flag_info:\n                flags.append(\"GLOBAL\")\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    def pagewalk_L5(self):\n        self.quiet_add_out(titlify(\"Level 5 Entry\"))\n        L5E = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"L4_BITS\"],\n            self.bits[\"L3_BITS\"],\n            self.bits[\"L2_BITS\"],\n            self.bits[\"L1_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        for va_base, table_base, parent_flags in self.TABLES:\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"L5_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # valid flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                sign_ext = 0xfe00_0000_0000_0000 if ((i >> (self.bits[\"L5_BITS\"] - 1)) & 1) else 0\n                new_va = va_base + (sign_ext | (i << bit_shift))\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc ppn\n                ppn = (entry >> 10) & 0xfff_ffff_ffff # 44 bit\n\n                # calc flags\n                flags = parent_flags.copy()\n                if ((entry >> 1) & 1) == 1:\n                    flags.append(\"R\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"W\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"X\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"U\")\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"G\")\n                if ((entry >> 6) & 1) == 1:\n                    flags.append(\"A\")\n                if ((entry >> 7) & 1) == 1:\n                    flags.append(\"D\")\n\n                if ((entry >> 1) & 0b111) == 0:\n                    # calc next table\n                    next_level_entry = ppn * get_pagesize()\n                    L5E.append([new_va, next_level_entry, flags])\n                    entry_type = \"TABLE\"\n                else:\n                    # make entry\n                    virt_addr = new_va\n                    phys_addr = ppn * get_pagesize()\n                    page_size = 256 * 1024 * 1024 * 1024 * 1024\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                    entry_type = \"256TB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    fmt = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\"\n                    line = fmt.format(addr, entry, new_va, new_va_end, entry_type, \" \".join(flags))\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"L5 Entry (256TB): {:d}\".format(len(L5E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(L5E)))\n        self.TABLES = L5E\n        self.PTE += PTE\n        return\n\n    def pagewalk_L4(self):\n        self.quiet_add_out(titlify(\"Level 4 Entry\"))\n        L4E = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"L3_BITS\"],\n            self.bits[\"L2_BITS\"],\n            self.bits[\"L1_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        for va_base, table_base, parent_flags in self.TABLES:\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"L4_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # valid flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                if \"L5_BITS\" in self.bits:\n                    new_va = va_base + (i << bit_shift)\n                    new_va_end = new_va + (1 << bit_shift)\n                else:\n                    sign_ext = 0xffff_0000_0000_0000 if ((i >> (self.bits[\"L4_BITS\"] - 1)) & 1) else 0\n                    new_va = va_base + (sign_ext | (i << bit_shift))\n                    new_va_end = new_va + (1 << bit_shift)\n\n                # calc ppn\n                ppn = (entry >> 10) & 0xfff_ffff_ffff # 44 bit\n\n                # calc flags\n                flags = parent_flags.copy()\n                if ((entry >> 1) & 1) == 1:\n                    flags.append(\"R\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"W\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"X\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"U\")\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"G\")\n                if ((entry >> 6) & 1) == 1:\n                    flags.append(\"A\")\n                if ((entry >> 7) & 1) == 1:\n                    flags.append(\"D\")\n\n                if ((entry >> 1) & 0b111) == 0:\n                    # calc next table\n                    next_level_entry = ppn * get_pagesize()\n                    L4E.append([new_va, next_level_entry, flags])\n                    entry_type = \"TABLE\"\n                else:\n                    # make entry\n                    virt_addr = new_va\n                    phys_addr = ppn * get_pagesize()\n                    page_size = 512 * 1024 * 1024 * 1024\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                    entry_type = \"512GB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    fmt = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\"\n                    line = fmt.format(addr, entry, new_va, new_va_end, entry_type, \" \".join(flags))\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"L4 Entry (512GB): {:d}\".format(len(L4E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(L4E)))\n        self.TABLES = L4E\n        self.PTE += PTE\n        return\n\n    def pagewalk_L3(self):\n        self.quiet_add_out(titlify(\"Level 3 Entry\"))\n        L3E = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"L2_BITS\"],\n            self.bits[\"L1_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        for va_base, table_base, parent_flags in self.TABLES:\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"L3_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # valid flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                if \"L4_BITS\" in self.bits:\n                    new_va = va_base + (i << bit_shift)\n                    new_va_end = new_va + (1 << bit_shift)\n                else:\n                    sign_ext = 0xffff_ff80_0000_0000 if ((i >> (self.bits[\"L3_BITS\"] - 1)) & 1) else 0\n                    new_va = va_base + (sign_ext | (i << bit_shift))\n                    new_va_end = new_va + (1 << bit_shift)\n\n                # calc ppn\n                ppn = (entry >> 10) & 0xfff_ffff_ffff # 44 bit\n\n                # calc flags\n                flags = parent_flags.copy()\n                if ((entry >> 1) & 1) == 1:\n                    flags.append(\"R\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"W\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"X\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"U\")\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"G\")\n                if ((entry >> 6) & 1) == 1:\n                    flags.append(\"A\")\n                if ((entry >> 7) & 1) == 1:\n                    flags.append(\"D\")\n\n                if ((entry >> 1) & 0b111) == 0:\n                    # calc next table\n                    next_level_entry = ppn * get_pagesize()\n                    L3E.append([new_va, next_level_entry, flags])\n                    entry_type = \"TABLE\"\n                else:\n                    # make entry\n                    virt_addr = new_va\n                    phys_addr = ppn * get_pagesize()\n                    page_size = 1 * 1024 * 1024 * 1024\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                    entry_type = \"1GB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    fmt = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\"\n                    line = fmt.format(addr, entry, new_va, new_va_end, entry_type, \" \".join(flags))\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"L3 Entry (1GB): {:d}\".format(len(L3E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(L3E)))\n        self.TABLES = L3E\n        self.PTE += PTE\n        return\n\n    def pagewalk_L2(self):\n        self.quiet_add_out(titlify(\"Level 2 Entry\"))\n        L2E = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"L1_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        for va_base, table_base, parent_flags in self.TABLES:\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"L2_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # valid flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base + (i << bit_shift)\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc ppn\n                if is_riscv64():\n                    ppn = (entry >> 10) & 0xfff_ffff_ffff # 44 bit\n                else:\n                    ppn = (entry >> 10) & 0x3f_ffff # 22 bit\n\n                # calc flags\n                flags = parent_flags.copy()\n                if ((entry >> 1) & 1) == 1:\n                    flags.append(\"R\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"W\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"X\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"U\")\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"G\")\n                if ((entry >> 6) & 1) == 1:\n                    flags.append(\"A\")\n                if ((entry >> 7) & 1) == 1:\n                    flags.append(\"D\")\n\n                if ((entry >> 1) & 0b111) == 0:\n                    # calc next table\n                    next_level_entry = ppn * get_pagesize()\n                    L2E.append([new_va, next_level_entry, flags])\n                    entry_type = \"TABLE\"\n                else:\n                    # make entry\n                    virt_addr = new_va\n                    phys_addr = ppn * get_pagesize()\n                    page_size = 2 * 1024 * 1024\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                    entry_type = \"2MB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    fmt = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\"\n                    line = fmt.format(addr, entry, new_va, new_va_end, entry_type, \" \".join(flags))\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"L2 Entry (2MB): {:d}\".format(len(L2E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(L2E)))\n        self.TABLES = L2E\n        self.PTE += PTE\n        return\n\n    def pagewalk_L1(self):\n        self.quiet_add_out(titlify(\"Level 1 Entry\"))\n        PTE = []\n        COUNT = 0\n        bit_shift = self.bits[\"OFFSET\"]\n        for va_base, table_base, parent_flags in self.TABLES:\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"L1_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # valid flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base + (i << bit_shift)\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc ppn\n                if is_riscv64():\n                    ppn = (entry >> 10) & 0xfff_ffff_ffff # 44 bit\n                else:\n                    ppn = (entry >> 10) & 0x3f_ffff # 22 bit\n\n                # calc flags\n                flags = parent_flags.copy()\n                if ((entry >> 1) & 1) == 1:\n                    flags.append(\"R\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"W\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"X\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"U\")\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"G\")\n                if ((entry >> 6) & 1) == 1:\n                    flags.append(\"A\")\n                if ((entry >> 7) & 1) == 1:\n                    flags.append(\"D\")\n\n                # make entry\n                virt_addr = new_va\n                phys_addr = ppn * get_pagesize()\n                page_size = 4 * 1024\n                page_count = 1\n                PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                entry_type = \"4KB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"L1 Entry (4KB): {:d}\".format(len(PTE)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PTE)))\n        self.PTE += PTE\n\n        self.quiet_add_out(titlify(\"Total\"))\n        self.quiet_info_add_out(\"PT Entry (Total): {:d}\".format(len(self.PTE)))\n        self.mappings = self.PTE\n        return\n\n    def pagewalk(self):\n        satp = get_register(\"satp\")\n        if satp is None:\n            self.err_add_out(\"Failed to read $satp\")\n            return\n        self.quiet_info_add_out(\"satp: {:#018x}\".format(satp))\n\n        sstatus = get_register(\"sstatus\")\n        if sstatus is None:\n            self.err_add_out(\"Failed to read $sstatus\")\n            return\n        self.quiet_info_add_out(\"sstatus: {:#018x}\".format(sstatus))\n\n        if is_riscv64():\n            mode = (satp >> 60) & 0b1111 # upper 4 bit\n            pagewalk_base = (satp & 0xfff_ffff_ffff) * get_pagesize() # lower 44 bit\n        else:\n            mode = (satp >> 31) & 0b1 # upper 1 bit\n            pagewalk_base = (satp & 0x3f_ffff) * get_pagesize() # lower 22 bit\n        self.sstatus_sum = (sstatus >> 18) & 1\n\n        # virtual address base\n        va_base = 0\n        flags = []\n\n        # do pagewalk\n        self.PTE = []\n        self.TABLES = [(va_base, pagewalk_base, flags)]\n        self.flags_strings_cache = {}\n\n        if is_riscv64():\n            if mode == 0:\n                self.err_add_out(\"RV64 bare page table is unsupported\")\n            elif mode == 11: # Sv64 is unsuppported\n                self.err_add_out(\"RV64 Sv64 page table is unsupported\")\n            elif mode == 10: # Sv57\n                self.quiet_info_add_out(\"RV64 Sv57 page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"L5_BITS\": 9, \"L4_BITS\": 9, \"L3_BITS\": 9, \"L2_BITS\": 9, \"L1_BITS\": 9, \"OFFSET\": 12,\n                }\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_L5()\n                    self.pagewalk_L4()\n                    self.pagewalk_L3()\n                    self.pagewalk_L2()\n                    self.pagewalk_L1()\n                    self.merging()\n            elif mode == 9: # Sv48\n                self.quiet_info_add_out(\"RV64 Sv48 page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"L4_BITS\": 9, \"L3_BITS\": 9, \"L2_BITS\": 9, \"L1_BITS\": 9, \"OFFSET\": 12,\n                }\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_L4()\n                    self.pagewalk_L3()\n                    self.pagewalk_L2()\n                    self.pagewalk_L1()\n                    self.merging()\n            elif mode == 8: # Sv39\n                self.quiet_info_add_out(\"RV64 Sv39 page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"L3_BITS\": 9, \"L2_BITS\": 9, \"L1_BITS\": 9, \"OFFSET\": 12,\n                }\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_L3()\n                    self.pagewalk_L2()\n                    self.pagewalk_L1()\n                    self.merging()\n            else:\n                self.err_add_out(\"RV64 unknown mode\")\n        else:\n            if mode == 0:\n                self.err_add_out(\"RV32 bare page table is unsupported\")\n            elif mode == 1: # Sv32\n                self.quiet_info_add_out(\"RV32 Sv32 page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 4,\n                    \"L2_BITS\": 10, \"L1_BITS\": 10, \"OFFSET\": 12,\n                }\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_L2()\n                    self.pagewalk_L1()\n                    self.merging()\n\n        self.flags_strings_cache = {}\n        self.make_out(self.mappings)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"RISCV32\", \"RISCV64\"))\n    def do_invoke(self, args):\n        if self.args.trace:\n            # You should not modify the self.args.vrange directly.\n            self.vrange = self.args.vrange + self.args.trace # merge vrange and trace\n            self.args.print_each_level = True # overwrite\n            self.args.use_cache = False # overwrite\n        else:\n            self.vrange = self.args.vrange\n\n        self.out = []\n        self.cache = {}\n        self.pagewalk()\n        self.cache = {} # The cache is huge, so it will be released as soon as possible.\n        self.print_output()\n        return\n\n\n@register_command\nclass PagewalkX64Command(PagewalkCommand):\n    \"\"\"Dump pagetable for x64/x86.\"\"\"\n\n    _cmdline_ = \"pagewalk x64\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [\"pagewalk x86\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-L\", \"--print-each-level\", action=\"store_true\", help=\"show all level pagetables.\")\n    parser.add_argument(\"-N\", \"--no-merge\", action=\"store_true\",\n                        help=\"do not merge similar/consecutive address.\")\n    parser.add_argument(\"-P\", \"--sort-by-phys\", action=\"store_true\",\n                        help=\"sort by physical address.\")\n    parser.add_argument(\"-Q\", \"--simple\", action=\"store_true\",\n                        help=\"merge with ignoring physical address consecutivness.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", action=\"append\", type=re.compile, default=[],\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-v\", \"--vrange\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified virtual address.\")\n    parser.add_argument(\"-p\", \"--prange\", metavar=\"PADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified physical address.\")\n    parser.add_argument(\"-t\", \"--trace\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"show all level pagetables only associated specified address.\")\n    parser.add_argument(\"-i\", \"--include-esp-fixup-stacks\", action=\"store_true\",\n                        help=\"include `%%esp fixup stacks` area (sometimes heavy memory use; x64 only).\")\n    parser.add_argument(\"-U\", \"--user-pt\", action=\"store_true\",\n                        help=\"print userland pagetables (for KPTI, x64 only, in kernel context).\")\n    parser.add_argument(\"--cr3\", dest=\"user_specified_cr3\", type=AddressUtil.parse_address,\n                        help=\"use specified value as cr3.\")\n    parser.add_argument(\"--cr4\", dest=\"user_specified_cr4\", type=AddressUtil.parse_address,\n                        help=\"use specified value as cr4.\")\n    parser.add_argument(\"--ept\", action=\"store_true\", help=\"parse cr3 as EPT (Extended Page Table).\")\n    parser.add_argument(\"-D\", \"--disable-color\", action=\"store_true\", help=\"disable RWX colored output\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        self.mappings = None\n        return\n\n    def format_flags(self, flag_info):\n        flag_info_key = tuple(flag_info)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n        if self.args.ept:\n            perm = \"\"\n            perm += [\"R\", \"-\"][\"NO_R\" in flag_info]\n            perm += [\"W\", \"-\"][\"NO_W\" in flag_info]\n            perm += [\"X\", \"-\"][\"NO_X\" in flag_info]\n            flags += [perm]\n        else:\n            if \"NO_RW\" in flag_info:\n                if \"XD\" in flag_info:\n                    flags += [\"R--\"]\n                else:\n                    flags += [\"R-X\"]\n            else:\n                if \"XD\" in flag_info:\n                    flags += [\"RW-\"]\n                else:\n                    flags += [\"RWX\"]\n            if \"NO_US\" in flag_info:\n                flags += [\"KERN\"]\n            else:\n                flags += [\"USER\"]\n\n        if not self.args.simple:\n            if \"A\" in flag_info:\n                flags += [\"ACCESSED\"]\n            if \"D\" in flag_info:\n                flags += [\"DIRTY\"]\n            if \"G\" in flag_info:\n                flags += [\"GLOBAL\"]\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    def pagewalk_PML5T(self):\n        self.quiet_add_out(titlify(\"PML5E: Page Map Level 5 Entry\"))\n        PML5E = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"PML4T_BITS\"],\n            self.bits[\"PDPT_BITS\"],\n            self.bits[\"PDT_BITS\"],\n            self.bits[\"PT_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(self.TABLES, leave=False, desc=\"PML5E\"):\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"PML5T_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                sign_ext = 0xfe00_0000_0000_0000 if ((i >> (self.bits[\"PML5T_BITS\"] - 1)) & 1) else 0\n                new_va = va_base + (sign_ext | (i << bit_shift))\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if self.args.ept:\n                    if ((entry >> 0) & 1) == 0:\n                        flags.append(\"NO_R\")\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_W\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_X\")\n                    if ((entry >> 8) & 1) == 1:\n                        flags.append(\"A\")\n                else:\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_RW\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_US\")\n                    if ((entry >> 5) & 1) == 1:\n                        flags.append(\"A\")\n                    if ((entry >> 63) & 1) == 1:\n                        flags.append(\"XD\")\n\n                # calc next table (drop the flag bits)\n                next_level_table = entry & 0x000f_ffff_ffff_f000\n\n                # make entry\n                PML5E.append([new_va, next_level_table, flags])\n                entry_type = \"TABLE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PML5 Entry: {:d}\".format(len(PML5E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PML5E)))\n        self.TABLES = PML5E\n        return\n\n    def pagewalk_PML4T(self):\n        self.quiet_add_out(titlify(\"PML4E: Page Map Level 4 Entry\"))\n        PML4E = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"PDPT_BITS\"],\n            self.bits[\"PDT_BITS\"],\n            self.bits[\"PT_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(self.TABLES, leave=False, desc=\"PML4E\"):\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"PML4T_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                if \"PML5T_BITS\" in self.bits:\n                    new_va = va_base + (i << bit_shift)\n                    new_va_end = new_va + (1 << bit_shift)\n                else:\n                    sign_ext = 0xffff_0000_0000_0000 if ((i >> (self.bits[\"PML4T_BITS\"] - 1)) & 1) else 0\n                    new_va = va_base + (sign_ext | (i << bit_shift))\n                    new_va_end = new_va + (1 << bit_shift)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if self.args.ept:\n                    if ((entry >> 0) & 1) == 0:\n                        flags.append(\"NO_R\")\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_W\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_X\")\n                    if ((entry >> 8) & 1) == 1:\n                        flags.append(\"A\")\n                else:\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_RW\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_US\")\n                    if ((entry >> 5) & 1) == 1:\n                        flags.append(\"A\")\n                    if ((entry >> 63) & 1) == 1:\n                        flags.append(\"XD\")\n\n                # calc next table (drop the flag bits)\n                next_level_table = entry & 0x000f_ffff_ffff_f000\n\n                # make entry\n                PML4E.append([new_va, next_level_table, flags])\n                entry_type = \"TABLE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PML4 Entry: {:d}\".format(len(PML4E)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PML4E)))\n        self.TABLES = PML4E\n        return\n\n    def pagewalk_PDPT(self):\n        self.quiet_add_out(titlify(\"PDPE: Page Directory Pointer Entry\"))\n\n        def is_set_PS(entry):\n            return ((entry >> 7) & 1) == 1\n\n        PDPTE = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"PDT_BITS\"],\n            self.bits[\"PT_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(self.TABLES, leave=False, desc=\"PDPE\"):\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"PDPT_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base + (i << bit_shift)\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if is_x86_64():\n                    if self.args.ept:\n                        if ((entry >> 0) & 1) == 0:\n                            flags.append(\"NO_R\")\n                        if ((entry >> 1) & 1) == 0:\n                            flags.append(\"NO_W\")\n                        if ((entry >> 2) & 1) == 0:\n                            flags.append(\"NO_X\")\n                        if ((entry >> 8) & 1) == 1:\n                            flags.append(\"A\")\n                        if is_set_PS(entry) and ((entry >> 9) & 1) == 1:\n                            flags.append(\"D\")\n                    else:\n                        if ((entry >> 1) & 1) == 0:\n                            flags.append(\"NO_RW\")\n                        if ((entry >> 2) & 1) == 0:\n                            flags.append(\"NO_US\")\n                        if ((entry >> 5) & 1) == 1:\n                            flags.append(\"A\")\n                        if is_set_PS(entry) and ((entry >> 6) & 1) == 1:\n                            flags.append(\"D\")\n                        if is_set_PS(entry) and ((entry >> 8) & 1) == 1:\n                            flags.append(\"G\")\n                        if ((entry >> 63) & 1) == 1:\n                            flags.append(\"XD\")\n                else: # x86_32 and PAE\n                    pass\n\n                # calc next table (drop the flag bits)\n                if is_x86_64() and is_set_PS(entry):\n                    next_level_table = entry & 0x000f_ffff_ffff_e000\n                else:\n                    next_level_table = entry & 0x000f_ffff_ffff_f000\n\n                # make entry\n                if is_set_PS(entry):\n                    virt_addr = new_va\n                    phys_addr = next_level_table\n                    page_size = 1 * 1024 * 1024 * 1024\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                    entry_type = \"1GB-PAGE\"\n                else:\n                    PDPTE.append([new_va, next_level_table, flags])\n                    entry_type = \"TABLE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PDPT Entry: {:d}\".format(len(PDPTE)))\n        self.quiet_info_add_out(\"PT Entry (1GB): {:d}\".format(len(PTE)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PDPTE) - len(PTE)))\n        self.TABLES = PDPTE\n        self.PTE += PTE\n        return\n\n    def pagewalk_PDT(self):\n        self.quiet_add_out(titlify(\"PDE: Page Directory Entry\"))\n\n        def is_set_PS(entry):\n            return ((entry >> 7) & 1) == 1\n\n        PDE = []\n        PTE = []\n        COUNT = 0\n        bit_shift = sum([\n            self.bits[\"PT_BITS\"],\n            self.bits[\"OFFSET\"],\n        ])\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(self.TABLES, leave=False, desc=\"PDE\"):\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"PDT_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n\n            if not self.args.include_esp_fixup_stacks:\n                if len({e & ~0b111 for e in entries}) == 1:\n                    continue\n\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base + (i << bit_shift)\n                new_va_end = new_va + (1 << bit_shift)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if self.args.ept:\n                    if ((entry >> 0) & 1) == 0:\n                        flags.append(\"NO_R\")\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_W\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_X\")\n                    if ((entry >> 8) & 1) == 1:\n                        flags.append(\"A\")\n                    if is_set_PS(entry) and ((entry >> 9) & 1) == 1:\n                        flags.append(\"D\")\n                else:\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_RW\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_US\")\n                    if ((entry >> 5) & 1) == 1:\n                        flags.append(\"A\")\n                    if is_set_PS(entry) and ((entry >> 6) & 1) == 1:\n                        flags.append(\"D\")\n                    if is_set_PS(entry) and ((entry >> 8) & 1) == 1:\n                        flags.append(\"G\")\n                    if self.PAE and ((entry >> 63) & 1) == 1:\n                        flags.append(\"XD\")\n\n                # calc next table (drop the flag bits)\n                if is_x86_64() and is_set_PS(entry):\n                    next_level_table = entry & 0x000f_ffff_ffff_e000\n                elif is_x86_32() and is_set_PS(entry):\n                    high = (entry >> 13) & 0xf\n                    low = (entry >> 22) & 0x3ff\n                    next_level_table = ((high << 10) | low) << 22\n                else:\n                    next_level_table = entry & 0x000f_ffff_ffff_f000\n\n                # make entry\n                if is_set_PS(entry):\n                    virt_addr = new_va\n                    phys_addr = next_level_table\n                    if self.PAE:\n                        page_size = 2 * 1024 * 1024\n                        entry_type = \"2MB-PAGE\"\n                    else:\n                        page_size = 4 * 1024 * 1024\n                        entry_type = \"4MB-PAGE\"\n                    page_count = 1\n                    PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                else:\n                    PDE.append([new_va, next_level_table, flags])\n                    entry_type = \"TABLE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PD Entry: {:d}\".format(len(PDE)))\n        self.quiet_info_add_out(\"PT Entry ({:d}MB): {:d}\".format(2 if self.PAE else 4, len(PTE)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PDE) - len(PTE)))\n        self.TABLES = PDE\n        self.PTE += PTE\n        return\n\n    def pagewalk_PT(self):\n        self.quiet_add_out(titlify(\"PTE: Page Table Entry\"))\n        PTE = []\n        COUNT = 0\n        bit_shift = self.bits[\"OFFSET\"]\n        flag_cache = {}\n\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(self.TABLES, leave=False, desc=\"PTE\"):\n            entries = self.read_physmem_cache(table_base, 2 ** self.bits[\"PT_BITS\"] * self.bits[\"ENTRY_SIZE\"])\n            entries = slice_unpack(entries, self.bits[\"ENTRY_SIZE\"])\n            COUNT += len(entries)\n\n            if not self.args.include_esp_fixup_stacks:\n                if len({e & ~0b111 for e in entries}) == 1:\n                    continue\n\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                virt_addr = va_base + (i << bit_shift)\n                virt_addr_end = virt_addr + (1 << bit_shift)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if self.args.ept:\n                    if ((entry >> 0) & 1) == 0:\n                        flags.append(\"NO_R\")\n                    if ((entry >> 1) & 1) == 0:\n                        flags.append(\"NO_W\")\n                    if ((entry >> 2) & 1) == 0:\n                        flags.append(\"NO_X\")\n                    if ((entry >> 8) & 1) == 1:\n                        flags.append(\"A\")\n                    if ((entry >> 9) & 1) == 1:\n                        flags.append(\"D\")\n                else:\n                    # This route passes many times, so make a memo\n                    entry_flags_key = entry & 0x8000_0000_0000_0166\n                    x = flag_cache.get(entry_flags_key, None)\n                    if x is not None:\n                        flags.extend(x)\n                    else:\n                        flags_tmp = []\n                        if ((entry >> 1) & 1) == 0:\n                            flags_tmp.append(\"NO_RW\")\n                        if ((entry >> 2) & 1) == 0:\n                            flags_tmp.append(\"NO_US\")\n                        if ((entry >> 5) & 1) == 1:\n                            flags_tmp.append(\"A\")\n                        if ((entry >> 6) & 1) == 1:\n                            flags_tmp.append(\"D\")\n                        if ((entry >> 8) & 1) == 1:\n                            flags_tmp.append(\"G\")\n                        if self.PAE and ((entry >> 63) & 1) == 1:\n                            flags_tmp.append(\"XD\")\n                        flag_cache[entry_flags_key] = flags_tmp\n                        flags.extend(flags_tmp)\n\n                # calc physical addr (drop the flag bits)\n                phys_addr = entry & 0x000f_ffff_ffff_f000\n\n                # make entry\n                page_size = 4 * 1024\n                page_count = 1\n                PTE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags(flags)])\n                entry_type = \"4KB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(virt_addr, virt_addr_end):\n                        continue\n                    addr = table_base + i * self.bits[\"ENTRY_SIZE\"]\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, virt_addr, virt_addr_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PT Entry (4KB): {:d}\".format(len(PTE)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(PTE)))\n        self.PTE += PTE\n\n        self.quiet_add_out(titlify(\"Total\"))\n        self.quiet_info_add_out(\"PT Entry (Total): {:d}\".format(len(self.PTE)))\n        self.mappings = self.PTE\n        return\n\n    def pagewalk(self):\n        # `info tlb` on qemu-monitor returns pagetable without intermediate pagetable information.\n        # for printing it, we will pagewalk manually.\n        if self.args.user_specified_cr3 is not None:\n            cr3 = self.args.user_specified_cr3\n        else:\n            cr3 = get_register(\"cr3\", use_monitor=True, use_mbed_exec=True)\n        if cr3 is None:\n            self.quiet_err(\"Failed to resolve cr3\")\n            return\n\n        if self.args.user_specified_cr4 is not None:\n            cr4 = self.args.user_specified_cr4\n        else:\n            cr4 = get_register(\"cr4\", use_monitor=True, use_mbed_exec=True)\n        if cr4 is None:\n            self.quiet_err(\"Failed to resolve cr4\")\n            return\n\n        if is_x86_64() and self.args.user_pt:\n            cr3 += get_pagesize()\n        self.quiet_info_add_out(\"cr3: {:#018x}\".format(cr3))\n        self.quiet_info_add_out(\"cr4: {:#018x}\".format(cr4))\n\n        # virtual address base\n        va_base = 0\n\n        # pagewalk base is from CR3 register\n        if self.args.user_specified_cr3 is not None:\n            pagewalk_base = cr3 # without mask\n        else:\n            if is_x86_64(): # 64bit\n                pagewalk_base = cr3 & ~0xfff\n            elif ((cr4 >> 5) & 1) == 1: # 32bit PAE\n                pagewalk_base = cr3 & ~0x1f\n            else: # 32bit non-PAE\n                pagewalk_base = cr3 & ~0xfff\n\n        # we ignore PWT and PCD flags.\n        flags = []\n\n        # do pagewalk\n        self.PTE = []\n        self.TABLES = [(va_base, pagewalk_base, flags)]\n        self.flags_strings_cache = {}\n        if is_x86_64():\n            if (cr4 >> 12) & 1: # PML5T check\n                # 64bit 5-level(4KB): 9,9,9,9,9,12\n                # 64bit 5-level(2MB): 9,9,9,9,0,21\n                # 64bit 5-level(1GB): 9,9,9,0,0,30\n                self.quiet_info_add_out(\"64-bit 5 level page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"PML5T_BITS\": 9, \"PML4T_BITS\": 9, \"PDPT_BITS\": 9, \"PDT_BITS\": 9, \"PT_BITS\": 9, \"OFFSET\": 12,\n                }\n                self.PAE = True\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_PML5T()\n                    self.pagewalk_PML4T()\n                    self.pagewalk_PDPT()\n                    self.pagewalk_PDT()\n                    self.pagewalk_PT()\n                    self.merging()\n            else:\n                # 64bit 4-level(4KB): 9,9,9,9,12\n                # 64bit 4-level(2MB): 9,9,9,0,21\n                # 64bit 4-level(1GB): 9,9,0,0,30\n                self.quiet_info_add_out(\"64-bit 4 level page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"PML4T_BITS\": 9, \"PDPT_BITS\": 9, \"PDT_BITS\": 9, \"PT_BITS\": 9, \"OFFSET\": 12,\n                }\n                self.PAE = True\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_PML4T()\n                    self.pagewalk_PDPT()\n                    self.pagewalk_PDT()\n                    self.pagewalk_PT()\n                    self.merging()\n        elif is_x86_32() or is_x86_16():\n            if (cr4 >> 5) & 1: # PAE check\n                # 32bit PAE(4KB): 2,9,9,12 (PTE Size: 64bit)\n                # 32bit PAE(2MB): 2,9,0,21 (PTE Size: 64bit)\n                self.quiet_info_add_out(\"32-bit {:s} page table\".format(Color.boldify(\"PAE\")))\n                self.bits = {\n                    \"ENTRY_SIZE\": 8,\n                    \"PDPT_BITS\": 2, \"PDT_BITS\": 9, \"PT_BITS\": 9, \"OFFSET\": 12,\n                }\n                self.PAE = True\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_PDPT()\n                    self.pagewalk_PDT()\n                    self.pagewalk_PT()\n                    self.merging()\n            else:\n                # 32bit(4KB): 10,10,12\n                # 32bit(4MB): 10,0,22\n                self.quiet_info_add_out(\"32-bit Non-PAE page table\")\n                self.bits = {\n                    \"ENTRY_SIZE\": 4,\n                    \"PDT_BITS\": 10, \"PT_BITS\": 10, \"OFFSET\": 12,\n                }\n                self.PAE = False\n                if not self.args.use_cache or not self.mappings:\n                    self.mappings = None\n                    self.pagewalk_PDT()\n                    self.pagewalk_PT()\n                    self.merging()\n        else:\n            self.err_add_out(\"Unsupported CPU\")\n            return\n\n        self.flags_strings_cache = None\n        self.make_out(self.mappings)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"x86_16\"))\n    def do_invoke(self, args):\n        if self.args.include_esp_fixup_stacks and not is_x86_64():\n            err(\"Unsupported --include-esp-fixup-stacks option in this arch\")\n            return\n\n        if self.args.trace:\n            # You should not modify the self.args.vrange directly.\n            self.vrange = self.args.vrange + self.args.trace # merge vrange and trace\n            self.args.print_each_level = True # overwrite\n            self.args.use_cache = False # overwrite\n        else:\n            self.vrange = self.args.vrange\n\n        if not is_x86_64() or not is_in_kernel():\n            self.args.user_pt = False # support x64 only\n\n        if args.ept:\n            if not self.args.user_specified_cr3:\n                err(\"Unsupported --ept option without --cr3 option\")\n                return\n\n        self.out = []\n        self.cache = {}\n        self.pagewalk()\n        self.cache = {} # The cache is huge, so it will be released as soon as possible.\n        self.print_output()\n        return\n\n\n@register_command\nclass PagewalkArmCommand(PagewalkCommand):\n    \"\"\"Dump pagetable for ARM Cortex-A. PL2 pagewalk is unsupported.\"\"\"\n\n    _cmdline_ = \"pagewalk arm\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [\"pagewalk arm32\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-S\", dest=\"force_secure\", action=\"store_true\", help=\"use TTBRn_ELm_S to parse start.\")\n    group.add_argument(\"-s\", dest=\"force_normal\", action=\"store_true\", help=\"use TTBRn_ELm to parse start.\")\n    parser.add_argument(\"-L\", \"--print-each-level\", action=\"store_true\", help=\"show all level pagetables.\")\n    parser.add_argument(\"-N\", \"--no-merge\", action=\"store_true\", help=\"do not merge similar/consecutive address.\")\n    parser.add_argument(\"-P\", \"--sort-by-phys\", action=\"store_true\", help=\"sort by physical address.\")\n    parser.add_argument(\"-Q\", \"--simple\", action=\"store_true\", help=\"merge with ignoring physical address consecutivness.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", action=\"append\", type=re.compile, default=[],\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-v\", \"--vrange\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified virtual address.\")\n    parser.add_argument(\"-p\", \"--prange\", metavar=\"PADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified physical address.\")\n    parser.add_argument(\"-t\", \"--trace\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"show all level pagetables only associated specified address.\")\n    parser.add_argument(\"--optee\", action=\"store_true\", help=\"show the secure world memory maps if used OP-TEE.\")\n    parser.add_argument(\"-D\", \"--disable-color\", action=\"store_true\", help=\"disable RWX colored output\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        self.ttbr0_mappings = None\n        self.ttbr1_mappings = None\n        return\n\n    def format_flags_short(self, flag_info):\n        return self.__format_flags_short(flag_info, self.PXN)\n\n    def __format_flags_short(self, flag_info, gPXN):\n        flag_info_key = (tuple(flag_info), gPXN)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n\n        XN = \"XN\" in flag_info\n        PXN = (\"PXN\" in flag_info) & gPXN\n\n        # AP[2:0] access permissions model\n        if \"AP=000\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/---\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/---\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/---\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/---\"] # XN, PXN\n        elif \"AP=001\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN, PXN\n        elif \"AP=010\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/R-X\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/R-X\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/R--\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/R--\", \"PL1/RW-\"] # XN, PXN\n        elif \"AP=011\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/RWX\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/RWX\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN, PXN\n        elif \"AP=100\" in flag_info:\n            flags += [\"PL0/???\", \"PL1/???\"] # undefined (reserved)\n        elif \"AP=101\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN, PXN\n        elif \"AP=110\" in flag_info: # deprecated\n            if XN is False and PXN is False:\n                flags += [\"PL0/R-X\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/R-X\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN, PXN\n        elif \"AP=111\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/R-X\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/R-X\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN, PXN\n        # AP[2:1] access permissions model\n        elif \"AP=00\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN, PXN\n        elif \"AP=01\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/RWX\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/RWX\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN, PXN\n        elif \"AP=10\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN, PXN\n        elif \"AP=11\" in flag_info:\n            if XN is False and PXN is False:\n                flags += [\"PL0/R-X\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/R-X\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN, PXN\n\n        if \"NS\" in flag_info:\n            flags += [\"NS\"]\n\n        if not self.args.simple:\n            # short description has no `AF` bit\n\n            if \"nG\" not in flag_info:\n                flags += [\"GLOBAL\"]\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    def format_flags_long(self, flag_info):\n        return self.__format_flags_long(flag_info, self.PXN)\n\n    def __format_flags_long(self, flag_info, gPXN):\n        flag_info_key = (tuple(flag_info), gPXN)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n\n        # AP/APTable parsing\n        if \"AP=00\" in flag_info:\n            disable_write_access = 0\n            enable_unpriv_access = 0\n        elif \"AP=01\" in flag_info:\n            disable_write_access = 0\n            enable_unpriv_access = 1\n        elif \"AP=10\" in flag_info:\n            disable_write_access = 1\n            enable_unpriv_access = 0\n        elif \"AP=11\" in flag_info:\n            disable_write_access = 1\n            enable_unpriv_access = 1\n        if \"APTable2=00\" in flag_info:\n            pass\n        elif \"APTable2=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable2=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable2=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n        if \"APTable1=00\" in flag_info:\n            pass\n        elif \"APTable1=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable1=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable1=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n        AP = (disable_write_access << 1) | enable_unpriv_access\n\n        # XN/XNTable, PXN/PXNTable, NS/NSTable parsing\n        XN = \"XN\" in flag_info\n        XN |= \"XNTable2\" in flag_info\n        XN |= \"XNTable1\" in flag_info\n        PXN = \"PXN\" in flag_info\n        PXN |= \"PXNTable2\" in flag_info\n        PXN |= \"PXNTable1\" in flag_info\n        PXN &= gPXN\n        NS = \"NS\" in flag_info\n        NS |= \"NSTable2\" in flag_info\n        NS |= \"NSTable1\" in flag_info\n\n        # AP[2:1] access permissions model\n        if AP == 0b00:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/RW-\"] # XN, PXN\n        elif AP == 0b01:\n            if XN is False and PXN is False:\n                flags += [\"PL0/RWX\", \"PL1/RWX\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/RWX\", \"PL1/RW-\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/RW-\", \"PL1/RW-\"] # XN, PXN\n        elif AP == 0b10:\n            if XN is False and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/---\", \"PL1/R--\"] # XN, PXN\n        elif AP == 0b11:\n            if XN is False and PXN is False:\n                flags += [\"PL0/R-X\", \"PL1/R-X\"] #\n            elif XN is False and PXN is True:\n                flags += [\"PL0/R-X\", \"PL1/R--\"] # PXN\n            elif XN is True and PXN is False:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN\n            elif XN is True and PXN is True:\n                flags += [\"PL0/R--\", \"PL1/R--\"] # XN, PXN\n\n        if NS:\n            flags += [\"NS\"]\n\n        if not self.args.simple:\n            if \"AF\" in flag_info:\n                flags += [\"ACCESSED\"]\n            if \"nG\" not in flag_info:\n                flags += [\"GLOBAL\"]\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    def do_pagewalk_short(self, table_base, va_base=0):\n        self.mappings = []\n\n        def has_next_level(entry):\n            return (entry & 0b11) == 0b01\n\n        def is_section(entry):\n            return (entry & 0b11) in [0b10, 0b11] and ((entry >> 18) & 1) == 0\n\n        def is_super_section(entry):\n            return self.XP and (entry & 0b11) in [0b10, 0b11] and ((entry >> 18) & 1) == 1\n\n        def is_large_page(entry):\n            return (entry & 0b11) == 0b01\n\n        def is_small_page(entry):\n            return (entry & 0b11) in [0b10, 0b11]\n\n        # 1st level parse\n        self.quiet_add_out(titlify(\"LEVEL 1\"))\n        LEVEL1 = []\n        SECTION = []\n        SUPER_SECTION = []\n        COUNT = 0\n        entries = self.read_physmem_cache(table_base, 4 * (2 ** (12 - self.N)))\n        entries = slice_unpack(entries, 4)\n        COUNT += len(entries)\n        for i, entry in enumerate(entries):\n            # present flag\n            if (entry & 0b11) == 0b00:\n                continue\n\n            # calc virtual address\n            new_va = va_base + (i << 20)\n            new_va_end = new_va + (1 << 20)\n\n            # calc flags\n            flags = []\n            if has_next_level(entry):\n                if self.XP and ((entry >> 2) & 1) == 1:\n                    flags.append(\"PXN\")\n                if self.XP and ((entry >> 3) & 1) == 1:\n                    flags.append(\"NS\")\n                flags.append(\"domain={:#x}\".format((entry >> 5) & 0b1111))\n            elif is_section(entry):\n                if ((entry >> 0) & 1) == 1:\n                    flags.append(\"PXN\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"B\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"C\")\n                if self.XP and ((entry >> 4) & 1) == 1:\n                    flags.append(\"XN\")\n                flags.append(\"domain={:#x}\".format((entry >> 5) & 0b1111))\n                ap = (((entry >> 15) & 1) << 2) + ((entry >> 10) & 0b11)\n                if self.AFE: # AP[2:1] access permissions model # codespell:ignore\n                    flags.append(\"AP={:02b}\".format(ap >> 1))\n                else: # AP[2:0] access permissions model\n                    flags.append(\"AP={:03b}\".format(ap))\n                flags.append(\"TEX={:#x}\".format((entry >> 12) & 0b111))\n                if self.XP and ((entry >> 16) & 1) == 1:\n                    flags.append(\"S\")\n                if self.XP and ((entry >> 17) & 1) == 1:\n                    flags.append(\"nG\")\n                if self.XP and ((entry >> 19) & 1) == 1:\n                    flags.append(\"NS\")\n            elif is_super_section(entry):\n                if ((entry >> 0) & 1) == 1:\n                    flags.append(\"PXN\")\n                if ((entry >> 2) & 1) == 1:\n                    flags.append(\"B\")\n                if ((entry >> 3) & 1) == 1:\n                    flags.append(\"C\")\n                if ((entry >> 4) & 1) == 1:\n                    flags.append(\"XN\")\n                ap = (((entry >> 15) & 1) << 2) + ((entry >> 10) & 0b11)\n                if self.AFE: # AP[2:1] access permissions model # codespell:ignore\n                    flags.append(\"AP={:02b}\".format(ap >> 1))\n                else: # AP[2:0] access permissions model\n                    flags.append(\"AP={:03b}\".format(ap))\n                flags.append(\"TEX={:#x}\".format((entry >> 12) & 0b111))\n                if ((entry >> 16) & 1) == 1:\n                    flags.append(\"S\")\n                if ((entry >> 17) & 1) == 1:\n                    flags.append(\"nG\")\n                if ((entry >> 19) & 1) == 1:\n                    flags.append(\"NS\")\n            else:\n                raise\n\n            # calc next table (drop the flag bits)\n            if has_next_level(entry):\n                next_level_table = entry & 0xffff_fc00\n            elif is_section(entry):\n                next_level_table = entry & 0xfff0_0000\n            elif is_super_section(entry):\n                next_level_table = entry & 0xff00_0000             # PA[31:24]\n                next_level_table += ((entry >> 20) & 0b1111) << 32 # PA[35:32]\n                next_level_table += ((entry >> 5) & 0b1111) << 36  # PA[39:36]\n\n            # make entry\n            if has_next_level(entry):\n                LEVEL1.append([new_va, next_level_table, flags])\n                entry_type = \"TABLE\"\n            elif is_section(entry):\n                virt_addr = new_va\n                phys_addr = next_level_table\n                page_size = 1 * 1024 * 1024\n                page_count = 1\n                SECTION.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_short(flags)])\n                entry_type = \"SECTION\"\n            elif is_super_section(entry):\n                virt_addr = new_va\n                phys_addr = next_level_table\n                page_size = 16 * 1024 * 1024\n                page_count = 1\n                SUPER_SECTION.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_short(flags)])\n                entry_type = \"SUPER_SECTION\"\n\n            # dump\n            if self.args.print_each_level:\n                if self.is_not_trace_target(new_va, new_va_end):\n                    continue\n                addr = table_base + i * 4\n                line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                    addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                )\n                if self.is_not_filter_target(line):\n                    continue\n                self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"Level 1 Entry: {:d}\".format(len(LEVEL1)))\n        self.quiet_info_add_out(\"PT Entry (supersection; 16MB): {:d}\".format(len(SUPER_SECTION)))\n        self.quiet_info_add_out(\"PT Entry (section; 1MB): {:d}\".format(len(SECTION)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL1) - len(SUPER_SECTION) - len(SECTION)))\n        self.mappings += SECTION + SUPER_SECTION\n\n        # 2nd level parse\n        self.quiet_add_out(titlify(\"LEVEL 2\"))\n        LARGE = []\n        SMALL = []\n        COUNT = 0\n\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(LEVEL1, leave=False, desc=\"LEVEL 2\"):\n            entries = self.read_physmem_cache(table_base, 4 * (2 ** 8))\n            entries = slice_unpack(entries, 4)\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 0b11) == 0b00:\n                    continue\n\n                # calc virtual address\n                virt_addr = va_base + (i << 12)\n                virt_addr_end = virt_addr + (1 << 12)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if is_large_page(entry):\n                    if ((entry >> 2) & 1) == 1:\n                        flags.append(\"B\")\n                    if ((entry >> 3) & 1) == 1:\n                        flags.append(\"C\")\n                    ap = (((entry >> 9) & 1) << 2) + ((entry >> 4) & 0b11)\n                    if self.AFE: # AP[2:1] access permissions model # codespell:ignore\n                        flags.append(\"AP={:02b}\".format(ap >> 1))\n                    else: # AP[2:0] access permissions model\n                        flags.append(\"AP={:03b}\".format(ap))\n                    if ((entry >> 10) & 1) == 1:\n                        flags.append(\"S\")\n                    if ((entry >> 11) & 1) == 1:\n                        flags.append(\"nG\")\n                    flags.append(\"TEX={:#x}\".format((entry >> 12) & 0b111))\n                    if ((entry >> 15) & 1) == 1:\n                        flags.append(\"XN\")\n                elif is_small_page(entry):\n                    if ((entry >> 0) & 1) == 1:\n                        flags.append(\"XN\")\n                    if ((entry >> 2) & 1) == 1:\n                        flags.append(\"B\")\n                    if ((entry >> 3) & 1) == 1:\n                        flags.append(\"C\")\n                    ap = (((entry >> 9) & 1) << 2) + ((entry >> 4) & 0b11)\n                    if self.AFE: # AP[2:1] access permissions model # codespell:ignore\n                        flags.append(\"AP={:02b}\".format(ap >> 1))\n                    else: # AP[2:0] access permissions model\n                        flags.append(\"AP={:03b}\".format(ap))\n                    flags.append(\"TEX={:#x}\".format((entry >> 6) & 0b111))\n                    if ((entry >> 10) & 1) == 1:\n                        flags.append(\"S\")\n                    if ((entry >> 11) & 1) == 1:\n                        flags.append(\"nG\")\n\n                # calc physical addr (drop the flag bits)\n                if is_large_page(entry):\n                    phys_addr = entry & 0xffff_0000\n                elif is_small_page(entry):\n                    phys_addr = entry & 0xffff_f000\n\n                # make entry\n                if is_large_page(entry):\n                    page_size = 64 * 1024\n                    page_count = 1\n                    LARGE.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_short(flags)])\n                    entry_type = \"LARGE\"\n                elif is_small_page(entry):\n                    page_size = 4 * 1024\n                    page_count = 1\n                    SMALL.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_short(flags)])\n                    entry_type = \"SMALL\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(virt_addr, virt_addr_end):\n                        continue\n                    addr = table_base + i * 4\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, virt_addr, virt_addr_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PT Entry (large; 64KB): {:d}\".format(len(LARGE)))\n        self.quiet_info_add_out(\"PT Entry (small; 4KB): {:d}\".format(len(SMALL)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LARGE) - len(SMALL)))\n        self.mappings += LARGE + SMALL\n\n        self.quiet_add_out(titlify(\"Total\"))\n        self.quiet_info_add_out(\"PT Entry (Total): {:d}\".format(len(self.mappings)))\n        self.mappings = sorted(self.mappings)\n        return\n\n    def do_pagewalk_long(self, table_base, va_base=0):\n        self.mappings = []\n\n        def has_next_level(entry):\n            return (entry & 0b11) == 0b11\n\n        def is_1GB_page(entry):\n            return (entry & 0b11) == 0b01\n\n        def is_2MB_page(entry):\n            return (entry & 0b11) == 0b01\n\n        self.quiet_add_out(titlify(\"LEVEL 1\"))\n        if self.N < 2:\n            # 1st level parse\n            LEVEL1 = []\n            GB = []\n            COUNT = 0\n            l1_count = 1 << max(0, 2 - self.N)\n            entries = self.read_physmem_cache(table_base, 8 * l1_count)\n            entries = slice_unpack(entries, 8)\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base | (i << 30)\n                new_va_end = new_va + (1 << 30)\n\n                # calc flags\n                flags = []\n                if has_next_level(entry):\n                    if ((entry >> 59) & 1) == 1:\n                        flags.append(\"PXNTable1\")\n                    if ((entry >> 60) & 1) == 1:\n                        flags.append(\"XNTable1\")\n                    flags.append(\"APTable1={:02b}\".format((entry >> 61) & 0b11))\n                    if ((entry >> 63) & 1) == 1:\n                        flags.append(\"NSTable1\")\n                elif is_1GB_page(entry):\n                    flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                    if ((entry >> 5) & 1) == 1:\n                        flags.append(\"NS\")\n                    flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                    flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                    if ((entry >> 10) & 1) == 1:\n                        flags.append(\"AF\")\n                    if ((entry >> 11) & 1) == 1:\n                        flags.append(\"nG\")\n                    if ((entry >> 52) & 1) == 1:\n                        flags.append(\"Contiguous\")\n                    if ((entry >> 53) & 1) == 1:\n                        flags.append(\"PXN\")\n                    if ((entry >> 54) & 1) == 1:\n                        flags.append(\"XN\")\n\n                # calc next table (drop the flag bits)\n                if has_next_level(entry):\n                    next_level_table = entry & 0x0000_00ff_ffff_f000\n                elif is_1GB_page(entry):\n                    next_level_table = entry & 0x0000_00ff_c000_0000\n\n                # make entry\n                if has_next_level(entry):\n                    LEVEL1.append([new_va, next_level_table, flags])\n                    entry_type = \"TABLE\"\n                elif is_1GB_page(entry):\n                    virt_addr = new_va\n                    phys_addr = next_level_table\n                    page_size = 1 * 1024 * 1024 * 1024\n                    page_count = 1\n                    GB.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_long(flags)])\n                    entry_type = \"1GB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * 8\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n            if self.args.print_each_level:\n                self.out.append(titlify(\"\"))\n\n            self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n            self.quiet_info_add_out(\"Level 1 Entry: {:d}\".format(len(LEVEL1)))\n            self.quiet_info_add_out(\"PT Entry (1GB): {:d}\".format(len(GB)))\n            self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL1) - len(GB)))\n            self.mappings += GB\n        else:\n            self.quiet_info_add_out(\"LEVEL 1 is skipped\")\n            flags = []\n            LEVEL1 = [[va_base, table_base, flags]]\n\n        # 2nd level parse\n        self.quiet_add_out(titlify(\"LEVEL 2\"))\n        LEVEL2 = []\n        MB = []\n        COUNT = 0\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for va_base, table_base, parent_flags in tqdm(LEVEL1, leave=False, desc=\"LEVEL 2\"):\n            entries = self.read_physmem_cache(table_base, 8 * (2 ** 9))\n            entries = slice_unpack(entries, 8)\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 1) == 0:\n                    continue\n\n                # calc virtual address\n                new_va = va_base | (i << 21)\n                new_va_end = new_va + (1 << 21)\n\n                # calc flags\n                flags = parent_flags.copy()\n                if has_next_level(entry):\n                    if ((entry >> 59) & 1) == 1:\n                        flags.append(\"PXNTable2\")\n                    if ((entry >> 60) & 1) == 1:\n                        flags.append(\"XNTable2\")\n                    flags.append(\"APTable2={:02b}\".format((entry >> 61) & 0b11))\n                    if ((entry >> 63) & 1) == 1:\n                        flags.append(\"NSTable2\")\n                elif is_2MB_page(entry):\n                    flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                    if ((entry >> 5) & 1) == 1:\n                        flags.append(\"NS\")\n                    flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                    flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                    if ((entry >> 10) & 1) == 1:\n                        flags.append(\"AF\")\n                    if ((entry >> 11) & 1) == 1:\n                        flags.append(\"nG\")\n                    if ((entry >> 52) & 1) == 1:\n                        flags.append(\"Contiguous\")\n                    if ((entry >> 53) & 1) == 1:\n                        flags.append(\"PXN\")\n                    if ((entry >> 54) & 1) == 1:\n                        flags.append(\"XN\")\n\n                # calc next table (drop the flag bits)\n                if has_next_level(entry):\n                    next_level_table = entry & 0x0000_00ff_ffff_f000\n                elif is_2MB_page(entry):\n                    next_level_table = entry & 0x0000_00ff_ffe0_0000\n\n                # make entry\n                if has_next_level(entry):\n                    LEVEL2.append([new_va, next_level_table, flags])\n                    entry_type = \"TABLE\"\n                elif is_2MB_page(entry):\n                    virt_addr = new_va\n                    phys_addr = next_level_table\n                    page_size = 2 * 1024 * 1024\n                    page_count = 1\n                    MB.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_long(flags)])\n                    entry_type = \"2MB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(new_va, new_va_end):\n                        continue\n                    addr = table_base + i * 8\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"Level 2 Entry: {:d}\".format(len(LEVEL2)))\n        self.quiet_info_add_out(\"PT Entry (2MB): {:d}\".format(len(MB)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL2) - len(MB)))\n        self.mappings += MB\n\n        # 3rd level parse\n        self.quiet_add_out(titlify(\"LEVEL 3\"))\n        KB = []\n        COUNT = 0\n\n        for va_base, table_base, parent_flags in tqdm(LEVEL2, leave=False, desc=\"LEVEL 3\"):\n            entries = self.read_physmem_cache(table_base, 8 * (2 ** 9))\n            entries = slice_unpack(entries, 8)\n            COUNT += len(entries)\n            for i, entry in enumerate(entries):\n                # present flag\n                if (entry & 0b11) != 0b11:\n                    continue\n\n                # calc virtual address\n                virt_addr = va_base | (i << 12)\n                virt_addr_end = virt_addr + (1 << 12)\n\n                # calc flags\n                flags = parent_flags.copy()\n                flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                if ((entry >> 5) & 1) == 1:\n                    flags.append(\"NS\")\n                flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                if ((entry >> 10) & 1) == 1:\n                    flags.append(\"AF\")\n                if ((entry >> 11) & 1) == 1:\n                    flags.append(\"nG\")\n                if ((entry >> 52) & 1) == 1:\n                    flags.append(\"Contiguous\")\n                if ((entry >> 53) & 1) == 1:\n                    flags.append(\"PXN\")\n                if ((entry >> 54) & 1) == 1:\n                    flags.append(\"XN\")\n\n                # calc physical addr (drop the flag bits)\n                phys_addr = entry & 0x0000_00ff_ffff_f000\n\n                # make entry\n                page_size = 4 * 1024\n                page_count = 1\n                KB.append([virt_addr, phys_addr, page_size, page_count, self.format_flags_long(flags)])\n                entry_type = \"4KB-PAGE\"\n\n                # dump\n                if self.args.print_each_level:\n                    if self.is_not_trace_target(virt_addr, virt_addr_end):\n                        continue\n                    addr = table_base + i * 8\n                    line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                        addr, entry, virt_addr, virt_addr_end, entry_type, \" \".join(flags),\n                    )\n                    if self.is_not_filter_target(line):\n                        continue\n                    self.out.append(line)\n\n        if self.args.print_each_level:\n            self.out.append(titlify(\"\"))\n\n        self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n        self.quiet_info_add_out(\"PT Entry (4KB): {:d}\".format(len(KB)))\n        self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(KB)))\n        self.mappings += KB\n\n        self.quiet_add_out(titlify(\"Total\"))\n        self.quiet_info_add_out(\"PT Entry (Total): {:d}\".format(len(self.mappings)))\n        self.mappings = sorted(self.mappings)\n        return\n\n    def pagewalk_short(self):\n        self.out.append(titlify(\"$TTBR0_EL1{}\".format(self.suffix), color=\"bold\", msg_color=\"bold\"))\n\n        TTBR0_EL1 = get_register(\"$TTBR0_EL1{}\".format(self.suffix))\n        if TTBR0_EL1 is None:\n            TTBR0_EL1 = get_register(\"$TTBR0\", use_mbed_exec=True)\n        if TTBR0_EL1 is None:\n            self.err_add_out(\"Could not find $TTBR0_EL1{}\".format(self.suffix))\n            return\n\n        TTBCR = get_register(\"$TTBCR{}\".format(self.suffix))\n        if TTBCR is None:\n            TTBCR = get_register(\"$TTBCR\", use_mbed_exec=True)\n        if TTBCR is None:\n            self.err_add_out(\"Could not find $TTBCR{}\".format(self.suffix))\n            return\n\n        # pagewalk TTBR0_EL1\n        self.N = TTBCR & 0b111\n        x = 14 - self.N\n        pl0_base = ((TTBR0_EL1 & 0xffff_ffff) >> x) << x\n        self.quiet_info_add_out(\"$TTBR0_EL1{}: {:#x}\".format(self.suffix, TTBR0_EL1))\n        self.quiet_info_add_out(\"$TTBCR{}: {:#x}\".format(self.suffix, TTBCR))\n        self.quiet_info_add_out(\"PL0 base: {:#x}\".format(pl0_base))\n        if not self.args.use_cache or not self.ttbr0_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk_short(pl0_base)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr0_mappings = self.mappings.copy()\n        self.make_out(self.ttbr0_mappings)\n\n        # pagewalk TTBR1_EL1\n        self.out.append(titlify(\"$TTBR1_EL1{}\".format(self.suffix), color=\"bold\", msg_color=\"bold\"))\n\n        TTBR1_EL1 = get_register(\"$TTBR1_EL1{}\".format(self.suffix))\n        if TTBR1_EL1 is None:\n            TTBR1_EL1 = get_register(\"$TTBR1\", use_mbed_exec=True)\n        if TTBR1_EL1 is None:\n            self.err_add_out(\"Could not find $TTBR1_EL1{}\".format(self.suffix))\n            return\n\n        if self.suffix:\n            # The reason is unclear, but the vabase of PL1 appears to be 0x0 when TTBR1_EL1_S is used.\n            pl1_vabase = 0\n        else:\n            pl1_vabase = {\n                0: None,\n                1: 0x8000_0000,\n                2: 0x4000_0000,\n                3: 0x2000_0000,\n                4: 0x1000_0000,\n                5: 0x0800_0000,\n                6: 0x0400_0000,\n                7: 0x0200_0000,\n            }[self.N]\n        pl1_base = ((TTBR1_EL1 & 0xffff_ffff) >> x) << x\n        # Whenever TTBCR.N is nonzero, the size of the translation table addressed by TTBR1 is 16KB (N=0).\n        self.N = 0\n        if pl1_vabase is not None:\n            self.quiet_info_add_out(\"$TTBR1_EL1{}: {:#x}\".format(self.suffix, TTBR1_EL1))\n            self.quiet_info_add_out(\"$TTBCR{}: {:#x}\".format(self.suffix, TTBCR))\n            self.quiet_info_add_out(\"PL1 base: {:#x}\".format(pl1_base))\n            self.quiet_info_add_out(\"PL1 va_base: {:#x}\".format(pl1_vabase))\n            if not self.args.use_cache or not self.ttbr1_mappings:\n                self.flags_strings_cache = {}\n                self.do_pagewalk_short(pl1_base, pl1_vabase)\n                self.flags_strings_cache = None\n                self.merging()\n                self.ttbr1_mappings = self.mappings.copy()\n            self.make_out(self.ttbr1_mappings)\n        else:\n            self.quiet_info_add_out(\"$TTBR1_EL1{} is unused\".format(self.suffix))\n        return\n\n    def pagewalk_long(self):\n        self.out.append(titlify(\"$TTBR0_EL1{}\".format(self.suffix), color=\"bold\", msg_color=\"bold\"))\n\n        TTBR0_EL1 = get_register(\"$TTBR0_EL1{}\".format(self.suffix))\n        if TTBR0_EL1 is None:\n            TTBR0_EL1 = get_register(\"$TTBR0\", use_mbed_exec=True)\n        if TTBR0_EL1 is None:\n            self.err_add_out(\"Could not find $TTBR0_EL1{}\".format(self.suffix))\n            return\n\n        TTBCR = get_register(\"$TTBCR{}\".format(self.suffix))\n        if TTBCR is None:\n            TTBCR = get_register(\"$TTBCR\", use_mbed_exec=True)\n        if TTBCR is None:\n            self.err_add_out(\"Could not find $TTBCR{}\".format(self.suffix))\n            return\n\n        def get_x(TxSZ):\n            if TxSZ > 1:\n                return 14 - TxSZ\n            else:\n                return 5 - TxSZ\n\n        # pagewalk TTBR0_EL1\n        T0SZ = TTBCR & 0b111\n        T1SZ = (TTBCR >> 16) & 0b111\n        self.N = T0SZ\n        x0 = get_x(T0SZ)\n        pl0_base = ((TTBR0_EL1 & 0xff_ffff_ffff) >> x0) << x0\n        self.quiet_info_add_out(\"$TTBR0_EL1{}: {:#x}\".format(self.suffix, TTBR0_EL1))\n        self.quiet_info_add_out(\"$TTBCR{}: {:#x}\".format(self.suffix, TTBCR))\n        self.quiet_info_add_out(\"T0SZ: {:#x}\".format(T0SZ))\n        self.quiet_info_add_out(\"PL0 base: {:#x}\".format(pl0_base))\n        if not self.args.use_cache or not self.ttbr0_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk_long(pl0_base)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr0_mappings = self.mappings.copy()\n        self.make_out(self.ttbr0_mappings)\n\n        # pagewalk TTBR1_EL1\n        self.out.append(titlify(\"$TTBR1_EL1{}\".format(self.suffix), color=\"bold\", msg_color=\"bold\"))\n\n        TTBR1_EL1 = get_register(\"$TTBR1_EL1{}\".format(self.suffix))\n        if TTBR1_EL1 is None:\n            TTBR1_EL1 = get_register(\"$TTBR1\", use_mbed_exec=True)\n        if TTBR1_EL1 is None:\n            self.err_add_out(\"Could not find $TTBR1_EL1{}\".format(self.suffix))\n            return\n\n        if T0SZ != 0 or T1SZ != 0:\n            self.N = T1SZ\n            x1 = get_x(T1SZ)\n            pl1_base = ((TTBR1_EL1 & 0xff_ffff_ffff) >> x1) << x1\n            if T1SZ == 0:\n                pl1_vabase = 2 ** (32 - T0SZ)\n            else:\n                pl1_vabase = (2 ** 32) - (2 ** (32 - T1SZ))\n            self.quiet_info_add_out(\"$TTBR1_EL1{}: {:#x}\".format(self.suffix, TTBR1_EL1))\n            self.quiet_info_add_out(\"$TTBCR{}: {:#x}\".format(self.suffix, TTBCR))\n            self.quiet_info_add_out(\"T1SZ: {:#x}\".format(T1SZ))\n            self.quiet_info_add_out(\"PL1 base: {:#x}\".format(pl1_base))\n            self.quiet_info_add_out(\"PL1 va_base: {:#x}\".format(pl1_vabase))\n            if not self.args.use_cache or not self.ttbr1_mappings:\n                self.flags_strings_cache = {}\n                self.do_pagewalk_long(pl1_base, pl1_vabase)\n                self.flags_strings_cache = None\n                self.merging()\n                self.ttbr1_mappings = self.mappings.copy()\n            self.make_out(self.ttbr1_mappings)\n        else:\n            self.quiet_info_add_out(\"$TTBR1_EL1{} is unused\".format(self.suffix))\n        return\n\n    def pagewalk(self):\n        # check use the register with`_S` suffix or not, and Seucre mode or not\n        if self.FORCE_PREFIX_S is None:\n            # auto detect\n            SCR_S = get_register(\"$SCR_S\")\n            SCR = get_register(\"$SCR\")\n\n            if (SCR, SCR_S) == (None, None):\n                self.SECURE = False\n                self.suffix = \"\"\n\n            elif SCR is not None and SCR_S is None:\n                # do not use \"_S\"\n                self.SECURE = (SCR & 0x1) == 0 # NS bit\n                self.suffix = \"\"\n\n            elif SCR is None and SCR_S is not None:\n                # use \"_S\"\n                self.SECURE = (SCR_S & 0x1) == 0 # NS bit\n                self.suffix = \"_S\"\n\n            elif SCR is not None and SCR_S is not None:\n                r = gdb.execute(\"monitor info mtree -f\", to_string=True)\n                if \".secure-ram\" in r:\n                    # do not use \"_S\"\n                    self.SECURE = (SCR & 0x1) == 0 # NS bit\n                    self.suffix = \"\"\n                else:\n                    # use \"_S\"\n                    self.SECURE = (SCR_S & 0x1) == 0 # NS bit\n                    self.suffix = \"_S\"\n\n        elif self.FORCE_PREFIX_S is True:\n            # use \"_S\"\n            SCR_S = get_register(\"$SCR_S\")\n            if SCR_S is not None:\n                self.SECURE = (SCR_S & 0x1) == 0 # NS bit\n            else:\n                self.SECURE = False\n            self.suffix = \"_S\"\n\n        elif self.FORCE_PREFIX_S is False:\n            # do not use \"_S\"\n            SCR = get_register(\"$SCR\")\n            if SCR is not None:\n                self.SECURE = (SCR & 0x1) == 0 # NS bit\n            else:\n                self.SECURE = False\n            self.suffix = \"\"\n\n        # check XP, AFE # codespell:ignore\n        SCTLR = get_register(\"$SCTLR{}\".format(self.suffix))\n        if SCTLR is not None:\n            self.XP = ((SCTLR >> 23) & 0x1) == 1\n            self.AFE = ((SCTLR >> 29) & 0x1) == 1 # codespell:ignore\n        else:\n            self.XP = False\n            self.AFE = False # codespell:ignore\n\n        if not self.XP:\n            self.quiet_info_add_out(\"VMSAv6 subpages is enabled\")\n            self.SECURE = False\n        else:\n            self.quiet_info_add_out(\"Secure world: {}\".format(self.SECURE))\n\n        # check enabled LPAE\n        TTBCR = get_register(\"$TTBCR{}\".format(self.suffix))\n        if TTBCR is not None:\n            self.LPAE = ((TTBCR >> 31) & 0x1) == 1\n        else:\n            self.LPAE = False\n\n        # check PXN supported\n        ID_MMFR0 = get_register(\"$ID_MMFR0{}\".format(self.suffix))\n        if ID_MMFR0 is not None:\n            self.PXN = ((ID_MMFR0 >> 2) & 0x1) == 1\n        else:\n            self.PXN = False\n\n        if self.PXN:\n            self.quiet_info_add_out(\"{:s} is supported\".format(Color.boldify(\"PXN\")))\n        else:\n            self.quiet_info_add_out(\"PXN is unsupported\")\n        self.quiet_info_add_out(\"PAN is unimplemented on all ARMv7\")\n\n        # pagewalk\n        if self.LPAE:\n            self.quiet_info_add_out(\"{:s} is enabled (using long description)\".format(Color.boldify(\"LPAE\")))\n            self.pagewalk_long()\n        else:\n            self.quiet_info_add_out(\"LPAE is disabled (using short description)\")\n            self.pagewalk_short()\n        return\n\n    def arm32_optee_exact_pagewalk(self):\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk arm -S --quiet --no-pager --disable-color\")\n        if not res:\n            return\n\n        # extract lines\n        entries = []\n        for line in res.splitlines():\n            if not line.startswith(\"0x\"):\n                continue\n\n            vrange, prange, total_size, page_size, count, flags = line.split(None, 5)\n            d = {}\n            d[\"va_start\"], d[\"va_end\"] = [int(x, 16) for x in vrange.split(\"-\")]\n            d[\"pa_start\"], d[\"pa_end\"] = [int(x, 16) for x in prange.split(\"-\")]\n            d.update({\n                \"total_size\": int(total_size, 16),\n                \"page_size\": int(page_size, 16),\n                \"count\": int(count, 16),\n                \"flags\": flags,\n            })\n            Entry = collections.namedtuple(\"Entry\", d.keys())\n            entry = Entry(*d.values())\n            entries.append(entry)\n\n        fmt = \"{:37s}  {:37s}  {:10s}  {:20s}  {:s}\"\n        legend = [\"Virtual address start-end\", \"Physical address start-end\", \"Total size\", \"Flags\", \"Hint (Maybe)\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        \"\"\"\n        gef> pagewalk --optee -n -q\n        Virtual address start-end              Physical address start-end             Total size  Flags                 Hint (Maybe)\n        0x000000000e100000-0x000000000e101000  0x000000000e100000-0x000000000e101000  0x1000      [PL0/--- PL1/R-X]     TEE-OS bootstrap region\n        0x00000000be700000-0x00000000be900000  0x000000007fe00000-0x0000000080000000  0x200000    [PL0/--- PL1/RW- NS]  NS<->S shared memory\n        0x00000000be9ab000-0x00000000bea00000  0x000000000e1ab000-0x000000000e200000  0x55000     [PL0/--- PL1/RW-]\n        0x00000000bea00000-0x00000000bf800000  0x000000000e200000-0x000000000f000000  0xe00000    [PL0/--- PL1/RW-]\n        0x00000000bf900000-0x00000000bfa00000  0x000000000e000000-0x000000000e100000  0x100000    [PL0/--- PL1/RW-]\n        0x00000000bfa00000-0x00000000bfb00000  0x0000000009000000-0x0000000009100000  0x100000    [PL0/--- PL1/RW-]     UART0_BASE\n        0x00000000bfb00000-0x00000000bfc00000  0x0000000008000000-0x0000000008100000  0x100000    [PL0/--- PL1/RW-]     GIC_BASE\n        0x00000000c2879000-0x00000000c2924000  0x000000000e100000-0x000000000e1ab000  0xab000     [PL0/--- PL1/R-X]     TEE-OS .text\n        0x00000000c2924000-0x00000000c295f000  0x000000000e1ab000-0x000000000e1e6000  0x3b000     [PL0/--- PL1/RW-]     TEE-OS .data / stack\n        gef>\n        \"\"\"\n        text_end = None\n        pl0_count = 0\n        after_ldelf = False\n        after_ta = False\n\n        for e in entries:\n            if \"PL0/---\" in e.flags:\n                after_ta = False\n\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-vexpress/conf.mk\n            if e.pa_start == 0x0e10_0000:\n                if e.va_start == 0x0e10_0000 and e.va_end - e.va_start == 0x1000:\n                    hint = \"TEE-OS bootstrap region\"\n                else:\n                    hint = \"TEE-OS .text\"\n                    text_end = e.va_end\n            elif text_end and e.va_start == text_end:\n                hint = \"TEE-OS .data / stack\"\n            elif e.pa_start == 0x7fe0_0000:\n                hint = \"NS<->S shared memory\"\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-vexpress/platform_config.h\n            elif e.pa_start == 0x0800_0000:\n                hint = \"GIC_BASE\"\n            elif e.pa_start == 0x0900_0000:\n                hint = \"UART0_BASE\"\n            elif e.pa_start == 0x0904_0000:\n                hint = \"UART1_BASE\"\n            elif e.pa_start == 0x0910_0000:\n                hint = \"PCSC_BASE\"\n            # others\n            elif \"[PL0/RW-\" in e.flags and pl0_count == 0:\n                hint = \"ldelf\"\n            elif \"[PL0/R-X\" in e.flags:\n                if pl0_count == 0:\n                    hint = \"ldelf\"\n                    after_ldelf = True\n                else:\n                    hint = \"TA\"\n                    after_ta = True\n                pl0_count += 1\n            elif after_ldelf:\n                hint = \"ldelf\"\n                after_ldelf = False\n            elif after_ta:\n                if \"NS\" in e.flags and e.total_size == 0x1000:\n                    hint = \"TA (param)\"\n                else:\n                    hint = \"TA .data / stack\"\n            else:\n                hint = \"\"\n            gef_print(\"{:#018x}-{:#018x}  {:#018x}-{:#018x}  {:<#10x}  {:20s}  {:s}\".format(\n                e.va_start, e.va_end, e.pa_start, e.pa_end, e.total_size, e.flags, hint,\n            ).rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\",))\n    def do_invoke(self, args):\n        if args.optee and is_qemu_system():\n            self.arm32_optee_exact_pagewalk()\n            return\n\n        if self.args.trace:\n            # You should not modify the self.args.vrange directly.\n            self.vrange = self.args.vrange + self.args.trace # merge vrange and trace\n            self.args.print_each_level = True # overwrite\n            self.args.use_cache = False # overwrite\n        else:\n            self.vrange = self.args.vrange\n\n        self.FORCE_PREFIX_S = None\n        if args.force_secure:\n            self.FORCE_PREFIX_S = True\n        elif args.force_normal:\n            self.FORCE_PREFIX_S = False\n\n        self.out = []\n        self.cache = {}\n        self.pagewalk()\n        self.cache = {} # The cache is huge, so it will be released as soon as possible.\n        self.print_output()\n        return\n\n\n@register_command\nclass PagewalkArm64Command(PagewalkCommand):\n    \"\"\"Dump pagetable for ARM64 Cortex-A (ARM v8.7 base).\"\"\"\n\n    _cmdline_ = \"pagewalk arm64\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [] # re-overwrite\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"target_el\", metavar=\"TARGET_EL\", nargs=\"?\", type=int,\n                        help=\"target Exception Level. (default: current EL)\")\n    parser.add_argument(\"-L\", \"--print-each-level\", action=\"store_true\", help=\"show all level pagetables.\")\n    parser.add_argument(\"-N\", \"--no-merge\", action=\"store_true\", help=\"do not merge similar/consecutive address.\")\n    parser.add_argument(\"-P\", \"--sort-by-phys\", action=\"store_true\", help=\"sort by physical address.\")\n    parser.add_argument(\"-Q\", \"--simple\", action=\"store_true\", help=\"merge with ignoring physical address consecutivness.\")\n    parser.add_argument(\"-f\", \"--filter\", metavar=\"REGEX\", action=\"append\", type=re.compile, default=[],\n                        help=\"filter by REGEX pattern.\")\n    parser.add_argument(\"-v\", \"--vrange\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified virtual address.\")\n    parser.add_argument(\"-p\", \"--prange\", metavar=\"PADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"filter by map included specified physical address.\")\n    parser.add_argument(\"-t\", \"--trace\", metavar=\"VADDR\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"show all level pagetables only associated specified address.\")\n    parser.add_argument(\"--optee\", action=\"store_true\", help=\"show the secure world memory maps if used OP-TEE.\")\n    parser.add_argument(\"-0\", \"--only-TTBR0_EL1\", action=\"store_true\", help=\"Display only TTBR0_EL1 (if target==EL1)\")\n    parser.add_argument(\"-1\", \"--only-TTBR1_EL1\", action=\"store_true\", help=\"display only TTBR1_EL1 (if target==EL1)\")\n    parser.add_argument(\"-D\", \"--disable-color\", action=\"store_true\", help=\"disable RWX colored output\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    # If you want to dump the secure world memory map, you need to break in the secure world.\n    # This is because unlike ARMv7, TTBR0_EL1_S and TTBR1_EL1_S do not exist.\n    # It is difficult to know the correct value of the secure world's system registers while in the normal world,\n    # as the secure monitor saves all system registers to memory when the world changes.\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        self.ttbr0el1_mappings = None\n        self.ttbr1el1_mappings = None\n        self.ttbr0el2_mappings = None\n        self.ttbr1el2_mappings = None\n        self.vttbrel2_mappings = None\n        self.ttbr0el3_mappings = None\n        return\n\n    def read_mem_wrapper(self, addr, size=8):\n        \"\"\"\n        When pagewalking EL0/EL1 of the guest OS, gdb pagewalks the physical memory according to $TTBR0_ELx.\n        However, even if you try to read the physical memory, access to the address will fail\n        because it is actually an intermediate physical memory.\n        Therefore, in order to perform a pagewalk of EL0/EL1, EL2 mapping information is required.\n        This function is for reading from physical memory with that in mind.\n        \"\"\"\n\n        if self.EL3_M and self.TargetEL == 3:\n            return read_memory(addr, size)\n\n        # translate via EL2 mappings\n        if self.EL2_VM and self.TargetEL == 1 and self.el2_mappings:\n\n            def search_pa(addr):\n                for entry_info in self.el2_mappings:\n                    va, entry, sz, cnt, flags = entry_info\n                    if isinstance(va, str):\n                        va = int(va, 16)\n                    pa = entry & 0x0000_ffff_ffff_f000\n                    if va <= addr < va + sz:\n                        offset = addr - va\n                        return pa + offset, sz - offset\n                else: # not found\n                    raise\n\n            out = b\"\"\n            while size > 0:\n                paddr, available_sz = search_pa(addr)\n                out += self.read_physmem_cache(paddr, min([size, available_sz]))\n                size -= min(size, available_sz)\n            return out\n\n        # direct physmem read\n        else:\n            return self.read_physmem_cache(addr, size)\n\n    def format_flags_stage2(self, flag_info):\n        flag_info_key = tuple(flag_info)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n\n        if \"S2AP=00\" in flag_info:\n            if \"XN=00\" in flag_info:\n                flags += [\"EL0/---\", \"EL1/---\"]\n            elif \"XN=01\" in flag_info:\n                flags += [\"EL0/---\", \"EL1/---\"]\n            elif \"XN=10\" in flag_info:\n                flags += [\"EL0/---\", \"EL1/---\"]\n            elif \"XN=11\" in flag_info:\n                flags += [\"EL0/---\", \"EL1/---\"]\n        elif \"S2AP=01\" in flag_info:\n            if \"XN=00\" in flag_info:\n                flags += [\"EL0/R-X\", \"EL1/R-X\"]\n            elif \"XN=01\" in flag_info:\n                flags += [\"EL0/R-X\", \"EL1/R--\"]\n            elif \"XN=10\" in flag_info:\n                flags += [\"EL0/R--\", \"EL1/R--\"]\n            elif \"XN=11\" in flag_info:\n                flags += [\"EL0/R--\", \"EL1/R-X\"]\n        elif \"S2AP=10\" in flag_info:\n            if \"XN=00\" in flag_info:\n                flags += [\"EL0/-W-\", \"EL1/-W-\"]\n            elif \"XN=01\" in flag_info:\n                flags += [\"EL0/-W-\", \"EL1/-W-\"]\n            elif \"XN=10\" in flag_info:\n                flags += [\"EL0/-W-\", \"EL1/-W-\"]\n            elif \"XN=11\" in flag_info:\n                flags += [\"EL0/-W-\", \"EL1/-W-\"]\n        elif \"S2AP=11\" in flag_info:\n            if \"XN=00\" in flag_info:\n                flags += [\"EL0/RWX\", \"EL1/RWX\"]\n            elif \"XN=01\" in flag_info:\n                flags += [\"EL0/RWX\", \"EL1/RW-\"]\n            elif \"XN=10\" in flag_info:\n                flags += [\"EL0/RW-\", \"EL1/RW-\"]\n            elif \"XN=11\" in flag_info:\n                flags += [\"EL0/RW-\", \"EL1/RWX\"]\n\n        if not self.args.simple:\n            if \"AF\" in flag_info:\n                flags += [\"ACCESSED\"]\n            if \"DBM\" in flag_info:\n                flags += [\"DIRTY\"]\n            # stage2 has no `nG` bit\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    def format_flags(self, flag_info):\n        return self.__format_flags(flag_info, self.TargetEL, self.EL1_WXN, self.EL2_WXN, self.EL2_M20, self.EL3_WXN)\n\n    def __format_flags(self, flag_info, TargetEL, EL1_WXN, EL2_WXN, EL2_M20, EL3_WXN):\n        flag_info_key = (tuple(flag_info), TargetEL, EL1_WXN, EL2_WXN, EL2_M20, EL3_WXN)\n        x = self.flags_strings_cache.get(flag_info_key, None)\n        if x is not None:\n            return x\n\n        flags = []\n\n        # AP/APTable parsing\n        if \"AP=00\" in flag_info:\n            disable_write_access = 0\n            enable_unpriv_access = 0\n        elif \"AP=01\" in flag_info:\n            disable_write_access = 0\n            enable_unpriv_access = 1\n        elif \"AP=10\" in flag_info:\n            disable_write_access = 1\n            enable_unpriv_access = 0\n        elif \"AP=11\" in flag_info:\n            disable_write_access = 1\n            enable_unpriv_access = 1\n        if \"APTable2=00\" in flag_info:\n            pass\n        elif \"APTable2=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable2=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable2=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n        if \"APTable1=00\" in flag_info:\n            pass\n        elif \"APTable1=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable1=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable1=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n        if \"APTable0=00\" in flag_info:\n            pass\n        elif \"APTable0=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable0=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable0=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n        if \"APTable-1=00\" in flag_info:\n            pass\n        elif \"APTable-1=01\" in flag_info:\n            enable_unpriv_access &= 0\n        elif \"APTable-1=10\" in flag_info:\n            disable_write_access |= 1\n        elif \"APTable-1=11\" in flag_info:\n            disable_write_access |= 1\n            enable_unpriv_access &= 0\n\n        # UXN/UXNTable, XN/XNTable, PXN/PXNTable, NS/NSTable parsing\n        UXN = \"UXN\" in flag_info\n        UXN |= \"UXNTable2\" in flag_info\n        UXN |= \"UXNTable1\" in flag_info\n        UXN |= \"UXNTable0\" in flag_info\n        UXN |= \"UXNTable-1\" in flag_info\n        XN = \"XN\" in flag_info\n        XN |= \"XNTable2\" in flag_info\n        XN |= \"XNTable1\" in flag_info\n        XN |= \"XNTable0\" in flag_info\n        XN |= \"XNTable-1\" in flag_info\n        PXN = \"PXN\" in flag_info\n        PXN |= \"PXNTable2\" in flag_info\n        PXN |= \"PXNTable1\" in flag_info\n        PXN |= \"PXNTable0\" in flag_info\n        PXN |= \"PXNTable-1\" in flag_info\n        NS = \"NS\" in flag_info\n        NS |= \"NSTable2\" in flag_info\n        NS |= \"NSTable1\" in flag_info\n        NS |= \"NSTable0\" in flag_info\n        NS |= \"NSTable-1\" in flag_info\n\n        if TargetEL == 1:\n            # always support 2VA ranges\n            if UXN is False and PXN is False:\n                if disable_write_access == 0 and enable_unpriv_access == 0:\n                    if not EL1_WXN:\n                        flags += [\"EL0/--X\", \"EL1/RWX\"]\n                    else:\n                        flags += [\"EL0/--X\", \"EL1/RW-\"]\n                elif disable_write_access == 0 and enable_unpriv_access == 1:\n                    if not EL1_WXN:\n                        flags += [\"EL0/RWX\", \"EL1/RW-\"]\n                    else:\n                        flags += [\"EL0/RW-\", \"EL1/RW-\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 0:\n                    flags += [\"EL0/--X\", \"EL1/R-X\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 1:\n                    flags += [\"EL0/R-X\", \"EL1/R-X\"]\n            elif UXN is False and PXN is True:\n                if disable_write_access == 0 and enable_unpriv_access == 0:\n                    flags += [\"EL0/--X\", \"EL1/RW-\"]\n                elif disable_write_access == 0 and enable_unpriv_access == 1:\n                    if not EL1_WXN:\n                        flags += [\"EL0/RWX\", \"EL1/RW-\"]\n                    else:\n                        flags += [\"EL0/RW-\", \"EL1/RW-\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 0:\n                    flags += [\"EL0/--X\", \"EL1/R--\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 1:\n                    flags += [\"EL0/R-X\", \"EL1/R--\"]\n            elif UXN is True and PXN is False:\n                if disable_write_access == 0 and enable_unpriv_access == 0:\n                    if not EL1_WXN:\n                        flags += [\"EL0/---\", \"EL1/RWX\"]\n                    else:\n                        flags += [\"EL0/---\", \"EL1/RW-\"]\n                elif disable_write_access == 0 and enable_unpriv_access == 1:\n                    flags += [\"EL0/RW-\", \"EL1/RW-\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 0:\n                    flags += [\"EL0/---\", \"EL1/R-X\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 1:\n                    flags += [\"EL0/R--\", \"EL1/R-X\"]\n            elif UXN is True and PXN is True:\n                if disable_write_access == 0 and enable_unpriv_access == 0:\n                    flags += [\"EL0/---\", \"EL1/RW-\"]\n                elif disable_write_access == 0 and enable_unpriv_access == 1:\n                    flags += [\"EL0/RW-\", \"EL1/RW-\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 0:\n                    flags += [\"EL0/---\", \"EL1/R--\"]\n                elif disable_write_access == 1 and enable_unpriv_access == 1:\n                    flags += [\"EL0/R--\", \"EL1/R--\"]\n        elif TargetEL == 2:\n            if EL2_M20:\n                # support 2VA ranges if HCR_EL2.{TGE,E2H} == {1,1} # codespell:ignore\n                if UXN is False and PXN is False:\n                    if disable_write_access == 0 and enable_unpriv_access == 0:\n                        if not EL2_WXN:\n                            flags += [\"EL0/--X\", \"EL2/RWX\"]\n                        else:\n                            flags += [\"EL0/--X\", \"EL2/RW-\"]\n                    elif disable_write_access == 0 and enable_unpriv_access == 1:\n                        if not EL2_WXN:\n                            flags += [\"EL0/RWX\", \"EL2/RW-\"]\n                        else:\n                            flags += [\"EL0/RW-\", \"EL2/RW-\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 0:\n                        flags += [\"EL0/--X\", \"EL2/R-X\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 1:\n                        flags += [\"EL0/R-X\", \"EL2/R-X\"]\n                elif UXN is False and PXN is True:\n                    if disable_write_access == 0 and enable_unpriv_access == 0:\n                        flags += [\"EL0/--X\", \"EL2/RW-\"]\n                    elif disable_write_access == 0 and enable_unpriv_access == 1:\n                        if not EL2_WXN:\n                            flags += [\"EL0/RWX\", \"EL2/RW-\"]\n                        else:\n                            flags += [\"EL0/RW-\", \"EL2/RW-\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 0:\n                        flags += [\"EL0/--X\", \"EL2/R--\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 1:\n                        flags += [\"EL0/R-X\", \"EL2/R--\"]\n                elif UXN is True and PXN is False:\n                    if disable_write_access == 0 and enable_unpriv_access == 0:\n                        if not EL2_WXN:\n                            flags += [\"EL0/---\", \"EL2/RWX\"]\n                        else:\n                            flags += [\"EL0/---\", \"EL2/RW-\"]\n                    elif disable_write_access == 0 and enable_unpriv_access == 1:\n                        flags += [\"EL0/RW-\", \"EL2/RW-\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 0:\n                        flags += [\"EL0/---\", \"EL2/R-X\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 1:\n                        flags += [\"EL0/R--\", \"EL2/R-X\"]\n                elif UXN is True and PXN is True:\n                    if disable_write_access == 0 and enable_unpriv_access == 0:\n                        flags += [\"EL0/---\", \"EL2/RW-\"]\n                    elif disable_write_access == 0 and enable_unpriv_access == 1:\n                        flags += [\"EL0/RW-\", \"EL2/RW-\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 0:\n                        flags += [\"EL0/---\", \"EL2/R--\"]\n                    elif disable_write_access == 1 and enable_unpriv_access == 1:\n                        flags += [\"EL0/R--\", \"EL2/R--\"]\n            else:\n                # not support 2VA ranges if HCR_EL2.{TGE,E2H} != {1,1} # codespell:ignore\n                if XN is False:\n                    if disable_write_access == 0:\n                        if not EL2_WXN:\n                            flags += [\"EL2/RWX\"]\n                        else:\n                            flags += [\"EL2/RW-\"]\n                    elif disable_write_access == 1:\n                        flags += [\"EL2/R-X\"]\n                elif XN is True:\n                    if disable_write_access == 0:\n                        flags += [\"EL2/RW-\"]\n                    elif disable_write_access == 1:\n                        flags += [\"EL2/R--\"]\n        elif TargetEL == 3:\n            if XN is False:\n                if disable_write_access == 0:\n                    if not EL3_WXN:\n                        flags += [\"EL3/RWX\"]\n                    else:\n                        flags += [\"EL3/RW-\"]\n                elif disable_write_access == 1:\n                    flags += [\"EL3/R-X\"]\n            elif XN is True:\n                if disable_write_access == 0:\n                    flags += [\"EL3/RW-\"]\n                elif disable_write_access == 1:\n                    flags += [\"EL3/R--\"]\n        if NS:\n            flags += [\"NS\"]\n\n        if not self.args.simple:\n            if \"AF\" in flag_info:\n                flags += [\"ACCESSED\"]\n            if \"DBM\" in flag_info:\n                flags += [\"DIRTY\"]\n            if \"nG\" not in flag_info:\n                flags += [\"GLOBAL\"]\n\n        flag_string = \" \".join(flags)\n        self.flags_strings_cache[flag_info_key] = flag_string\n        return flag_string\n\n    \"\"\"\n    Relation diagram when CPU uses\n\n      Stage1                  |     Stage2\n    -------------------------------------------------------\n    +----------------------+  |   +----------------------+\n    | Guest OS table       | -|-> | Virtualization table |\n    +----------------------+  |   +----------------------+\n      TTBR0_EL1, TTBR1_EL1    |     VTTBR0_EL2\n                              |\n    +----------------------+  |\n    | Hypervisor table     |  |\n    +----------------------+  |\n      TTBR0_EL2, TTBR1_EL2    |\n                              |\n    +----------------------+  |\n    | Secure monitor table |  |\n    +----------------------+  |\n      TTBR0_EL3               |\n                              |\n\n    Since it is an implementation that dumps for each EL, consider as follows.\n\n      TargetEL=1              |    TargetEL=2              |    TargetEL=3\n    ---------------------------------------------------------------------------------\n    +----------------------+  |  +----------------------+  |  +----------------------+\n    | Guest OS table       |  |  | Virtualization table |  |  | Secure monitor table |\n    +----------------------+  |  +----------------------+  |  +----------------------+\n      TTBR0_EL1, TTBR1_EL1    |    VTTBR0_EL2              |    TTBR0_EL3\n                              |                            |\n                              |  +----------------------+  |\n                              |  | Hypervisor table     |  |\n                              |  +----------------------+  |\n                              |    TTBR0_EL2, TTBR1_EL2    |\n                              |                            |\n    \"\"\"\n\n    def parse_bit_range(self, granule_bits, region_bits):\n        IA_LVA_MAX = 52 if self.FEAT_LVA else 48\n        if granule_bits == 12: # 4KB granule\n            self.LEVELM1_BIT_RANGE = [48, min(IA_LVA_MAX, region_bits)] if region_bits > 48 else None # no block descriptor\n            self.LEVEL0_BIT_RANGE = [39, min(48, region_bits)] if region_bits > 39 else None          # 512GB\n            self.LEVEL1_BIT_RANGE = [30, min(39, region_bits)] if region_bits > 30 else None          # 1GB\n            self.LEVEL2_BIT_RANGE = [21, min(30, region_bits)] if region_bits > 21 else None          # 2MB\n            self.LEVEL3_BIT_RANGE = [12, min(21, region_bits)] if region_bits > 12 else None          # 4KB\n            self.OFFSET_BIT_RANGE = [0, 12]\n        elif granule_bits == 14: # 16KB granule\n            self.LEVELM1_BIT_RANGE = None\n            self.LEVEL0_BIT_RANGE = [47, min(IA_LVA_MAX, region_bits)] if region_bits > 47 else None  # no block descriptor\n            self.LEVEL1_BIT_RANGE = [36, min(47, region_bits)] if region_bits > 36 else None          # 64GB\n            self.LEVEL2_BIT_RANGE = [25, min(36, region_bits)] if region_bits > 25 else None          # 32MB\n            self.LEVEL3_BIT_RANGE = [14, min(25, region_bits)] if region_bits > 14 else None          # 16KB\n            self.OFFSET_BIT_RANGE = [0, 14]\n        elif granule_bits == 16: # 64KB granule\n            self.LEVELM1_BIT_RANGE = None\n            self.LEVEL0_BIT_RANGE = None\n            self.LEVEL1_BIT_RANGE = [42, min(IA_LVA_MAX, region_bits)] if region_bits > 42 else None  # 4TB\n            self.LEVEL2_BIT_RANGE = [29, min(42, region_bits)] if region_bits > 29 else None          # 512MB\n            self.LEVEL3_BIT_RANGE = [16, min(29, region_bits)] if region_bits > 16 else None          # 64KB\n            self.OFFSET_BIT_RANGE = [0, 16]\n        else:\n            if not self.silent:\n                self.err_add_out(\"Unsupported granule_bits\")\n            return\n\n        if not self.silent:\n            self.quiet_info_add_out(\"granule_bits: {:d}\".format(granule_bits))\n            self.quiet_info_add_out(\"LEVELM1_BIT_RANGE: \" + str(self.LEVELM1_BIT_RANGE))\n            self.quiet_info_add_out(\"LEVEL0_BIT_RANGE: \" + str(self.LEVEL0_BIT_RANGE))\n            self.quiet_info_add_out(\"LEVEL1_BIT_RANGE: \" + str(self.LEVEL1_BIT_RANGE))\n            self.quiet_info_add_out(\"LEVEL2_BIT_RANGE: \" + str(self.LEVEL2_BIT_RANGE))\n            self.quiet_info_add_out(\"LEVEL3_BIT_RANGE: \" + str(self.LEVEL3_BIT_RANGE))\n            self.quiet_info_add_out(\"OFFSET_BIT_RANGE: \" + str(self.OFFSET_BIT_RANGE))\n        return\n\n    def get_entries_per_table(self, BIT_RANGE, granule_bits, region_bits, is_first_level):\n        if is_first_level and region_bits > BIT_RANGE[1]:\n            idx_bits = {12: 9, 14: 11, 16: 13}[granule_bits]\n            offset_bits = granule_bits\n            remainder = (region_bits - offset_bits) % idx_bits\n            entries_per_table = 1 << (idx_bits + remainder)\n        else:\n            used_from_ia = BIT_RANGE[1] - BIT_RANGE[0]\n            entries_per_table = 1 << used_from_ia\n\n        if not self.silent:\n            self.quiet_info_add_out(\"Entries per table: {:d}\".format(entries_per_table))\n        return entries_per_table\n\n    def do_pagewalk(self, table_base, granule_bits, region_start, region_bits, start_level, is_stage2=False, is_2VAranges=False):\n        # table_base: The start address of pagewalk.\n        # granule_bits: One of [12, 14, 16]; It specifies how to separate the bits used for address translation.\n        # region_start: The base address of translated address.\n        # start_level: The start level of the pagewalking.\n        # is_stage2: Whether VTTBR0_EL2 or not. Affects entry bitfield interpretation.\n        # is_2VAranges: TTBR0/TTBR1 presence at target EL. Affects entry bitfield interpretation.\n        self.mappings = []\n\n        is_4k_granule = granule_bits == 12\n        is_16k_granule = granule_bits == 14\n        is_64k_granule = granule_bits == 16\n\n        def has_next_level(entry): # for Level0, 1, 2 but not Level3\n            return (entry & 0b11) == 0b11\n\n        flags = []\n        TABLE_BASE = [[region_start, table_base, flags]]\n\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n\n        # level -1 parse for 4KB granule\n        if not self.silent:\n            self.quiet_add_out(titlify(\"LEVEL -1\"))\n        if self.LEVELM1_BIT_RANGE is not None and start_level == -1:\n            entries_per_table = self.get_entries_per_table(\n                self.LEVELM1_BIT_RANGE, granule_bits, region_bits, is_first_level=(start_level == -1),\n            )\n            LEVELM1 = []\n            COUNT = 0\n            for va_base, table_base, parent_flags in tqdm(TABLE_BASE, leave=False, desc=\"LEVEL -1\"):\n                entries = self.read_mem_wrapper(table_base, 8 * entries_per_table)\n                entries = slice_unpack(entries, 8)\n                COUNT += len(entries)\n                for i, entry in enumerate(entries):\n                    # present flag\n                    if entry & 1 == 0:\n                        continue\n\n                    # calc virtual address\n                    new_va = va_base + (i << self.LEVELM1_BIT_RANGE[0])\n                    new_va_end = new_va + (1 << self.LEVELM1_BIT_RANGE[0])\n\n                    # calc flags\n                    flags = parent_flags.copy()\n                    if has_next_level(entry):\n                        if is_stage2:\n                            # VTTBR_EL2 does not have level -1\n                            raise\n                        elif is_2VAranges:\n                            if ((entry >> 59) & 1) == 1:\n                                flags.append(\"PXNTable-1\")\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"UXNTable-1\")\n                            flags.append(\"APTable-1={:02b}\".format((entry >> 61) & 0b11))\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable-1\")\n                        else:\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"XNTable-1\") # Use XNTable, not UXNTable # PXNTable is undefined\n                            flags.append(\"APTable-1={:02b}\".format((entry >> 61) & 0b11 & 0b10)) # APTable[0] must be 0\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable-1\")\n                    else:\n                        # In ARMv8.7, level -1 has no block descriptors\n                        raise\n\n                    # calc next table / output phys addr (drop the flag bits)\n                    if has_next_level(entry):\n                        # In aRMv8.7, level -1 must be 4k_granule\n                        if self.TCR_ELx_DS:\n                            next_level_table = (entry & 0x0003_ffff_ffff_f000) | (((entry >> 8) & 0b11) << 50)\n                        else:\n                            next_level_table = entry & 0x0003_ffff_ffff_f000\n                    else:\n                        # In ARMv8.7, level -1 has no block descriptors\n                        raise\n\n                    # make entry\n                    if has_next_level(entry):\n                        LEVELM1.append([new_va, next_level_table, flags])\n                        entry_type = \"TABLE\"\n                    else:\n                        # In ARMv8.7, level -1 has no block descriptors\n                        raise\n\n                    # dump\n                    if self.args.print_each_level:\n                        if self.is_not_trace_target(new_va, new_va_end):\n                            continue\n                        addr = table_base + i * 8\n                        line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                            addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                        )\n                        if self.is_not_filter_target(line):\n                            continue\n                        self.out.append(line)\n\n            if not self.silent:\n                if self.args.print_each_level:\n                    self.out.append(titlify(\"\"))\n                self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n                self.quiet_info_add_out(\"Level -1 Entry: {:d}\".format(len(LEVELM1)))\n                self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVELM1)))\n            self.mappings += []\n        else:\n            if not self.silent:\n                self.quiet_info_add_out(\"LEVEL -1 is skipped\")\n            LEVELM1 = TABLE_BASE\n\n        # level 0 parse for 4KB/16KB granule\n        if not self.silent:\n            self.quiet_add_out(titlify(\"LEVEL 0\"))\n        if self.LEVEL0_BIT_RANGE is not None and start_level <= 0:\n            entries_per_table = self.get_entries_per_table(\n                self.LEVEL0_BIT_RANGE, granule_bits, region_bits, is_first_level=(start_level == 0),\n            )\n            LEVEL0 = []\n            GB512 = []\n            COUNT = 0\n            for va_base, table_base, parent_flags in tqdm(LEVELM1, leave=False, desc=\"LEVEL 0\"):\n                entries = self.read_mem_wrapper(table_base, 8 * entries_per_table)\n                entries = slice_unpack(entries, 8)\n                COUNT += len(entries)\n                for i, entry in enumerate(entries):\n                    # present flag\n                    if entry & 1 == 0:\n                        continue\n\n                    # calc virtual address\n                    new_va = va_base + (i << self.LEVEL0_BIT_RANGE[0])\n                    new_va_end = new_va + (1 << self.LEVEL0_BIT_RANGE[0])\n\n                    # calc flags\n                    flags = parent_flags.copy()\n                    if has_next_level(entry):\n                        if is_stage2:\n                            # There are no flags in the table for VTTBR0_EL2.\n                            pass\n                        elif is_2VAranges:\n                            if ((entry >> 59) & 1) == 1:\n                                flags.append(\"PXNTable0\")\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"UXNTable0\")\n                            flags.append(\"APTable0={:02b}\".format((entry >> 61) & 0b11))\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable0\")\n                        else:\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"XNTable0\") # Use XNTable, not UXNTable # PXNTable is undefined\n                            flags.append(\"APTable0={:02b}\".format((entry >> 61) & 0b11 & 0b10)) # APTable[0] must be 0\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable0\")\n                    else:\n                        if is_stage2:\n                            flags.append(\"MemAttr={:#x}\".format((entry >> 2) & 0b1111))\n                            flags.append(\"S2AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            flags.append(\"XN={:02b}\".format((entry >> 53) & 0b11)) # Use XN, not UXN\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        elif is_2VAranges:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 53) & 1) == 1:\n                                flags.append(\"PXN\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"UXN\")\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        else:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11 & 0b10)) # AP[0] must be 0\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"XN\") # Use XN, not UXN # PXN is undefined\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n\n                    # calc next table / output phys addr (drop the flag bits)\n                    if has_next_level(entry):\n                        if self.FEAT_LPA:\n                            # In aRMv8.7, level 0 must be 4k_granule or 16k_granule\n                            if self.TCR_ELx_DS:\n                                next_level_table = (entry & 0x0003_ffff_ffff_f000) | (((entry >> 8) & 0b11) << 50)\n                            else:\n                                next_level_table = entry & 0x0003_ffff_ffff_f000\n                        else:\n                            next_level_table = entry & 0x0000_ffff_ffff_f000\n                    else:\n                        if self.FEAT_LPA:\n                            # In aRMv8.7, level 0 must be 4k_granule or 16k_granule\n                            if self.TCR_ELx_DS:\n                                phys_addr = (entry & 0x0003_ffff_fffe_0000) | (((entry >> 8) & 0b11) << 50)\n                            else:\n                                phys_addr = entry & 0x0003_ffff_fffe_0000\n                        else:\n                            # In ARMv8.7, level 0 + no-FEAT_LPA has no block descriptors\n                            raise\n\n                    # make entry\n                    if has_next_level(entry):\n                        LEVEL0.append([new_va, next_level_table, flags])\n                        entry_type = \"TABLE\"\n                    else:\n                        virt_addr = new_va\n                        page_count = 1\n                        if is_stage2:\n                            flag_string = self.format_flags_stage2(flags)\n                        else:\n                            flag_string = self.format_flags(flags)\n                        if is_4k_granule:\n                            page_size = 512 * 1024 * 1024 * 1024\n                            GB512.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"512GB-PAGE\"\n                        else:\n                            raise\n\n                    # dump\n                    if self.args.print_each_level:\n                        if self.is_not_trace_target(new_va, new_va_end):\n                            continue\n                        addr = table_base + i * 8\n                        line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                            addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                        )\n                        if self.is_not_filter_target(line):\n                            continue\n                        self.out.append(line)\n\n            if not self.silent:\n                if self.args.print_each_level:\n                    self.out.append(titlify(\"\"))\n                self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n                self.quiet_info_add_out(\"Level 0 Entry: {:d}\".format(len(LEVEL0)))\n                self.quiet_info_add_out(\"PT Entry (512GB): {:d}\".format(len(GB512)))\n                self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL0) - len(GB512)))\n            self.mappings += GB512\n        else:\n            if not self.silent:\n                self.quiet_info_add_out(\"LEVEL 0 is skipped\")\n            LEVEL0 = TABLE_BASE\n\n        # level 1 parse for 4KB/16KB/64KB granule\n        if not self.silent:\n            self.quiet_add_out(titlify(\"LEVEL 1\"))\n        if self.LEVEL1_BIT_RANGE is not None and start_level <= 1:\n            entries_per_table = self.get_entries_per_table(\n                self.LEVEL1_BIT_RANGE, granule_bits, region_bits, is_first_level=(start_level == 1),\n            )\n            LEVEL1 = []\n            GB1 = []\n            TB4 = []\n            GB64 = []\n            COUNT = 0\n            for va_base, table_base, parent_flags in tqdm(LEVEL0, leave=False, desc=\"LEVEL 1\"):\n                entries = self.read_mem_wrapper(table_base, 8 * entries_per_table)\n                entries = slice_unpack(entries, 8)\n                COUNT += len(entries)\n                for i, entry in enumerate(entries):\n                    # present flag\n                    if entry & 1 == 0:\n                        continue\n\n                    # calc virtual address\n                    new_va = va_base + (i << self.LEVEL1_BIT_RANGE[0])\n                    new_va_end = new_va + (1 << self.LEVEL1_BIT_RANGE[0])\n\n                    # calc flags\n                    flags = parent_flags.copy()\n                    if has_next_level(entry):\n                        if is_stage2:\n                            # There are no flags in the table for VTTBR0_EL2.\n                            pass\n                        elif is_2VAranges:\n                            if ((entry >> 59) & 1) == 1:\n                                flags.append(\"PXNTable1\")\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"UXNTable1\")\n                            flags.append(\"APTable1={:02b}\".format((entry >> 61) & 0b11))\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable1\")\n                        else:\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"XNTable1\") # Use XNTable, not UXNTable # PXNTable is undefined\n                            flags.append(\"APTable1={:02b}\".format((entry >> 61) & 0b11 & 0b10)) # APTable[0] must be 0\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable1\")\n                    else:\n                        if is_stage2:\n                            flags.append(\"MemAttr={:#x}\".format((entry >> 2) & 0b1111))\n                            flags.append(\"S2AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            flags.append(\"XN={:02b}\".format((entry >> 53) & 0b11)) # Use XN, not UXN\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        elif is_2VAranges:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 53) & 1) == 1:\n                                flags.append(\"PXN\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"UXN\")\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        else:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11 & 0b10)) # AP[0] must be 0\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"XN\") # Use XN, not UXN # PXN is undefined\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n\n                    # calc next table / output phys addr (drop the flag bits)\n                    if has_next_level(entry):\n                        if self.FEAT_LPA:\n                            if is_64k_granule:\n                                next_level_table = (entry & 0x0000_ffff_ffff_0000) | (((entry >> 12) & 0b1111) << 48)\n                            else: # 4k or 16k\n                                if self.TCR_ELx_DS:\n                                    next_level_table = (entry & 0x0003_ffff_ffff_f000) | (((entry >> 8) & 0b11) << 50)\n                                else:\n                                    next_level_table = entry & 0x0003_ffff_ffff_f000\n                        else:\n                            next_level_table = entry & 0x0000_ffff_ffff_f000\n                    else:\n                        if self.FEAT_LPA:\n                            if is_64k_granule:\n                                phys_addr = (entry & 0x0000_ffff_fffe_0000) | (((entry >> 12) & 0b1111) << 48)\n                            else: # 4k or 16k\n                                if self.TCR_ELx_DS:\n                                    phys_addr = (entry & 0x0003_ffff_fffe_0000) | (((entry >> 8) & 0b11) << 50)\n                                else:\n                                    phys_addr = entry & 0x0003_ffff_fffe_0000\n                        else:\n                            phys_addr = entry & 0x0000_ffff_fffe_0000\n\n                    # make entry\n                    if has_next_level(entry):\n                        LEVEL1.append([new_va, next_level_table, flags])\n                        entry_type = \"TABLE\"\n                    else:\n                        virt_addr = new_va\n                        page_count = 1\n                        if is_stage2:\n                            flag_string = self.format_flags_stage2(flags)\n                        else:\n                            flag_string = self.format_flags(flags)\n                        if is_4k_granule:\n                            page_size = 1 * 1024 * 1024 * 1024\n                            GB1.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"1GB-PAGE\"\n                        elif is_16k_granule:\n                            page_size = 64 * 1024 * 1024 * 1024\n                            GB64.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"64GB-PAGE\"\n                        elif is_64k_granule:\n                            page_size = 4 * 1024 * 1024 * 1024 * 1024\n                            TB4.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"4TB-PAGE\"\n\n                    # dump\n                    if self.args.print_each_level:\n                        if self.is_not_trace_target(new_va, new_va_end):\n                            continue\n                        addr = table_base + i * 8\n                        line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                            addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                        )\n                        if self.is_not_filter_target(line):\n                            continue\n                        self.out.append(line)\n\n            if not self.silent:\n                if self.args.print_each_level:\n                    self.out.append(titlify(\"\"))\n                self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n                self.quiet_info_add_out(\"Level 1 Entry: {:d}\".format(len(LEVEL1)))\n                self.quiet_info_add_out(\"PT Entry (1GB): {:d}\".format(len(GB1)))\n                self.quiet_info_add_out(\"PT Entry (64GB): {:d}\".format(len(GB64)))\n                self.quiet_info_add_out(\"PT Entry (4TB): {:d}\".format(len(TB4)))\n                self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL1) - len(GB1) - len(GB64) - len(TB4)))\n            self.mappings += GB1 + GB64 + TB4\n        else:\n            if not self.silent:\n                self.quiet_info_add_out(\"LEVEL 1 is skipped\")\n            LEVEL1 = LEVEL0\n\n        # level 2 parse for 4KB/16KB/64KB granule\n        if not self.silent:\n            self.quiet_add_out(titlify(\"LEVEL 2\"))\n        if self.LEVEL2_BIT_RANGE is not None and start_level <= 2:\n            entries_per_table = self.get_entries_per_table(\n                self.LEVEL2_BIT_RANGE, granule_bits, region_bits, is_first_level=(start_level == 2),\n            )\n            LEVEL2 = []\n            MB2 = []\n            MB32 = []\n            MB512 = []\n            COUNT = 0\n            for va_base, table_base, parent_flags in tqdm(LEVEL1, leave=False, desc=\"LEVEL 2\"):\n                entries = self.read_mem_wrapper(table_base, 8 * entries_per_table)\n                entries = slice_unpack(entries, 8)\n                COUNT += len(entries)\n                for i, entry in enumerate(entries):\n                    # present flag\n                    if entry & 1 == 0:\n                        continue\n\n                    # calc virtual address\n                    new_va = va_base + (i << self.LEVEL2_BIT_RANGE[0])\n                    new_va_end = new_va + (1 << self.LEVEL2_BIT_RANGE[0])\n\n                    # calc flags\n                    flags = parent_flags.copy()\n                    if has_next_level(entry):\n                        if is_stage2:\n                            # There are no flags in the table for VTTBR0_EL2.\n                            pass\n                        elif is_2VAranges:\n                            if ((entry >> 59) & 1) == 1:\n                                flags.append(\"PXNTable2\")\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"UXNTable2\")\n                            flags.append(\"APTable2={:02b}\".format((entry >> 61) & 0b11))\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable2\")\n                        else:\n                            if ((entry >> 60) & 1) == 1:\n                                flags.append(\"XNTable2\") # Use XNTable, not UXNTable # PXNTable is undefined\n                            flags.append(\"APTable2={:02b}\".format((entry >> 61) & 0b11 & 0b10)) # APTable[0] must be 0\n                            if ((entry >> 63) & 1) == 1:\n                                flags.append(\"NSTable2\")\n                    else:\n                        if is_stage2:\n                            flags.append(\"MemAttr={:#x}\".format((entry >> 2) & 0b1111))\n                            flags.append(\"S2AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            flags.append(\"XN={:02b}\".format((entry >> 53) & 0b11)) # Use XN, not UXN\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        elif is_2VAranges:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 53) & 1) == 1:\n                                flags.append(\"PXN\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"UXN\")\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        else:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11 & 0b10)) # AP[0] must be 0\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"XN\") # Use XN, not UXN # PXN is undefined\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n\n                    # calc next table / output phys addr (drop the flag bits)\n                    if has_next_level(entry):\n                        if self.FEAT_LPA:\n                            if is_64k_granule:\n                                next_level_table = (entry & 0x0000_ffff_ffff_0000) | (((entry >> 12) & 0b1111) << 48)\n                            else: # 4k or 16k\n                                if self.TCR_ELx_DS:\n                                    next_level_table = (entry & 0x0003_ffff_ffff_f000) | (((entry >> 8) & 0b11) << 50)\n                                else:\n                                    next_level_table = entry & 0x0003_ffff_ffff_f000\n                        else:\n                            next_level_table = entry & 0x0000_ffff_ffff_f000\n                    else:\n                        if self.FEAT_LPA:\n                            if is_64k_granule:\n                                phys_addr = (entry & 0x0000_ffff_fffe_0000) | (((entry >> 12) & 0b1111) << 48)\n                            else: # 4k or 16k\n                                if self.TCR_ELx_DS:\n                                    phys_addr = (entry & 0x0003_ffff_fffe_0000) | (((entry >> 8) & 0b11) << 50)\n                                else:\n                                    phys_addr = entry & 0x0003_ffff_fffe_0000\n                        else:\n                            phys_addr = entry & 0x0000_ffff_fffe_0000\n\n                    # make entry\n                    if has_next_level(entry):\n                        LEVEL2.append([new_va, next_level_table, flags])\n                        entry_type = \"TABLE\"\n                    else:\n                        virt_addr = new_va\n                        page_count = 1\n                        if is_stage2:\n                            flag_string = self.format_flags_stage2(flags)\n                        else:\n                            flag_string = self.format_flags(flags)\n                        if is_4k_granule:\n                            page_size = 2 * 1024 * 1024\n                            MB2.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"2MB-PAGE\"\n                        elif is_16k_granule:\n                            page_size = 32 * 1024 * 1024\n                            MB32.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"32MB-PAGE\"\n                        elif is_64k_granule:\n                            page_size = 512 * 1024 * 1024\n                            MB512.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                            entry_type = \"512MB-PAGE\"\n\n                    # dump\n                    if self.args.print_each_level:\n                        if self.is_not_trace_target(new_va, new_va_end):\n                            continue\n                        addr = table_base + i * 8\n                        line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                            addr, entry, new_va, new_va_end, entry_type, \" \".join(flags),\n                        )\n                        if self.is_not_filter_target(line):\n                            continue\n                        self.out.append(line)\n\n            if not self.silent:\n                if self.args.print_each_level:\n                    self.out.append(titlify(\"\"))\n                self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n                self.quiet_info_add_out(\"Level 2 Entry: {:d}\".format(len(LEVEL2)))\n                self.quiet_info_add_out(\"PT Entry (2MB): {:d}\".format(len(MB2)))\n                self.quiet_info_add_out(\"PT Entry (32MB): {:d}\".format(len(MB32)))\n                self.quiet_info_add_out(\"PT Entry (512MB): {:d}\".format(len(MB512)))\n                self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(LEVEL2) - len(MB2) - len(MB32) - len(MB512)))\n            self.mappings += MB2 + MB32 + MB512\n        else:\n            if not self.silent:\n                self.quiet_info_add_out(\"LEVEL 2 is skipped\")\n            LEVEL2 = LEVEL1\n\n        # level 3 parse for 4KB/16KB/64KB granule\n        if not self.silent:\n            self.quiet_add_out(titlify(\"LEVEL 3\"))\n        if self.LEVEL3_BIT_RANGE is not None and start_level <= 3:\n            entries_per_table = self.get_entries_per_table(\n                self.LEVEL3_BIT_RANGE, granule_bits, region_bits, is_first_level=False,\n            )\n            KB4 = []\n            KB16 = []\n            KB64 = []\n            COUNT = 0\n            flag_cache = {}\n\n            for va_base, table_base, parent_flags in tqdm(LEVEL2, leave=False, desc=\"LEVEL 3\"):\n                entries = self.read_mem_wrapper(table_base, 8 * entries_per_table)\n                entries = slice_unpack(entries, 8)\n                COUNT += len(entries)\n                for i, entry in enumerate(entries):\n                    # present flag\n                    if entry & 1 == 0:\n                        continue\n\n                    # calc virtual address\n                    virt_addr = va_base + (i << self.LEVEL3_BIT_RANGE[0])\n                    virt_addr_end = virt_addr + (1 << self.LEVEL3_BIT_RANGE[0])\n\n                    # calc flags\n                    flags = parent_flags.copy()\n                    if (entry & 0b11) == 0b11:\n                        if is_stage2:\n                            flags.append(\"MemAttr={:#x}\".format((entry >> 2) & 0b1111))\n                            flags.append(\"S2AP={:02b}\".format((entry >> 6) & 0b11))\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            flags.append(\"XN={:02b}\".format((entry >> 53) & 0b11)) # Use XN, not UXN\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                        elif is_2VAranges:\n                            # This route passes many times, so make a memo\n                            entry_flags_key = entry & 0x787c_0000_0001_0ffc\n                            x = flag_cache.get(entry_flags_key, None)\n                            if x is not None:\n                                flags.extend(x)\n                            else:\n                                flags_tmp = []\n                                flags_tmp.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                                if ((entry >> 5) & 1) == 1:\n                                    flags_tmp.append(\"NS\")\n                                flags_tmp.append(\"AP={:02b}\".format((entry >> 6) & 0b11))\n                                flags_tmp.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                                if ((entry >> 10) & 1) == 1:\n                                    flags_tmp.append(\"AF\")\n                                if ((entry >> 11) & 1) == 1:\n                                    flags_tmp.append(\"nG\")\n                                if ((entry >> 16) & 1) == 1:\n                                    flags_tmp.append(\"nT\")\n                                if ((entry >> 50) & 1) == 1:\n                                    flags_tmp.append(\"GP\")\n                                if ((entry >> 51) & 1) == 1:\n                                    flags_tmp.append(\"DBM\")\n                                if ((entry >> 52) & 1) == 1:\n                                    flags_tmp.append(\"Contiguous\")\n                                if ((entry >> 53) & 1) == 1:\n                                    flags_tmp.append(\"PXN\")\n                                if ((entry >> 54) & 1) == 1:\n                                    flags_tmp.append(\"UXN\")\n                                flags_tmp.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                                flag_cache[entry_flags_key] = flags_tmp\n                                flags.extend(flags_tmp)\n                        else:\n                            flags.append(\"AttrIndx={:03b}\".format((entry >> 2) & 0b111))\n                            if ((entry >> 5) & 1) == 1:\n                                flags.append(\"NS\")\n                            flags.append(\"AP={:02b}\".format((entry >> 6) & 0b11 & 0b10)) # AP[0] must be 0\n                            flags.append(\"SH={:02b}\".format((entry >> 8) & 0b11))\n                            if ((entry >> 10) & 1) == 1:\n                                flags.append(\"AF\")\n                            if ((entry >> 11) & 1) == 1:\n                                flags.append(\"nG\")\n                            if ((entry >> 16) & 1) == 1:\n                                flags.append(\"nT\")\n                            if ((entry >> 50) & 1) == 1:\n                                flags.append(\"GP\")\n                            if ((entry >> 51) & 1) == 1:\n                                flags.append(\"DBM\")\n                            if ((entry >> 52) & 1) == 1:\n                                flags.append(\"Contiguous\")\n                            if ((entry >> 54) & 1) == 1:\n                                flags.append(\"XN\") # Use XN, not UXN # PXN is undefined\n                            flags.append(\"PBHA={:#x}\".format((entry >> 59) & 0b1111))\n                    else:\n                        # In ARMv8.7, level 3 has no table descriptors\n                        raise\n\n                    # calc next table / output phys addr (drop the flag bits)\n                    if is_4k_granule:\n                        if self.FEAT_LPA:\n                            if self.TCR_ELx_DS:\n                                phys_addr = (entry & 0x0003_ffff_ffff_f000) | (((entry >> 8) & 0b11) << 50)\n                            else:\n                                phys_addr = entry & 0x0003_ffff_ffff_f000\n                        else:\n                            phys_addr = entry & 0x0000_ffff_ffff_f000\n                    elif is_16k_granule:\n                        if self.FEAT_LPA:\n                            if self.TCR_ELx_DS:\n                                phys_addr = (entry & 0x0003_ffff_ffff_c000) | (((entry >> 8) & 0b11) << 50)\n                            else:\n                                phys_addr = entry & 0x0003_ffff_ffff_c000\n                        else:\n                            phys_addr = entry & 0x0000_ffff_ffff_c000\n                    elif is_64k_granule:\n                        if self.FEAT_LPA:\n                            phys_addr = (entry & 0x0000_ffff_ffff_0000) | (((entry >> 12) & 0b1111) << 48)\n                        else:\n                            phys_addr = entry & 0x0000_ffff_ffff_0000\n\n                    # make entry\n                    page_count = 1\n                    if is_stage2:\n                        flag_string = self.format_flags_stage2(flags)\n                    else:\n                        flag_string = self.format_flags(flags)\n                    if is_4k_granule:\n                        page_size = 4 * 1024\n                        KB4.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                        entry_type = \"4KB-PAGE\"\n                    elif is_16k_granule:\n                        page_size = 16 * 1024\n                        KB16.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                        entry_type = \"16KB-PAGE\"\n                    elif is_64k_granule:\n                        page_size = 64 * 1024\n                        KB64.append([virt_addr, phys_addr, page_size, page_count, flag_string])\n                        entry_type = \"64KB-PAGE\"\n\n                    # dump\n                    if self.args.print_each_level:\n                        if self.is_not_trace_target(virt_addr, virt_addr_end):\n                            continue\n                        addr = table_base + i * 8\n                        line = \"{:#018x}: {:#018x} (virt:{:#018x}-{:#018x},type:{:s}) {:s}\".format(\n                            addr, entry, virt_addr, virt_addr_end, entry_type, \" \".join(flags),\n                        )\n                        if self.is_not_filter_target(line):\n                            continue\n                        self.out.append(line)\n\n            if not self.silent:\n                if self.args.print_each_level:\n                    self.out.append(titlify(\"\"))\n                self.quiet_info_add_out(\"Number of entries: {:d}\".format(COUNT))\n                self.quiet_info_add_out(\"PT Entry (4KB): {:d}\".format(len(KB4)))\n                self.quiet_info_add_out(\"PT Entry (16KB): {:d}\".format(len(KB16)))\n                self.quiet_info_add_out(\"PT Entry (64KB): {:d}\".format(len(KB64)))\n                self.quiet_info_add_out(\"Invalid entries: {:d}\".format(COUNT - len(KB4) - len(KB16) - len(KB64)))\n            self.mappings += KB4 + KB16 + KB64\n        else:\n            if not self.silent:\n                self.quiet_info_add_out(\"LEVEL 3 is skipped\")\n\n        # finalize\n        if not self.silent:\n            self.quiet_add_out(titlify(\"Total\"))\n            self.quiet_info_add_out(\"PT Entry (Total): {:d}\".format(len(self.mappings)))\n        self.mappings = sorted(self.mappings)\n        return\n\n    def switch_el(self):\n        self.SAVED_CPSR = 0\n        CPSR = get_register(\"$cpsr\") & 0xffff_ffff\n        CurrentEL = int((CPSR >> 2) & 0b11)\n        # change EL\n        try:\n            if self.TargetEL < 1 or self.TargetEL > 3:\n                self.err_add_out(\"Invalid argument (ELx>=1 && ELx<=3)\")\n                return\n            if self.TargetEL != CurrentEL:\n                self.SAVED_CPSR = CPSR\n                CPSR = CPSR & ~(0b11 << 2) # clear EL\n                CPSR |= self.TargetEL << 2 # set desired EL\n                gdb.parse_and_eval(\"$cpsr = {:#x}\".format(CPSR))\n                self.quiet_info_add_out(\"Moving to EL{:d}\".format(self.TargetEL))\n        except ValueError:\n            self.err_add_out(\"Invalid argument (ELx integer required)\")\n            return\n        except gdb.error:\n            self.err_add_out(\"Maybe unsupported to change to EL{:d}\".format(self.TargetEL))\n            return\n        # reload CPSR\n        CPSR = get_register(\"$cpsr\") & 0xffff_ffff\n        CurrentEL = int((CPSR >> 2) & 0b11)\n        self.quiet_info_add_out(\"CPSR: EL{:d}\".format(CurrentEL))\n        return True\n\n    def revert_el(self):\n        if self.SAVED_CPSR:\n            gdb.parse_and_eval(\"$cpsr = {:#x}\".format(self.SAVED_CPSR))\n            SavedEL = (self.SAVED_CPSR >> 2) & 0b11\n            self.quiet_info_add_out(\"Moving back to EL{:d}\".format(SavedEL))\n        return\n\n    def get_granule_bits(self, TG, reg_name):\n        if reg_name == \"TG0\":\n            if TG == 0b00:\n                return 12 # 4KB\n            elif TG == 0b01:\n                return 16 # 64KB\n            elif TG == 0b10:\n                return 14 # 16KB\n        elif reg_name == \"TG1\":\n            if TG == 0b01:\n                return 14 # 16KB\n            elif TG == 0b10:\n                return 12 # 4KB\n            elif TG == 0b11:\n                return 16 # 64KB\n        self.err_add_out(\"Unsupported {:s}\".format(reg_name))\n        return None\n\n    def get_pa_size_for_ps(self, ps, granule):\n        if ps == 0b110:\n            if granule == 16:\n                return 52\n            if (granule == 14 or granule == 12) and self.TCR_ELx_DS:\n                return 52\n            return 48\n\n        return {\n            0b000: 32,\n            0b001: 36,\n            0b010: 40,\n            0b011: 42,\n            0b100: 44,\n            0b101: 48,\n            0b110: 52,\n            0b111: 56, # unsupported for TCR_EL2\n        }[ps]\n\n    def get_start_level(self, TnSZ, granule_bits):\n        if self.FEAT_LPA2:\n            if self.TCR_ELx_DS:\n                if granule_bits == 12:\n                    if TnSZ < 0x10:\n                        return -1\n        return 0\n\n    def get_translation_base_addr(self, PS, TTBR):\n        if PS == 0b110:\n            if self.FEAT_LPA:\n                high = TTBR & 0xffff_ffff_ffc0\n                low = (TTBR >> 2) & 0b1111\n                return high | (low << 48)\n            else:\n                self.err_add_out(\"Unsupported FEAT_LPA and IPS pair\")\n                return None\n        return TTBR & 0xffff_ffff_fffe\n\n    def pagewalk_TTBR0_EL1(self):\n        self.out.append(titlify(\"$TTBR0_EL1\", color=\"bold\", msg_color=\"bold\"))\n\n        TTBR0_EL1 = get_register(\"$TTBR0_EL1\", use_mbed_exec=True)\n        TCR_EL1 = get_register(\"$TCR_EL1\", use_mbed_exec=True)\n        if TTBR0_EL1 == 0:\n            self.warn_add_out(\"Maybe unused TTBR0_EL1\")\n            return\n\n        self.TCR_ELx_DS = ((TCR_EL1 >> 59) & 1) == 1\n        IPS = (TCR_EL1 >> 32) & 0b111\n        TG0 = (TCR_EL1 >> 14) & 0b11\n        T0SZ = TCR_EL1 & 0b111111\n\n        granule_bits = self.get_granule_bits(TG0, \"TG0\")\n        if granule_bits is None:\n            return\n\n        region_start = 0\n        region_end = region_start + (2 ** (64 - T0SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        intermediate_pa_size = self.get_pa_size_for_ps(IPS, granule_bits)\n        start_level = self.get_start_level(T0SZ, granule_bits)\n\n        translation_base_addr = self.get_translation_base_addr(IPS, TTBR0_EL1)\n        if translation_base_addr is None:\n            return\n\n        self.quiet_info_add_out(\"$TTBR0_EL1: {:#x}\".format(TTBR0_EL1))\n        self.quiet_info_add_out(\"$TCR_EL1: {:#x}\".format(TCR_EL1))\n        self.quiet_info_add_out(\"Intermediate Physical Address Size: {:d} bits\".format(intermediate_pa_size))\n        self.quiet_info_add_out(\"EL1 User Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n        self.quiet_info_add_out(\"EL1 User Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.ttbr0el1_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, start_level, is_2VAranges=True)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr0el1_mappings = self.mappings.copy()\n        self.make_out(self.ttbr0el1_mappings)\n        return\n\n    def pagewalk_TTBR1_EL1(self):\n        self.out.append(titlify(\"$TTBR1_EL1\", color=\"bold\", msg_color=\"bold\"))\n\n        TTBR1_EL1 = get_register(\"$TTBR1_EL1\", use_mbed_exec=True)\n        TCR_EL1 = get_register(\"$TCR_EL1\", use_mbed_exec=True)\n        if TTBR1_EL1 == 0:\n            self.warn_add_out(\"Maybe unused TTBR1_EL1\")\n            return\n\n        self.TCR_ELx_DS = ((TCR_EL1 >> 59) & 1) == 1\n        IPS = (TCR_EL1 >> 32) & 0b111\n        TG1 = (TCR_EL1 >> 30) & 0b11\n        T1SZ = (TCR_EL1 >> 16) & 0b111111\n\n        granule_bits = self.get_granule_bits(TG1, \"TG1\")\n        if granule_bits is None:\n            return\n\n        region_end = 2 ** 64\n        region_start = region_end - (2 ** (64 - T1SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        intermediate_pa_size = self.get_pa_size_for_ps(IPS, granule_bits)\n        start_level = self.get_start_level(T1SZ, granule_bits)\n\n        translation_base_addr = self.get_translation_base_addr(IPS, TTBR1_EL1)\n        if translation_base_addr is None:\n            return\n\n        self.quiet_info_add_out(\"$TTBR1_EL1: {:#x}\".format(TTBR1_EL1))\n        self.quiet_info_add_out(\"$TCR_EL1: {:#x}\".format(TCR_EL1))\n        self.quiet_info_add_out(\"Intermediate Physical Address Size: {:d} bits\".format(intermediate_pa_size))\n        self.quiet_info_add_out(\"EL1 Kernel Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n        self.quiet_info_add_out(\"EL1 Kernel Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.ttbr1el1_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, start_level, is_2VAranges=True)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr1el1_mappings = self.mappings.copy()\n        self.make_out(self.ttbr1el1_mappings)\n        return\n\n    def pagewalk_VTTBR_EL2(self):\n        if not self.silent:\n            self.out.append(titlify(\"$VTTBR_EL2\", color=\"bold\", msg_color=\"bold\"))\n\n        VTTBR_EL2 = get_register(\"$VTTBR_EL2\")\n        VTCR_EL2 = get_register(\"$VTCR_EL2\")\n        if VTTBR_EL2 == 0:\n            if not self.silent:\n                self.warn_add_out(\"Maybe unused VTTBR_EL2\")\n            return\n\n        self.TCR_ELx_DS = ((VTCR_EL2 >> 32) & 1) == 1\n        SL2 = (VTCR_EL2 >> 33) & 0b1\n        PS = (VTCR_EL2 >> 16) & 0b111\n        TG0 = (VTCR_EL2 >> 14) & 0b11\n        SL0 = (VTCR_EL2 >> 6) & 0b11\n        T0SZ = VTCR_EL2 & 0b111111\n\n        granule_bits = self.get_granule_bits(TG0, \"TG0\")\n        if granule_bits is None:\n            return\n\n        region_start = 0\n        region_end = region_start + (2 ** (64 - T0SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        pa_size = self.get_pa_size_for_ps(PS, granule_bits)\n\n        if self.FEAT_TTST:\n            if SL0 == 0b00:\n                if TG0 == 0b00:\n                    if self.FEAT_LPA2 and SL2 == 1:\n                        stage2_start_level = -1\n                    else:\n                        stage2_start_level = 2\n                else:\n                    stage2_start_level = 3\n            elif SL0 == 0b01:\n                if TG0 == 0b00:\n                    if self.FEAT_LPA2 and SL2 == 1:\n                        if not self.silent:\n                            self.err_add_out(\"Unsupported stage2 start level\")\n                        return\n                    else:\n                        stage2_start_level = 1\n                else:\n                    stage2_start_level = 2\n            elif SL0 == 0b10:\n                if TG0 == 0b00:\n                    if self.FEAT_LPA2 and SL2 == 1:\n                        if not self.silent:\n                            self.err_add_out(\"Unsupported stage2 start level\")\n                        return\n                    else:\n                        stage2_start_level = 0\n                else:\n                    stage2_start_level = 1\n            elif SL0 == 0b11:\n                if TG0 == 0b00:\n                    if self.FEAT_LPA2 and SL2 == 1:\n                        if not self.silent:\n                            self.err_add_out(\"Unsupported stage2 start level\")\n                        return\n                    else:\n                        stage2_start_level = 3\n                else:\n                    stage2_start_level = 0\n        else:\n            if SL0 == 0b00:\n                if TG0 == 0b00:\n                    stage2_start_level = 2\n                else:\n                    stage2_start_level = 3\n            elif SL0 == 0b01:\n                if TG0 == 0b00:\n                    stage2_start_level = 1\n                else:\n                    stage2_start_level = 2\n            elif SL0 == 0b10:\n                if TG0 == 0b00:\n                    stage2_start_level = 0\n                else:\n                    stage2_start_level = 1\n            else:\n                if not self.silent:\n                    self.err_add_out(\"Unsupported stage2 start level\")\n                return\n\n        translation_base_addr = self.get_translation_base_addr(PS, VTTBR_EL2)\n        if translation_base_addr is None:\n            return\n\n        if not self.silent:\n            self.quiet_info_add_out(\"$VTTBR_EL2: {:#x}\".format(VTTBR_EL2))\n            self.quiet_info_add_out(\"$VTCR_EL2: {:#x}\".format(VTCR_EL2))\n            self.quiet_info_add_out(\"Physical Address Size: {:d} bits\".format(pa_size))\n            self.quiet_info_add_out(\"EL2 Starting Level: {:d}\".format(SL0))\n            self.quiet_info_add_out(\"EL2 Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n            self.quiet_info_add_out(\"EL2 Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.vttbrel2_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, stage2_start_level, is_stage2=True)\n            self.flags_strings_cache = None\n            if not self.silent:\n                self.merging()\n                self.vttbrel2_mappings = self.mappings.copy()\n\n        if not self.silent:\n            self.make_out(self.vttbrel2_mappings)\n        return\n\n    def pagewalk_TTBR0_EL2(self):\n        self.out.append(titlify(\"$TTBR0_EL2\", color=\"bold\", msg_color=\"bold\"))\n\n        TTBR0_EL2 = get_register(\"$TTBR0_EL2\")\n        TCR_EL2 = get_register(\"$TCR_EL2\")\n        if TTBR0_EL2 == 0:\n            self.warn_add_out(\"Maybe unused TTBR0_EL2\")\n            return\n\n        self.TCR_ELx_DS = ((TCR_EL2 >> 32) & 1) == 1\n        PS = (TCR_EL2 >> 16) & 0b111\n        TG0 = (TCR_EL2 >> 14) & 0b11\n        T0SZ = TCR_EL2 & 0b111111\n\n        granule_bits = self.get_granule_bits(TG0, \"TG0\")\n        if granule_bits is None:\n            return\n\n        region_start = 0\n        region_end = region_start + (2 ** (64 - T0SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        pa_size = self.get_pa_size_for_ps(PS, granule_bits)\n        start_level = self.get_start_level(T0SZ, granule_bits)\n\n        translation_base_addr = self.get_translation_base_addr(PS, TTBR0_EL2)\n        if translation_base_addr is None:\n            return\n\n        self.quiet_info_add_out(\"$TTBR0_EL2: {:#x}\".format(TTBR0_EL2))\n        self.quiet_info_add_out(\"$TCR_EL2: {:#x}\".format(TCR_EL2))\n        if self.EL2_E2H:\n            self.quiet_info_add_out(\"Intermediate Physical Address Size: {:d} bits\".format(pa_size))\n        else:\n            self.quiet_info_add_out(\"Physical Address Size: {:d} bits\".format(pa_size))\n        if self.EL2_M20:\n            self.quiet_info_add_out(\"EL2 User Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n            self.quiet_info_add_out(\"EL2 USer Page Size: {:d}KB (per page)\".format(page_size))\n        else:\n            self.quiet_info_add_out(\"EL2 Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n            self.quiet_info_add_out(\"EL2 Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.ttbr0el2_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, start_level, is_2VAranges=self.EL2_M20)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr0el2_mappings = self.mappings.copy()\n        self.make_out(self.ttbr0el2_mappings)\n        return\n\n    def pagewalk_TTBR1_EL2(self):\n        self.out.append(titlify(\"$TTBR1_EL2\", color=\"bold\", msg_color=\"bold\"))\n\n        TTBR1_EL2 = get_register(\"$TTBR1_EL2\")\n        TCR_EL2 = get_register(\"$TCR_EL2\")\n        if TTBR1_EL2 == 0:\n            self.warn_add_out(\"Maybe unused TTBR1_EL2\")\n            return\n\n        self.TCR_ELx_DS = ((TCR_EL2 >> 32) & 1) == 1\n        IPS = (TCR_EL2 >> 32) & 0b111\n        TG1 = (TCR_EL2 >> 30) & 0b11\n        T1SZ = (TCR_EL2 >> 16) & 0b111111\n\n        granule_bits = self.get_granule_bits(TG1, \"TG1\")\n        if granule_bits is None:\n            return\n\n        region_end = 2 ** 64\n        region_start = region_end - (2 ** (64 - T1SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        intermediate_pa_size = self.get_pa_size_for_ps(IPS, granule_bits)\n        start_level = self.get_start_level(T1SZ, granule_bits)\n\n        translation_base_addr = self.get_translation_base_addr(IPS, TTBR1_EL2)\n        if translation_base_addr is None:\n            return\n\n        self.quiet_info_add_out(\"$TTBR1_EL2: {:#x}\".format(TTBR1_EL2))\n        self.quiet_info_add_out(\"$TCR_EL2: {:#x}\".format(TCR_EL2))\n        self.quiet_info_add_out(\"Intermediate Physical Address Size: {:d} bits\".format(intermediate_pa_size))\n        self.quiet_info_add_out(\"EL2 Kernel Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n        self.quiet_info_add_out(\"EL2 Kernel Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.ttbr1el2_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, start_level, is_2VAranges=self.EL2_M20)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr1el2_mappings = self.mappings.copy()\n        self.make_out(self.ttbr1el2_mappings)\n        return\n\n    def pagewalk_TTBR0_EL3(self):\n        self.out.append(titlify(\"$TTBR0_EL3\", color=\"bold\", msg_color=\"bold\"))\n\n        TTBR0_EL3 = get_register(\"$TTBR0_EL3\")\n        TCR_EL3 = get_register(\"$TCR_EL3\")\n        if TTBR0_EL3 == 0:\n            self.warn_add_out(\"Maybe unused TTBR0_EL3\")\n            return\n\n        self.TCR_ELx_DS = ((TCR_EL3 >> 32) & 1) == 1\n        PS = (TCR_EL3 >> 16) & 0b111\n        TG0 = (TCR_EL3 >> 14) & 0b11\n        T0SZ = TCR_EL3 & 0b111111\n\n        granule_bits = self.get_granule_bits(TG0, \"TG0\")\n        if granule_bits is None:\n            return\n\n        region_start = 0\n        region_end = region_start + (2 ** (64 - T0SZ))\n        region_bits = GefUtil.log2(region_end - region_start)\n        page_size = 2 ** (granule_bits - 10)\n        pa_size = self.get_pa_size_for_ps(PS, granule_bits)\n        start_level = self.get_start_level(T0SZ, granule_bits)\n\n        translation_base_addr = self.get_translation_base_addr(PS, TTBR0_EL3)\n        if translation_base_addr is None:\n            return\n\n        self.quiet_info_add_out(\"$TTBR0_EL3: {:#x}\".format(TTBR0_EL3))\n        self.quiet_info_add_out(\"$TCR_EL3: {:#x}\".format(TCR_EL3))\n        self.quiet_info_add_out(\"Physical Address Size: {:d} bits\".format(pa_size))\n        self.quiet_info_add_out(\"EL3 Region: {:#018x} - {:#018x} ({:d} bits)\".format(region_start, region_end - 1, region_bits))\n        self.quiet_info_add_out(\"EL3 Page Size: {:d}KB (per page)\".format(page_size))\n\n        self.parse_bit_range(granule_bits, region_bits)\n        if not self.args.use_cache or not self.ttbr0el3_mappings:\n            self.flags_strings_cache = {}\n            self.do_pagewalk(translation_base_addr, granule_bits, region_start, region_bits, start_level)\n            self.flags_strings_cache = None\n            self.merging()\n            self.ttbr0el3_mappings = self.mappings.copy()\n        self.make_out(self.ttbr0el3_mappings)\n        return\n\n    def pagewalk_init(self):\n        res = get_register(\"$TTBR0_EL1\", use_mbed_exec=True)\n        if res is None:\n            self.err_add_out(\"Could not find system registers\")\n            return False\n\n        SCTLR_EL1 = get_register(\"$SCTLR_EL1\", use_mbed_exec=True)\n        if SCTLR_EL1 is None:\n            SCTLR_EL1 = get_register(\"$SCTLR\")\n        if SCTLR_EL1 is not None:\n            self.EL1_M = (SCTLR_EL1 & 1) == 1\n            self.EL1_WXN = ((SCTLR_EL1 >> 19) & 1) == 1\n        else:\n            self.EL1_M = False\n            self.EL1_WXN = False\n\n        HCR_EL2 = get_register(\"$HCR_EL2\")\n        if HCR_EL2 is not None:\n            self.EL2_TGE = ((HCR_EL2 >> 27) & 1) == 1\n            self.EL2_E2H = ((HCR_EL2 >> 34) & 1) == 1\n            self.EL2_M20 = self.EL2_TGE and self.EL2_E2H\n            self.EL2_VM = (HCR_EL2 & 1) == 1\n        else:\n            self.EL2_TGE = False\n            self.EL2_E2H = False\n            self.EL2_M20 = False\n            self.EL2_VM = False\n\n        SCTLR_EL2 = get_register(\"$SCTLR_EL2\")\n        if SCTLR_EL2 is not None:\n            self.EL2_M = (SCTLR_EL2 & 1) == 1\n            self.EL2_WXN = ((SCTLR_EL2 >> 19) & 1) == 1\n        else:\n            self.EL2_M = False\n            self.EL2_WXN = False\n\n        SCTLR_EL3 = get_register(\"$SCTLR_EL3\")\n        if SCTLR_EL3 is not None:\n            self.EL3_M = (SCTLR_EL3 & 1) == 1\n            self.EL3_WXN = ((SCTLR_EL3 >> 19) & 1) == 1\n        else:\n            self.EL3_M = False\n            self.EL3_WXN = False\n\n        ID_AA64MMFR0_EL1 = get_register(\"$ID_AA64MMFR0_EL1\", use_mbed_exec=True)\n        if ID_AA64MMFR0_EL1 is not None:\n            TGran4_2 = (ID_AA64MMFR0_EL1 >> 40) & 0b1111\n            TGran16_2 = (ID_AA64MMFR0_EL1 >> 32) & 0b1111\n            TGran4 = (ID_AA64MMFR0_EL1 >> 28) & 0b1111\n            TGran16 = (ID_AA64MMFR0_EL1 >> 20) & 0b1111\n            self.FEAT_LPA2 = (TGran4_2 == 0b0011) or (TGran16_2 == 0b0011) or (TGran4 == 0b0001) or (TGran16 == 0b0010)\n            self.FEAT_LPA = (ID_AA64MMFR0_EL1 & 0b1111) == 0b0110\n        else:\n            self.FEAT_LPA2 = False\n            self.FEAT_LPA = False\n\n        ID_AA64MMFR1_EL1 = get_register(\"$ID_AA64MMFR1_EL1\", use_mbed_exec=True)\n        if ID_AA64MMFR1_EL1 is not None:\n            self.FEAT_PAN = ((ID_AA64MMFR1_EL1 >> 20) & 0b1111) != 0b0000\n        else:\n            self.FEAT_PAN = False\n        self.quiet_info_add_out(\"{:s} is supported on all ARMv8\".format(Color.boldify(\"PXN\")))\n        if self.FEAT_PAN:\n            self.quiet_info_add_out(\"{:s} is supported\".format(Color.boldify(\"PAN\")))\n        else:\n            self.quiet_info_add_out(\"PAN is unsupported\")\n\n        ID_AA64MMFR2_EL1 = get_register(\"$ID_AA64MMFR2_EL1\", use_mbed_exec=True)\n        if ID_AA64MMFR2_EL1 is not None:\n            self.FEAT_TTST = ((ID_AA64MMFR2_EL1 >> 28) & 0b1111) == 0b0001\n            self.FEAT_LVA = ((ID_AA64MMFR2_EL1 >> 16) & 0b1111) == 0b0001\n        else:\n            self.FEAT_TTST = False\n            self.FEAT_LVA = False\n        return True\n\n    def pagewalk(self):\n        # parse system registers\n        if not self.pagewalk_init():\n            return\n\n        self.silent = False\n        self.mappings = None\n        self.el2_mappings = None\n\n        # TODO: implementation for VSTTBR_EL2, VSTCR_EL2 pattern\n\n        # do pagewalk\n        if self.TargetEL < 1 or 3 < self.TargetEL:\n            self.warn_add_out(\"No paging in EL{:d}\".format(self.TargetEL))\n            return\n        if self.TargetEL == 1 and self.EL1_M:\n            if self.EL2_VM:\n                # el2_mapping is needed because read_mem() uses PA, but not IPA\n                self.silent = True\n                self.pagewalk_VTTBR_EL2()\n                if self.mappings:\n                    self.el2_mappings = self.mappings.copy()\n                    self.mappings = None\n                self.silent = False\n            if self.args.only_TTBR0_EL1:\n                self.pagewalk_TTBR0_EL1()\n            elif self.args.only_TTBR1_EL1:\n                self.pagewalk_TTBR1_EL1()\n            else:\n                self.pagewalk_TTBR0_EL1()\n                self.pagewalk_TTBR1_EL1()\n        if self.TargetEL == 1 and not self.EL1_M:\n            self.quiet_info_add_out(\"EL1/0 translation is unused\")\n        if self.TargetEL == 2 and self.EL2_VM:\n            self.pagewalk_VTTBR_EL2()\n        if self.TargetEL == 2 and not self.EL2_VM:\n            self.quiet_info_add_out(\"EL2(as stage2) translation is unused\")\n        if self.TargetEL == 2 and self.EL2_M:\n            self.pagewalk_TTBR0_EL2()\n            if self.EL2_M20:\n                self.pagewalk_TTBR1_EL2()\n        if self.TargetEL == 2 and self.EL2_VM:\n            self.quiet_info_add_out(\"EL2(as stage1) translation is unused\")\n        if self.TargetEL == 3 and self.EL3_M:\n            if not self.switch_el():\n                return\n            self.pagewalk_TTBR0_EL3()\n            self.revert_el()\n        if self.TargetEL == 3 and not self.EL3_M:\n            self.quiet_info_add_out(\"EL3 translation is unused\")\n        return\n\n    def aarch64_optee_pseudo_pagewalk(self):\n        Cache.reset_gef_caches()\n        maps = PageMap.get_page_maps_arm64_optee_secure_memory(verbose=not self.args.quiet)\n        if not maps:\n            return\n        fmt = \"{:37s}  {:37s}  {:10s}  {:s}\"\n        legend = [\"Virtual address start-end\", \"Physical address start-end\", \"Total size\", \"Hint (Maybe)\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        \"\"\"\n        [Newer version]\n        gef> pagewalk --optee -n -q\n        Virtual address start-end              Physical address start-end             Total size  Hint (Maybe)\n        0x000000000e100000-0x000000000e102000  0x000000000e100000-0x000000000e102000  0x2000      TEE-OS bootstrap region\n        0x000000009e400000-0x000000009e600000  0x0000000042000000-0x0000000042200000  0x200000    NS<->S shared memory\n        0x000000009e600000-0x000000009e800000  0x0000000009000000-0x0000000009200000  0x200000    UART0_BASE\n        0x000000009e800000-0x000000009f800000  0x0000000008000000-0x0000000009000000  0x1000000   GIC_BASE\n        0x000000009fa00000-0x00000000a0400000  0x0000000000000000-0x0000000000a00000  0xa00000\n        0x00000000a0600000-0x00000000a2600000  0x0000000000000000-0x0000000002000000  0x2000000\n        0x00000000a2900000-0x00000000a3600000  0x000000000e300000-0x000000000f000000  0xd00000\n        0x00000000a362a000-0x00000000a36ae000  0x000000000e100000-0x000000000e184000  0x84000     TEE-OS .text\n        0x00000000a36ae000-0x00000000a382a000  0x000000000e184000-0x000000000e300000  0x17c000    TEE-OS .data / stack\n        gef>\n\n        [Older version]\n        gef> pagewalk --optee -n -q\n        Virtual address start-end              Physical address start-end             Total size  Hint (Maybe)\n        0x000000000e100000-0x000000000e15d000  0x000000000e100000-0x000000000e15d000  0x5d000     TEE-OS .text\n        0x000000000e15d000-0x000000000e300000  0x000000000e15d000-0x000000000e300000  0x1a3000    TEE-OS .data / stack\n        0x000000000e300000-0x000000000f000000  0x000000000e300000-0x000000000f000000  0xd00000\n        0x000000000f200000-0x000000000fa00000  0x0000000000000000-0x0000000000800000  0x800000\n        0x000000000fa00000-0x0000000011a00000  0x0000000000000000-0x0000000002000000  0x2000000\n        0x0000000011a00000-0x0000000011c00000  0x0000000009000000-0x0000000009200000  0x200000    UART0_BASE\n        0x0000000011c00000-0x0000000011e00000  0x0000000042000000-0x0000000042200000  0x200000    NS<->S shared memory\n        0x000000000f000000-0x000000000f200000  0x0000000040000000-0x0000000040200000  0x200000\n        gef>\n        \"\"\"\n        text_end = None\n        for va_start, va_end, pa_start, pa_end in maps:\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-vexpress/conf.mk\n            if pa_start == 0x0e10_0000:\n                if va_start == 0x0e10_0000 and va_end - va_start == 0x2000:\n                    hint = \"TEE-OS bootstrap region\"\n                else:\n                    hint = \"TEE-OS .text\"\n                    text_end = va_end\n            elif text_end and va_start == text_end:\n                hint = \"TEE-OS .data / stack\"\n            elif pa_start == 0x4200_0000:\n                hint = \"NS<->S shared memory\"\n            # https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-vexpress/platform_config.h\n            elif pa_start == 0x0800_0000:\n                hint = \"GIC_BASE\"\n            elif pa_start == 0x0900_0000:\n                hint = \"UART0_BASE\"\n            elif pa_start == 0x0904_0000:\n                hint = \"UART1_BASE\"\n            else:\n                hint = \"\"\n            gef_print(\"{:#018x}-{:#018x}  {:#018x}-{:#018x}  {:<#10x}  {:s}\".format(\n                va_start, va_end, pa_start, pa_end, va_end - va_start, hint,\n            ).rstrip())\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        if args.optee and is_qemu_system():\n            self.aarch64_optee_pseudo_pagewalk()\n            return\n\n        if args.only_TTBR0_EL1 and args.only_TTBR1_EL1:\n            err(\"Unsupported combination (-0 and -1)\")\n            return\n\n        if self.args.trace:\n            # You should not modify the self.args.vrange directly.\n            self.vrange = self.args.vrange + self.args.trace # merge vrange and trace\n            self.args.print_each_level = True # overwrite\n            self.args.use_cache = False # overwrite\n        else:\n            self.vrange = self.args.vrange\n\n        if args.target_el is None:\n            CPSR = get_register(\"$cpsr\")\n            self.TargetEL = (CPSR >> 2) & 0b11\n            if self.TargetEL == 0:\n                # Since $pc is in EL0 (unprivileged), temporarily elevate to EL1\n                # to inspect TTBR0_EL1 and TTBR1_EL1 page tables.\n                self.TargetEL = 1\n        else:\n            self.TargetEL = args.target_el\n\n        if is_kgdb():\n            if self.TargetEL != 1:\n                err(\"Unsupported target EL\")\n                return\n\n        self.out = []\n        self.cache = {}\n        self.pagewalk()\n        self.cache = {} # The cache is huge, so it will be released as soon as possible.\n        self.print_output()\n        return\n\n\n@register_command\nclass SwitchELCommand(GenericCommand):\n    \"\"\"Switch EL (Exception Level) on ARM64 architecture.\"\"\"\n\n    _cmdline_ = \"switch-el\"\n    _category_ = \"06-b. Qemu-system/KGDB Cooperation - Register\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"target_el\", metavar=\"TARGET_EL\", nargs=\"?\", type=int,\n                        help=\"Exception Level to change to.\")\n    _syntax_ = parser.format_help()\n\n    def switch_el(self, target_el):\n        # current EL\n        CPSR = get_register(\"$cpsr\") & 0xffff_ffff\n        CurrentEL = (CPSR >> 2) & 0b11\n\n        # check argv\n        if target_el is None:\n            info(\"$cpsr = {:#x} (EL{:d})\".format(CPSR, CurrentEL))\n            return\n\n        # check target EL\n        try:\n            if target_el < 0 or target_el > 3:\n                err(\"Invalid argument (ELx>=0 && ELx<=3)\")\n                return\n        except ValueError:\n            err(\"Invalid argument (ELx integer required)\")\n            return\n\n        # change CPSR\n        if target_el != CurrentEL:\n            CPSR = CPSR & ~(0b11 << 2) # clear EL\n            CPSR |= target_el << 2 # set desired EL\n            gdb.parse_and_eval(\"$cpsr = {:#x}\".format(CPSR))\n            info(\"Moving to EL{:d}\".format(target_el))\n        else:\n            info(\"Already at EL{:d}\".format(target_el))\n\n        # reprint CPSR\n        CPSR = int(gdb.parse_and_eval(\"$cpsr\")) & 0xffff_ffff\n        CurrentEL = (CPSR >> 2) & 0b11\n        info(\"$cpsr = {:#x} (EL{:d})\".format(CPSR, CurrentEL))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM64\",))\n    def do_invoke(self, args):\n        self.switch_el(args.target_el)\n        return\n\n\n@register_command\nclass KernelVMMapCommand(GenericCommand, BufferingOutput):\n    \"\"\"Print kernel memory map.\"\"\"\n\n    _cmdline_ = \"kvmmap\"\n    _category_ = \"06-a. Qemu-system/KGDB Cooperation - Memory Map\"\n    _aliases_ = [\"pagewalk-with-hints\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-U\", \"--exclude-user\", action=\"store_true\", help=\"exclude userland memory.\")\n    parser.add_argument(\"-i\", \"--include-esp-fixup-stacks\", action=\"store_true\",\n                        help=\"include `%%esp fixup stacks` area (sometimes heavy memory use; x64 only).\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"count\", default=0,\n                        help=\"increase output verbosity. (-v, -vv, -vvv)\")\n    parser.add_argument(\"address_filter\", metavar=\"ADDRESS\", nargs=\"*\", type=AddressUtil.parse_address,\n                        help=\"filtering by specified address.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    class Region:\n        def __init__(self, addr_start, addr_end, perm, description=\"\", merge=True,\n                     addr_start_str=None, addr_end_str=None, size_str=None):\n            self.addr_start = addr_start\n            self.addr_end = addr_end\n            self.perm = perm\n\n            self.description = description\n            self.merge = merge\n\n            self.addr_start_str = addr_start_str\n            self.addr_end_str = addr_end_str\n            self.size_str = size_str\n            return\n\n        def add_description(self, description):\n            if not self.description:\n                self.description = description\n                return\n            if description in self.description:\n                return\n            self.description = \"{:s}, {:s}\".format(self.description, description)\n            return\n\n        @property\n        def size(self):\n            return self.addr_end - self.addr_start\n\n        def __str__(self):\n            line = \"{:18s}-{:18s} {:18s} [{:s}] {:s}\".format(\n                self.addr_start_str if self.addr_start_str else \"{:#018x}\".format(self.addr_start),\n                self.addr_end_str if self.addr_end_str else \"{:#018x}\".format(self.addr_end),\n                self.size_str if self.size_str else \"{:#018x}\".format(self.size),\n                self.perm, self.description,\n            ).rstrip()\n\n            # coloring\n            if self.perm == \"r--\":\n                line_color = Config.get_gef_setting(\"theme.address_readonly\")\n            elif self.perm == \"rw-\":\n                line_color = Config.get_gef_setting(\"theme.address_writable\")\n            elif self.perm.endswith(\"x\"):\n                line_color = Config.get_gef_setting(\"theme.address_code\")\n            else:\n                line_color = \"\"\n            if self.perm == \"rwx\":\n                line_color += \" \" + Config.get_gef_setting(\"theme.address_rwx\")\n            return Color.colorify(line, line_color)\n\n    def page_start_align(self, x):\n        return x & get_pagesize_mask_high()\n\n    def page_end_align(self, x):\n        if x & get_pagesize_mask_low():\n            return (x & get_pagesize_mask_high()) + get_pagesize()\n        else:\n            return x\n\n    def insert_region(self, to_insert_address, to_insert_size, description, merge=True):\n        target_address_start = to_insert_address\n        target_address_end = to_insert_address + to_insert_size\n\n        updated = False\n        for _key, r in sorted(self.regions.items()):\n            # no overwrap\n            if r.addr_end <= target_address_start:\n                continue\n            if target_address_end <= r.addr_start:\n                break\n\n            # found, let's split\n            # pattern1\n            #   - target_address_start\n            #     (ignore)\n            #   - r.addr_start\n            #     (size_2nd)\n            #   - target_address_end\n            #     (size_3rd)\n            #   - r.addr_end\n\n            # pattern2\n            #   - target_address_start\n            #     (ignore)\n            #   - r.addr_start\n            #     (size_2nd)\n            #   - r.addr_end\n            #     (treat by next loop)\n            #   - target_address_end\n\n            # pattern3\n            #   - r.addr_start\n            #     (size_1st)\n            #   - target_address_start\n            #     (size_2nd)\n            #   - target_address_end\n            #     (size_3rd)\n            #   - r.addr_end\n\n            # pattern4\n            #   - r.addr_start\n            #     (size_1st)\n            #   - target_address_start\n            #     (size_2nd)\n            #   - r.addr_end\n            #     (treat by next loop)\n            #   - target_address_end\n\n            size_1st = max(target_address_start - r.addr_start, 0)\n            size_2nd = min(target_address_end, r.addr_end) - max(target_address_start, r.addr_start)\n            size_3rd = max(r.addr_end - target_address_end, 0)\n\n            # then insert (old one is overwritten)\n            if size_1st > 0:\n                addr_start_1st = r.addr_start\n                addr_end_1st = addr_start_1st + size_1st\n                self.regions[addr_start_1st] = self.Region(addr_start_1st, addr_end_1st, r.perm, r.description, merge)\n                updated = True\n            if size_2nd > 0:\n                addr_start_2nd = max(target_address_start, r.addr_start)\n                addr_end_2nd = addr_start_2nd + size_2nd\n                if r.description:\n                    if description in r.description:\n                        new_description = r.description\n                    else:\n                        new_description = r.description + \", \" + description\n                else:\n                    new_description = description\n                self.regions[addr_start_2nd] = self.Region(addr_start_2nd, addr_end_2nd, r.perm, new_description, merge)\n                updated = True\n            if size_3rd > 0:\n                addr_start_3rd = target_address_end\n                addr_end_3rd = addr_start_3rd + size_3rd\n                self.regions[addr_start_3rd] = self.Region(addr_start_3rd, addr_end_3rd, r.perm, r.description, merge)\n                updated = True\n\n            if r.addr_end < target_address_end:\n                target_address_start = r.addr_end\n        return updated\n\n    def insert_region_range(self, to_insert_address, to_insert_end, description, merge=True):\n        return self.insert_region(to_insert_address, to_insert_end - to_insert_address, description, merge)\n\n    def merge_region(self):\n        new_regions = {}\n        prev_key, prev_r = None, None\n        for key, r in sorted(self.regions.items()):\n            # for 1st element\n            if prev_key is None:\n                prev_key, prev_r = key, r\n                continue\n\n            # no_merge flag\n            if not r.merge:\n                new_regions[prev_key] = prev_r\n                prev_key, prev_r = key, r\n                continue\n\n            if prev_r and not prev_r.merge:\n                new_regions[prev_key] = prev_r\n                prev_key, prev_r = key, r\n                continue\n\n            # not match, so append\n            if prev_r.addr_end != r.addr_start:\n                new_regions[prev_key] = prev_r\n                prev_key, prev_r = key, r\n                continue\n\n            if prev_r.perm != r.perm:\n                new_regions[prev_key] = prev_r\n                prev_key, prev_r = key, r\n                continue\n\n            if prev_r.description != r.description:\n                new_regions[prev_key] = prev_r\n                prev_key, prev_r = key, r\n                continue\n\n            # match, so let's merge\n            prev_r.addr_end += r.size\n\n        # add last element\n        if prev_key is not None:\n            new_regions[prev_key] = prev_r\n\n        # replace\n        self.regions = new_regions\n        return\n\n    def filter_region(self):\n        if not self.args.address_filter:\n            return\n\n        # filtering\n        new_regions = {}\n        for key, r in self.regions.items():\n            if any(r.addr_start <= a < r.addr_end for a in self.args.address_filter):\n                new_regions[key] = r\n\n        # replace\n        self.regions = new_regions\n        return\n\n    def get_maps(self):\n        option = \"\"\n        if self.args.include_esp_fixup_stacks:\n            option = \" --include-esp-fixup-stacks\"\n        res = PageMap.get_page_maps_by_pagewalk(\"pagewalk --quiet --no-pager --disable-color\" + option)\n        res = sorted(set(res.splitlines()))\n        res = list(filter(lambda line: line.endswith(\"]\"), res))\n        res = list(filter(lambda line: \"[+]\" not in line, res))\n\n        def is_userland(line, addr_start):\n            if is_x86():\n                return \"USER\" in line\n            elif is_arm32():\n                if \"[PL0/---\" not in line and addr_start != 0xffff_0000:\n                    return True\n            elif is_arm64():\n                return not AddressUtil.is_msb_on(addr_start)\n            return False\n\n        regions = {} # {addr_start: Region(), ...}\n        for line in res:\n            line = line.split()\n\n            # parse address\n            addr_start_str, addr_end_str = line[0].split(\"-\")\n            # Note that for espfix it looks like `0xffffff5b****e000-0xffffff5b****f000`\n            addr_start = int(addr_start_str.replace(\"*\", \"0\"), 16)\n            addr_end = int(addr_end_str.replace(\"*\", \"f\"), 16)\n\n            # userland filter\n            if self.args.exclude_user:\n                if is_userland(line, addr_start):\n                    continue\n\n            # parse permission\n            if is_x86():\n                perm = Permission.from_process_maps(line[5][1:4].lower())\n            elif is_arm64() or is_arm32():\n                perm = Permission.from_process_maps(line[6][4:7].lower())\n\n            # add region\n            if \"*\" in addr_start_str:\n                regions[addr_start] = self.Region(\n                    addr_start, addr_end, str(perm), merge=False,\n                    description=\"esp_fixup (=0x1000*N)\",\n                    addr_start_str=addr_start_str, addr_end_str=addr_end_str, size_str=\"0x0000000000001000\",\n                )\n            elif is_userland(line, addr_start):\n                regions[addr_start] = self.Region(\n                    addr_start, addr_end, str(perm), description=\"userland\",\n                )\n            else:\n                regions[addr_start] = self.Region(\n                    addr_start, addr_end, str(perm),\n                )\n        return regions\n\n    def resolve_kbase(self):\n        self.quiet_info(\"Resolving kbase\")\n\n        kinfo = Kernel.get_kernel_layout()\n\n        # .text\n        stext = Symbol.get_ksymaddr(\"_stext\")\n        etext = Symbol.get_ksymaddr(\"_etext\")\n        if stext and etext:\n            stext = self.page_start_align(stext)\n            etext = self.page_end_align(etext)\n            self.insert_region(stext, etext - stext, \"kernel .text\")\n        else:\n            if kinfo.text_base in self.regions:\n                self.regions[kinfo.text_base].add_description(\"maybe kernel .text\")\n\n        # .rodata\n        start_rodata = Symbol.get_ksymaddr(\"__start_rodata\")\n        end_rodata = Symbol.get_ksymaddr(\"__end_rodata\")\n        if start_rodata and end_rodata:\n            start_rodata = self.page_start_align(start_rodata)\n            end_rodata = self.page_end_align(end_rodata)\n            self.insert_region(start_rodata, end_rodata - start_rodata, \"kernel .rodata\")\n        else:\n            # In a 32-bit environment, the range of rodata may not be measured correctly, so it is not used.\n            if is_64bit():\n                if kinfo.ro_base in self.regions:\n                    self.regions[kinfo.ro_base].add_description(\"maybe kernel .rodata\")\n\n        # .data\n        sdata = Symbol.get_ksymaddr(\"_sdata\")\n        edata = Symbol.get_ksymaddr(\"_edata\")\n        if sdata and edata:\n            sdata = self.page_start_align(sdata)\n            edata = self.page_end_align(edata)\n            self.insert_region(sdata, edata - sdata, \"kernel .data\")\n        else:\n            # In a 32-bit environment, the range of rodata may not be measured correctly, so it is not used.\n            if is_64bit():\n                if kinfo.rw_base in self.regions:\n                    self.regions[kinfo.rw_base].add_description(\"maybe kernel .data\")\n        return\n\n    def resolve_direct_map(self):\n        self.quiet_info(\"Resolving direct map\")\n\n        PAGE_OFFSET = KernelAddressHeuristicFinder.get_PAGE_OFFSET()\n        PAGE_OFFSET_END = KernelAddressHeuristicFinder.get_PAGE_OFFSET_END()\n        if PAGE_OFFSET and PAGE_OFFSET_END:\n            self.insert_region_range(PAGE_OFFSET, PAGE_OFFSET_END, \"physmap\")\n        return\n\n    def resolve_vmalloc(self):\n        self.quiet_info(\"Resolving vmalloc\")\n\n        VMALLOC_START = KernelAddressHeuristicFinder.get_VMALLOC_START()\n        VMALLOC_END = KernelAddressHeuristicFinder.get_VMALLOC_END()\n        if VMALLOC_END and VMALLOC_END:\n            self.insert_region_range(VMALLOC_START, VMALLOC_END, \"vmalloc\")\n        return\n\n    def resolve_vmemmap(self):\n        if is_x86_64() or is_arm64():\n            self.quiet_info(\"Resolving vmemmap\")\n            VMEMMAP_START = KernelAddressHeuristicFinder.get_VMEMMAP_START()\n            VMEMMAP_END = KernelAddressHeuristicFinder.get_VMEMMAP_END()\n            if VMEMMAP_START and VMEMMAP_END:\n                self.insert_region_range(VMEMMAP_START, VMEMMAP_END, \"vmemmap(=page[])\")\n\n        elif is_x86_32() or is_arm32():\n            if KernelAddressHeuristicFinder.consts().CONFIG_FLATMEM:\n                self.quiet_info(\"Resolving mem_map\")\n                mem_map = KernelAddressHeuristicFinder.consts().mem_map\n                mem_map &= get_pagesize_mask_high()\n                # already there\n                if mem_map in self.regions:\n                    self.regions[mem_map].add_description(\"mem_map(=page[])\")\n                    return\n                # require division\n                for _key, r in sorted(self.regions.items()):\n                    if r.addr_start <= mem_map < r.addr_end:\n                        size = r.addr_end - mem_map\n                        self.insert_region(mem_map, size, \"mem_map(=page[])\")\n                        return\n\n            elif KernelAddressHeuristicFinder.consts().CONFIG_SPARSEMEM:\n                self.quiet_info(\"Resolving mem_section\")\n                mem_section = KernelAddressHeuristicFinder.consts().mem_section\n                NR_MEM_SECTIONS = KernelAddressHeuristicFinder.consts().NR_MEM_SECTIONS\n                sizeof_mem_section = KernelAddressHeuristicFinder.consts().sizeof_mem_section\n                # parse mem_section\n                for i in range(NR_MEM_SECTIONS):\n                    section_mem_map = read_int_from_memory(mem_section + sizeof_mem_section * i)\n                    section_mem_map &= get_pagesize_mask_high()\n                    if not is_valid_addr(section_mem_map):\n                        continue\n                    # already there\n                    if section_mem_map in self.regions:\n                        self.regions[section_mem_map].add_description(\"section_mem_map(=page[])\")\n                        continue\n                    # require division\n                    for _key, r in sorted(self.regions.items()):\n                        if r.addr_start <= section_mem_map < r.addr_end:\n                            size = r.addr_end - section_mem_map\n                            self.insert_region(section_mem_map, size, \"section_mem_map(=page[])\")\n                            break\n        return\n\n    def resolve_ldt(self):\n        if not is_x86():\n            return\n\n        self.quiet_info(\"Resolving ldt\")\n        if is_x86_64() or is_x86_32():\n            LDT_BASE_ADDR = KernelAddressHeuristicFinder.consts().LDT_BASE_ADDR\n            LDT_END_ADDR = KernelAddressHeuristicFinder.consts().LDT_END_ADDR\n            if LDT_BASE_ADDR and LDT_END_ADDR:\n                self.insert_region_range(LDT_BASE_ADDR, LDT_END_ADDR, \"ldt\")\n        return\n\n    def resolve_module(self):\n        self.quiet_info(\"Resolving module\")\n        MODULES_VADDR = KernelAddressHeuristicFinder.consts().MODULES_VADDR\n        MODULES_END = KernelAddressHeuristicFinder.consts().MODULES_END\n        if MODULES_VADDR and MODULES_END:\n            self.insert_region_range(MODULES_VADDR, MODULES_END, \"modules\")\n        return\n\n    def resolve_cpu_entry(self):\n        if not is_x86():\n            return\n\n        self.quiet_info(\"Resolving cpu entry\")\n        if is_x86_64() or is_x86_32():\n            CPU_ENTRY_AREA_BASE = KernelAddressHeuristicFinder.consts().CPU_ENTRY_AREA_BASE\n            CPU_ENTRY_AREA_END = KernelAddressHeuristicFinder.consts().CPU_ENTRY_AREA_END\n            if CPU_ENTRY_AREA_BASE and CPU_ENTRY_AREA_END:\n                self.insert_region_range(CPU_ENTRY_AREA_BASE, CPU_ENTRY_AREA_END, \"cpu_entry\")\n        return\n\n    def resolve_efi(self):\n        if not is_x86_64():\n            return\n\n        self.quiet_info(\"Resolving efi\")\n        if is_x86_64():\n            EFI_VA_START = KernelAddressHeuristicFinder.consts().EFI_VA_START\n            EFI_VA_END = KernelAddressHeuristicFinder.consts().EFI_VA_END\n            if EFI_VA_START and EFI_VA_END:\n                self.insert_region_range(EFI_VA_START, EFI_VA_END, \"efi\")\n        return\n\n    def resolve_dtb(self):\n        if not is_arm32():\n            return\n\n        self.quiet_info(\"Resolving device tree blob\")\n        if is_arm32():\n            DTB_START = KernelAddressHeuristicFinder.consts().DTB_START\n            DTB_END = KernelAddressHeuristicFinder.consts().DTB_END\n            if DTB_START and DTB_END:\n                self.insert_region_range(DTB_START, DTB_END, \"dtb\")\n        return\n\n    def resolve_reserved(self):\n        if not is_arm32():\n            return\n\n        self.quiet_info(\"Resolving reserved\")\n        if is_arm32():\n            RESERVED_START = KernelAddressHeuristicFinder.consts().RESERVED_START\n            RESERVED_END = KernelAddressHeuristicFinder.consts().RESERVED_END\n            if RESERVED_START and RESERVED_END:\n                self.insert_region_range(RESERVED_START, RESERVED_END, \"reserved\")\n        return\n\n    def resolve_fixmap(self):\n        self.quiet_info(\"Resolving fixmap\")\n        FIXADDR_START = KernelAddressHeuristicFinder.consts().FIXADDR_START\n        FIXADDR_TOP = KernelAddressHeuristicFinder.consts().FIXADDR_TOP\n        if FIXADDR_START and FIXADDR_TOP:\n            self.insert_region_range(FIXADDR_START, FIXADDR_TOP, \"fixmap\")\n        return\n\n    def resolve_vsyscall(self):\n        if not is_x86_64():\n            return\n\n        self.quiet_info(\"Resolving vsyscall\")\n        if is_x86_64():\n            VSYSCALL_ADDR = KernelAddressHeuristicFinder.consts().VSYSCALL_ADDR\n            VSYSCALL_END = KernelAddressHeuristicFinder.consts().VSYSCALL_END\n            if VSYSCALL_ADDR and VSYSCALL_END:\n                self.insert_region_range(VSYSCALL_ADDR, VSYSCALL_END, \"vsyscall\")\n        return\n\n    def resolve_pci(self):\n        if not is_arm64():\n            return\n\n        self.quiet_info(\"Resolving pci\")\n        if is_arm64():\n            PCI_IO_START = KernelAddressHeuristicFinder.consts().PCI_IO_START\n            PCI_IO_END = KernelAddressHeuristicFinder.consts().PCI_IO_END\n            if PCI_IO_START and PCI_IO_END:\n                self.insert_region_range(PCI_IO_START, PCI_IO_END, \"pci\")\n        return\n\n    def resolve_vector(self):\n        if not is_arm32():\n            return\n\n        self.quiet_info(\"Resolving vector\")\n        if is_arm32():\n            self.insert_region_range(0xffff_0000, 0xffff_1000, \"vector\")\n        return\n\n    def resolve_buddy(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving buddy: skipped (args.verbose < 1)\")\n            return\n\n        self.quiet_info(\"Resolving buddy\")\n\n        try:\n            res = gdb.execute(\"buddy-dump --quiet --no-pager --sort\", to_string=True)\n        except gdb.error:\n            return\n\n        for line in res.splitlines():\n            line = Color.remove_color(line)\n            if not line.startswith(\"    \"):\n                continue\n\n            _page_str, size_str, virt_str, _phys_str, *pcp = line.split()\n\n            if \"???\" in virt_str: # maybe x86 highmem\n                continue\n\n            size = int(size_str[5:], 16)\n            virt = int(virt_str[5:].split(\"-\")[0], 16)\n            if pcp:\n                description = \"free page in buddy allocator {:s}\".format(\" \".join(pcp))\n            else:\n                description = \"free page in buddy allocator\"\n            self.insert_region(virt, size, description, merge=False)\n        return\n\n    def resolve_kstack(self):\n        self.quiet_info(\"Resolving kstack\")\n\n        try:\n            res = gdb.execute(\"ktask --quiet --no-pager --print-thread\", to_string=True)\n        except gdb.error:\n            return\n\n        # calc kstack address pattern\n        kstacks = []\n        for line in res.splitlines():\n            line = line.split()\n            if len(line) >= 2:\n                kstack = int(line[-2], 16)\n                kstacks.append(kstack & 0xffff)\n\n        # calc kstack size\n        kstacks = sorted(set(kstacks))\n        diffs = []\n        for i in range(len(kstacks) - 1):\n            diff = kstacks[i + 1] - kstacks[i]\n            diffs.append(diff)\n        if len(diffs) == 0:\n            kstack_size = get_pagesize() *2\n        else:\n            kstack_size = min(diffs)\n\n        # kstack\n        for line in res.splitlines():\n            elems = line.split()\n            pid, kstack = int(elems[3]), int(elems[-2], 16)\n            process_name = line.split(maxsplit=4)[4][:16].strip()\n            description = \"kstack PID:{:d} ({:s})\".format(pid, process_name)\n            self.insert_region(kstack, kstack_size, description)\n        return\n\n    def resolve_userland(self):\n        self.quiet_info(\"Resolving userland\")\n\n        # If current is a kernel thread, the userland memory map details will not be displayed.\n        # Even if you are in a kernel thread, you may be able to see the userland memory map,\n        # but it takes time to identify which process it belongs to.\n        try:\n            th_num = gdb.selected_thread().num\n            res = gdb.execute(\"kcurrent --quiet\", to_string=True)\n            r = re.search(r\"current \\(cpu{:d}\\): (0x\\S+) .*\".format(th_num - 1), res)\n            if not r:\n                return\n            curr_task = int(r.group(1), 16)\n        except Exception:\n            return\n\n        try:\n            res = gdb.execute(f\"ktask --quiet --no-pager -u --task-filter {curr_task:#x}\", to_string=True)\n            if not res:\n                return\n            res = gdb.execute(f\"ktask --quiet --no-pager -u --task-filter {curr_task:#x} -m\", to_string=True)\n        except gdb.error:\n            return\n\n        pid = -1\n        comm = \"?\"\n        for line in res.splitlines():\n            if not line.startswith(\"0x\"):\n                continue\n            line = line.split()\n\n            # process name\n            if \"-\" not in line[0]:\n                pid, comm = int(line[3]), line[4]\n                continue\n\n            # map name\n            addr_start, addr_end = line[0].split(\"-\")\n            addr_start = int(addr_start, 16)\n            addr_end = int(addr_end, 16)\n            map_size = addr_end - addr_start\n            description = \"PID:{:d} ({:s}) {:s}\".format(pid, comm, \" \".join(line[2:]))\n            self.insert_region(addr_start, map_size, description.rstrip())\n        return\n\n    def resolve_full_slub(self):\n        if self.args.verbose < 2:\n            self.quiet_warn(\"Resolving full slub: skipped (args.verbose < 2)\")\n            return\n        self.quiet_info(\"Resolving full slub (skip if target region size >= 0x200000)\")\n\n        old_regions = list(self.regions.items())[::]\n        tqdm = GefUtil.get_tqdm()\n        for _region_addr, region in tqdm(old_regions, leave=False):\n            if \"slab cache\" in region.description:\n                continue\n            if region.perm != \"rw-\":\n                continue\n            if region.size >= 0x20_0000: # heuristic threshold\n                continue\n            current = region.addr_start\n            while current < region.addr_end:\n                try:\n                    res = Kernel.get_slab_contains(current)\n                except gdb.error:\n                    break\n                if not res:\n                    current += get_pagesize()\n                    continue\n\n                r = re.search(r\"name: (\\S+)  .+  num_pages: (\\S+)\", res)\n                if not r:\n                    current += get_pagesize()\n                    continue\n\n                name = r.group(1)\n                # something is wrong\n                if name and not all(x in String.STRING_PRINTABLE for x in name):\n                    current += get_pagesize()\n                    continue\n\n                num_pages = int(r.group(2), 16)\n                # something is wrong\n                if num_pages == 0:\n                    current += get_pagesize()\n                    continue\n\n                description = \"slab cache ({:s}; full)\".format(name)\n                total_page_size = get_pagesize() * num_pages\n\n                self.insert_region(current, total_page_size, description, merge=False)\n                current += total_page_size\n        return\n\n    def resolve_slub(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving slub: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Resolving slub\")\n\n        try:\n            res = gdb.execute(\"slub-dump --quiet --no-pager -vv\", to_string=True)\n        except gdb.error:\n            return\n\n        name, address, size = None, None, None\n        for line in res.splitlines():\n            r = re.search(r\"name: (.+)\", line)\n            if r:\n                name = Color.remove_color(r.group(1))\n                continue\n            r = re.search(r\"virtual address: (.+0x.+)\", line)\n            if r:\n                address = Color.remove_color(r.group(1))\n                address = int(address, 16)\n                continue\n            r = re.search(r\"num pages: (\\d+)\", line)\n            if r:\n                size = int(r.group(1)) * get_pagesize()\n                description = \"slab cache ({:s})\".format(name)\n                if address:\n                    self.insert_region(address, size, description, merge=False)\n                address, size = None, None # for detect logic error. name will be reused until next parsing\n                continue\n\n        self.resolve_full_slub()\n        return\n\n    def resolve_slab(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving slab: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Resolving slab\")\n\n        try:\n            res = gdb.execute(\"slab-dump --quiet --no-pager\", to_string=True)\n        except gdb.error:\n            return\n\n        name, address, size = None, None, None\n        for line in res.splitlines():\n            r = re.search(r\"name: (.+)\", line)\n            if r:\n                name = Color.remove_color(r.group(1))\n                continue\n            r = re.search(r\"virtual address \\(s_mem & ~0xfff\\): (.+0x.+)\", line)\n            if r:\n                address = Color.remove_color(r.group(1))\n                address = int(address, 16)\n                continue\n            r = re.search(r\"num pages: (\\d+)\", line)\n            if r:\n                size = int(r.group(1)) * get_pagesize()\n                description = \"slab cache ({:s})\".format(name)\n                if address:\n                    self.insert_region(address, size, description, merge=False)\n                address, size = None, None # for detect logic error. name will be reused until next parsing\n                continue\n        return\n\n    def resolve_slob(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving slob: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Resolving slob\")\n\n        try:\n            res = gdb.execute(\"slob-dump --quiet --no-pager\", to_string=True)\n        except gdb.error:\n            return\n\n        address, size = None, None\n        for line in res.splitlines():\n            r = re.search(r\"virtual address: (.+0x.+)\", line)\n            if r:\n                address = Color.remove_color(r.group(1))\n                address = int(address, 16)\n                continue\n            r = re.search(r\"num pages: (\\d+)\", line)\n            if r:\n                size = int(r.group(1)) * get_pagesize()\n                description = \"slab cache\"\n                if address:\n                    self.insert_region(address, size, description, merge=False)\n                address, size = None, None # for detect logic error\n                continue\n        return\n\n    def resolve_slub_tiny(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving slub-tiny: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Resolving slub-tiny\")\n\n        try:\n            res = gdb.execute(\"slub-tiny-dump --quiet --no-pager\", to_string=True)\n        except gdb.error:\n            return\n\n        name, address, size = None, None, None\n        for line in res.splitlines():\n            r = re.search(r\"name: (.+)\", line)\n            if r:\n                name = Color.remove_color(r.group(1))\n                continue\n            r = re.search(r\"virtual address: (.+0x.+)\", line)\n            if r:\n                address = Color.remove_color(r.group(1))\n                address = int(address, 16)\n                continue\n            r = re.search(r\"num pages: (\\d+)\", line)\n            if r:\n                size = int(r.group(1)) * get_pagesize()\n                description = \"slab cache ({:s})\".format(name)\n                if address:\n                    self.insert_region(address, size, description, merge=False)\n                address, size = None, None # for detect logic error. name will be reused\n                continue\n        return\n\n    def resolve_each_slab(self):\n        allocator = Kernel.get_slab_type()\n        if allocator == \"SLUB\":\n            self.resolve_slub()\n        elif allocator == \"SLUB_TINY\":\n            self.resolve_slub_tiny()\n        elif allocator == \"SLAB\":\n            self.resolve_slab()\n        elif allocator == \"SLOB\":\n            self.resolve_slob()\n        return\n\n    def resolve_each_module(self):\n        self.quiet_info(\"Resolving each module\")\n\n        try:\n            res = gdb.execute(\"kmod --quiet --no-pager\", to_string=True)\n        except gdb.error:\n            return\n\n        for line in res.splitlines():\n            if not line:\n                continue\n            line = line.split()\n            module_name = line[1]\n            module_base = int(line[2], 16)\n            module_size = align_to_pagesize(int(line[3], 16))\n            description = \"kernel module ({:s})\".format(module_name)\n            self.insert_region(module_base, module_size, description)\n        return\n\n    def resolve_vdso(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Resolving vdso: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Resolving vdso\")\n\n        if is_x86_64():\n            vdso_image_64 = KernelAddressHeuristicFinder.get_vdso_image_64()\n            if vdso_image_64:\n                vdso_start = read_int_from_memory(vdso_image_64)\n                vdso_size = read_int_from_memory(vdso_image_64 + current_arch.ptrsize)\n                self.insert_region(vdso_start, vdso_size, \"vdso_image_64\")\n\n        if is_x86_64() or is_x86_32():\n            vdso_image_32 = KernelAddressHeuristicFinder.get_vdso_image_32()\n            if vdso_image_32:\n                vdso_start = read_int_from_memory(vdso_image_32)\n                vdso_size = read_int_from_memory(vdso_image_32 + current_arch.ptrsize)\n                self.insert_region(vdso_start, vdso_size, \"vdso_image_32\")\n\n        if is_x86_64():\n            vdso_image_x32 = KernelAddressHeuristicFinder.get_vdso_image_x32()\n            if vdso_image_x32:\n                vdso_start = read_int_from_memory(vdso_image_x32)\n                vdso_size = read_int_from_memory(vdso_image_x32 + current_arch.ptrsize)\n                self.insert_region(vdso_start, vdso_size, \"vdso_image_x32\")\n\n        if is_arm64() or is_arm32():\n            vdso_start = KernelAddressHeuristicFinder.get_vdso_start()\n            if vdso_start:\n                vdso_size = get_pagesize()\n                self.insert_region(vdso_start, vdso_size, \"vdso_start\")\n\n        if is_arm64():\n            vdso32_start = KernelAddressHeuristicFinder.get_vdso32_start()\n            if vdso32_start:\n                vdso_size = get_pagesize()\n                self.insert_region(vdso32_start, vdso_size, \"vdso32_start\")\n        return\n\n    def resolve_device_physmem(self):\n        if self.args.verbose < 2:\n            self.quiet_warn(\"Resolving device physmem: skipped (args.verbose < 2)\")\n            return\n        self.quiet_info(\"Resolving device physmem\")\n\n        try:\n            res = gdb.execute(\"monitor info mtree -f\", to_string=True)\n        except gdb.error:\n            return\n\n        maps = PageMap.get_page_maps(None)\n        if maps is None:\n            return\n\n        for line in res.splitlines():\n            if not line.startswith(\"  \"):\n                continue\n\n            m = re.search(r\"  ([0-9a-f]+)-([0-9a-f]+) \\(.+?\\): (.+)\", line)\n            if not m:\n                continue\n\n            paddr = int(m.group(1), 16)\n            if paddr % 0x1000:\n                continue\n\n            pend = int(m.group(2), 16)\n            if (pend & 0xfff) == 0xfff:\n                pend += 1\n            if pend % 0x1000:\n                continue\n\n            size = pend - paddr\n            if size % 0x1000 or size == 0:\n                continue\n\n            device_name = \"device ({:s})\".format(m.group(3))\n\n            vaddrs = PageMap.p2v_from_map(paddr, maps)\n            for vaddr in vaddrs:\n                self.insert_region(vaddr, size, device_name)\n        return\n\n    def detect_zero_page(self):\n        if self.args.verbose < 1:\n            self.quiet_warn(\"Detecting zero page: skipped (args.verbose < 1)\")\n            return\n        self.quiet_info(\"Detecting zero page\")\n\n        page_size = get_pagesize()\n        z10 = b\"\\0\" * 0x10\n        cc10 = b\"\\xcc\" * 0x10\n        ff10 = b\"\\xff\" * 0x10\n        z1000 = b\"\\0\" * page_size\n        ff1000 = b\"\\xff\" * page_size\n        cc1000 = b\"\\xcc\" * page_size\n\n        for _key, r in self.regions.copy().items():\n            if r.description != \"\":\n                continue\n            if r.size >= page_size * 0x10:\n                continue\n            for addr in range(r.addr_start, r.addr_end, page_size):\n                try:\n                    x = read_memory(addr, 0x10)\n                except gdb.MemoryError:\n                    self.insert_region(addr, page_size, \"can not access\")\n                    continue\n\n                if x not in [z10, ff10, cc10]:\n                    continue\n                try:\n                    x = read_memory(addr, page_size)\n                except gdb.MemoryError:\n                    continue\n                if x == z1000:\n                    self.insert_region(addr, page_size, \"0x00-filled\")\n                elif x == cc1000:\n                    self.insert_region(addr, page_size, \"0xcc-filled\")\n                elif x == ff1000:\n                    self.insert_region(addr, page_size, \"0xff-filled\")\n        return\n\n    def add_legend(self):\n        if not self.args.quiet:\n            fmt = \"{:37s} {:18s} {:5s} {:s}\"\n            legend = [\"Virtual address start-end\", \"Total size\", \"Perm\", \"Hint\"]\n            self.out.append(GefUtil.make_legend(fmt.format(*legend)))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        if self.args.include_esp_fixup_stacks and not is_x86_64():\n            err(\"Unsupported --include-esp-fixup-stacks option in this arch\")\n            return\n\n        if Kernel.kernel_version() is None:\n            err(\"Could not find Linux kernel\")\n            return\n\n        # initial regions\n        self.regions = self.get_maps()\n\n        # add info\n        self.out = []\n        self.add_legend()\n        self.resolve_userland()\n        self.resolve_ldt()\n        self.resolve_direct_map()\n        self.resolve_vmalloc()\n        self.resolve_vmemmap()\n        self.resolve_cpu_entry()\n        self.resolve_efi()\n        self.resolve_dtb()\n        self.resolve_kbase()\n        self.resolve_kstack()\n        self.resolve_module()\n        self.resolve_fixmap()\n        self.resolve_vsyscall()\n        self.resolve_pci()\n        self.resolve_vector()\n        self.resolve_reserved()\n\n        self.resolve_device_physmem()\n        self.resolve_buddy()\n        self.resolve_each_slab()\n        self.resolve_each_module()\n        self.resolve_vdso()\n        self.detect_zero_page()\n\n        self.merge_region()\n        self.filter_region()\n\n        # make output\n        for _, r in sorted(self.regions.items()):\n            self.out.append(str(r))\n        self.print_output()\n        return\n\n\n@register_command\nclass PageCommand(GenericCommand):\n    \"\"\"The base command to convert between virtual addresses, physical addresses, and page addresses.\"\"\"\n\n    _cmdline_ = \"page\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-hh\", \"--help-simple\", action=\"store_true\", help=\"show help without ASCII diagram.\")\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=False)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"to_virt\")\n    subparsers.add_parser(\"to_phys\")\n    subparsers.add_parser(\"from_virt\")\n    subparsers.add_parser(\"from_phys\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"Simplified page structure:\",\n        \"\",\n        \"[x86_64 / CONFIG_SPARSEMEM_VMEMMAP]\",\n        \"VMEMMAP_START--------->+-struct page[]-+\",\n        \"                       | pfn#0 page    | --> physmem 0x0\",\n        \"                       +---------------+\",\n        \"                       | pfn#1 page    | --> physmem 0x1000\",\n        \"                       +---------------+\",\n        \"                       | ...           |\",\n        \"                       +---------------+\",\n        \"                       | pfn#N page    | --> ...\",\n        \"                       +---------------+\",\n        \"\",\n        \"\",\n        \"[arm64 / CONFIG_SPARSEMEM_VMEMMAP]\",\n        \"* This pattern uses `VMEMMAP_START`, but it needs `memstart_pfn` adjustment.\",\n        \"vmemmap--------------->+-struct page[]-----------+\",\n        \"                       | pfn#0 page              | --> physmem 0x0\",\n        \"                       +-------------------------+\",\n        \"                       | ...                     | --> ...\",\n        \"VMEMMAP_START--------->+-------------------------+\",\n        \"                       | pfn#memstart_pfn   page | --> physmem memstart_addr\",\n        \"                       +-------------------------+\",\n        \"                       | pfn#memstart_pfn+1 page | --> physmem memstart_addr+0x1000\",\n        \"                       +-------------------------+\",\n        \"                       | ...                     |\",\n        \"                       +-------------------------+\",\n        \"                       | pfn#memstart_pfn+N page | --> ...\",\n        \"                       +-------------------------+\",\n        \"\",\n        \"\",\n        \"[x86_32 / CONFIG_FLATMEM]\",\n        \"mem_map--------------->+-struct page[]-+\",\n        \"                       | pfn#0 page    | --> physmem 0x0\",\n        \"                       +---------------+\",\n        \"                       | pfn#1 page    | --> physmem 0x1000\",\n        \"                       +---------------+\",\n        \"                       | ...           |\",\n        \"                       +---------------+\",\n        \"                       | pfn#N page    | --> ...\",\n        \"                       +---------------+\",\n        \"\",\n        \"\",\n        \"[arm32 / CONFIG_FLATMEM]\",\n        \"* `mem_map` starts at pfn#PHYS_PFN_OFFSET, not pfn#0.\",\n        \"mem_map--------------->+-struct page[]--------------+\",\n        \"                       | pfn#PHYS_PFN_OFFSET   page | --> physmem PHYS_OFFSET\",\n        \"                       +----------------------------+\",\n        \"                       | pfn#PHYS_PFN_OFFSET+1 page | --> physmem PHYS_OFFSET+0x1000\",\n        \"                       +----------------------------+\",\n        \"                       | ...                        |\",\n        \"                       +----------------------------+\",\n        \"                       | pfn#PHYS_PFN_OFFSET+N page | --> ...\",\n        \"                       +----------------------------+\",\n        \"\",\n        \"\",\n        \"[x86_32 or arm32 / CONFIG_SPARSEMEM]\",\n        \"* This pattern uses `mem_section[]`, i.e. multiple section-specific mem_maps.\",\n        \"* `section_id` can be obtained from `page->flags`.\",\n        \"* `section_mem_map` is encoded and used to locate the page descriptor array.\",\n        \"+-------------------------------------------------------------------------------------------+\",\n        \"|                                                                                           |\",\n        \"|  +-struct mem_section[]-+                                                                 |\",\n        \"|  | section_mem_map      |     +-->+-struct page[]----------------+                        |\",\n        \"|  +----------------------+     |   | pfn#section_start_pfn   page | --> physmem ...        |\",\n        \"+->| section_mem_map      |-----+   |  flags                       | --> section_id (=idx)--+\",\n        \"   +----------------------+         +------------------------------+\",\n        \"   | ...                  |         | pfn#section_start_pfn+1 page | --> physmem ...\",\n        \"   +----------------------+         |  flags                       |\",\n        \"   | section_mem_map      |         +------------------------------+\",\n        \"   +----------------------+         | ...                          |\",\n        \"                                    +------------------------------+\",\n        \"                                    | pfn#section_start_pfn+N page | --> ...\",\n        \"                                    |  flags                       |\",\n        \"                                    +------------------------------+\",\n        \"\",\n        \"* CONFIG_SPARSEMEM_EXTREME is currently unsupported by this command.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        complete = kwargs.get(\"complete\", gdb.COMPLETE_NONE)\n        super().__init__(prefix=prefix, complete=complete)\n        return\n\n    def initialize(self):\n        if hasattr(PageCommand, \"initialized\") and PageCommand.initialized:\n            return True\n\n        info(\"Wait for memory scan\")\n\n        PageCommand.PAGE_SHIFT = KernelAddressHeuristicFinder.consts().PAGE_SHIFT\n\n        if is_x86_64():\n            PageCommand.VMEMMAP_START = KernelAddressHeuristicFinder.get_VMEMMAP_START()\n            if self.VMEMMAP_START is None:\n                err(\"Could not find VMEMMAP_START\")\n                return False\n\n            PageCommand.sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n            if self.sizeof_struct_page is None:\n                err(\"Could not find sizeof(struct page)\")\n                return False\n\n        elif is_x86_32():\n            if KernelAddressHeuristicFinder.consts().CONFIG_FLATMEM:\n                PageCommand.mode = \"FLATMEM\"\n                PageCommand.mem_map = KernelAddressHeuristicFinder.consts().mem_map\n                sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n                if sizeof_struct_page is None:\n                    return False\n                PageCommand.sizeof_struct_page = sizeof_struct_page\n\n            elif KernelAddressHeuristicFinder.consts().CONFIG_SPARSEMEM:\n                PageCommand.mode = \"SPARSEMEM\"\n                PageCommand.mem_section = KernelAddressHeuristicFinder.consts().mem_section\n                sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n                if sizeof_struct_page is None:\n                    return False\n                PageCommand.sizeof_struct_page = sizeof_struct_page\n                PageCommand.SECTION_HAS_MEM_MAP = KernelAddressHeuristicFinder.consts().SECTION_HAS_MEM_MAP\n                PageCommand.sizeof_mem_section = KernelAddressHeuristicFinder.consts().sizeof_mem_section\n                PageCommand.SECTIONS_PGSHIFT = KernelAddressHeuristicFinder.consts().SECTIONS_PGSHIFT\n                PageCommand.SECTIONS_MASK = KernelAddressHeuristicFinder.consts().SECTIONS_MASK\n                PageCommand.SECTION_MAP_MASK = KernelAddressHeuristicFinder.consts().SECTION_MAP_MASK\n                PageCommand.PFN_SECTION_SHIFT = KernelAddressHeuristicFinder.consts().PFN_SECTION_SHIFT\n\n            else:\n                err(\"Could not find mem_map and mem_section\")\n                return False\n\n        elif is_arm64():\n            PageCommand.VMEMMAP_START = KernelAddressHeuristicFinder.get_VMEMMAP_START()\n            if self.VMEMMAP_START is None:\n                err(\"Could not find VMEMMAP_START\")\n                return False\n\n            PageCommand.sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n            if self.sizeof_struct_page is None:\n                err(\"Could not find sizeof(struct page)\")\n                return False\n\n            memstart_addr = KernelAddressHeuristicFinder.consts().memstart_addr\n            if memstart_addr is None:\n                err(\"Could not find memstart_addr\")\n                return False\n\n            pQ = lambda a: struct.pack(\"<Q\", a & 0xffff_ffff_ffff_ffff)\n            uq = lambda a: struct.unpack(\"<q\", a)[0]\n            u2i = lambda a: uq(pQ(a))\n            PageCommand.memstart_addr = u2i(memstart_addr)\n\n        elif is_arm32():\n            if KernelAddressHeuristicFinder.consts().CONFIG_FLATMEM:\n                PageCommand.mode = \"FLATMEM\"\n                PageCommand.mem_map = KernelAddressHeuristicFinder.consts().mem_map\n                sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n                if sizeof_struct_page is None:\n                    err(\"Could not find sizeof(struct page)\")\n                    return False\n                PageCommand.sizeof_struct_page = sizeof_struct_page\n                PageCommand.PHYS_PFN_OFFSET = KernelAddressHeuristicFinder.consts().PHYS_PFN_OFFSET\n\n            elif KernelAddressHeuristicFinder.consts().CONFIG_SPARSEMEM:\n                PageCommand.mode = \"SPARSEMEM\"\n                PageCommand.mem_section = KernelAddressHeuristicFinder.consts().mem_section\n                sizeof_struct_page = KernelAddressHeuristicFinder.consts().sizeof_struct_page\n                if sizeof_struct_page is None:\n                    err(\"Could not find sizeof(struct page)\")\n                    return False\n                PageCommand.sizeof_struct_page = sizeof_struct_page\n                PageCommand.sizeof_mem_section = KernelAddressHeuristicFinder.consts().sizeof_mem_section\n                PageCommand.SECTION_HAS_MEM_MAP = KernelAddressHeuristicFinder.consts().SECTION_HAS_MEM_MAP\n                PageCommand.SECTIONS_PGSHIFT = KernelAddressHeuristicFinder.consts().SECTIONS_PGSHIFT\n                PageCommand.SECTIONS_MASK = KernelAddressHeuristicFinder.consts().SECTIONS_MASK\n                PageCommand.SECTION_MAP_MASK = KernelAddressHeuristicFinder.consts().SECTION_MAP_MASK\n                PageCommand.PFN_SECTION_SHIFT = KernelAddressHeuristicFinder.consts().PFN_SECTION_SHIFT\n                PageCommand.PHYS_PFN_OFFSET = KernelAddressHeuristicFinder.consts().PHYS_PFN_OFFSET\n\n            else:\n                err(\"Could not find mem_map and mem_section\")\n                return False\n\n        PageCommand.initialized = True\n        return True\n\n    def page2phys(self, page):\n        if not is_valid_addr(page):\n            err(\"Memory read error\")\n            return None\n\n        if is_x86_64():\n            delta = page - self.VMEMMAP_START\n            if delta < 0:\n                return None\n            if delta % self.sizeof_struct_page != 0:\n                return None\n            pfn = delta // self.sizeof_struct_page\n\n        elif is_x86_32():\n            if self.mode == \"FLATMEM\":\n                delta = page - self.mem_map\n                if delta < 0:\n                    return None\n                if delta % self.sizeof_struct_page != 0:\n                    return None\n                pfn = (delta // self.sizeof_struct_page)\n\n            elif self.mode == \"SPARSEMEM\":\n                flags = read_int_from_memory(page)\n                section_id = (flags >> self.SECTIONS_PGSHIFT) & self.SECTIONS_MASK\n\n                mem_section_i = self.mem_section + self.sizeof_mem_section * section_id\n                if not is_valid_addr(mem_section_i):\n                    return None\n\n                section_mem_map_i = read_int_from_memory(mem_section_i)\n                if (section_mem_map_i & self.SECTION_HAS_MEM_MAP) == 0:\n                    return None\n\n                biased_map = section_mem_map_i & self.SECTION_MAP_MASK\n                delta = page - biased_map\n                if delta < 0:\n                    return None\n                if delta % self.sizeof_struct_page != 0:\n                    return None\n                pfn = delta // self.sizeof_struct_page\n            else:\n                return None\n\n        elif is_arm64():\n            delta = page - self.VMEMMAP_START\n            if delta < 0:\n                return None\n            if delta % self.sizeof_struct_page != 0:\n                return None\n            memstart_pfn = self.memstart_addr >> self.PAGE_SHIFT\n            pfn = (delta // self.sizeof_struct_page) + memstart_pfn\n\n        elif is_arm32():\n            if self.mode == \"FLATMEM\":\n                delta = page - self.mem_map\n                if delta < 0:\n                    return None\n                if delta % self.sizeof_struct_page != 0:\n                    return None\n                pfn = (delta // self.sizeof_struct_page) + self.PHYS_PFN_OFFSET\n\n            elif self.mode == \"SPARSEMEM\":\n                flags = read_int_from_memory(page)\n                section_id = (flags >> self.SECTIONS_PGSHIFT) & self.SECTIONS_MASK\n\n                mem_section_i = self.mem_section + self.sizeof_mem_section * section_id\n                if not is_valid_addr(mem_section_i):\n                    return None\n\n                section_mem_map_i = read_int_from_memory(mem_section_i)\n                if (section_mem_map_i & self.SECTION_HAS_MEM_MAP) == 0:\n                    return None\n\n                biased_map = section_mem_map_i & self.SECTION_MAP_MASK\n                delta = page - biased_map\n                if delta < 0:\n                    return None\n                if delta % self.sizeof_struct_page != 0:\n                    return None\n                pfn = delta // self.sizeof_struct_page\n            else:\n                return None\n\n        else:\n            return None\n\n        if pfn < 0:\n            return None\n        return pfn << self.PAGE_SHIFT\n\n    def phys2page(self, phys):\n        if phys < 0:\n            return None\n        if phys & ((1 << self.PAGE_SHIFT) - 1):\n            return None\n\n        pfn = phys >> self.PAGE_SHIFT\n\n        if is_x86_64():\n            page = self.VMEMMAP_START + (pfn * self.sizeof_struct_page)\n\n        elif is_x86_32():\n            if self.mode == \"FLATMEM\":\n                if pfn < 0:\n                    return None\n                page = self.mem_map + (pfn * self.sizeof_struct_page)\n\n            elif self.mode == \"SPARSEMEM\":\n                section_id = pfn >> self.PFN_SECTION_SHIFT\n                mem_section_i = self.mem_section + self.sizeof_mem_section * section_id\n                if not is_valid_addr(mem_section_i):\n                    return None\n\n                section_mem_map_i = read_int_from_memory(mem_section_i)\n                if (section_mem_map_i & self.SECTION_HAS_MEM_MAP) == 0:\n                    return None\n\n                biased_map = section_mem_map_i & self.SECTION_MAP_MASK\n                page = biased_map + (pfn * self.sizeof_struct_page)\n            else:\n                return None\n\n        elif is_arm64():\n            memstart_pfn = self.memstart_addr >> self.PAGE_SHIFT\n            if pfn < memstart_pfn:\n                return None\n            page = self.VMEMMAP_START + ((pfn - memstart_pfn) * self.sizeof_struct_page)\n\n        elif is_arm32():\n            if self.mode == \"FLATMEM\":\n                if pfn < self.PHYS_PFN_OFFSET:\n                    return None\n                page = self.mem_map + ((pfn - self.PHYS_PFN_OFFSET) * self.sizeof_struct_page)\n\n            elif self.mode == \"SPARSEMEM\":\n                section_id = pfn >> self.PFN_SECTION_SHIFT\n                mem_section_i = self.mem_section + self.sizeof_mem_section * section_id\n                if not is_valid_addr(mem_section_i):\n                    return None\n\n                section_mem_map_i = read_int_from_memory(mem_section_i)\n                if (section_mem_map_i & self.SECTION_HAS_MEM_MAP) == 0:\n                    return None\n\n                biased_map = section_mem_map_i & self.SECTION_MAP_MASK\n                page = biased_map + (pfn * self.sizeof_struct_page)\n            else:\n                return None\n\n        else:\n            return None\n\n        if not is_valid_addr(page):\n            err(\"Address in invalid range\")\n            return None\n        return page\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        self.usage(simple=True)\n        return\n\n\n@register_command\nclass PageToVirtCommand(PageCommand, BufferingOutput):\n    \"\"\"Resolve virtual addresses mapped to the page.\"\"\"\n\n    _cmdline_ = \"page to_virt\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n    _aliases_ = [\"page2virt\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"page\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the page address to translate.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"One page may correspond to multiple virtual addresses.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        if args.rescan:\n            PageCommand.initialized = False\n\n        if is_arm64():\n            kversion = Kernel.kernel_version()\n            if kversion < \"4.7\":\n                err(\"Unsupported before v4.7\")\n                return\n\n        ret = self.initialize()\n        if ret is False:\n            err(\"Failed to initialize\")\n            return\n\n        self.out = []\n\n        paddr = self.page2phys(args.page)\n        if paddr is None:\n            err(\"Failed to resolve phys\")\n            return\n        # A page may be associated with multiple virtual addresses.\n        vaddrs = Kernel.p2v(paddr)\n        if not vaddrs:\n            err(\"Failed to resolve virt\")\n            return\n        for vaddr in vaddrs:\n            self.out.append(\"Page: {:#x} -> Virt: {:#x}\".format(args.page, vaddr))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PageFromVirtCommand(PageCommand, BufferingOutput):\n    \"\"\"Resolve the struct page for a virtual address.\"\"\"\n\n    _cmdline_ = \"page from_virt\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n    _aliases_ = [\"virt2page\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"virt\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the virtual address to translate.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        if args.rescan:\n            PageCommand.initialized = False\n\n        if is_arm64():\n            kversion = Kernel.kernel_version()\n            if kversion < \"4.7\":\n                err(\"Unsupported before v4.7\")\n                return\n\n        ret = self.initialize()\n        if ret is False:\n            err(\"Failed to initialize\")\n            return\n\n        self.out = []\n\n        vaddr = args.virt\n        if vaddr & 0xfff:\n            warn(\"The address must be page aligned, round down and then calculate\")\n            vaddr &= get_pagesize_mask_high()\n\n        paddr = Kernel.v2p(vaddr)\n        if paddr is None:\n            err(\"Failed to resolve phys\")\n            return\n        page = self.phys2page(paddr)\n        if page is None:\n            err(\"Failed to resolve page\")\n            return\n        self.out.append(\"Virt: {:#x} -> Page: {:#x}\".format(vaddr, page))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PageToPhysCommand(PageCommand, BufferingOutput):\n    \"\"\"Resolve the physical address for a struct page.\"\"\"\n\n    _cmdline_ = \"page to_phys\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n    _aliases_ = [\"page2phys\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"page\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the page address to translate.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        if args.rescan:\n            PageCommand.initialized = False\n\n        if is_arm64():\n            kversion = Kernel.kernel_version()\n            if kversion < \"4.7\":\n                err(\"Unsupported before v4.7\")\n                return\n\n        ret = self.initialize()\n        if ret is False:\n            err(\"Failed to initialize\")\n            return\n\n        self.out = []\n\n        paddr = self.page2phys(args.page)\n        if paddr is None:\n            err(\"Failed to resolve phys\")\n            return\n        self.out.append(\"Page: {:#x} -> Phys: {:#x}\".format(args.page, paddr))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PhysToPageCommand(PageCommand, BufferingOutput):\n    \"\"\"Resolve the struct page for a physical address.\"\"\"\n\n    _cmdline_ = \"page from_phys\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n    _aliases_ = [\"phys2page\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"phys\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"the physical address to translate.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False, complete=gdb.COMPLETE_LOCATION)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\", \"kgdb\"))\n    @only_if_specific_arch(arch=(\"x86_64\", \"x86_32\", \"ARM64\", \"ARM32\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        if args.rescan:\n            PageCommand.initialized = False\n\n        if is_arm64():\n            kversion = Kernel.kernel_version()\n            if kversion < \"4.7\":\n                err(\"Unsupported before v4.7\")\n                return\n\n        ret = self.initialize()\n        if ret is False:\n            err(\"Failed to initialize\")\n            return\n\n        self.out = []\n\n        paddr = args.phys\n        if paddr & 0xfff:\n            warn(\"The address must be page aligned, round down and then calculate\")\n            paddr &= get_pagesize_mask_high()\n\n        page = self.phys2page(paddr)\n        if page is None:\n            err(\"Failed to resolve page\")\n            return\n        self.out.append(\"Phys: {:#x} -> Page: {:#x}\".format(paddr, page))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass SlabVirtualCommand(GenericCommand):\n    \"\"\"Convert between slab-virtual addresses and page addresses.\"\"\"\n\n    _cmdline_ = \"slab-virtual\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    modes = [\"to_virt\", \"to_page\", \"from_virt\", \"from_page\"]\n    parser.add_argument(\"mode\", choices=modes, help=\"conversion mode.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address, help=\"the address to convert.\")\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command works only in CONFIG_SLAB_VIRTUAL=y (implemented at https://github.com/thejh/linux).\",\n        \"Used in the Google Kernel CTF mitigation instance.\",\n        \"\",\n        \"CONFIG_SLAB_VIRTUAL=n (normal kernel):\",\n        \"  Both `struct slab` and `struct page` directly manage physmap area.\",\n        \"\",\n        \"  [physmap area]\",\n        \"                     +------------+\",\n        \"                     | virt       | <-- size: 0x1000\",\n        \"                     +------------+\",\n        \"                     | ...        |\",\n        \"                     +------------+\",\n        \"  [vmemmap area]\",\n        \"                     +------------+\",\n        \"                     | page/slab  | <-- size: sizeof(page) or sizeof(slab)\",\n        \"                     +------------+\",\n        \"                     | ...        |\",\n        \"                     +------------+\",\n        \"\",\n        \"CONFIG_SLAB_VIRTUAL=y (mitigated kernel):\",\n        \"  `struct slab` no longer manages physmap area. Instead, `struct slab` manages the slab_data area.\",\n        \"\",\n        \"  [physmap area]\",\n        \"                     +------------+\",\n        \"                     | virt       | <-- size: 0x1000\",\n        \"                     +------------+\",\n        \"                     | ...        |\",\n        \"                     +------------+\",\n        \"  [vmemmap area]\",\n        \"                     +------------+\",\n        \"                     | page       | <-- size: sizeof(page)\",\n        \"                     +------------+\",\n        \"                     | ...        |\",\n        \"                     +------------+\",\n        \"  [slab_meta area]\",\n        \"           ^         +------------+ SLAB_BASE_ADDR (=0xfffffe8000000000)\",\n        \"           |         | slab       |\",\n        \"           |         +------------+\",\n        \"    SLAB_META_SIZE   | slab       | <-- meta entry size: STRUCT_SLAB_SIZE               # v6.1~v6.1.55\",\n        \"           |         +------------+                      or sizeof(struct slab)         # v6.1.56~v6.6, v6.12~\",\n        \"           |         | ...        |                      or sizeof(struct virtual_slab) # v6.6~v6.12\",\n        \"           v         +------------+ \",\n        \"  [slab_data area]\",\n        \"                     +------------+ SLAB_DATA_BASE_ADDR (=0xfffffe8800000000)\",\n        \"                     | virt       | \",\n        \"                     +------------+\",\n        \"                     | virt       | <-- size: 0x1000\",\n        \"                     +------------+\",\n        \"                     | ...        |\",\n        \"                     +------------+ SLAB_END_ADDR (=0xffffff0000000000)\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        self.PAGE_SHIFT = 12\n        P4D_SHIFT = 39\n\n        self.SLAB_BASE_ADDR = (-3 << P4D_SHIFT) & 0xffff_ffff_ffff_ffff\n        self.quiet_info(\"SLAB_BASE_ADDR: {:#x}\".format(self.SLAB_BASE_ADDR))\n\n        self.SLAB_END_ADDR = self.SLAB_BASE_ADDR + (1 << P4D_SHIFT)\n        self.quiet_info(\"SLAB_END_ADDR: {:#x}\".format(self.SLAB_END_ADDR))\n\n        SLAB_VPAGES = (self.SLAB_END_ADDR - self.SLAB_BASE_ADDR) >> self.PAGE_SHIFT\n        self.quiet_info(\"SLAB_VPAGES: {:#x}\".format(SLAB_VPAGES))\n\n        self.sizeof_struct_page = 0x40\n        self.quiet_info(\"sizeof(struct page): {:#x}\".format(self.sizeof_struct_page))\n\n        kversion = Kernel.kernel_version()\n\n        def align_kernel(x, alignment_size):\n            mask = alignment_size - 1\n            return (x + mask) & (mask ^ 0xffff_ffff_ffff_ffff)\n\n        # size of a single slab meta unit, SLAB_META_SIZE\n        if kversion < \"6.1.56\":\n            # branch: slub-virtual-v6.1, slub-virtual-v6.1-lts\n            # include/linux/slab.h\n            STRUCT_SLAB_SIZE = 24 * current_arch.ptrsize\n            self.SLAB_META_SIZE = align_kernel(SLAB_VPAGES * STRUCT_SLAB_SIZE, 1 << self.PAGE_SHIFT)\n            # mm/slub.c\n            self.slab_meta_entry_size = STRUCT_SLAB_SIZE\n        elif \"6.1.56\" <= kversion < \"6.6\":\n            # branch: mitigations-v6.1.56\n            # arch/x86/include/asm/pgtable_64_types.h\n            STRUCT_SLAB_SIZE = 32 * current_arch.ptrsize\n            self.SLAB_META_SIZE = align_kernel(SLAB_VPAGES * STRUCT_SLAB_SIZE, 1 << self.PAGE_SHIFT)\n            # mm/slab.h\n            \"\"\"\n            gef> dt slab\n            struct slab {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    struct slab * compound_slab_head;\n                /* 0x0008 | 0x0008 */    struct folio * backing_folio;\n                /* 0x0010 | 0x0004 */    struct kmem_cache_order_objects oo;\n                /* 0x0014 | 0x0004 */    spinlock_t slab_lists_lock;\n                /* 0x0018 | 0x0010 */    struct list_head flush_list_elem;\n                /* 0x0028 | 0x0008 */    unsigned long align_mask;\n                /* 0x0030 | 0x0004 */    atomic_t pinstate;\n                /* 0x0038 | 0x0010 */    union {...} ;\n                /* 0x0048 | 0x0008 */    struct kmem_cache * slab_cache;\n                /* 0x0050 | 0x0010 */    struct {...} ;\n                /* 0x0060 | 0x0004 */    unsigned int __unused;\n                /* 0x0068 | 0x0008 */    unsigned long memcg_data;\n            } // total: 0x70 bytes\n            gef>\n            \"\"\"\n            self.slab_meta_entry_size = 0x70 # sizeof(struct slab)\n        elif \"6.6\" <= kversion < \"6.12\":\n            # branch: slub-virtual-v6.6\n            # arch/x86/include/asm/pgtable_64_types.h\n            STRUCT_VIRTUAL_SLAB_SIZE = 32 * current_arch.ptrsize\n            self.SLAB_META_SIZE = align_kernel(SLAB_VPAGES * STRUCT_VIRTUAL_SLAB_SIZE, 1 << self.PAGE_SHIFT)\n            # mm/slab.h\n            \"\"\"\n            gef> dt slab\n            struct slab {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    union {...} ;\n                /* 0x0008 | 0x0008 */    struct kmem_cache * slab_cache;\n                /* 0x0010 | 0x0020 */    union {...} ;\n                /* 0x0030 | 0x0004 */    struct kmem_cache_order_objects oo;\n                /* 0x0034 | 0x0004 */    union {...} ;\n                /* 0x0038 | 0x0008 */    unsigned long memcg_data;\n            } // total: 0x40 bytes\n            gef> dt virtual_slab\n            struct virtual_slab {\n                /* offset | size   */\n                /* 0x0000 | 0x0040 */    struct slab slab;\n                /* 0x0040 | 0x0008 */    struct virtual_slab * compound_slab_head;\n                /* 0x0048 | 0x0008 */    unsigned long align_mask;\n            } // total: 0x50 bytes\n            gef>\n            \"\"\"\n            self.slab_meta_entry_size = 0x50 # sizeof(struct virtual_slab)\n        else: # 6.12~\n            # branch: mitigations-next (linux-6.12 base)\n            # arch/x86/include/asm/pgtable_64_types.h\n            STRUCT_SLAB_SIZE = 32 * current_arch.ptrsize\n            self.SLAB_META_SIZE = align_kernel(SLAB_VPAGES * STRUCT_SLAB_SIZE, 1 << self.PAGE_SHIFT)\n            # mm/slab.h\n            \"\"\"\n            gef> dt slab\n            struct slab {\n                /* offset | size   */\n                /* 0x0000 | 0x0008 */    struct slab * compound_slab_head;\n                /* 0x0008 | 0x0008 */    struct folio * backing_folio;\n                /* 0x0010 | 0x0004 */    struct kmem_cache_order_objects oo;\n                /* 0x0018 | 0x0010 */    struct list_head flush_list_elem;\n                /* 0x0028 | 0x0008 */    unsigned long align_mask;\n                /* 0x0030 | 0x0004 */    spinlock_t slab_lock;\n                /* 0x0038 | 0x0008 */    struct kmem_cache * slab_cache;\n                /* 0x0040 | 0x0020 */    union {...} ;\n                /* 0x0060 | 0x0008 */    unsigned long obj_exts;\n            } // total: 0x70 bytes\n            gef>\n            \"\"\"\n            self.slab_meta_entry_size = 0x70 # sizeof(struct slab)\n\n        self.quiet_info(\"SLAB_META_SIZE: {:#x}\".format(self.SLAB_META_SIZE))\n        self.quiet_info(\"single slab meta size: {:#x}\".format(self.slab_meta_entry_size))\n\n        # offsetof(slab, compound_slab_head)         if kernel != 6.6\n        # offsetof(virtual_slab, compound_slab_head) if kernel == 6.6\n        # offsetof(slab, backing_folio)\n        if kversion < \"6.6\" or \"6.12\" <= kversion:\n            self.slab_offset_compound_slab_head = 0\n            self.quiet_info(\"offsetof(slab, compound_slab_head): {:#x}\".format(self.slab_offset_compound_slab_head))\n            self.slab_offset_backing_folio = current_arch.ptrsize\n        else: # 6.6\n            self.slab_offset_compound_slab_head = current_arch.ptrsize * 8\n            self.quiet_info(\"offsetof(virtual_slab, compound_slab_head): {:#x}\".format(self.slab_offset_compound_slab_head))\n            self.slab_offset_backing_folio = 0\n        self.quiet_info(\"offsetof(slab, backing_folio): {:#x}\".format(self.slab_offset_backing_folio))\n\n        self.SLAB_DATA_BASE_ADDR = self.SLAB_BASE_ADDR + self.SLAB_META_SIZE\n        self.quiet_info(\"SLAB_DATA_BASE_ADDR: {:#x}\".format(self.SLAB_DATA_BASE_ADDR))\n\n        self.initialized = True\n        return True\n\n    def is_slab_virtual_meta(self, slab):\n        return slab in range(self.SLAB_BASE_ADDR, self.SLAB_DATA_BASE_ADDR)\n\n    def is_slab_virtual_addr(self, address): # for developer\n        return address in range(self.SLAB_DATA_BASE_ADDR, self.SLAB_END_ADDR)\n\n    def slab_to_virt(self, slab):\n        \"\"\"Convert slab-meta (aka slab-virtual) into virt (aka slab-data).\"\"\"\n        if not is_valid_addr(slab):\n            err(\"Memory Error\")\n            return None\n\n        if not self.is_slab_virtual_meta(slab):\n            err(\"Address is not in valid range\")\n            return None\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"6.1.56\":\n            slab_base = slab_data_base = self.SLAB_BASE_ADDR\n        else:\n            slab_base = self.SLAB_BASE_ADDR\n            slab_data_base = self.SLAB_DATA_BASE_ADDR\n\n        slab_idx, is_not_aligned = divmod(slab - slab_base, self.slab_meta_entry_size)\n        if is_not_aligned:\n            warn(\"Address is not aligned for the size of slab ({:#x})\".format(self.slab_meta_entry_size))\n        return slab_data_base + (1 << self.PAGE_SHIFT) * slab_idx\n\n    def virt_to_slab(self, virt):\n        \"\"\"Convert virt (aka slab-data) into slab (aka slab-meta or slab-virtual).\"\"\"\n        if not is_valid_addr(virt):\n            err(\"Memory error\")\n            return None\n\n        if not self.is_slab_virtual_addr(virt):\n            err(\"Address is not slab address\")\n            return None\n\n        if virt & 0xfff:\n            warn(\"Address is NOT aligned\")\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"6.1.56\":\n            slab_base = slab_data_base = self.SLAB_BASE_ADDR\n        else:\n            slab_base = self.SLAB_BASE_ADDR\n            slab_data_base = self.SLAB_DATA_BASE_ADDR\n\n        slab_idx = (virt - slab_data_base) >> self.PAGE_SHIFT\n        slab = slab_base + slab_idx * self.slab_meta_entry_size\n        return read_int_from_memory(slab + self.slab_offset_compound_slab_head) # s->compound_head\n\n    def slab_to_page(self, slab):\n        \"\"\"Convert slab (aka slab-meta) into page (aka backing_folio).\"\"\"\n        if not is_valid_addr(slab):\n            err(\"Memory error\")\n            return None\n        return read_int_from_memory(slab + self.slab_offset_backing_folio)\n\n    def get_vmemmap_base(self):\n        # Do NOT use `KF.get_VMEMMAP_START()` here.\n        # If CONFIG_KALLSYMS_ALL=n, `KF.get_VMEMMAP_START()` uses plan 3 and returns\n        # slab-virtual address (NOT page address).\n        # The returned value may be the first entry address of slab-virtual.\n\n        # plan 1 (directly)\n        addr = Symbol.get_ksymaddr(\"vmemmap_base\")\n        if addr:\n            return read_int_from_memory(addr)\n\n        # plan 2 (from `slab_virt_to_phys`)\n        addr = Symbol.get_ksymaddr(\"slab_virt_to_phys\")\n        if addr:\n            res = gdb.execute(\"x/30i {:#x}\".format(addr), to_string=True)\n            g = KernelAddressHeuristicFinderUtil.x64_qword_ptr_rip_base(res, read_valid=True)\n            for x in g:\n                return read_int_from_memory(x)\n\n        kversion = Kernel.kernel_version()\n\n        # plan 3 (available in 6.6-based only from `slub_addr_base` and `slub_addr_current`)\n        # In 6.6-based, `slub_addr_base` is fixed after setup KASLR, and uses\n        # `slub_addr_current` as watermark of once-allocated slabs.\n        # Active range of slab-data area is [slub_addr_base, slub_addr_current).\n        # So, slab-meta area in\n        #    virt_to_slab(slub_addr_base) ~ virt_to_slab(slub_addr_current - 1)\n        # points vmemmmap area via member `backing_folio` in struct `slab`/`slab_virtual`.\n        if \"6.6\" <= kversion < \"6.12\":\n            addr = KernelAddressHeuristicFinder.get_slub_addr_base()\n            if not addr:\n                return None\n            self.quiet_info(\"slub_addr_base @ {:#x}\".format(addr))\n            slub_addr_base = read_int_from_memory(addr)\n\n            slab_of_slub_addr_base = self.virt_to_slab(slub_addr_base)\n            addr = KernelAddressHeuristicFinder.get_slub_addr_current()\n            if not addr:\n                return None\n            self.quiet_info(\"slub_addr_current @ {:#x}\".format(addr))\n\n            slub_addr_current = read_int_from_memory(addr)\n            slab_of_slub_addr_current = self.virt_to_slab(slub_addr_current - 1)\n\n            # Scan backing_folio referenced from slab-virtual area (so slow)\n            vmemmap_entries = []\n            tqdm = GefUtil.get_tqdm(not self.args.quiet)\n            self.quiet_info(\"Wait for memory scan\")\n            for slab in tqdm(range(\n                    slab_of_slub_addr_base, slab_of_slub_addr_current, self.slab_meta_entry_size,\n                ), leave=False):\n                backing_folio = read_int_from_memory(slab + self.slab_offset_backing_folio)\n                if not is_valid_addr(backing_folio):\n                    continue\n                vmemmap_entries.append(backing_folio)\n            # The masked address of min page may be vmemmap_base(likely plan 3 of `KF.get_VMEMMAP_START()`)\n            vmemmap_base = min(vmemmap_entries) & 0xffff_ffff_c000_0000 # ~((1 << PUD_SHIFT) - 1)\n            return vmemmap_base\n\n        return None\n\n    def page_to_slab(self, page):\n        \"\"\"Convert page (aka backing_folio) into slab (aka slab-meta/slab-virtual).\"\"\"\n        if not is_valid_addr(page):\n            err(\"Memory error\")\n            return None\n\n        # Step1: find `vmemmap_base`\n        vmemmap_base = self.get_vmemmap_base()\n        if vmemmap_base is None:\n            return None\n        self.quiet_info(\"vmemmap_base: {:#x}\".format(vmemmap_base))\n\n        # Step2: get physical addr and mapped virtual address\n        pfn = (page - vmemmap_base) // self.sizeof_struct_page\n        phys_addr = pfn << self.PAGE_SHIFT\n\n        # `p2v` returns 2 results (direct mapping area and slab data)\n        r = Kernel.p2v(phys_addr)\n        if not r or len(r) < 2:\n            return None\n        return self.virt_to_slab(max(r))\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        kversion = Kernel.kernel_version()\n        if kversion < \"6.1\":\n            err(\"Unsupported before v6.1\")\n            return False\n\n        # detect CONFIG_SLAB_VIRTUAL=y without `slub-dump`\n        if KernelAddressHeuristicFinder.get_slub_tlbflush_queue() is None:\n            err(\"CONFIG_SLAB_VIRTUAL=n is NOT supported\")\n            return\n\n        if args.rescan:\n            self.initialized = False\n\n        ret = self.initialize()\n        if ret is False:\n            err(\"Failed to initialize\")\n            return\n\n        out = []\n        if args.mode == \"to_virt\":\n            data = self.slab_to_virt(args.address)\n            if data is None:\n                err(\"Failed to resolve\")\n                return\n            out.append(\"Slab: {:#x} -> Virt: {:#x}\".format(args.address, data))\n        elif args.mode == \"to_page\":\n            page = self.slab_to_page(args.address)\n            if page is None:\n                err(\"Failed to resolve\")\n                return\n            out.append(\"Slab: {:#x} -> Page: {:#x}\".format(args.address, page))\n        elif args.mode == \"from_virt\":\n            slab = self.virt_to_slab(args.address)\n            if slab is None:\n                err(\"Failed to resolve\")\n                return\n            out.append(\"Virt: {:#x} -> Slab: {:#x}\".format(args.address, slab))\n        elif args.mode == \"from_page\":\n            slab = self.page_to_slab(args.address)\n            if slab is None:\n                err(\"Failed to resolve\")\n                return\n            out.append(\"Page: {:#x} -> Slab: {:#x}\".format(args.address, slab))\n        gef_print(\"\\n\".join(out))\n        return\n\n\n@register_command\nclass PageInfoCommand(GenericCommand):\n    \"\"\"Dump struct page flags and page_type.\"\"\"\n\n    _cmdline_ = \"pageinfo\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"-p\", \"--page\", type=AddressUtil.parse_address, help=\"page address to dump.\")\n    group.add_argument(\"virt\", metavar=\"VIRT\", nargs=\"?\", type=AddressUtil.parse_address, help=\"virtual address to dump.\")\n    _syntax_ = parser.format_help()\n\n    \"\"\"\n    struct page {\n        memdesc_flags_t flags;\n        union { ... }; // 5 words\n        union {\n            unsigned int page_type;\n            atomic_t _mapcount;\n        };\n        atomic_t _refcount;\n        ...\n    };\n    \"\"\"\n\n    @staticmethod\n    def get_flags_str(flags_value):\n        kversion = Kernel.kernel_version()\n\n        # PG_uncached, PG_hwpoison, PG_young, PG_idle, PG_arch_2, PG_arch3:\n        # Because it varies depending on the environment, GEF does not support it\n        if \"4.18\" <= kversion < \"4.20\":\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_error\",\n                0x0000_0000_0000_0004: \"PG_referenced\",\n                0x0000_0000_0000_0008: \"PG_uptodate\",\n                0x0000_0000_0000_0010: \"PG_dirty\",\n                0x0000_0000_0000_0020: \"PG_lru\",\n                0x0000_0000_0000_0040: \"PG_active\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_slab\",\n                0x0000_0000_0000_0200: \"PG_owner_priv_1\",\n                0x0000_0000_0000_0400: \"PG_arch_1\",\n                0x0000_0000_0000_0800: \"PG_reserved\",\n                0x0000_0000_0000_1000: \"PG_private\",\n                0x0000_0000_0000_2000: \"PG_private_2\",\n                0x0000_0000_0000_4000: \"PG_writeback\",\n                0x0000_0000_0000_8000: \"PG_head\",\n                0x0000_0000_0001_0000: \"PG_mappedtodisk\",\n                0x0000_0000_0002_0000: \"PG_reclaim\",\n                0x0000_0000_0004_0000: \"PG_swapbacked\",\n                0x0000_0000_0008_0000: \"PG_unevictable\",\n                0x0000_0000_0010_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n        elif \"4.20\" <= kversion < \"6.6\":\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_referenced\",\n                0x0000_0000_0000_0004: \"PG_uptodate\",\n                0x0000_0000_0000_0008: \"PG_dirty\",\n                0x0000_0000_0000_0010: \"PG_lru\",\n                0x0000_0000_0000_0020: \"PG_active\",\n                0x0000_0000_0000_0040: \"PG_workingset\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_error\",\n                0x0000_0000_0000_0200: \"PG_slab\",\n                0x0000_0000_0000_0400: \"PG_owner_priv_1\",\n                0x0000_0000_0000_0800: \"PG_arch_1\",\n                0x0000_0000_0000_1000: \"PG_reserved\",\n                0x0000_0000_0000_2000: \"PG_private\",\n                0x0000_0000_0000_4000: \"PG_private_2\",\n                0x0000_0000_0000_8000: \"PG_writeback\",\n                0x0000_0000_0001_0000: \"PG_head\",\n                0x0000_0000_0002_0000: \"PG_mappedtodisk\",\n                0x0000_0000_0004_0000: \"PG_reclaim\",\n                0x0000_0000_0008_0000: \"PG_swapbacked\",\n                0x0000_0000_0010_0000: \"PG_unevictable\",\n                0x0000_0000_0020_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n        elif \"6.6\" <= kversion < \"6.10\":\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_writeback\",\n                0x0000_0000_0000_0004: \"PG_referenced\",\n                0x0000_0000_0000_0008: \"PG_uptodate\",\n                0x0000_0000_0000_0010: \"PG_dirty\",\n                0x0000_0000_0000_0020: \"PG_lru\",\n                0x0000_0000_0000_0040: \"PG_head\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_active\",\n                0x0000_0000_0000_0200: \"PG_workingset\",\n                0x0000_0000_0000_0400: \"PG_error\",\n                0x0000_0000_0000_0800: \"PG_slab\",\n                0x0000_0000_0000_1000: \"PG_owner_priv_1\",\n                0x0000_0000_0000_2000: \"PG_arch_1\",\n                0x0000_0000_0000_4000: \"PG_reserved\",\n                0x0000_0000_0000_8000: \"PG_private\",\n                0x0000_0000_0001_0000: \"PG_private_2\",\n                0x0000_0000_0002_0000: \"PG_mappedtodisk\",\n                0x0000_0000_0004_0000: \"PG_reclaim\",\n                0x0000_0000_0008_0000: \"PG_swapbacked\",\n                0x0000_0000_0010_0000: \"PG_unevictable\",\n                0x0000_0000_0020_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n        elif \"6.10\" <= kversion < \"6.12\":\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_writeback\",\n                0x0000_0000_0000_0004: \"PG_referenced\",\n                0x0000_0000_0000_0008: \"PG_uptodate\",\n                0x0000_0000_0000_0010: \"PG_dirty\",\n                0x0000_0000_0000_0020: \"PG_lru\",\n                0x0000_0000_0000_0040: \"PG_head\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_active\",\n                0x0000_0000_0000_0200: \"PG_workingset\",\n                0x0000_0000_0000_0400: \"PG_error\",\n                0x0000_0000_0000_0800: \"PG_owner_priv_1\",\n                0x0000_0000_0000_1000: \"PG_arch_1\",\n                0x0000_0000_0000_2000: \"PG_reserved\",\n                0x0000_0000_0000_4000: \"PG_private\",\n                0x0000_0000_0000_8000: \"PG_private_2\",\n                0x0000_0000_0001_0000: \"PG_mappedtodisk\",\n                0x0000_0000_0002_0000: \"PG_reclaim\",\n                0x0000_0000_0004_0000: \"PG_swapbacked\",\n                0x0000_0000_0008_0000: \"PG_unevictable\",\n                0x0000_0000_0010_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n        elif \"6.12\" <= kversion < \"6.14\":\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_writeback\",\n                0x0000_0000_0000_0004: \"PG_referenced\",\n                0x0000_0000_0000_0008: \"PG_uptodate\",\n                0x0000_0000_0000_0010: \"PG_dirty\",\n                0x0000_0000_0000_0020: \"PG_lru\",\n                0x0000_0000_0000_0040: \"PG_head\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_active\",\n                0x0000_0000_0000_0200: \"PG_workingset\",\n                0x0000_0000_0000_0400: \"PG_owner_priv_1\",\n                0x0000_0000_0000_0800: \"PG_owner_2\",\n                0x0000_0000_0000_1000: \"PG_arch_1\",\n                0x0000_0000_0000_2000: \"PG_reserved\",\n                0x0000_0000_0000_4000: \"PG_private\",\n                0x0000_0000_0000_8000: \"PG_private_2\",\n                0x0000_0000_0001_0000: \"PG_reclaim\",\n                0x0000_0000_0002_0000: \"PG_swapbacked\",\n                0x0000_0000_0004_0000: \"PG_unevictable\",\n                0x0000_0000_0008_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n        elif \"6.14\" <= kversion:\n            flags_dic = {\n                0x0000_0000_0000_0001: \"PG_locked\",\n                0x0000_0000_0000_0002: \"PG_writeback\",\n                0x0000_0000_0000_0004: \"PG_referenced\",\n                0x0000_0000_0000_0008: \"PG_uptodate\",\n                0x0000_0000_0000_0010: \"PG_dirty\",\n                0x0000_0000_0000_0020: \"PG_lru\",\n                0x0000_0000_0000_0040: \"PG_head\",\n                0x0000_0000_0000_0080: \"PG_waiters\",\n                0x0000_0000_0000_0100: \"PG_active\",\n                0x0000_0000_0000_0200: \"PG_workingset\",\n                0x0000_0000_0000_0400: \"PG_owner_priv_1\",\n                0x0000_0000_0000_0800: \"PG_owner_2\",\n                0x0000_0000_0000_1000: \"PG_arch_1\",\n                0x0000_0000_0000_2000: \"PG_reserved\",\n                0x0000_0000_0000_4000: \"PG_private\",\n                0x0000_0000_0000_8000: \"PG_private_2\",\n                0x0000_0000_0001_0000: \"PG_reclaim\",\n                0x0000_0000_0002_0000: \"PG_swapbacked\",\n                0x0000_0000_0004_0000: \"PG_unevictable\",\n                0x0000_0000_0008_0000: \"PG_dropbehind\",\n                0x0000_0000_0010_0000: \"PG_mlocked\", # CONFIG_MMU is always defined\n            }\n\n        flags = []\n        for k, v in flags_dic.items():\n            if flags_value & k:\n                flags.append(v)\n\n        flags_str = \" | \".join(flags)\n        if flags_str == \"\":\n            flags_str = \"none\"\n        return flags_str\n\n    @staticmethod\n    def get_pagetype_str(flags_value):\n        kversion = Kernel.kernel_version()\n        if \"4.18\" <= kversion < \"5.1\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_balloon\",\n                0x0000_0200: \"PG_kmemcg\",\n                0x0000_0400: \"PG_table\",\n            }\n        elif \"5.1\" <= kversion < \"5.3\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_offline\",\n                0x0000_0200: \"PG_kmemcg\",\n                0x0000_0400: \"PG_table\",\n            }\n        elif \"5.3\" <= kversion < \"5.11\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_offline\",\n                0x0000_0200: \"PG_kmemcg\",\n                0x0000_0400: \"PG_table\",\n                0x0000_0800: \"PG_guard\",\n            }\n        elif \"5.11\" <= kversion < \"6.6\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_offline\",\n                0x0000_0200: \"PG_table\",\n                0x0000_0400: \"PG_guard\",\n            }\n        elif \"6.6\" <= kversion < \"6.10\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_offline\",\n                0x0000_0200: \"PG_table\",\n                0x0000_0400: \"PG_guard\",\n                0x0000_0800: \"PG_hugetlb\",\n            }\n        elif \"6.10\" <= kversion < \"6.11\":\n            flags_dic = {\n                0x0000_0080: \"PG_buddy\",\n                0x0000_0100: \"PG_offline\",\n                0x0000_0200: \"PG_table\",\n                0x0000_0400: \"PG_guard\",\n                0x0000_0800: \"PG_hugetlb\",\n                0x0000_1000: \"PG_slab\",\n            }\n        elif \"6.11\" <= kversion < \"6.12\":\n            flags_dic = {\n                0x4000_0000: \"PG_buddy\",\n                0x2000_0000: \"PG_offline\",\n                0x1000_0000: \"PG_table\",\n                0x0800_0000: \"PG_guard\",\n                0x0400_0000: \"PG_hugetlb\",\n                0x0200_0000: \"PG_slab\",\n                0x0100_0000: \"PG_zsmalloc\",\n            }\n        elif \"6.12\" <= kversion:\n            flags_dic = {\n                0xf0: \"PGTY_buddy\",\n                0xf1: \"PGTY_offline\",\n                0xf2: \"PGTY_table\",\n                0xf3: \"PGTY_guard\",\n                0xf4: \"PGTY_hugetlb\",\n                0xf5: \"PGTY_slab\",\n                0xf6: \"PGTY_zsmalloc\",\n                0xf7: \"PGTY_unaccepted\",\n                0xf8: \"PGTY_large_kmalloc\", # 6.15~\n            }\n\n        if kversion < \"6.12\":\n            flags = []\n            for k, v in flags_dic.items():\n                if ~flags_value & k:\n                    flags.append(v)\n            flags_str = \" | \".join(flags)\n            if flags_str == \"\":\n                flags_str = \"none\"\n        else:\n            type_value = (flags_value >> 24) & 0xff\n            flags_str = flags_dic.get(type_value, \"none\")\n        return flags_str\n\n    def dump_page_info(self, page_addr, virt_addr):\n        flags = read_int_from_memory(page_addr)\n        compound_head = read_int32_from_memory(page_addr + current_arch.ptrsize * 1)\n        page_type = read_int32_from_memory(page_addr + current_arch.ptrsize * 6)\n        refcount = read_int32_from_memory(page_addr + current_arch.ptrsize * 6 + 4)\n\n        gef_print(\"Page        : {:#x}\".format(page_addr))\n        if virt_addr is None:\n            gef_print(\"Virt        : None\")\n        else:\n            gef_print(\"Virt        : {:#x}\".format(virt_addr))\n\n        gef_print(\"flags       : {:#x} ({:s})\".format(flags, PageInfoCommand.get_flags_str(flags)))\n        gef_print(\"is_tailpage : {}\".format(bool(compound_head & 1)))\n        gef_print(\"page_type   : {:#x} ({:s})\".format(page_type, PageInfoCommand.get_pagetype_str(page_type)))\n        if refcount == 0:\n            gef_print(\"refcount    : {:#x} (freed)\".format(refcount))\n        else:\n            gef_print(\"refcount    : {:#x} (allocated)\".format(refcount))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        kversion = Kernel.kernel_version()\n        if kversion < \"4.18\":\n            err(\"Unsupported before v4.18\")\n            return\n\n        if args.virt is not None:\n            virt_addr = args.virt & get_pagesize_mask_high()\n            page_addr = Kernel.virt2page(args.virt & get_pagesize_mask_high())\n        else:\n            page_addr = args.page\n            virt_addr = Kernel.page2virt(args.page)\n\n        if not is_valid_addr(page_addr):\n            err(\"Invalid page address\")\n            return\n\n        self.dump_page_info(page_addr, virt_addr)\n        return\n\n\n@register_command\nclass HighMemDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump HighMem mappings.\"\"\"\n\n    _cmdline_ = \"highmem-dump\"\n    _category_ = \"06-d. Qemu-system/KGDB Cooperation - Virt/Phys/Page\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-s\", \"--sort-by-virt\", action=\"store_true\", help=\"sort by virtual address.\")\n    group.add_argument(\"-S\", \"--sort-by-page\", action=\"store_true\", help=\"sort by page address.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"show result only.\")\n    _syntax_ = parser.format_help()\n\n    def dump_entry(self, page, virt):\n        heap_page_address_color = Config.get_gef_setting(\"theme.heap_page_address\")\n        virt_str = Color.colorify_hex(virt, heap_page_address_color)\n        self.out.append(\"page:{:#010x}  virt:{:s}\".format(page, virt_str))\n        return\n\n    def dump_slot(self, page_slot):\n        seen = [page_slot]\n        current = read_int_from_memory(page_slot)\n        while current not in seen:\n            seen.append(current)\n            if not is_valid_addr(current):\n                break\n            try:\n                page = read_int_from_memory(current - current_arch.ptrsize * 2)\n                virt = read_int_from_memory(current - current_arch.ptrsize * 1)\n            except gdb.MemoryError:\n                self.err_add_out(\"Corrupted? ({:#x})\".format(current))\n                break\n            self.dump_entry(page, virt)\n            current = read_int_from_memory(current)\n        return\n\n    def dump_table(self, page_address_htable):\n        PA_HASH_ORDER = 7\n        sizeof_cache_align = 0x40\n        found = False\n        for i in range(2 ** PA_HASH_ORDER):\n            page_slot = page_address_htable + sizeof_cache_align * i\n            if not is_double_link_list(page_slot, min_len=1):\n                continue\n            self.quiet_add_out(titlify(\"slot[{:d}] @ {:#x}\".format(i, page_slot)))\n            self.dump_slot(page_slot)\n            found = True\n\n        if not found:\n            self.info_add_out(\"No highmem entries were found.\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"ARM32\"))\n    @only_if_in_kernel_or_kpti_disabled\n    def do_invoke(self, args):\n        self.quiet_info(\"Wait for memory scan\")\n\n        page_address_htable = KernelAddressHeuristicFinder.get_page_address_htable()\n        if page_address_htable is None:\n            err(\"Could not find page_address_htable\")\n            return\n\n        self.out = []\n        self.dump_table(page_address_htable)\n\n        if self.args.sort_by_page:\n            self.out = sorted(x for x in self.out if x.startswith(\"page:\"))\n        elif self.args.sort_by_virt:\n            self.out = sorted([x for x in self.out if x.startswith(\"page:\")], key=lambda x:x.split()[1])\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass QemuDeviceInfoCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump device information for qemu-escape.\"\"\"\n\n    _cmdline_ = \"qemu-device-info\"\n    _category_ = \"06-k. Qemu-system/KGDB Cooperation - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-d\", \"--device\", help=\"device name.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -d cydf-vga  # Specify a device name\",\n        \"{0:s} -d cydf      # Specify a characteristic part of the device name\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"qemu-system must be running on the local host.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def get_device_name(self):\n        \"\"\"Identify the device from qemu's command line arguments,\n        or can force the use of the user specified device.\"\"\"\n        # user specific\n        if self.args.device:\n            self.info_add_out(\"device name: {:s}\".format(Color.boldify(self.args.device)))\n            return self.args.device\n\n        # scan from command line\n\n        # check for existence\n        qemu_cmdline_path = \"/proc/{:d}/cmdline\".format(Pid.get_pid())\n        if not os.path.exists(qemu_cmdline_path):\n            err(\"Could not find {:s}\".format(qemu_cmdline_path))\n            return None\n\n        # check if it can be loaded\n        try:\n            content = open(qemu_cmdline_path, \"rb\").read()\n        except Exception:\n            err(\"Failed to read {:s}\".format(qemu_cmdline_path))\n            return\n\n        # check if it is from qemu-system\n        cmdline = String.bytes2str(content).split(\"\\0\")\n        if \"qemu-system\" not in \" \".join(cmdline):\n            err(\"Could not find `qemu-system` in {:s}\".format(qemu_cmdline_path))\n            return None\n\n        # check if the number of devices\n        # the device specified by -device is likely to be the target of CTF attacks\n        if cmdline.count(\"-device\") == 0:\n            err(\"Could not find `-device` option in qemu-system cmdline\")\n            return None\n\n        # if multiple entries, it will be considered an error because it cannot be uniquely identified\n        if cmdline.count(\"-device\") >= 2:\n            devices = []\n            for i in range(len(cmdline)):\n                if cmdline[i] == \"-device\":\n                    devices.append(cmdline[i + 1])\n            devices_str = Color.boldify(\", \".join(devices))\n            err(\"Multiple `-device` options are found in qemu-system cmdline: {:s}\".format(devices_str))\n            return None\n\n        # found\n        device_name = cmdline[cmdline.index(\"-device\") + 1]\n        self.info_add_out(\"device name: {:s}\".format(Color.boldify(device_name)))\n        return device_name\n\n    def dump_qdm(self, device_name):\n        \"\"\"Filter and display the target device from the list of devices recognized by qemu.\"\"\"\n        res = gdb.execute(\"monitor info qdm\", to_string=True)\n        for line in res.splitlines():\n            if device_name in line:\n                self.info_add_out(\"qdev device model: {:s}\".format(Color.boldify(line)))\n        return\n\n    def dump_memmap(self, device_name):\n        \"\"\"Display information related to the target device from the memory managed by qemu.\"\"\"\n        # get physmem map / IO map\n        res = gdb.execute(\"monitor info mtree\", to_string=True)\n        self.info_add_out(\"Related memory address:\")\n        maps = [line.strip() for line in res.splitlines() if device_name in line and line.strip().startswith(\"0\")]\n        maps = sorted(set(maps)) # uniq\n        for m in maps:\n            self.out.append(\"    \" + m)\n        return\n\n    def dump_symbol_related_device(self, device_name):\n        \"\"\"Show symbol information for the qemu-system related to the target device.\"\"\"\n        # get nm\n        try:\n            nm = GefUtil.which(Config.get_gef_setting(\"gef.nm_command\"))\n        except FileNotFoundError as e:\n            self.err_add_out(\"{}\".format(e))\n            return\n\n        # get qemu-system path\n        qemu_path = os.readlink(\"/proc/{:d}/exe\".format(Pid.get_pid()))\n        self.info_add_out(\"qemu path: {:s}\".format(qemu_path))\n\n        # get symbol related device\n        try:\n            result = GefUtil.gef_execute_external([nm, qemu_path], as_list=True)\n        except subprocess.CalledProcessError:\n            self.err_add_out(\"Executing `nm` error\")\n            return\n\n        for line in result:\n            if device_name not in line:\n                continue\n            if line.endswith((\"read\", \"write\")):\n                index = line.rfind(\" \")\n                self.out.append(\"    {:s} {:s}\".format(line[:index], Color.boldify(line[index + 1:])))\n            else:\n                self.out.append(\"    {:s}\".format(line))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    def do_invoke(self, args):\n        self.out = []\n        device_name = self.get_device_name()\n        if device_name is None:\n            return\n\n        self.dump_qdm(device_name)\n        self.dump_memmap(device_name)\n        self.dump_symbol_related_device(device_name)\n\n        if not args.device:\n            self.info_add_out(\"use `-d` if less information\")\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass QemuMemoryRegionDumpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Dump memory regions for qemu-system.\"\"\"\n\n    _cmdline_ = \"qemu-system-memory-region-dump\"\n    _category_ = \"07-g. Misc - Qemu-system\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\",\n                        help=\"show only entries where read or write is not the default.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def get_rw_map(self):\n        filepath = Path.get_filepath(append_proc_root_prefix=False)\n        maps = ProcessMap.get_process_maps_linux(Pid.get_pid())\n        RW = Permission.READ | Permission.WRITE\n        rw_maps = []\n        for m in maps:\n            if m.permission.value != RW:\n                continue\n            if m.path == filepath:\n                rw_maps.append(m)\n                continue\n            if len(rw_maps) > 0:\n                if m.page_start == rw_maps[-1].page_end:\n                    # concat\n                    new_m = Section(\n                        page_start=rw_maps[-1].page_start,\n                        page_end=m.page_end,\n                        offset=rw_maps[-1].offset,\n                        permission=rw_maps[-1].permission,\n                        inode=rw_maps[-1].inode,\n                        path=rw_maps[-1].path,\n                    )\n                    rw_maps[-1] = new_m\n        if len(rw_maps) == 1:\n            return rw_maps[0]\n        return None\n\n    def get_memory_region(self, name_target):\n        \"\"\"\n        static MemoryRegion *system_memory;\n        static MemoryRegion *system_io;\n\n        AddressSpace address_space_io;\n        AddressSpace address_space_memory;\n\n        struct AddressSpace {\n            struct rcu_head rcu; // ptrsize * 2 bytes\n            char *name; // -> \"memory\" or \"I/O\"\n            MemoryRegion *root;\n            struct FlatView *current_map;\n            ...\n        };\n        \"\"\"\n        rw_map = self.get_rw_map()\n        if rw_map is None:\n            return None\n\n        rw_content = read_memory(rw_map.page_start, rw_map.size)\n        rw_content_sliced = slice_unpack(rw_content, current_arch.ptrsize)\n\n        # Since it is near the end of the RW area, searching in reverse is faster\n        for i, val in enumerate(rw_content_sliced[::-1], start=1):\n            if not is_valid_addr(val):\n                continue\n\n            # name check\n            name = read_cstring_from_memory(val)\n            if name != name_target:\n                continue\n            ofs_name = rw_map.size - (current_arch.ptrsize * i)\n\n            # root check\n            ofs_root = ofs_name + current_arch.ptrsize\n            root = read_int_from_memory(rw_map.page_start + ofs_root)\n            if not is_valid_addr(root):\n                continue\n            root = ProcessMap.lookup_address(root)\n            if not root.section.is_writable():\n                continue\n\n            # current_map check\n            ofs_current_map = ofs_root + current_arch.ptrsize\n            current_map = read_int_from_memory(rw_map.page_start + ofs_current_map)\n            if not is_valid_addr(current_map):\n                continue\n            current_map = ProcessMap.lookup_address(current_map)\n            if not current_map.section.is_writable():\n                continue\n\n            # found\n            return root.value\n        return None\n\n    def get_system_memory(self):\n        # fast path\n        try:\n            system_memory = AddressUtil.parse_address(\"&system_memory\")\n            return read_int_from_memory(system_memory)\n        except gdb.error:\n            pass\n        # slow path\n        return self.get_memory_region(\"memory\")\n\n    def get_system_io(self):\n        # fast path\n        try:\n            system_io = AddressUtil.parse_address(\"&system_io\")\n            return read_int_from_memory(system_io)\n        except gdb.error:\n            pass\n        # slow path\n        return self.get_memory_region(\"I/O\")\n\n    def initialize(self):\n        if hasattr(self, \"initialized\") and self.initialized:\n            return True\n\n        # root (system_memory, system_io)\n        self.system_memory = self.get_system_memory()\n        if self.system_memory is None:\n            self.quiet_err(\"Could not find system_memory\")\n            return False\n        self.quiet_info_add_out(\"system_memory: {:#x}\".format(self.system_memory))\n\n        self.system_io = self.get_system_io()\n        if self.system_io is None:\n            self.quiet_err(\"Could not find system_io\")\n            return False\n        self.quiet_info_add_out(\"system_io: {:#x}\".format(self.system_io))\n\n        # name\n        for offset in range(0, 0x100, current_arch.ptrsize):\n            name_ptr_addr = self.system_memory + offset\n            name_ptr = read_int_from_memory(name_ptr_addr)\n            if not is_valid_addr(name_ptr):\n                continue\n            if read_cstring_from_memory(name_ptr) == \"system\":\n                self.offset_name = offset\n                break\n        else:\n            self.quiet_err(\"Could not find offsetof(MemoryRegion, name)\")\n            return False\n        self.quiet_info_add_out(\"offsetof(MemoryRegion, name): {:#x}\".format(self.offset_name))\n\n        # ops\n        for offset in range(0, 0x80, current_arch.ptrsize):\n            ops_addr = self.system_memory + offset\n            ops = read_int_from_memory(ops_addr)\n            # ops itself is r-x addr\n            if not is_valid_addr(ops):\n                continue\n            if ProcessMap.lookup_address(ops).section.is_writable():\n                continue\n            # ops->read: zero or r-x addr\n            read_func = read_int_from_memory(ops + current_arch.ptrsize * 0)\n            if read_func:\n                if ProcessMap.lookup_address(read_func).section.is_writable():\n                    continue\n            # ops->write: zero or r-x addr\n            write_func = read_int_from_memory(ops + current_arch.ptrsize * 1)\n            if write_func:\n                if ProcessMap.lookup_address(write_func).section.is_writable():\n                    continue\n            self.offset_ops = offset\n            break\n        else:\n            self.quiet_err(\"Could not find offsetof(MemoryRegion, ops)\")\n            return False\n        self.quiet_info_add_out(\"offsetof(MemoryRegion, ops): {:#x}\".format(self.offset_ops))\n\n        # subregions, subregions_link\n        self.offset_subregions = self.offset_name - current_arch.ptrsize * 6\n        self.quiet_info_add_out(\"offsetof(MemoryRegion, subregions): {:#x}\".format(self.offset_subregions))\n        self.offset_subregions_link = self.offset_name - current_arch.ptrsize * 4\n        self.quiet_info_add_out(\"offsetof(MemoryRegion, subregions_link): {:#x}\".format(self.offset_subregions_link))\n\n        self.initialized = True\n        return\n\n    def make_symbol_string(self, addr):\n        addr = ProcessMap.lookup_address(addr)\n        sym = Symbol.get_symbol_string(addr.value, nosymbol_string=\" <NO_SYMBOL>\")\n        return \"{!s}{:s}\".format(addr, sym)\n\n    def print_region_smart(self, name, ops, level):\n        # skip if uninteresting\n        if not ops:\n            return\n\n        # skip if seen\n        if ops in self.seen:\n            return\n        self.seen.append(ops)\n\n        # print\n        indent = \"  \" * level\n        read_func = read_int_from_memory(ops + current_arch.ptrsize * 0)\n        write_func = read_int_from_memory(ops + current_arch.ptrsize * 1)\n        if read_func or write_func:\n            self.out.append(\"{:s}MemoryRegion: {:s}\".format(indent, Color.boldify(name)))\n            self.out.append(\"{:s}  ops:{:s}\".format(indent, self.make_symbol_string(ops)))\n            self.out.append(\"{:s}    read:{:s}, write:{:s}\".format(\n                indent,\n                self.make_symbol_string(read_func),\n                self.make_symbol_string(write_func),\n            ))\n        return\n\n    def print_region(self, name, ops, level):\n        # print always\n        indent = \"  \" * level\n        self.out.append(\"{:s}MemoryRegion: {:s}\".format(indent, Color.boldify(name)))\n        if not ops:\n            self.out.append(\"{:s}  ops:{:#x}\".format(indent, ops))\n            return\n\n        # print\n        self.out.append(\"{:s}  ops:{:s}\".format(indent, self.make_symbol_string(ops)))\n        read_func = read_int_from_memory(ops + current_arch.ptrsize * 0)\n        write_func = read_int_from_memory(ops + current_arch.ptrsize * 1)\n        if read_func or write_func:\n            self.out.append(\"{:s}    read:{:s}, write:{:s}\".format(\n                indent,\n                self.make_symbol_string(read_func),\n                self.make_symbol_string(write_func),\n            ))\n        return\n\n    def dump_region(self, mr, level):\n        name_ptr = read_int_from_memory(mr + self.offset_name)\n        name = read_cstring_from_memory(name_ptr) or \"\"\n        ops = read_int_from_memory(mr + self.offset_ops)\n\n        # dump ops\n        if self.args.smart:\n            self.print_region_smart(name, ops, level)\n        else:\n            self.print_region(name, ops, level)\n\n        # parse recursively\n        link = read_int_from_memory(mr + self.offset_subregions)\n        while link:\n            self.dump_region(link, level + 1)\n            link = read_int_from_memory(link + self.offset_subregions_link)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.out = []\n        if self.initialize() is False:\n            return\n\n        # dump system_memory\n        self.seen = []\n        self.quiet_info_add_out(\"system_memory\")\n        self.dump_region(self.system_memory, 0)\n\n        # dump system_io\n        self.seen = []\n        self.quiet_info_add_out(\"system_io\")\n        self.dump_region(self.system_io, 0)\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass XUntilCommand(GenericCommand):\n    \"\"\"Execute until specified address easily.\"\"\"\n\n    _cmdline_ = \"xuntil\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"exec-next\", \"stepover\", \"until-next\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the address to stop.\")\n    parser.add_argument(\"--from-wrapper\", action=\"store_true\",\n                        help=\"[FOR DEVELOPER] used internally in gef, please don't use it.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        if args.address is None:\n            stop_addr = Disasm.gef_instruction_n(current_arch.pc, 1).address\n        else:\n            stop_addr = args.address\n        # `until` command has a bug(?) because sometimes fail,\n        # so we should use `tbreak` and `continue` instead of `until`.\n        SimpleInternalTemporaryBreakpoint(loc=stop_addr)\n\n        if args.from_wrapper:\n            gdb.execute(\"continue\") # do not use c wrapper because cycle reference\n        else:\n            gdb.execute(\"c\")\n        return\n\n\n@register_command\nclass ExecUntilCommand(GenericCommand):\n    \"\"\"The base command to execute until specific condition.\"\"\"\n\n    _cmdline_ = \"exec-until\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"call\")\n    subparsers.add_parser(\"jmp\")\n    subparsers.add_parser(\"syscall\")\n    subparsers.add_parser(\"ret\")\n    subparsers.add_parser(\"all-branch\")\n    subparsers.add_parser(\"indirect-branch\")\n    subparsers.add_parser(\"memaccess\")\n    subparsers.add_parser(\"keyword\")\n    subparsers.add_parser(\"cond\")\n    subparsers.add_parser(\"user-code\")\n    subparsers.add_parser(\"libc-code\")\n    subparsers.add_parser(\"secure-world\")\n    subparsers.add_parser(\"region-change\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} call                                 # execute until call instruction\",\n        \"{0:s} jmp                                  # execute until jmp instruction\",\n        \"{0:s} syscall                              # execute until syscall instruction\",\n        \"{0:s} ret                                  # execute until ret instruction\",\n        \"{0:s} all-branch                           # execute until call/jmp/ret instruction\",\n        \"{0:s} indirect-branch                      # execute until indirect branch instruction (x64/x86 only)\",\n        \"{0:s} memaccess                            # execute until '[' is included by the instruction\",\n        '{0:s} keyword \"call +r[ab]x\"               # execute until specified keyword (regex)',\n        '{0:s} cond \"$rax==0xdead && $rbx==0xcafe\"  # execute until specified condition is filled',\n        \"{0:s} user-code                            # execute until user code\",\n        \"{0:s} libc-code                            # execute until libc code\",\n        \"{0:s} secure-world                         # execute until secure world (ARM/ARM64 only)\",\n        \"{0:s} region-change                        # execute until different region (e.g., binary itself -> libc)\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        return\n\n    def close_stdout_stderr(self):\n        self.stdout = 1\n        self.stdout_bak = os.dup(self.stdout)\n        f = open(\"/dev/null\")\n        os.dup2(f.fileno(), self.stdout)\n        f.close()\n\n        self.stderr = 2\n        self.stderr_bak = os.dup(self.stderr)\n        f = open(\"/dev/null\")\n        os.dup2(f.fileno(), self.stderr)\n        f.close()\n        return\n\n    def revert_stdout_stderr(self):\n        os.dup2(self.stdout_bak, self.stdout)\n        os.close(self.stdout_bak)\n        os.dup2(self.stderr_bak, self.stderr)\n        os.close(self.stderr_bak)\n        return\n\n    def force_write_stdout(self, msg):\n        open(\"/proc/self/fd/0\", \"wb\").write(msg)\n        return\n\n    def check_jump_taken(self, insn):\n        if not current_arch.is_jump(insn):\n            return False\n\n        if (self.args.only_taken, self.args.only_not_taken) == (False, False):\n            return True\n\n        if (self.args.only_taken, self.args.only_not_taken) == (True, False):\n            if current_arch.is_conditional_branch(insn):\n                taken, _reason = current_arch.is_branch_taken(insn)\n                return taken\n            else:\n                return True # non-conditional, so always jump\n\n        if (self.args.only_taken, self.args.only_not_taken) == (False, True):\n            if current_arch.is_conditional_branch(insn):\n                taken, _reason = current_arch.is_branch_taken(insn)\n                return not taken\n            else:\n                return False # non-conditional, so always jump\n        raise\n\n    def get_breakpoint_list(self):\n        lines = gdb.execute(\"info breakpoints\", to_string=True).splitlines()\n        if lines[0] == \"No breakpoints or watchpoints.\":\n            return []\n        if lines[0] == \"No breakpoints, watchpoints, tracepoints, or catchpoints.\": # gdb 15.x ~\n            return []\n\n        enable_idx = lines[0].index(\"Enb\")\n        addr_idx = lines[0].index(\"Address\")\n\n        bp_list = []\n        for line in lines[1:]:\n            try:\n                if line[0] == \"\\t\":\n                    continue\n                enable = line[enable_idx]\n                addr = int(line[addr_idx:].split()[0], 16)\n                if enable == \"y\":\n                    bp_list.append(addr)\n            except Exception:\n                pass\n        # breakpoint with condition is unsupported\n        return bp_list\n\n    def exec_next(self):\n        bp_list = self.get_breakpoint_list()\n        EventHooking.gef_on_stop_unhook(EventHandler.hook_stop_handler)\n        self.close_stdout_stderr()\n        self.err = None\n\n        prev_addr = -1\n        try:\n            count = 0\n            while True:\n                # progress\n                if not self.args.print_insn and count % 100 == 0:\n                    self.force_write_stdout([b\"\\r|\", b\"\\r/\", b\"\\r-\", b\"\\r\\\\\"][count // 100 % 4])\n\n                # backup\n                prev_prev_addr = prev_addr\n                prev_addr = current_arch.pc\n\n                # execute 1 instruction\n                insn = get_insn()\n                if self.args.use_ni or (self.args.skip_lib and \"@plt>\" in str(insn)):\n                    gdb.execute(\"ni\") # use ni wrapper\n                else:\n                    gdb.execute(\"si\") # use si wrapper\n\n                # check breakpoint\n                insn = get_insn()\n                if current_arch.pc in bp_list:\n                    break\n\n                # $pc is not changed\n                if prev_prev_addr == prev_addr == current_arch.pc: # for faster, repeat insn is skip\n                    # infinity self loop\n                    if current_arch.is_call(insn) or current_arch.is_jump(insn) or current_arch.is_ret(insn):\n                        self.err = \"Detected infinity loop prev_addr ({:#x})\".format(prev_addr)\n                        break\n                    # maybe rep prefix\n                    gdb.execute(\"xuntil\")\n                    # recheck\n                    if prev_prev_addr == prev_addr == current_arch.pc:\n                        self.err = \"Detected infinity loop prev_addr ({:#x})\".format(prev_addr)\n                        break\n                    insn = get_insn()\n\n                if self.args.print_insn:\n                    self.force_write_stdout((str(insn) + \"\\n\").encode())\n\n                # found and break\n                if self.is_target_insn(insn) and current_arch.pc not in self.args.exclude:\n                    if not self.args.print_insn:\n                        self.force_write_stdout(b\"\\r \\r\")\n                    break\n\n                count += 1\n\n        except KeyboardInterrupt:\n            pass\n\n        except Exception:\n            if is_alive():\n                exc_type, exc_value, exc_traceback = sys.exc_info()\n                self.err = exc_value\n            else:\n                pass\n\n        finally:\n            self.revert_stdout_stderr() # anytime needed\n            EventHooking.gef_on_stop_hook(EventHandler.hook_stop_handler) # anytime needed\n            Cache.reset_gef_caches()\n            if self.err:\n                err(self.err)\n            else:\n                gdb.execute(\"context\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass ExecUntilCallCommand(ExecUntilCommand):\n    \"\"\"Execute until call instruction.\"\"\"\n\n    _cmdline_ = \"exec-until call\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-call\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        return current_arch.is_call(insn)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilJumpCommand(ExecUntilCommand):\n    \"\"\"Execute until jmp instruction.\"\"\"\n\n    _cmdline_ = \"exec-until jmp\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-jmp\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-t\", \"--only-taken\", action=\"store_true\", help=\"break only if jump will be taken.\")\n    group.add_argument(\"-T\", \"--only-not-taken\", action=\"store_true\", help=\"break only if jump will be not taken.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        return self.check_jump_taken(insn)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilIndirectBranchCommand(ExecUntilCommand):\n    \"\"\"Execute until indirect call/jmp instruction (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"exec-until indirect-branch\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-indirect-branch\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-t\", \"--only-taken\", action=\"store_true\", help=\"break only if jump will be taken.\")\n    group.add_argument(\"-T\", \"--only-not-taken\", action=\"store_true\", help=\"break only if jump will be not taken.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        if current_arch.is_call(insn) or self.check_jump_taken(insn):\n            if \"[\" in str(insn):\n                return True\n            for reg in current_arch.general_registers:\n                if reg.replace(\"$\", \"\") in str(insn):\n                    return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilAllBranchCommand(ExecUntilCommand):\n    \"\"\"Execute until call/jump/ret instruction.\"\"\"\n\n    _cmdline_ = \"exec-until all-branch\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-all-branch\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-t\", \"--only-taken\", action=\"store_true\", help=\"break only if jump will be taken.\")\n    group.add_argument(\"-T\", \"--only-not-taken\", action=\"store_true\", help=\"break only if jump will be not taken.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        return current_arch.is_call(insn) or self.check_jump_taken(insn) or current_arch.is_ret(insn)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilSyscallCommand(ExecUntilCommand):\n    \"\"\"Execute until syscall instruction.\"\"\"\n\n    _cmdline_ = \"exec-until syscall\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-syscall\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", default=[], help=\"filter by specified syscall.\")\n    parser.add_argument(\"-i\", \"--ignore\", action=\"append\", default=[], help=\"ignore specified syscall.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        if current_arch.is_syscall(insn):\n            if not self.args.filter and not self.args.ignore:\n                return True\n            _reg, nr = SyscallArgsCommand.get_nr()\n            syscall_table = get_syscall_table()\n            if syscall_table is None:\n                return True # for debug\n            if nr not in syscall_table.nr_table:\n                return True # for debug\n            syscall_name = syscall_table.nr_table[nr].name\n            if self.args.ignore and syscall_name in self.args.ignore:\n                return False\n            if self.args.filter:\n                return syscall_name in self.args.filter\n            else:\n                return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"wine\",))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilRetCommand(ExecUntilCommand):\n    \"\"\"Execute until ret instruction.\"\"\"\n\n    _cmdline_ = \"exec-until ret\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-ret\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        return current_arch.is_ret(insn)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilMemaccessCommand(ExecUntilCommand):\n    \"\"\"Execute until memory access instruction.\"\"\"\n\n    _cmdline_ = \"exec-until memaccess\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-mem\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        return \"[\" in str(insn)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilKeywordReCommand(ExecUntilCommand):\n    \"\"\"Execute until specified keyword instruction.\"\"\"\n\n    _cmdline_ = \"exec-until keyword\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-keyword\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    parser.add_argument(\"keyword\", metavar=\"KEYWORD\", type=re.compile, nargs=\"+\",\n                        help=\"filter by specified regex keyword.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"call +r[ab]x\"                         # execute until specified keyword',\n        '{0:s} \"(push|pop) +(r[a-d]x|r[ds]i|r[sb]p)\"  # another example',\n        '{0:s} \"mov +rax, QWORD PTR \\\\\\\\[\"              # another example (need double escape)',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        for re_pattern in self.args.keyword:\n            if re_pattern.search(str(insn)):\n                return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilCondCommand(ExecUntilCommand):\n    \"\"\"Execute until specified condition is filled.\"\"\"\n\n    _cmdline_ = \"exec-until cond\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-cond\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    parser.add_argument(\"condition\", metavar=\"CONDITION\", help=\"filter by condition.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        '{0:s} \"$rax==0xdead && $rbx==0xcafe\"  # execute until specified condition is filled',\n        '{0:s} \"*(int*)$rbx==0x12\"             # memory access is supported',\n        '{0:s} \"$ALL_REG==0x34\"                # compare with all regs. e.g., `($rax==0x34||$rbx==0x34||...)`',\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        try:\n            v = gdb.parse_and_eval(self.condition)\n        except gdb.error:\n            return False\n        if v not in [0x0, 0x1]:\n            self.err = \"condition result should be True or False\"\n            return True\n        return bool(v)\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        condition = args.condition\n        if re.search(r\"[^><!=]=[^=]\", condition):\n            err(\"Should not use `=` since it will be replace register/memory value, try use `==`\")\n            return\n\n        match = re.search(r\"\\$ALL_REG==(\\w+)\", condition)\n        if match:\n            value = match.groups()[0]\n            replace_cond = []\n            if hasattr(current_arch, \"general_registers\"):\n                regs = current_arch.general_registers\n            else:\n                regs = current_arch.all_registers\n                if hasattr(current_arch, \"flag_register\"):\n                    if current_arch.flag_register in regs:\n                        regs.remove(current_arch.flag_register)\n            for regname in regs:\n                replace_cond.append(\"{:s}=={:s}\".format(regname, value))\n            replace_string = \"(\" + \"||\".join(replace_cond) + \")\"\n            condition = re.sub(r\"\\$ALL_REG==(\\w+)\", replace_string, condition)\n\n        info(\"Condition: {:s}\".format(condition))\n        self.condition = condition\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilUserCodeCommand(ExecUntilCommand):\n    \"\"\"Execute until instruction in user-code.\"\"\"\n\n    _cmdline_ = \"exec-until user-code\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-user-code\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        for p in self.code_addrs:\n            if p.page_start <= insn.address < p.page_end:\n                return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        filepath = Path.get_filepath(append_proc_root_prefix=False)\n        if not filepath and is_remote_debug():\n            filepath = gdb.current_progspace().filename\n            if filepath and filepath.startswith(\"target:\"):\n                filepath = filepath[7:]\n\n        maps = ProcessMap.get_process_maps()\n        self.code_addrs = [p for p in maps if p.permission.value & Permission.EXECUTE and p.path == filepath]\n        if not self.code_addrs:\n            err(\"Could not find code address\")\n            return\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilLibcCodeCommand(ExecUntilCommand):\n    \"\"\"Execute until instruction in libc code.\"\"\"\n\n    _cmdline_ = \"exec-until libc-code\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-libc-code\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-N\", \"--skip-lib\", action=\"store_true\",\n                        help=\"use `ni` instead of `si` if instruction is `call xxx@plt`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        for p in self.libc_addrs:\n            if p.page_start <= insn.address < p.page_end:\n                return True\n        return False\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        libc_targets = (\"libc-2.\", \"libc.so.6\", \"libuClibc-\")\n        libc = ProcessMap.process_lookup_path(libc_targets)\n        maps = ProcessMap.get_process_maps()\n        self.libc_addrs = [p for p in maps if p.permission.value & Permission.EXECUTE and p.path == libc.path]\n        if not self.libc_addrs:\n            err(\"Could not find libc address\")\n            return\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilSecureWorldCommand(ExecUntilCommand):\n    \"\"\"Execute until instruction in the secure-world (ARM/ARM64 only).\"\"\"\n\n    _cmdline_ = \"exec-until secure-world\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-secure-world\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, _insn):\n        return is_in_secure()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"ARM32\", \"ARM64\"))\n    def do_invoke(self, args):\n        self.args.skip_lib = False\n\n        if not is_support_secure_world():\n            err(\"Could not find secure-world\")\n            return\n\n        self.exec_next()\n        return\n\n\n@register_command\nclass ExecUntilRegionChangeCommand(ExecUntilCommand):\n    \"\"\"Execute until different region.\"\"\"\n\n    _cmdline_ = \"exec-until region-change\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n    _aliases_ = [\"next-region-change\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-I\", \"--print-insn\", action=\"store_true\", help=\"print each instruction during execution.\")\n    parser.add_argument(\"-n\", \"--use-ni\", action=\"store_true\", help=\"use `ni` instead of `si`.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"the address to exclude from breakpoints.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def is_target_insn(self, insn):\n        if self.initial_map_start <= insn.address < self.initial_map_end:\n            return False\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    @require_arch_set\n    def do_invoke(self, args):\n        self.args.skip_lib = False\n\n        start_range = ProcessMap.lookup_address(current_arch.pc)\n        if not start_range.valid:\n            err(\"Invalid address\")\n            return\n        self.initial_map_start = start_range.section.page_start\n        self.initial_map_end = start_range.section.page_end\n\n        self.exec_next()\n        return\n\n\n@register_command\nclass CallTraceCommand(ExecUntilCommand):\n    \"\"\"Trace call, ret, and syscall using exec-until.\"\"\"\n\n    _cmdline_ = \"call-trace\"\n    _category_ = \"01-d. Debugging Support - Execution\"\n    _repeat_ = True\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-a\", \"--print-args\", action=\"store_true\",\n                        help=\"dump arguments, return value, and syscall args.\")\n    _syntax_ = parser.format_help()\n    _example_ = None\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    def print_insn(self, insn, indent):\n        colors_table = [\n            Color.redify,\n            Color.greenify,\n            Color.blueify,\n            Color.yellowify,\n        ]\n        color_func = colors_table[(indent // 2) % len(colors_table)]\n        insn_b = String.str2bytes(color_func(str(insn)))\n        msg = b\" \" * indent + insn_b + b\"\\n\"\n        self.force_write_stdout(msg)\n        return\n\n    def print_insn_call(self, insn, indent):\n        self.print_insn(insn, indent)\n        if self.args.print_args:\n            res = gdb.execute(\"registers {:s}\".format(\" \".join(current_arch.function_parameters)), to_string=True)\n            res = \"\\n\".join(\" \" * indent + x for x in res.splitlines()) + \"\\n\"\n            self.force_write_stdout(String.str2bytes(res))\n        return\n\n    def print_insn_ret(self, insn, indent):\n        self.print_insn(insn, indent)\n        if self.args.print_args:\n            res = gdb.execute(\"registers {:s}\".format(current_arch.return_register), to_string=True)\n            res = \"\\n\".join(\" \" * indent + x for x in res.splitlines()) + \"\\n\"\n            self.force_write_stdout(String.str2bytes(res))\n        return\n\n    def print_insn_syscall(self, insn, indent):\n        self.print_insn(insn, indent)\n        if self.args.print_args:\n            res = gdb.execute(\"syscall-args\", to_string=True)\n            res = \"\\n\".join(\" \" * indent + x for x in res.splitlines()) + \"\\n\"\n            self.force_write_stdout(String.str2bytes(res))\n        return\n\n    def call_trace(self):\n        bp_list = self.get_breakpoint_list()\n        EventHooking.gef_on_stop_unhook(EventHandler.hook_stop_handler)\n        self.close_stdout_stderr()\n        self.err = None\n\n        prev_addr = -1\n        next_should_print = False # flag to dump instructions to which calls and rets are jumped\n        print_indent = 0\n        try:\n            while True:\n                printed_already = False # flag to not output the same insn twice\n\n                # backup\n                prev_prev_addr = prev_addr\n                prev_addr = current_arch.pc\n\n                # execute 1 instruction\n                gdb.execute(\"si\") # use si wrapper\n                insn = get_insn()\n\n                if next_should_print:\n                    next_should_print = False\n                    self.print_insn(insn, print_indent)\n                    printed_already = True\n\n                # check breakpoint\n                if current_arch.pc in bp_list:\n                    break\n\n                # $pc is not changed\n                if prev_prev_addr == prev_addr == current_arch.pc: # for faster, repeat insn is skip\n                    # infinity self loop\n                    if current_arch.is_call(insn) or current_arch.is_jump(insn) or current_arch.is_ret(insn):\n                        self.err = \"Detected infinity loop prev_addr ({:#x})\".format(prev_addr)\n                        break\n                    # maybe rep prefix\n                    gdb.execute(\"xuntil\")\n                    # recheck\n                    if prev_prev_addr == prev_addr == current_arch.pc:\n                        self.err = \"Detected infinity loop prev_addr ({:#x})\".format(prev_addr)\n                        break\n                    insn = get_insn()\n\n                # call or ret\n                if current_arch.is_call(insn):\n                    if not printed_already:\n                        self.print_insn_call(insn, print_indent)\n                    next_should_print = True\n                    print_indent += 2\n                elif current_arch.is_ret(insn):\n                    if not printed_already:\n                        self.print_insn_ret(insn, print_indent)\n                    next_should_print = True\n                    print_indent = max(print_indent - 2, 0)\n                elif current_arch.is_syscall(insn):\n                    if not printed_already:\n                        self.print_insn_syscall(insn, print_indent)\n\n        except KeyboardInterrupt:\n            pass\n\n        except Exception:\n            if is_alive():\n                exc_type, exc_value, exc_traceback = sys.exc_info()\n                self.err = exc_value\n            else:\n                pass\n\n        finally:\n            self.revert_stdout_stderr() # anytime needed\n            EventHooking.gef_on_stop_hook(EventHandler.hook_stop_handler) # anytime needed\n            Cache.reset_gef_caches()\n            if self.err:\n                err(self.err)\n            else:\n                gdb.execute(\"context\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        self.call_trace()\n        return\n\n\nclass CallUsermodehelperSetupBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print argv information at call_usermodehelper_setup.\"\"\"\n\n    def __init__(self, loc):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        return\n\n    def stop(self):\n        ptr1, addr1 = current_arch.get_ith_parameter(0)\n        ptr2, addr2 = current_arch.get_ith_parameter(1)\n        path = read_cstring_from_memory(addr1)\n        argv = []\n        while True:\n            string_addr = read_int_from_memory(addr2)\n            if string_addr == 0:\n                break\n            string = read_cstring_from_memory(string_addr)\n            argv.append(\"'{:s}'\".format(string))\n            addr2 += current_arch.ptrsize\n        gef_print(\"{:s}: {:#x} -> '{:s}'\".format(ptr1, addr1, path))\n        gef_print(\"{:s}: {:#x} -> [{:s}]\".format(ptr2, addr2, \",\".join(argv)))\n        return False # continue\n\n\n@register_command\nclass UsermodehelperTracerCommand(GenericCommand):\n    \"\"\"Collect and display information that is executed by call_usermodehelper_setup.\"\"\"\n\n    _cmdline_ = \"usermodehelper-tracer\"\n    _category_ = \"06-i. Qemu-system/KGDB Cooperation - Linux Dynamic Inspection\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        info(\"Resolving the function addresses\")\n        addr = Symbol.get_ksymaddr(\"call_usermodehelper_setup\")\n        if addr is None:\n            err(\"Could not find call_usermodehelper_setup\")\n            return\n        CallUsermodehelperSetupBreakpoint(addr)\n        info(\"Setup is complete. Try `continue`\")\n        return\n\n\nclass ThunkBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print caller address for thunk function.\"\"\"\n\n    def __init__(self, loc, sym, reg, maps):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        self.loc = loc\n        self.sym = sym\n        self.reg = reg\n        self.maps = maps\n        self.seen = []\n        return\n\n    def search_perm(self, target):\n        for m in self.maps:\n            addr, size, perm = m\n            if addr <= target < addr + size:\n                return perm.lower()\n        return \"?\"\n\n    def stop(self):\n        try:\n            return_address = gdb.selected_frame().older().pc()\n            caller_address = Disasm.gdb_get_nth_previous_instruction_address(return_address, 1)\n            target_address = get_register(self.reg)\n        except gdb.error:\n            return False # continue\n\n        # duplicate, check\n        if (caller_address, target_address) in self.seen:\n            return False # continue\n        else:\n            self.seen.append((caller_address, target_address))\n\n        # get caller address, symbol\n        caller_symbol = Symbol.get_symbol_string(caller_address, nosymbol_string=\" <NO_SYMBOL>\")\n\n        # get callee address, symbol\n        target_symbol = Symbol.get_symbol_string(target_address, nosymbol_string=\" <NO_SYMBOL>\")\n\n        # print information\n        if caller_address is None:\n            info(\"{:s}{:s} -> {:#x} <{:s}> -> {:#x}{:s}\".format(\n                \"???(unknown)\", caller_symbol, self.loc, self.sym, target_address, target_symbol,\n            ))\n        else:\n            info(\"{:#x}{:s} -> {:#x} <{:s}> -> {:#x}{:s}\".format(\n                caller_address, caller_symbol, self.loc, self.sym, target_address, target_symbol,\n            ))\n\n        # print preferred register condition\n        pattern = [0] + [(x + 1) * y for x, y in itertools.product(range(0x100), [1, -1])] # [0, 1, -1, 2, -2, ...]\n        for reg in current_arch.general_registers:\n            reg_value = get_register(reg)\n            for i in pattern:\n                slide = current_arch.ptrsize * i\n                reg_value_slided = reg_value + slide\n                try:\n                    mem_value = read_int_from_memory(reg_value_slided)\n                except (gdb.MemoryError, OverflowError):\n                    continue\n                if mem_value != target_address:\n                    continue\n                perm = self.search_perm(reg_value_slided)\n                reg_value_slided_symbol = Symbol.get_symbol_string(reg_value_slided, nosymbol_string=\" <NO_SYMBOL>\")\n                mem_value_symbol = Symbol.get_symbol_string(mem_value, nosymbol_string=\" <NO_SYMBOL>\")\n                info(\"    {:s}{:+#x}: {:#x}{:s} [{:s}]  ->  {:#x}{:s}\".format(\n                    reg, slide, reg_value_slided, reg_value_slided_symbol, perm, mem_value, mem_value_symbol,\n                ))\n                break\n        return False # continue\n\n\n@register_command\nclass ThunkTracerCommand(GenericCommand):\n    \"\"\"Collect and display the thunk addresses that are called automatically (x64/x86 only).\"\"\"\n\n    _cmdline_ = \"thunk-tracer\"\n    _category_ = \"06-i. Qemu-system/KGDB Cooperation - Linux Dynamic Inspection\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        info(\"Wait for memory scan\")\n        maps = Kernel.get_maps() # [vaddr, size, perm]\n        info(\"Resolving thunk function addresses\")\n        for reg in current_arch.general_registers:\n            if reg in [\"$esp\", \"$rsp\", \"$eip\", \"$rip\"]:\n                continue\n            sym = \"__x86_indirect_thunk_{}\".format(reg.replace(\"$\", \"\"))\n            addr = Symbol.get_ksymaddr(sym)\n            if addr is None:\n                continue\n            gef_print(sym + \": \", end=\"\")\n            ThunkBreakpoint(addr, sym, reg, maps)\n        info(\"Setup is complete, try `continue`\")\n        return\n\n\nclass KmallocBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of kmalloc.\"\"\"\n\n    def __init__(self, loc, sym, index_of_size_arg, option, extra):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        self.sym = sym\n        self.index_of_size_arg = index_of_size_arg\n        self.option = option\n        self.extra = extra\n        self.enabled = False\n        return\n\n    def check_nested(self, task_addr):\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ in [\"KmallocRetBreakpoint\"]:\n                    if bp.enabled and bp.task_addr == task_addr:\n                        return True\n            except Exception:\n                pass\n        return False\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # fast return if nested break\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.check_nested(task_addr):\n            return False\n\n        # filtering by task addr\n        if self.option.target_task and task_addr != self.option.target_task:\n            return False\n\n        # filtering by task name\n        if self.option.task_name and task_name not in self.option.task_name:\n            return False\n\n        # get size from arguments\n        if self.index_of_size_arg >= 0:\n            # e.g., kmalloc(size, ...)\n            _, size = current_arch.get_ith_parameter(self.index_of_size_arg)\n        else:\n            # e.g., kmem_cache_alloc_node has no `size` argument\n            _, kmem_cache = current_arch.get_ith_parameter(0)\n            slab_cache_name_ptr = read_int_from_memory(kmem_cache + self.extra.kmem_cache_offset_name)\n            slab_cache_name = read_cstring_from_memory(slab_cache_name_ptr)\n            if not slab_cache_name.startswith(\"kmalloc-\"):\n                return False\n            size = read_int32_from_memory(kmem_cache + self.extra.kmem_cache_offset_size)\n\n        # Use gdb.Breakpoint instead of gdb.FinishBreakpoint because gdb.FinishBreakpoint is buggy\n        ret_addr = gdb.newest_frame().older().pc()\n        KmallocRetBreakpoint(ret_addr, self.sym, size, task_addr, self.option, self.extra)\n        return False\n\n\nclass KmallocRetBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of kmalloc.\"\"\"\n\n    def __init__(self, loc, sym, size, task_addr, option, extra):\n        # Note that specifying temporary=True does not remove the breakpoint if stop() returns False.\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=True)\n        self.size = size\n        self.sym = sym\n        self.task_addr = task_addr\n        self.option = option\n        self.extra = extra\n        KmallocTracerCommand.clear_disabled_breakpoints(\"KmallocRetBreakpoint\")\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # check if another thread is detected\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.task_addr != task_addr:\n            return False\n\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        allocated = AddressUtil.parse_address(current_arch.return_register)\n        allocated_s = Color.colorify_hex(allocated, Config.get_gef_setting(\"theme.heap_chunk_address_used\"))\n\n        if self.extra:\n            ret = KmallocTracerCommand.virt2name_and_size(allocated)\n            if ret:\n                # print more info\n                name, chunk_size = ret\n                if not name.startswith(\"kmalloc-\"):\n                    self.enabled = False\n                    return False\n                if self.option.filter and name not in self.option.filter:\n                    self.enabled = False\n                    return False\n                name_s = Color.colorify(name, Config.get_gef_setting(\"theme.heap_chunk_label\"))\n                chunk_size_s = Color.colorify(\"{:<#6x}\".format(chunk_size), Config.get_gef_setting(\"theme.heap_chunk_size\"))\n                gef_print(\"{:s} {:40s}: {:s} (size: {:s} name: {:s})\".format(\n                    task_prefix, self.sym, allocated_s, chunk_size_s, name_s,\n                ))\n                KmallocTracerCommand.print_backtrace(self.option.backtrace)\n                KmallocTracerCommand.dump_chunk(self.option.dump_chunk, allocated)\n                self.enabled = False\n                return False\n            # fall through\n\n        # print less info\n        gef_print(\"{:s} {:40s}: {:s} (size: {:<#6x})\".format(task_prefix, self.sym, allocated_s, self.size))\n        KmallocTracerCommand.print_backtrace(self.option.backtrace)\n        KmallocTracerCommand.dump_chunk(self.option.dump_chunk, allocated)\n        self.enabled = False\n        return False\n\n\nclass KfreeBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of kfree.\"\"\"\n\n    def __init__(self, loc, sym, index_of_addr_arg, option, extra):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        self.sym = sym\n        self.index_of_addr_arg = index_of_addr_arg\n        self.option = option\n        self.extra = extra\n        self.enabled = False\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # check if NULL\n        _, to_free = current_arch.get_ith_parameter(self.index_of_addr_arg)\n        if not self.option.print_null and to_free == 0:\n            return False\n\n        # filtering by task addr\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.option.target_task and task_addr != self.option.target_task:\n            return False\n\n        # filtering by task name\n        if self.option.task_name and task_name not in self.option.task_name:\n            return False\n\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        to_free_s = Color.colorify_hex(to_free, Config.get_gef_setting(\"theme.heap_chunk_address_freed\"))\n\n        if self.extra:\n            ret = KmallocTracerCommand.virt2name_and_size(to_free)\n            if ret:\n                # print more info\n                name, chunk_size = ret\n                if not name.startswith(\"kmalloc-\"):\n                    return False\n                if self.option.filter and name not in self.option.filter:\n                    return False\n                name_s = Color.colorify(name, Config.get_gef_setting(\"theme.heap_chunk_label\"))\n                chunk_size_s = Color.colorify(\"{:<#6x}\".format(chunk_size), Config.get_gef_setting(\"theme.heap_chunk_size\"))\n                gef_print(\"{:s} {:40s}: {:s} (size: {:s} name: {:s})\".format(\n                    task_prefix, self.sym, to_free_s, chunk_size_s, name_s,\n                ))\n                KmallocTracerCommand.print_backtrace(self.option.backtrace)\n                KmallocTracerCommand.dump_chunk(self.option.dump_chunk, to_free)\n                return False\n            # fall through\n\n        # print less info\n        gef_print(\"{:s} {:40s}: {:s}\".format(task_prefix, self.sym, to_free_s))\n        KmallocTracerCommand.print_backtrace(self.option.backtrace)\n        KmallocTracerCommand.dump_chunk(self.option.dump_chunk, to_free)\n        return False\n\n\nclass AllocPagesBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of __alloc_pages.\"\"\"\n\n    def __init__(self, loc, sym, index_of_order_arg, option, extra):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        self.sym = sym\n        self.index_of_order_arg = index_of_order_arg\n        self.option = option\n        self.extra = extra\n        self.enabled = False\n        return\n\n    def check_nested(self, task_addr):\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ in [\"AllocPagesRetBreakpoint\"]:\n                    if bp.enabled and bp.task_addr == task_addr:\n                        return True\n            except Exception:\n                pass\n        return False\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # fast return if nested break\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.check_nested(task_addr):\n            return False\n\n        # filtering by task addr\n        if self.option.target_task and task_addr != self.option.target_task:\n            return False\n\n        # filtering by task name\n        if self.option.task_name and task_name not in self.option.task_name:\n            return False\n\n        # get order from arguments\n        _, order = current_arch.get_ith_parameter(self.index_of_order_arg)\n\n        # Use gdb.Breakpoint instead of gdb.FinishBreakpoint because gdb.FinishBreakpoint is buggy\n        ret_addr = gdb.newest_frame().older().pc()\n        AllocPagesRetBreakpoint(ret_addr, self.sym, order, task_addr, self.option, self.extra)\n        return False\n\n\nclass AllocPagesRetBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of __alloc_pages.\"\"\"\n\n    def __init__(self, loc, sym, order, task_addr, option, extra):\n        # Note that specifying temporary=True does not remove the breakpoint if stop() returns False.\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=True)\n        self.order = order\n        self.sym = sym\n        self.task_addr = task_addr\n        self.option = option\n        self.extra = extra\n        KmallocTracerCommand.clear_disabled_breakpoints(\"AllocPagesRetBreakpoint\")\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # check if another thread is detected\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.task_addr != task_addr:\n            return False\n\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        allocated_page = AddressUtil.parse_address(current_arch.return_register)\n        if not is_valid_addr(allocated_page):\n            allocated_virt = 0\n        else:\n            allocated_virt = Kernel.page2virt(allocated_page)\n        if allocated_virt is None:\n            allocated_virt = 0\n        allocated_virt_s = Color.colorify_hex(\n            allocated_virt, Config.get_gef_setting(\"theme.heap_page_address\"),\n        )\n        size = KernelAddressHeuristicFinder.consts().PAGE_SIZE * (2 ** self.order)\n\n        # print less info\n        gef_print(\"{:s} {:40s}: {:s} (page: {:#x}, order: {:d}, size: {:#x})\".format(\n            task_prefix, self.sym, allocated_virt_s, allocated_page, self.order, size,\n        ))\n        KmallocTracerCommand.print_backtrace(self.option.backtrace)\n        KmallocTracerCommand.dump_chunk(self.option.dump_chunk, allocated_virt)\n        self.enabled = False\n        return False\n\n\nclass FreePagesBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information of __free_pages.\"\"\"\n\n    def __init__(self, loc, sym, index_of_addr_arg, index_of_order_arg, option, extra):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=False)\n        self.sym = sym\n        self.index_of_addr_arg = index_of_addr_arg\n        self.index_of_order_arg = index_of_order_arg\n        self.option = option\n        self.extra = extra\n        self.enabled = False\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        _, to_free_page = current_arch.get_ith_parameter(self.index_of_addr_arg)\n        _, order = current_arch.get_ith_parameter(self.index_of_order_arg)\n\n        # filtering by task addr\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.option.target_task and task_addr != self.option.target_task:\n            return False\n\n        # filtering by task name\n        if self.option.task_name and task_name not in self.option.task_name:\n            return False\n\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        if not is_valid_addr(to_free_page):\n            to_free_virt = 0\n        else:\n            to_free_virt = Kernel.page2virt(to_free_page)\n        if to_free_virt is None:\n            to_free_virt = 0\n        to_free_virt_s = Color.colorify_hex(\n            to_free_virt, Config.get_gef_setting(\"theme.heap_page_address\")\n        )\n        size = KernelAddressHeuristicFinder.consts().PAGE_SIZE * (2 ** order)\n\n        # print less info\n        gef_print(\"{:s} {:40s}: {:s} (page: {:#x}, order: {:d}, size: {:#x})\".format(\n            task_prefix, self.sym, to_free_virt_s, to_free_page, order, size,\n        ))\n        KmallocTracerCommand.print_backtrace(self.option.backtrace)\n        KmallocTracerCommand.dump_chunk(self.option.dump_chunk, to_free_virt)\n        return False\n\n\n@register_command\nclass KmallocTracerCommand(GenericCommand):\n    \"\"\"Collect and display information when kmalloc/kfree.\"\"\"\n\n    _cmdline_ = \"kmalloc-tracer\"\n    _category_ = \"06-i. Qemu-system/KGDB Cooperation - Linux Dynamic Inspection\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", default=[], help=\"filter specified slab name (e.g., kmalloc-XX)\")\n    parser.add_argument(\"-T\", \"--task-name\", action=\"append\", default=[], help=\"filter specified task name (e.g., sh)\")\n    parser.add_argument(\"-N\", \"--print-null\", action=\"store_true\", help=\"display free(NULL).\")\n    parser.add_argument(\"-t\", \"--backtrace\", action=\"store_true\", help=\"display backtrace.\")\n    parser.add_argument(\"-d\", \"--dump-chunk\", action=\"store_true\", help=\"dump the first 0x40 bytes of each chunk.\")\n    parser.add_argument(\"-p\", \"--enable-page-allocator-trace\", action=\"store_true\",\n                        help=\"in addition to kmalloc and kfree, it also monitors __alloc_pages and __free_pages.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"print meta information.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}       # simple output\",\n        \"{0:s} -dtv  # useful output\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Disable `-enable-kvm` option for qemu-system (#PF may occur).\",\n        \"Append `tsc=unstable` option for kernel cmdline.\",\n        \"Tracing `kmem_cache_alloc` type is not supported.\",\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @staticmethod\n    def create_option_info(args, target_task=None):\n        dic = {\n            \"print_null\": args.print_null,\n            \"backtrace\": args.backtrace,\n            \"filter\": args.filter,\n            \"dump_chunk\": args.dump_chunk,\n            \"task_name\": getattr(args, \"task_name\", []),\n            \"target_task\": target_task,\n        }\n        OptionInfo = collections.namedtuple(\"OptionInfo\", dic.keys())\n        option_info = OptionInfo(*dic.values())\n        return option_info\n\n    @staticmethod\n    def clear_disabled_breakpoints(name, force=False):\n        for bp in gdb.breakpoints():\n            try:\n                if bp.__class__.__name__ != name:\n                    continue\n                if force is False and bp.enabled:\n                    continue\n                bp.delete()\n            except Exception:\n                pass\n        return\n\n    @staticmethod\n    def initialize(allocator, verbose):\n        if allocator != \"SLUB\":\n            # Do nothing other than SLUB.\n            return None\n\n        res = gdb.execute(\"slub-dump --meta\", to_string=True)\n\n        r = re.search(r\"offsetof\\((?:page|slab), slab_cache\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        page_offset_slab_cache = int(r.group(1), 16)\n        if verbose:\n            info(\"offsetof({:s}, slab_cache): {:#x}\".format(Kernel.slab_page_str(), page_offset_slab_cache))\n\n        r = re.search(r\"offsetof\\(kmem_cache, name\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        kmem_cache_offset_name = int(r.group(1), 16)\n        if verbose:\n            info(\"offsetof(kmem_cache, name): {:#x}\".format(kmem_cache_offset_name))\n\n        r = re.search(r\"offsetof\\(kmem_cache, size\\): (0x\\S+)\", res)\n        if not r:\n            return False\n        kmem_cache_offset_size = int(r.group(1), 16)\n        if verbose:\n            info(\"offsetof(kmem_cache, size): {:#x}\".format(kmem_cache_offset_size))\n\n        # create extra_info\n        dic = {\n            \"kmem_cache_offset_name\": kmem_cache_offset_name,\n            \"kmem_cache_offset_size\": kmem_cache_offset_size,\n            \"page_offset_slab_cache\": page_offset_slab_cache,\n        }\n        ExtraInfo = collections.namedtuple(\"ExtraInfo\", dic.keys())\n        extra_info = ExtraInfo(*dic.values())\n        return extra_info\n\n    @staticmethod\n    def get_task():\n        th_num = gdb.selected_thread().num\n        res = gdb.execute(\"kcurrent --quiet\", to_string=True)\n        r = re.search(r\"current \\(cpu{:d}\\): (0x\\S+) (.*)\".format(th_num - 1), res)\n        if r:\n            task = int(r.group(1), 16)\n            name = r.group(2)\n            return task, name\n        return 0, \"\"\n\n    @staticmethod\n    def virt2name_and_size(vaddr):\n        ret = Kernel.get_slab_contains(vaddr)\n        if not ret:\n            return None\n        r = re.search(r\"name: (\\S+)  object_size: (\\S+)\", ret)\n        if not r:\n            return None\n        slab_cache_name = r.group(1)\n        slab_cache_size = int(r.group(2), 16)\n        return slab_cache_name, slab_cache_size\n\n    @staticmethod\n    def print_backtrace(backtrace):\n        if not backtrace:\n            return\n\n        try:\n            frame = gdb.newest_frame()\n            while frame and frame.is_valid():\n                addr = frame.pc()\n                if not is_valid_addr(addr):\n                    break\n                sym = Symbol.get_symbol_string(addr, nosymbol_string=\" <NO_SYMBOL>\")\n                gef_print(\"  {:#018x}{:s}\".format(addr, sym))\n                frame = frame.older()\n        except gdb.error:\n            return\n\n    @staticmethod\n    def dump_chunk(dump, loc):\n        if not dump:\n            return\n        if not is_valid_addr(loc):\n            err(\"Invalid address\")\n            return\n        gdb.execute(\"dereference -n {:#x} 8\".format(loc))\n        return\n\n    @staticmethod\n    def set_bp_to_kmalloc_kfree(option_info, extra_info):\n        # `kmalloc` is always inlined and not exported, so its symbol cannot be identified.\n        # Therefore, you must set a breakpoint in a function that is exported instead of kmalloc.\n        # This can be done by checking EXPORT_SYMBOL, and a tool to automate this is dev/update-kmalloc-tracer.\n        # The same symbol may be found multiple times from different *.c files, and they can be treated as the same.\n        \"\"\"\n        [3.0~3.15]\n        EXPORT_SYMBOL(__kmalloc);\n        EXPORT_SYMBOL(__kmalloc_node);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller);\n        EXPORT_SYMBOL(__kmalloc_track_caller);\n        EXPORT_SYMBOL(__krealloc);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_order_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc);\n        EXPORT_SYMBOL(kmem_cache_alloc_node);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc_trace);\n        EXPORT_SYMBOL(krealloc);\n        [3.16~5.5]\n        EXPORT_SYMBOL(__kmalloc);\n        EXPORT_SYMBOL(__kmalloc_node);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller);\n        EXPORT_SYMBOL(__kmalloc_track_caller);\n        EXPORT_SYMBOL(__krealloc);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_order);\n        EXPORT_SYMBOL(kmalloc_order_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc);\n        EXPORT_SYMBOL(kmem_cache_alloc_node);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc_trace);\n        EXPORT_SYMBOL(krealloc);\n        [5.6~5.17]\n        EXPORT_SYMBOL(__kmalloc);\n        EXPORT_SYMBOL(__kmalloc_node);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller);\n        EXPORT_SYMBOL(__kmalloc_track_caller);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_order);\n        EXPORT_SYMBOL(kmalloc_order_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc);\n        EXPORT_SYMBOL(kmem_cache_alloc_node);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc_trace);\n        EXPORT_SYMBOL(krealloc);\n        [5.18~6.0]\n        EXPORT_SYMBOL(__kmalloc);\n        EXPORT_SYMBOL(__kmalloc_node);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller);\n        EXPORT_SYMBOL(__kmalloc_track_caller);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_order);\n        EXPORT_SYMBOL(kmalloc_order_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc);\n        EXPORT_SYMBOL(kmem_cache_alloc_lru);\n        EXPORT_SYMBOL(kmem_cache_alloc_node);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc_trace);\n        EXPORT_SYMBOL(krealloc);\n        [6.1~6.9]\n        EXPORT_SYMBOL(__kmalloc);\n        EXPORT_SYMBOL(__kmalloc_node);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_large);\n        EXPORT_SYMBOL(kmalloc_large_node);\n        EXPORT_SYMBOL(kmalloc_node_trace);\n        EXPORT_SYMBOL(kmalloc_trace);\n        EXPORT_SYMBOL(kmem_cache_alloc);\n        EXPORT_SYMBOL(kmem_cache_alloc_lru);\n        EXPORT_SYMBOL(kmem_cache_alloc_node);\n        EXPORT_SYMBOL(krealloc);\n        [6.10]\n        EXPORT_SYMBOL(__kmalloc_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_noprof);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmalloc_large_node_noprof);\n        EXPORT_SYMBOL(kmalloc_large_noprof);\n        EXPORT_SYMBOL(kmalloc_node_trace_noprof);\n        EXPORT_SYMBOL(kmalloc_node_track_caller_noprof);\n        EXPORT_SYMBOL(kmalloc_trace_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_lru_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_noprof);\n        EXPORT_SYMBOL(krealloc_noprof);\n        [6.11~6.17]\n        EXPORT_SYMBOL(__kmalloc_cache_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_cache_noprof);\n        EXPORT_SYMBOL(__kmalloc_large_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_large_noprof);\n        EXPORT_SYMBOL(__kmalloc_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller_noprof);\n        EXPORT_SYMBOL(__kmalloc_noprof);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmem_cache_alloc_lru_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_noprof);\n        EXPORT_SYMBOL(krealloc_noprof);\n        [6.18~]\n        EXPORT_SYMBOL(__kmalloc_cache_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_cache_noprof);\n        EXPORT_SYMBOL(__kmalloc_large_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_large_noprof);\n        EXPORT_SYMBOL(__kmalloc_node_noprof);\n        EXPORT_SYMBOL(__kmalloc_node_track_caller_noprof);\n        EXPORT_SYMBOL(__kmalloc_noprof);\n        EXPORT_SYMBOL(kfree);\n        EXPORT_SYMBOL(kmem_cache_alloc_lru_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_node_noprof);\n        EXPORT_SYMBOL(kmem_cache_alloc_noprof);\n        EXPORT_SYMBOL(krealloc_node_align_noprof);\n        EXPORT_SYMBOL_GPL(kfree_nolock);\n        EXPORT_SYMBOL_GPL(kmalloc_nolock_noprof);\n        \"\"\"\n\n        # This list may be incomplete.\n        # If you know of any memory-allocating functions that may be freed with kfree, please let me know.\n        # The number is the argument index of the size. -1 means index 0 is `struct kmem_cache*`.\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.16\":\n            kmalloc_syms = [\n                [\"__kmalloc\", 0],\n                [\"__kmalloc_node\", 0],\n                [\"__kmalloc_node_track_caller\", 0],\n                [\"__kmalloc_track_caller\", 0],\n                [\"__krealloc\", 1],\n                [\"kmalloc_order_trace\", 0],\n                [\"kmem_cache_alloc\", -1],\n                [\"kmem_cache_alloc_node\", -1],\n                [\"kmem_cache_alloc_node_trace\", 3],\n                [\"kmem_cache_alloc_trace\", 2],\n                [\"krealloc\", 1],\n            ]\n        elif kversion < \"5.6\":\n            kmalloc_syms = [\n                [\"__kmalloc\", 0],\n                [\"__kmalloc_node\", 0],\n                [\"__kmalloc_node_track_caller\", 0],\n                [\"__kmalloc_track_caller\", 0],\n                [\"__krealloc\", 1],\n                [\"kmalloc_order\", 0],\n                [\"kmalloc_order_trace\", 0],\n                [\"kmem_cache_alloc\", -1],\n                [\"kmem_cache_alloc_node\", -1],\n                [\"kmem_cache_alloc_node_trace\", 3],\n                [\"kmem_cache_alloc_trace\", 2],\n                [\"krealloc\", 1],\n            ]\n        elif kversion < \"5.18\":\n            kmalloc_syms = [\n                [\"__kmalloc\", 0],\n                [\"__kmalloc_node\", 0],\n                [\"__kmalloc_node_track_caller\", 0],\n                [\"__kmalloc_track_caller\", 0],\n                [\"kmalloc_order\", 0],\n                [\"kmalloc_order_trace\", 0],\n                [\"kmem_cache_alloc\", -1],\n                [\"kmem_cache_alloc_node\", -1],\n                [\"kmem_cache_alloc_node_trace\", 3],\n                [\"kmem_cache_alloc_trace\", 2],\n                [\"krealloc\", 1],\n            ]\n        elif kversion < \"6.1\":\n            kmalloc_syms = [\n                [\"__kmalloc\", 0],\n                [\"__kmalloc_node\", 0],\n                [\"__kmalloc_node_track_caller\", 0],\n                [\"__kmalloc_track_caller\", 0],\n                [\"kmalloc_order\", 0],\n                [\"kmalloc_order_trace\", 0],\n                [\"kmem_cache_alloc\", -1],\n                [\"kmem_cache_alloc_lru\", -1],\n                [\"kmem_cache_alloc_node\", -1],\n                [\"kmem_cache_alloc_node_trace\", 3],\n                [\"kmem_cache_alloc_trace\", 2],\n                [\"krealloc\", 1],\n            ]\n        elif kversion < \"6.10\":\n            kmalloc_syms = [\n                [\"__kmalloc\", 0],\n                [\"__kmalloc_node\", 0],\n                [\"__kmalloc_node_track_caller\", 0],\n                [\"kmalloc_large\", 0],\n                [\"kmalloc_large_node\", 0],\n                [\"kmalloc_node_trace\", 3],\n                [\"kmalloc_trace\", 2],\n                [\"kmem_cache_alloc\", -1],\n                [\"kmem_cache_alloc_lru\", -1],\n                [\"kmem_cache_alloc_node\", -1],\n                [\"krealloc\", 1],\n            ]\n        elif kversion < \"6.11\":\n            kmalloc_syms = [\n                [\"__kmalloc_node_noprof\", 0],\n                [\"__kmalloc_noprof\", 0],\n                [\"kmalloc_large_node_noprof\", 0],\n                [\"kmalloc_large_noprof\", 0],\n                [\"kmalloc_node_trace_noprof\", 3],\n                [\"kmalloc_node_track_caller_noprof\", 0],\n                [\"kmalloc_trace_noprof\", 2],\n                [\"kmem_cache_alloc_lru_noprof\", -1],\n                [\"kmem_cache_alloc_node_noprof\", -1],\n                [\"kmem_cache_alloc_noprof\", -1],\n                [\"krealloc_noprof\", 1],\n            ]\n        elif kversion < \"6.18\":\n            kmalloc_syms = [\n                [\"__kmalloc_cache_node_noprof\", 3],\n                [\"__kmalloc_cache_noprof\", 2],\n                [\"__kmalloc_large_node_noprof\", 0],\n                [\"__kmalloc_large_noprof\", 0],\n                [\"__kmalloc_node_noprof\", 0],\n                [\"__kmalloc_node_track_caller_noprof\", 0],\n                [\"__kmalloc_noprof\", 0],\n                [\"kmem_cache_alloc_lru_noprof\", -1],\n                [\"kmem_cache_alloc_node_noprof\", -1],\n                [\"kmem_cache_alloc_noprof\", -1],\n                [\"krealloc_noprof\", 1],\n            ]\n        else:\n            kmalloc_syms = [\n                [\"__kmalloc_cache_node_noprof\", 3],\n                [\"__kmalloc_cache_noprof\", 2],\n                [\"__kmalloc_large_node_noprof\", 0],\n                [\"__kmalloc_large_noprof\", 0],\n                [\"__kmalloc_node_noprof\", 0],\n                [\"__kmalloc_node_track_caller_noprof\", 0],\n                [\"__kmalloc_noprof\", 0],\n                [\"kmem_cache_alloc_lru_noprof\", -1],\n                [\"kmem_cache_alloc_node_noprof\", -1],\n                [\"kmem_cache_alloc_noprof\", -1],\n                [\"krealloc_node_align_noprof\", 1],\n                [\"kmalloc_nolock_noprof\", 0],\n            ]\n\n        if kversion < \"6.18\":\n            kfree_syms = [\n                [\"kfree\", 0],\n            ]\n        else:\n            kfree_syms = [\n                [\"kfree\", 0],\n                [\"kfree_nolock\", 0],\n            ]\n\n        breakpoints = []\n        for sym, index_of_size_arg in kmalloc_syms:\n            func_addr = Symbol.get_ksymaddr(sym)\n            if func_addr:\n                gef_print(sym + \": \", end=\"\")\n                bp = KmallocBreakpoint(func_addr, sym, index_of_size_arg, option_info, extra_info)\n                breakpoints.append(bp)\n        for sym, index_of_addr_arg in kfree_syms:\n            func_addr = Symbol.get_ksymaddr(sym)\n            if func_addr:\n                gef_print(sym + \": \", end=\"\")\n                bp = KfreeBreakpoint(func_addr, sym, index_of_addr_arg, option_info, extra_info)\n                breakpoints.append(bp)\n        return breakpoints\n\n    @staticmethod\n    def set_bp_to_alloc_free_pages(option_info, extra_info):\n        \"\"\"\n        [3.0~5.12]\n        EXPORT_SYMBOL(__alloc_pages_nodemask);\n        EXPORT_SYMBOL(__free_pages);\n        [5.13~6.9]\n        EXPORT_SYMBOL(__alloc_pages);\n        EXPORT_SYMBOL(__free_pages);\n        [6.10~6.13]\n        EXPORT_SYMBOL(__alloc_pages_noprof);\n        EXPORT_SYMBOL(__free_pages);\n        [6.14~]\n        EXPORT_SYMBOL(__alloc_frozen_pages_noprof);\n        EXPORT_SYMBOL(__free_pages);\n        \"\"\"\n\n        # This list may be incomplete.\n        # If you know of any memory-allocating functions that may be freed with kfree, please let me know.\n        # The number is the argument index of the order.\n        kversion = Kernel.kernel_version()\n        if kversion < \"5.13\":\n            alloc_pages_sym = [\n                [\"__alloc_pages_nodemask\", 1],\n            ]\n        elif kversion < \"6.10\":\n            alloc_pages_sym = [\n                [\"__alloc_pages\", 1],\n            ]\n        elif kversion < \"6.14\":\n            alloc_pages_sym = [\n                [\"__alloc_pages_noprof\", 1],\n            ]\n        else:\n            alloc_pages_sym = [\n                [\"__alloc_frozen_pages_noprof\", 1],\n            ]\n\n        free_pages_sym = [\n            [\"__free_pages\", 0, 1],\n        ]\n\n        breakpoints = []\n        for sym, index_of_order_arg in alloc_pages_sym:\n            func_addr = Symbol.get_ksymaddr(sym)\n            if func_addr:\n                gef_print(sym + \": \", end=\"\")\n                bp = AllocPagesBreakpoint(func_addr, sym, index_of_order_arg, option_info, extra_info)\n                breakpoints.append(bp)\n        for sym, index_of_addr_arg, index_of_order_arg in free_pages_sym:\n            func_addr = Symbol.get_ksymaddr(sym)\n            if func_addr:\n                gef_print(sym + \": \", end=\"\")\n                bp = FreePagesBreakpoint(func_addr, sym, index_of_addr_arg, index_of_order_arg, option_info, extra_info)\n                breakpoints.append(bp)\n        return breakpoints\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.0\":\n            err(\"Unsupported before v3.0\")\n            return\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"Unknown\":\n            err(\"Unsupported: Unknown allocator\")\n            return\n        if allocator != \"SLUB\":\n            warn(\"Unsupported viewing detailed information for SLAB, SLOB, SLUB_TINY\")\n            # fall through\n\n        # initialize\n        if not hasattr(self, \"initialized\"):\n            ret = KmallocTracerCommand.initialize(allocator, args.verbose)\n            if ret is False:\n                err(\"Failed to initialize\")\n                return\n            self.initialized = True\n            self.extra_info = ret # allow None\n        else:\n            if args.verbose and self.extra_info:\n                info(\"offsetof({:s}, slab_cache): {:#x}\".format(Kernel.slab_page_str(), self.extra_info.page_offset_slab_cache))\n                info(\"offsetof(kmem_cache, name): {:#x}\".format(self.extra_info.kmem_cache_offset_name))\n                info(\"offsetof(kmem_cache, size): {:#x}\".format(self.extra_info.kmem_cache_offset_size))\n\n        # create option_info\n        option_info = KmallocTracerCommand.create_option_info(args)\n\n        # set breakpoints\n        breakpoints = KmallocTracerCommand.set_bp_to_kmalloc_kfree(option_info, self.extra_info)\n        if args.enable_page_allocator_trace:\n            breakpoints += KmallocTracerCommand.set_bp_to_alloc_free_pages(option_info, self.extra_info)\n        for bp in breakpoints:\n            bp.enabled = True\n\n        # doit\n        info(\"Setup is complete. continuing...\")\n        gdb.execute(\"continue\")\n\n        # clean up\n        info(\"kmalloc-tracer is complete, cleaning up...\")\n        for bp in breakpoints:\n            bp.delete()\n        KmallocTracerCommand.clear_disabled_breakpoints(\"KmallocRetBreakpoint\", force=True)\n        if args.enable_page_allocator_trace:\n            KmallocTracerCommand.clear_disabled_breakpoints(\"AllocPagesRetBreakpoint\", force=True)\n        return\n\n\nclass KmallocAllocatedBy_UserlandHardwareBreakpoint(gdb.Breakpoint):\n    \"\"\"Breakpoint to userland `sleep` process for KmallocAllocatedByCommand.\"\"\"\n\n    def __init__(self, loc):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_HARDWARE_BREAKPOINT, internal=False)\n        self.silent = True\n        return\n\n    def stop(self):\n        return True # stop\n\n\n@register_command\nclass KmallocAllocatedByCommand(GenericCommand):\n    \"\"\"Call predefined system-calls and print kmalloc-N chunks allocated and freed (x64 only).\"\"\"\n\n    _cmdline_ = \"kmalloc-allocated-by\"\n    _category_ = \"06-i. Qemu-system/KGDB Cooperation - Linux Dynamic Inspection\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", default=[], help=\"filter specified name (e.g., kmalloc-XX)\")\n    parser.add_argument(\"-N\", \"--print-null\", action=\"store_true\", help=\"display free(NULL).\")\n    parser.add_argument(\"-t\", \"--backtrace\", action=\"store_true\", help=\"display backtrace.\")\n    parser.add_argument(\"-d\", \"--dump-chunk\", action=\"store_true\", help=\"dump the first 0x40 bytes of each chunk.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"print meta information.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s}       # simple output\",\n        \"{0:s} -dtv  # useful output\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    _note_ = [\n        \"Disable `-enable-kvm` option for qemu-system (#PF may occur).\",\n        \"Disable `-smp N` option for qemu-system (write memory error may occur).\",\n        \"Append `tsc=unstable` option for kernel cmdline.\",\n        \"This command requires CONFIG_RANDSTRUCT=n.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    def setup_syscall(self, syscall_name, args):\n        gdb.execute(\"set $pc-={:#x}\".format(len(current_arch.syscall_insn)), to_string=True)\n        nr = self.syscall_table[syscall_name]\n        gdb.execute(\"set $rax={:#x}\".format(nr), to_string=True)\n        sp = current_arch.sp\n        for reg, arg in zip(current_arch.syscall_parameters, args):\n            if arg is None:\n                break\n            if isinstance(arg, str):\n                arg = String.str2bytes(arg)\n            if isinstance(arg, bytes):\n                write_memory(sp, arg)\n                gdb.execute(\"set {:s}={:#x}\".format(reg, sp), to_string=True)\n                sp = align(sp + len(arg), current_arch.ptrsize * 2)\n            else:\n                gdb.execute(\"set {:s}={:#x}\".format(reg, arg), to_string=True)\n        self.tested_syscall.add(syscall_name)\n        return\n\n    def dump_untested_syscall(self):\n        valid_syscall = []\n        for line in self.syscall_table_view_ret.splitlines():\n            tag, _, valid, name, *__ = Color.remove_color(line).split()\n            if tag != \"x86_64\":\n                continue\n            if valid != \"valid\":\n                continue\n            valid_syscall.append(name)\n\n        invalid_syscall = []\n        tested_syscall = []\n        untested_syscall = []\n        skipped_syscall = []\n        # sort by index and translate from set to list\n        for name, _nr in self.syscall_table.items():\n            if name not in valid_syscall:\n                invalid_syscall.append(name)\n            elif name in self.tested_syscall:\n                tested_syscall.append(name)\n            elif name in self.scheduled_syscall:\n                skipped_syscall.append(name)\n            elif name in self.skipped_syscall:\n                skipped_syscall.append(name)\n            else:\n                untested_syscall.append(name)\n\n        gef_print(titlify(\"Tested syscall\"))\n        gef_print(\", \".join(tested_syscall))\n\n        gef_print(titlify(\"Untested syscall\"))\n        gef_print(\", \".join(untested_syscall))\n\n        gef_print(titlify(\"Skipped syscall\"))\n        gef_print(\", \".join(skipped_syscall))\n\n        gef_print(titlify(\"Invalid (Unsupported) syscall\"))\n        gef_print(\", \".join(invalid_syscall))\n        return\n\n    def test_syscall(self, breakpoints):\n\n        def u2i(x):\n            x = struct.pack(\"<Q\", x & 0xffff_ffff_ffff_ffff)\n            return struct.unpack(\"<q\", x)[0]\n\n        def gen_testcase():\n            # It is implemented with a generator because\n            # it requires delayed execution in order to use the previous result.\n\n            nonlocal ret_history\n\n            yield \"msgget -> msgsnd -> msgrcv -> msgctl\"\n            yield (\"msqid = msgget(IPC_PRIVATE, IPC_CREAT|0666)\", \"msgget\", [0, 0o1000 | 0o666])\n            msgsize = 0x100\n            msg = p64(1) + b\"A\" * msgsize\n            if u2i(ret_history[-1]) >= 0:\n                msqid = ret_history[-1]\n                yield (\"msgsnd(msqid, &msg, msgsize, 0)\", \"msgsnd\", [msqid, msg, msgsize, 0])\n                yield (\"msgrcv(msqid, &msg, msgsize, 0, 0)\", \"msgrcv\", [msqid, msg, msgsize, 0, 0])\n                yield (\"msgctl(msqid, IPC_RMID, 0)\", \"msgctl\", [msqid, 0, 0])\n\n            yield \"shmget -> shmat -> shmdt -> shmctl\"\n            yield (\"shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT|0666)\", \"shmget\", [0, 0x400, 0o1000 | 0o666])\n            if u2i(ret_history[-1]) >= 0:\n                shmid = ret_history[-1]\n                yield (\"addr = shmat(shmid, NULL, 0)\", \"shmat\", [shmid, 0, 0])\n                addr = ret_history[-1]\n                yield (\"shmdt(addr)\", \"shmdt\", [addr])\n                yield (\"shmctl(shmid, IPC_RMID, 0)\", \"shmctl\", [shmid, 0, 0])\n\n            yield \"semget -> semop -> semctl\"\n            yield (\"semid = semget(IPC_PRIVATE, 1, IPC_CREAT|0666)\", \"semget\", [0, 1, 0o1000 | 0o666])\n            if u2i(ret_history[-1]) >= 0:\n                semid = ret_history[-1]\n                sembuf = p16(0)  # sem_num\n                sembuf += p16(2) # sem_op\n                sembuf += p16(0) # sem_flg\n                yield (\"semop(semid, &sembuf, 1)\", \"semop\", [semid, sembuf, 1])\n                self.skipped_syscall.add(\"semtimedop\")\n                yield (\"semctl(semid, 0, IPC_RMID)\", \"semctl\", [semid, 0, 0])\n\n            yield \"mq_open -> mq_timedsend -> mq_timedreceive -> mq_notify -> mq_getsetattr -> mq_unlink -> close\"\n            MQ_NAME = \"mq_test\\0\"\n            attr = p64(0o4000) # mq_flags: O_NONBLOCK\n            attr += p64(10)    # mq_maxmsg\n            attr += p64(0x100) # mq_msgsize\n            attr += p64(0)     # mq_curmsgs\n            attr += p64(0) * 4 # __reserved[4]\n            yield (\n                'fd = mq_open(\"mq_test\", O_RDWR|O_CREAT, 0700, &attr)',\n                \"mq_open\", [MQ_NAME, 0o2 | 0o100, 0o700, attr],\n            )\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                msg = \"A\" * 0x100\n                yield (\"mq_timedsend(fd, &msg, sizeof(msg), 0, NULL)\", \"mq_timedsend\", [fd, msg, len(msg), 0, 0])\n                buf = \"\\0\" * 0x100\n                prio = p32(0)\n                timeout = p64(0)  # tv_sec\n                timeout += p64(0) # tv_nsec\n                yield (\n                    \"mq_timedreceive(fd, &buf, sizeof(buf), &prio, &timeout)\",\n                    \"mq_timedreceive\", [fd, buf, len(buf), prio, timeout],\n                )\n                sigevent = p32(0)   # sigev_notify: SIGEV_SIGNAL\n                sigevent += p32(10) # sigev_signo: SIGUSR1\n                sigevent += p64(0)  # sigev_value\n                sigevent += p64(0)  # sigev_notify_function\n                sigevent += p64(0)  # sigev_notify_attributes\n                sigevent += p64(0)  # sigev_notify_thread_id\n                yield (\"mq_notify(fd, &sigevent)\", \"mq_notify\", [fd, sigevent])\n                attr = p64(0)      # mq_flags\n                attr += p64(0)     # mq_maxmsg\n                attr += p64(0)     # mq_msgsize\n                attr += p64(0)     # mq_curmsgs\n                attr += p64(0) * 4 # __reserved[4]\n                yield (\"mq_getsetattr(fd, NULL, &attr)\", \"mq_getsetattr\", [fd, 0, attr])\n                yield ('mq_unlink(\"mq_test\")', \"mq_unlink\", [MQ_NAME])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"signalfd4 -> close\"\n            mask = \"\\0\" * 8\n            yield (\"fd = signalfd4(-1, &mask, sizeof(mask), 0)\", \"signalfd4\", [-1, mask, len(mask), 0])\n            self.skipped_syscall.add(\"signalfd\")\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"setitimer -> getitimer\"\n            new_value = p64(0)  # it_interval.tv_sec\n            new_value += p64(0) # it_interval.tv_nsec\n            new_value += p64(0) # it_value.tv_sec\n            new_value += p64(0) # it_value.tv_nsec\n            old_value = p64(0)  # it_interval.tv_sec\n            old_value += p64(0) # it_interval.tv_nsec\n            old_value += p64(0) # it_value.tv_sec\n            old_value += p64(0) # it_value.tv_nsec\n            yield (\"setitimer(ITIMER_REAL, &new_value, &old_value)\", \"setitimer\", [0, new_value, old_value])\n            curr_value = p64(0)  # it_interval.tv_sec\n            curr_value += p64(0) # it_interval.tv_nsec\n            curr_value += p64(0) # it_value.tv_sec\n            curr_value += p64(0) # it_value.tv_nsec\n            yield (\"getitimer(ITIMER_REAL, &curr_value)\", \"getitimer\", [0, curr_value])\n\n            yield \"timerfd_create -> timerfd_settime -> timerfd_gettime -> close\"\n            yield (\"fd = timerfd_create(CLOCK_MONOTONIC, 0)\", \"timerfd_create\", [1, 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                new_value = p64(0)  # it_interval.tv_sec\n                new_value += p64(0) # it_interval.tv_nsec\n                new_value += p64(0) # it_value.tv_sec\n                new_value += p64(0) # it_value.tv_nsec\n                old_value = p64(0)  # it_interval.tv_sec\n                old_value += p64(0) # it_interval.tv_nsec\n                old_value += p64(0) # it_value.tv_sec\n                old_value += p64(0) # it_value.tv_nsec\n                yield (\n                    \"timerfd_settime(fd, 0, &new_value, &old_value)\",\n                    \"timerfd_settime\", [fd, 0, new_value, old_value],\n                )\n                curr_value = p64(0)  # it_interval.tv_sec\n                curr_value += p64(0) # it_interval.tv_nsec\n                curr_value += p64(0) # it_value.tv_sec\n                curr_value += p64(0) # it_value.tv_nsec\n                yield (\"timerfd_gettime(fd, &curr_value)\", \"timerfd_gettime\", [fd, curr_value])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"timer_create -> timer_settime -> timier_gettime -> timer_getoverrun -> timer_delete\"\n            timerid = p64(0)\n            yield (\"timer_create(CLOCK_MONOTONIC, NULL, &timerid)\", \"timer_create\", [1, 0, timerid])\n            if u2i(ret_history[-1]) == 0:\n                timerid = read_int_from_memory(current_arch.sp)\n                new_value = p64(0)  # it_interval.tv_sec\n                new_value += p64(0) # it_interval.tv_nsec\n                new_value += p64(0) # it_value.tv_sec\n                new_value += p64(0) # it_value.tv_nsec\n                old_value = p64(0)  # it_interval.tv_sec\n                old_value += p64(0) # it_interval.tv_nsec\n                old_value += p64(0) # it_value.tv_sec\n                old_value += p64(0) # it_value.tv_nsec\n                yield (\n                    \"timer_settime(timerid, 0, &new_value, &old_value)\",\n                    \"timer_settime\", [timerid, 0, new_value, old_value],\n                )\n                curr_value = p64(0)  # it_interval.tv_sec\n                curr_value += p64(0) # it_interval.tv_nsec\n                curr_value += p64(0) # it_value.tv_sec\n                curr_value += p64(0) # it_value.tv_nsec\n                yield (\"timer_gettime(timerid, &curr_value)\", \"timer_gettime\", [timerid, curr_value])\n                yield (\"timer_getoverrun(timerid)\", \"timer_getoverrun\", [timerid])\n                yield (\"timer_delete(timerid)\", \"timer_delete\", [timerid])\n\n            yield \"epoll_create1 -> epoll_ctl -> epoll_wait -> close\"\n            yield (\"epfd = epoll_create1(0)\", \"epoll_create1\", [0])\n            self.skipped_syscall.add(\"epoll_create\")\n            if u2i(ret_history[-1]) >= 0:\n                epfd = ret_history[-1]\n                event = p32(1)  # events: EPOLLIN\n                event += p64(0) # data\n                yield (\"epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event)\", \"epoll_ctl\", [epfd, 1, 0, event])\n                yield (\"epoll_wait(epfd, &events, 1, 0)\", \"epoll_wait\", [epfd, event, 1, 0])\n                self.skipped_syscall.add(\"epoll_pwait\")\n                self.skipped_syscall.add(\"epoll_pwait2\")\n                yield (\"close(epfd)\", \"close\", [epfd])\n\n            yield \"eventfd2 -> close\"\n            yield (\"fd = eventfd2(0, 0)\", \"eventfd2\", [0, 0])\n            self.skipped_syscall.add(\"eventfd\")\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"perf_event_open (need kernel.perf_event_paranoid <= 2) -> close\"\n            attr = p32(1)      # type: PERF_TYPE_SOFTWARE\n            attr += p32(0x80)  # size: sizeof(attr)\n            attr += p64(9)     # config: PERF_COUNT_SW_DUMMY\n            attr += p64(0)     # sample_period or sample_freq\n            attr += p64(0)     # sample_type\n            attr += p64(0)     # read_format\n            flags = 1 << 5     # execlude_kernel=1\n            flags |= 1 << 6    # execlude_hv=1\n            flags |= 1 << 8    # mmap=1\n            flags |= 1 << 17   # mmap_data=1\n            attr += p64(flags) # flags\n            attr += p32(0)     # wakeup_events or wakeup_watermalk\n            attr += p32(0)     # bp_type\n            attr += p64(0)     # bp_addr or kprobe_func or uprobe_path or config1\n            attr += p64(0)     # bp_len or kprobe_addr or probe_offset or config2\n            attr += p64(0)     # branch_sample_type\n            attr += p64(0)     # sample_regs_user\n            attr += p32(0)     # sample_stack_user\n            attr += p32(0)     # clockid\n            attr += p64(0)     # sample_regs_intr\n            attr += p32(0)     # aux_watermark\n            attr += p16(0)     # sample_max_stack\n            attr += p16(0)     # __reserved_2\n            attr += p32(0)     # aux_sample_size\n            attr += p32(0)     # __reserved_3\n            attr += p64(0)     # sig_data\n            attr += p64(0)     # config3\n            yield (\"fd = perf_event_open(&attr, 0, -1, -1, 0)\", \"perf_event_open\", [attr, 0, -1, -1, 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"bpf (need kernel.unprivileged_bpf_disabled == 0) -> close\"\n            attr = p32(2)     # map_type: BPF_MAP_TYPE_ARRAY\n            attr += p32(4)    # key_size\n            attr += p32(0x10) # value_size\n            attr += p32(0x10) # max_entries\n            yield (\"bpf(BPF_MAP_CREATE, &attr, sizeof(attr))\", \"bpf\", [0, attr, len(attr)])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"mmap -> mprotect -> mremap -> msync -> madvise -> munmap\"\n            size = get_pagesize()\n            yield (\n                \"addr = mmap(NULL, 0x1000, RWX, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)\",\n                \"mmap\", [0, size, 7, 0x20 | 0x2, -1, 0],\n            )\n            if u2i(ret_history[-1]) >= 0:\n                addr = ret_history[-1]\n                yield (\"mprotect(addr, 0x1000, R--)\", \"mprotect\", [addr, size, 1])\n                size2 = size * 2\n                yield (\"addr2 = mremap(addr, 0x1000, 0x2000, MREMAP_MAYMOVE)\", \"mremap\", [addr, size, size2, 1])\n                if u2i(ret_history[-1]) >= 0:\n                    addr2 = ret_history[-1]\n                    yield (\"msync(addr2, 0x2000, MS_SYNC)\", \"msync\", [addr2, size2, 4])\n                    yield (\"madvise(addr2, 0x2000, MADV_DONTNEED)\", \"madvise\", [addr2, size2, 4])\n                    self.skipped_syscall.add(\"process_madvise\")\n                    yield (\"munmap(addr2, 0x2000)\", \"munmap\", [addr2, size2])\n\n            yield \"mmap -> mincore -> mbind -> move_pages -> migrate_pages -> munmap\"\n            size = get_pagesize()\n            yield (\n                \"addr = mmap(NULL, 0x1000, RWX, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)\",\n                \"mmap\", [0, size, 7, 0x20 | 0x2, -1, 0],\n            )\n            if u2i(ret_history[-1]) >= 0:\n                addr = ret_history[-1]\n                vec = \"\\0\" * 0x100\n                yield (\"mincore(addr, 0x1000, &vec)\", \"mincore\", [addr, size, vec])\n                yield (\"mbind(addr, 0x1000, MPOL_DEFAULT, NULL, 0, 0)\", \"mbind\", [addr, size, 0, 0, 0, 0])\n                pages = p64(addr)\n                status = p64(0)\n                yield (\"move_pages(0, 1, &pages, NULL, &status, 0)\", \"move_pages\", [0, 1, pages, 0, status, 0])\n                maxnode = 8\n                old_nodes = \"\\x02\"\n                new_nodes = \"\\x01\"\n                yield (\n                    \"migrate_pages(0, 8, old_nodes, new_nodes)\",\n                    \"migrate_pages\", [0, maxnode, old_nodes, new_nodes],\n                )\n                yield (\"munmap(addr, 0x1000)\", \"munmap\", [addr, size])\n\n            yield \"brk -> userfaultfd -> ioctl -> close\"\n            yield (\"addr = brk(0)\", \"brk\", [0])\n            last_page = ret_history[-1] - get_pagesize()\n            yield (\"fd = userfaultfd(O_CLOEXEC|O_NONBLOCK)\", \"userfaultfd\", [0o2000000 | 0o4000])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                uffdio_api = p64(0xaa) # api: UFFD_API\n                uffdio_api += p64(0)   # features\n                uffdio_api += p64(0)   # ioctls\n                yield (\"ioctl(fd, UFFDIO_API, &uffdio_api)\", \"ioctl\", [fd, 0xc018aa3f, uffdio_api])\n                uffdio_register = p64(last_page)          # range.start\n                uffdio_register += p64(get_pagesize()) # range.len\n                uffdio_register += p64(1)                 # mode: UFFDIO_REGISTER_MODE_MISSING\n                uffdio_register += p64(0)                 # ioctls\n                yield (\"ioctl(fd, UFFDIO_REGISTER, &uffdio_register)\", \"ioctl\", [fd, 0xc020aa00, uffdio_register])\n                yield (\"ioctl(fd, UFFDIO_UNREGISTER, &uffdio_register)\", \"ioctl\", [fd, 0x8010aa01, uffdio_register])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"mlockall -> munlockall\"\n            yield (\"mlockall(MCL_CURRENT)\", \"mlockall\", [1])\n            self.skipped_syscall.add(\"mlock\")\n            self.skipped_syscall.add(\"mlock2\")\n            yield (\"munlockall()\", \"munlockall\", [])\n            self.skipped_syscall.add(\"munlock\")\n\n            yield \"get_robust_list -> set_robust_list\"\n            head_ptr = p64(0)\n            len_ptr = p64(0)\n            yield (\"get_robust_list(0, &head_ptr, &len_ptr)\", \"get_robust_list\", [0, head_ptr, len_ptr])\n            if u2i(ret_history[-1]) >= 0:\n                head = read_int_from_memory(current_arch.sp)\n                len_ = read_int_from_memory(current_arch.sp + 0x10)\n                yield (\"set_robust_list(head, len)\", \"set_robust_list\", [head, len_])\n\n            yield \"prctl -> arch_prctl -> set_tid_address\"\n            buf = p32(0)\n            yield (\"prctl(PR_GET_PDEATHSIG, &buf)\", \"prctl\", [2, buf])\n            yield (\"prctl(PR_GET_DUMPABLE)\", \"prctl\", [3])\n            yield (\"prctl(PR_GET_KEEPCAPS)\", \"prctl\", [7])\n            yield (\"prctl(PR_GET_TIMING)\", \"prctl\", [13])\n            buf = \"\\0\" * 16\n            yield (\"prctl(PR_GET_NAME, &buf)\", \"prctl\", [16, buf])\n            yield (\"prctl(PR_GET_SECCOMP)\", \"prctl\", [21])\n            yield (\"prctl(PR_CAPBSET_READ, CAP_CHOWN)\", \"prctl\", [23, 0])\n            buf = p32(0)\n            yield (\"prctl(PR_GET_TSC, &buf)\", \"prctl\", [25, buf])\n            yield (\"prctl(PR_GET_SECUREBITS)\", \"prctl\", [27])\n            yield (\"prctl(PR_GET_TIMERSLACK)\", \"prctl\", [30])\n            yield (\"prctl(PR_TASK_PERF_EVENTS_DISABLE)\", \"prctl\", [31])\n            yield (\"prctl(PR_MCE_KILL_GET, 0, 0, 0, 0)\", \"prctl\", [34, 0, 0, 0, 0])\n            buf = p32(0)\n            yield (\"prctl(PR_GET_CHILD_SUBREAPER, &buf)\", \"prctl\", [37, buf])\n            yield (\"prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0)\", \"prctl\", [39, 0, 0, 0, 0])\n            yield (\"prctl(PR_GET_TID_ADDRESS)\", \"prctl\", [40, buf])\n            yield (\"prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0)\", \"prctl\", [42, 0, 0, 0, 0])\n            yield (\"arch_prctl(ARCH_GET_CPUID)\", \"arch_prctl\", [0x1011])\n            buf = p64(0)\n            yield (\"arch_prctl(ARCH_GET_GS, &buf)\", \"arch_prctl\", [0x1001, buf])\n            buf = p64(0)\n            yield (\"arch_prctl(ARCH_GET_FS, &buf)\", \"arch_prctl\", [0x1003, buf])\n            fsbase = ret_history[-1]\n            yield (\"set_tid_address(fsbase)\", \"set_tid_address\", [fsbase])\n\n            yield \"futex\"\n            uaddr = p64(0)\n            yield (\"futex(&uaddr, FUTEX_WAKE, 1, &timeout, 0, 0)\", \"futex\", [uaddr, 1, 1, 0, 0, 0])\n\n            yield \"time\"\n            yield (\"time(NULL)\", \"time\", [0])\n\n            yield \"times\"\n            buf = p64(0)  # tms_utime\n            buf += p64(0) # tms_stime\n            buf += p64(0) # tms_cutime\n            buf += p64(0) # tms_cstime\n            yield (\"times(&buf)\", \"times\", [buf])\n\n            yield \"gettimeofday\"\n            tv = p64(0)  # tv_sec\n            tv += p64(0) # tv_usec\n            tz = p32(0)  # tz_minuteswest\n            tz += p32(0) # tz_dsttime\n            yield (\"gettimeofday(&tv, &tz)\", \"gettimeofday\", [tv, tz])\n\n            yield \"nanosleep\"\n            req = p64(0)     # tv_sec\n            req += p64(1000) # tv_nsec\n            rem = p64(0)     # tv_sec\n            rem += p64(0)    # tv_nsec\n            yield (\"nanosleep(&req, &rem)\", \"nanosleep\", [req, rem])\n            self.skipped_syscall.add(\"clock_nanosleep\")\n\n            yield \"clock_getres -> clock_gettime\"\n            res = p64(0)  # tv_sec\n            res += p64(0) # tv_nsec\n            yield (\"clock_getres(CLOCK_PROCESS_CPUTIME_ID, &res)\", \"clock_getres\", [2, res])\n            tp = p64(0)  # tv_sec\n            tp += p64(0) # tv_nsec\n            yield (\"clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp)\", \"clock_gettime\", [2, tp])\n\n            yield \"adjtimex\"\n            buf = p64(0)  # modes\n            buf += p64(0) # offset\n            buf += p64(0) # freq\n            buf += p64(0) # maxerror\n            buf += p64(0) # esterror\n            buf += p64(0) # status\n            buf += p64(0) # constant\n            buf += p64(0) # precision\n            buf += p64(0) # tolerance\n            buf += p64(0) # time.tv_sec\n            buf += p64(0) # time.tv_usec\n            buf += p64(0) # tick\n            buf += p64(0) # ppsfreq\n            buf += p64(0) # jitter\n            buf += p64(0) # shift\n            buf += p64(0) # stabil\n            buf += p64(0) # jitcnt\n            buf += p64(0) # calcnt\n            buf += p64(0) # errcnt\n            buf += p64(0) # stbcnt\n            buf += p64(0) # tai\n            yield (\"adjtimex(&buf)\", \"adjtimex\", [buf])\n            self.skipped_syscall.add(\"clock_adjtime\")\n\n            yield \"membarrier\"\n            yield (\"membarrier(MEMBARRIER_CMD_QUERY, 0, 0)\", \"membarrier\", [0, 0, 0])\n\n            yield \"getcwd\"\n            buf = \"\\0\" * 0x100\n            yield (\"getcwd(&buf, sizeof(buf))\", \"getcwd\", [buf, len(buf)])\n\n            yield \"uname\"\n            buf = \"\\0\" * 0x400\n            yield (\"uname(&buf)\", \"uname\", [buf])\n\n            yield \"getrandom\"\n            buf = \"\\0\" * 0x100\n            yield (\"getrandom(&buf, sizeof(buf), 0)\", \"getrandom\", [buf, len(buf), 0])\n\n            yield \"getrlimit -> setrlimit\"\n            rlim = p64(0)  # rlim_cur\n            rlim += p64(0) # rlim_max\n            yield (\"getrlimit(RLIMIT_STACK, &rlim, sizeof(rlim))\", \"getrlimit\", [3, rlim, len(rlim)])\n            rlim = read_memory(current_arch.sp, 16)\n            yield (\"setrlimit(RLIMIT_STACK, &rlim, sizeof(rlim))\", \"setrlimit\", [3, rlim, len(rlim)])\n            self.skipped_syscall.add(\"prlimit64\")\n\n            yield \"sched_yield\"\n            yield (\"sched_yield()\", \"sched_yield\", [])\n\n            yield \"sched_getscheduler -> sched_setscheduler\"\n            yield (\"sched_getscheduler(0)\", \"sched_getscheduler\", [0])\n            param = p32(0)\n            yield (\"sched_setscheduler(0, SCHED_OTHER, &param)\", \"sched_setscheduler\", [0, 0, param])\n\n            yield \"sched_getparam -> sched_setparam\"\n            param = p32(0)\n            yield (\"sched_getparam(0, &param)\", \"sched_getparam\", [0, param])\n            yield (\"sched_setparam(0, &param)\", \"sched_setparam\", [0, param])\n\n            yield \"sched_getaffinity -> sched_setaffinity\"\n            mask = \"\\0\" * 0x80\n            yield (\"sched_getaffinity(0, sizeof(mask), &mask)\", \"sched_getaffinity\", [0, len(mask), mask])\n            mask = read_memory(current_arch.sp, 0x80)\n            yield (\"sched_setaffinity(0, sizeof(mask), &mask)\", \"sched_setaffinity\", [0, len(mask), mask])\n\n            yield \"sched_get_priority_max -> sched_get_priority_min\"\n            yield (\"sched_get_priority_max(SCHED_OTHER)\", \"sched_get_priority_max\", [0])\n            yield (\"sched_get_priority_min(SCHED_OTHER)\", \"sched_get_priority_min\", [0])\n\n            yield \"sched_rr_get_interval\"\n            tp = p64(0)  # tv_sec\n            tp += p64(0) # tv_nsec\n            yield (\"sched_rr_get_interval(0, &tp)\", \"sched_rr_get_interval\", [0, tp])\n\n            yield \"sched_getattr -> sched_setattr\"\n            attr = p32(8 * 6) # size\n            attr += p32(0) # sched_policy: SCHED_OTHER\n            attr += p64(0) # sched_flags\n            attr += p32(0) # sched_nice\n            attr += p32(0) # sched_priority\n            attr += p64(0) # sched_runtime\n            attr += p64(0) # sched_deadline\n            attr += p64(0) # sched_period\n            yield (\"sched_getattr(0, &attr, sizeof(attr), 0)\", \"sched_getattr\", [0, attr, len(attr), 0])\n            # sched_setattr must be called before setpriority, or failed.\n            yield (\"sched_setattr(0, &attr, 0)\", \"sched_setattr\", [0, attr, 0])\n\n            yield \"getpriority -> setpriority\"\n            yield (\"getpriority(PRIO_PROCESS, 0)\", \"getpriority\", [0, 0])\n            yield (\"setpriority(PRIO_PROCESS, 0, 1)\", \"setpriority\", [0, 0, 1])\n\n            yield \"ioprio_get -> ioprio_set\"\n            yield (\"ioprio_get(IOPRIO_WHO_PROCESS, 0)\", \"ioprio_get\", [1, 0])\n            yield (\"ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(2, 0))\", \"ioprio_set\", [1, 0, 0x4000])\n\n            yield \"getrusage\"\n            buf = p64(0)  # ru_utime.tv_sec\n            buf += p64(0) # ru_utime.tv_usec\n            buf += p64(0) # ru_stime.tv_sec\n            buf += p64(0) # ru_stime.tv_usec\n            buf += p64(0) # ru_maxrss\n            buf += p64(0) # ru_ixrss\n            buf += p64(0) # ru_idrss\n            buf += p64(0) # ru_isrss\n            buf += p64(0) # ru_minflt\n            buf += p64(0) # ru_majflt\n            buf += p64(0) # ru_nswap\n            buf += p64(0) # ru_inblock\n            buf += p64(0) # ru_oublock\n            buf += p64(0) # ru_msgsnd\n            buf += p64(0) # ru_msgrcv\n            buf += p64(0) # ru_nsignals\n            buf += p64(0) # ru_nvcsw\n            buf += p64(0) # ru_nivcsw\n            yield (\"getrusage(RUSAGE_SELF, &buf)\", \"getrusage\", [0, buf])\n\n            yield \"personality\"\n            yield (\"personality(0xffffffff)\", \"personality\", [0xffff_ffff])\n\n            yield \"get_mempolicy -> set_mempolicy\"\n            nodemask = p64(0)\n            yield (\"get_mempolicy(0, &nodemask, 8, 0, MPOL_F_MEMS_ALLOWED)\", \"get_mempolicy\", [0, nodemask, 8, 0, 4])\n            yield (\"set_mempolicy(MPOL_DEFAULT, NULL, 8)\", \"set_mempolicy\", [0, 0, 8])\n\n            yield \"getcpu\"\n            cpu = p32(0)\n            node = p32(0)\n            yield (\"getcpu(&cpu, &node, NULL)\", \"getcpu\", [cpu, node, 0])\n\n            yield \"sysinfo\"\n            buf = p64(0)      # uptime\n            buf += p64(0) * 3 # loads[3]\n            buf += p64(0)     # totalram\n            buf += p64(0)     # freeram\n            buf += p64(0)     # sharedram\n            buf += p64(0)     # bufferram\n            buf += p64(0)     # totalswap\n            buf += p64(0)     # freeswap\n            buf += p16(0)     # procs\n            buf += p8(0) * 22 # padding\n            yield (\"sysinfo(&buf)\", \"sysinfo\", [buf])\n\n            yield \"sysfs\"\n            buf = \"\\0\" * 0x100\n            yield (\"sysfs(2, 0, &buf)\", \"sysfs\", [2, 0, buf])\n\n            yield \"sigaltstack\"\n            oss = p64(0)  # ss_sp\n            oss += p32(0) # ss_flags\n            oss += p32(0) # padding\n            oss += p64(0) # ss_size\n            yield (\"sigaltstack(NULL, &oss)\", \"sigaltstack\", [0, oss])\n\n            yield \"rt_sigprocmask -> rt_sigpending\"\n            oldset = \"\\0\" * 0x100\n            sigsetsize = 8\n            yield (\"rt_sigprocmask(0, NULL, &oldset, sigsetsize)\", \"rt_sigprocmask\", [0, 0, oldset, sigsetsize])\n            set_ = \"\\0\" * 0x100\n            yield (\"rt_sigpending(&set)\", \"rt_sigpending\", [set_])\n\n            yield \"getpid -> getppid -> getsid -> gettid -> getpgid -> setpgid -> getpgrp -> kcmp\"\n            yield (\"pid = getpid()\", \"getpid\", [])\n            pid = ret_history[-1]\n            yield (\"getppid()\", \"getppid\", [])\n            yield (\"getsid(pid)\", \"getsid\", [pid])\n            yield (\"gettid()\", \"gettid\", [])\n            tid = ret_history[-1]\n            yield (\"pgid = getpgid(pid)\", \"getpgid\", [pid])\n            pgid = ret_history[-1]\n            yield (\"setpgid(pid, pgid)\", \"setpgid\", [pid, pgid])\n            yield (\"getpgrp()\", \"getpgrp\", [])\n            yield (\"kcmp(pid, pid, KCMP_FS, 0, 0)\", \"kcmp\", [pid, pid, 3, 0, 0])\n\n            yield \"getuid -> setuid -> setreuid -> setfsuid -> geteuid -> getresuid -> setresuid\"\n            yield (\"uid = getuid()\", \"getuid\", [])\n            uid = ret_history[-1]\n            yield (\"setuid(uid)\", \"setuid\", [uid])\n            yield (\"setreuid(uid, uid)\", \"setreuid\", [uid, uid])\n            yield (\"setfsuid(uid)\", \"setfsuid\", [uid])\n            yield (\"geteuid()\", \"geteuid\", [])\n            ruid = euid = suid = p32(0)\n            yield (\"getresuid(&ruid, &euid, &suid)\", \"getresuid\", [ruid, euid, suid])\n            yield (\"setresuid(uid, uid, uid)\", \"setresuid\", [uid, uid, uid])\n\n            yield \"getgid -> setgid -> setregid -> setfsgid -> getegid -> getresgid -> setresgid -> getgroups\"\n            yield (\"gid = getgid()\", \"getgid\", [])\n            gid = ret_history[-1]\n            yield (\"setgid(gid)\", \"setgid\", [gid])\n            yield (\"setregid(gid, gid)\", \"setregid\", [gid, gid])\n            yield (\"setfsgid(uid)\", \"setfsgid\", [gid])\n            yield (\"getegid()\", \"getegid\", [])\n            rgid = egid = sgid = p32(0)\n            yield (\"getresgid(&rgid, &egid, &sgid)\", \"getresgid\", [rgid, egid, sgid])\n            yield (\"setresgid(gid, gid, gid)\", \"setresgid\", [gid, gid, gid])\n            yield (\"getgroups(0, NULL)\", \"getgroups\", [0, 0])\n\n            yield \"rt_sigaction -> alarm -> kill -> tkill -> rt_sigtimedwait\"\n            act = p64(1)    # sa_handler: SIG_IGN\n            act += p64(0)   # sa_flags\n            act += p64(0)   # sa_restorer\n            act += p64(0xe) # sa_mask: SIGALRM\n            oldact = p64(0)  # sa_handler\n            oldact += p64(0) # sa_flags\n            oldact += p64(0) # sa_restorer\n            oldact += p64(0) # sa_mask: SIGALRM\n            sigsetsize = 8\n            yield (\"rt_sigaction(SIGALRM, &act, &oldact, sigsetsize)\", \"rt_sigaction\", [14, act, oldact, sigsetsize])\n            yield (\"alarm(1000)\", \"alarm\", [1000])\n            yield (\"kill(pid, SIGALRM)\", \"kill\", [pid, 14])\n            yield (\"tkill(tid, SIGALRM)\", \"kill\", [tid, 14])\n            self.skipped_syscall.add(\"tgkill\")\n            self.skipped_syscall.add(\"rt_sigqueueinfo\")\n            self.skipped_syscall.add(\"rt_tgsigqueueinfo\")\n            set_ = \"\\0\" * 0x100\n            info = p32(0)  # si_signo\n            info += p32(0) # si_code\n            info += p64(0) # si_value\n            info += p32(0) # si_errno\n            info += p32(0) # si_pid\n            info += p32(0) # si_uid\n            info += p32(0) # padding\n            info += p64(0) # si_addr\n            info += p32(0) # si_status\n            info += p32(0) # si_band\n            timeout = p64(0)  # tv_sec\n            timeout += p64(0) # tv_nsec\n            sigsetsize = 8\n            yield (\n                \"rt_sigtimedwait(&set, &info, &timeout, sigsetsize)\",\n                \"rt_sigtimedwait\", [set_, info, timeout, sigsetsize],\n            )\n\n            yield \"pidfd_open -> pidfd_getfd -> pidfd_send_signal -> close\"\n            yield (\"pfdfd = pidfd_open(pid, 0)\", \"pidfd_open\", [pid, 0])\n            if u2i(ret_history[-1]) >= 0:\n                pidfd = ret_history[-1]\n                yield (\"fd = pidfd_getfd(pidfd, STDIN_FILENO, 0)\", \"pidfd_getfd\", [pidfd, 0, 0])\n                if u2i(ret_history[-1]) >= 0:\n                    fd = ret_history[-1]\n                    yield (\"close(fd)\", \"close\", [fd])\n                yield (\"pidfd_send_signal(pidfd, SIGALRM, NULL, 0)\", \"pidfd_send_signal\", [pidfd, 14, 0, 0])\n                yield (\"close(pidfd)\", \"close\", [pidfd])\n\n            yield \"capget -> capset\"\n            hdrp = p32(0x20080522) # version\n            hdrp += p32(pid)       # pid\n            datap = p32(0)  # effective\n            datap += p32(0) # permitted\n            datap += p32(0) # inheritable\n            yield (\"capget(&hdrp, &datap)\", \"capget\", [hdrp, datap])\n            datap = read_memory(current_arch.sp + 0x10, 4 * 3)\n            yield (\"capset(&hdrp, &datap)\", \"capset\", [hdrp, datap])\n\n            yield \"umask\"\n            yield (\"umask(022)\", \"umask\", [0o022])\n\n            yield \"open -> fallocate -> write -> fdatasync -> fsync -> syncfs -> fadvise64 -> close\"\n            TMP_XXX = \"/tmp/xxx\\0\"\n            yield ('fd = open(\"/tmp/xxx\", 0_WRONLY|O_CREAT, 0666)', \"open\", [TMP_XXX, 0o1 | 0o100, 0o666])\n            self.skipped_syscall.add(\"creat\")\n            self.skipped_syscall.add(\"openat\")\n            self.skipped_syscall.add(\"openat2\")\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"fallocate(fd, 0, 0, 0x100)\", \"fallocate\", [fd, 0, 0, 0x100])\n                buf = \"A\" * 4\n                yield ('write(fd, \"AAAA\", 4)', \"write\", [fd, buf, len(buf)])\n                self.skipped_syscall.add(\"writev\")\n                self.skipped_syscall.add(\"pwrite64\")\n                self.skipped_syscall.add(\"pwritev\")\n                self.skipped_syscall.add(\"pwritev2\")\n                self.skipped_syscall.add(\"process_vm_writev\")\n                yield (\"fdatasync(fd)\", \"fdatasync\", [fd])\n                yield (\"fsync(fd)\", \"fsync\", [fd])\n                yield (\"syncfs(fd)\", \"syncfs\", [fd])\n                self.skipped_syscall.add(\"sync\")\n                yield (\"fadvise64(fd, 0, 0x100, POSIX_FADV_DONTNEED)\", \"fadvise64\", [fd, 0, 0x100, 4])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"open -> flock -> lseek -> readahead -> poll -> read -> dup -> close_range\"\n            yield ('fd = open(\"/tmp/xxx\", 0_RDONLY)', \"open\", [TMP_XXX, 0o0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"flock(fd, LOCK_SH|LOCK_NB)\", \"flock\", [fd, 1 | 4])\n                yield (\"lseek(fd, SEEK_SET, 0)\", \"lseek\", [fd, 0, 0])\n                yield (\"readahead(fd, 0, 0x1000)\", \"readahead\", [fd, 0, 0x1000])\n                fds = p32(fd) # fd\n                fds += p16(0) # events\n                fds += p16(0) # revents\n                yield (\"poll(&fds, 1, 0)\", \"poll\", [fds, 1, 0])\n                self.skipped_syscall.add(\"ppoll\")\n                buf = \"\\0\" * 4\n                yield (\"read(fd, &buf, 4)\", \"read\", [fd, buf, len(buf)])\n                self.skipped_syscall.add(\"readv\")\n                self.skipped_syscall.add(\"pread64\")\n                self.skipped_syscall.add(\"preadv\")\n                self.skipped_syscall.add(\"preadv2\")\n                self.skipped_syscall.add(\"process_vm_readv\")\n                yield (\"fd2 = dup(fd)\", \"dup\", [fd])\n                self.skipped_syscall.add(\"dup2\")\n                self.skipped_syscall.add(\"dup3\")\n                fd2 = ret_history[-1]\n                yield (\"close_range(fd, fd2, 0)\", \"close_range\", [fd, fd2, 0])\n\n            yield \"open -> mmap -> remap_file_pages -> munmap -> close\"\n            yield ('fd = open(\"/tmp/xxx\", 0_RDONLY)', \"open\", [TMP_XXX, 0o0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                size = get_pagesize()\n                yield (\n                    \"addr = mmap(NULL, 0x1000, R--, MAP_ANONYMOUS|MAP_SHARED, -1, 0)\",\n                    \"mmap\", [0, size, 1, 0x20 | 0x1, fd, 0],\n                )\n                if u2i(ret_history[-1]) >= 0:\n                    addr = ret_history[-1]\n                    yield (\"remap_file_pages(addr, 0x1000, 0, 0, 0)\", \"remap_file_pages\", [addr, size, 0, 0, 0])\n                    yield (\"munmap(addr, 0x1000)\", \"munmap\", [addr, size])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"chmod -> chown\"\n            yield ('chmod(\"/tmp/xxx\", 0o664)', \"chmod\", [TMP_XXX, 0o664])\n            self.skipped_syscall.add(\"fchmod\")\n            self.skipped_syscall.add(\"fchmodat\")\n            yield ('chown(\"/tmp/xxx\", -1, -1)', \"chown\", [TMP_XXX, -1, -1])\n            self.skipped_syscall.add(\"fchown\")\n            self.skipped_syscall.add(\"lchown\")\n            self.skipped_syscall.add(\"fchownat\")\n\n            yield \"open -> pipe -> sendfile -> splice -> select -> vmsplice -> close_range -> close\"\n            yield ('fd = open(\"/tmp/xxx\", 0_RDONLY)', \"open\", [TMP_XXX, 0o0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                pipefd_array = p32(0) * 2 # pipefd[2]\n                yield (\"pipe(&pipefd[])\", \"pipe\", [pipefd_array])\n                self.skipped_syscall.add(\"pipe2\")\n                if u2i(ret_history[-1]) >= 0:\n                    pipefd0 = read_int32_from_memory(current_arch.sp)\n                    pipefd1 = read_int32_from_memory(current_arch.sp + 4)\n                    offset = p64(0)\n                    yield (\"sendfile(pipefd[1], fd, &offset, 4)\", \"sendfile\", [pipefd1, fd, offset, 4])\n                    off_in = p64(0)\n                    yield (\"splice(fd, &off_in, pipefd[1], NULL, 4, 0)\", \"splice\", [fd, off_in, pipefd1, 0, 4, 0])\n                    readfds = [0] * 1024\n                    readfds[pipefd0] = 1\n                    readfds = slicer(\"\".join([str(x) for x in readfds]), 64)\n                    readfds = b\"\".join([p64(int(x[::-1], 2)) for x in readfds])\n                    nfds = pipefd0 + 1\n                    yield (\"select(nfds, readfds, NULL, NULL, NULL)\", \"select\", [nfds, readfds, 0, 0, 0])\n                    self.skipped_syscall.add(\"pselect6\")\n                    iov = p64(current_arch.sp + 0x10) # iov_base\n                    iov += p64(0x100)                 # iov_len\n                    yield (\"vmsplice(pipefd[0], &iov, 1, 0)\", \"vmsplice\", [pipefd0, iov, 1, 0])\n                    yield (\"close_range(pipefd[0], pipefd[1], 0)\", \"close_range\", [pipefd0, pipefd1, 0])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"pipe -> pipe -> tee -> close_range\"\n            pipefd_array = p32(0) * 2 # pipefd[2]\n            yield (\"pipe(&pipefd[])\", \"pipe\", [pipefd_array])\n            pipefd0 = read_int32_from_memory(current_arch.sp)\n            _pipefd1 = read_int32_from_memory(current_arch.sp + 4)\n            yield (\"pipe(&pipefd[])\", \"pipe\", [pipefd_array])\n            _pipefd2 = read_int32_from_memory(current_arch.sp)\n            pipefd3 = read_int32_from_memory(current_arch.sp + 4)\n            yield (\"tee(pipefd[0], pipefd[3], 0\", \"tee\", [pipefd0, pipefd3])\n            yield (\"close_range(pipefd[0], pipefd[3], 0)\", \"close_range\", [pipefd0, pipefd3, 0])\n\n            yield \"mknod -> unlink\"\n            TMP_PIPE = \"/tmp/pipe\\0\"\n            yield ('mknod(\"/tmp/pipe\", S_IFIFO|0644, 0)', \"mknod\", [TMP_PIPE, 0o10000 | 0o644, 0])\n            self.skipped_syscall.add(\"mknodat\")\n            if u2i(ret_history[-1]) >= 0:\n                yield ('unlink(\"/tmp/pipe\")', \"unlink\", [TMP_PIPE])\n\n            yield \"open -> sync_file_range -> copy_file_range -> close -> unlink -> close\"\n            TMP_XXX2 = \"/tmp/xxx2\\0\"\n            yield ('fd_in = open(\"/tmp/xxx\", 0_RDONLY)', \"open\", [TMP_XXX, 0o0])\n            if u2i(ret_history[-1]) >= 0:\n                fd_in = ret_history[-1]\n                yield ('fd_out = open(\"/tmp/xxx2\", 0_WRONLY|O_CREAT, 0666)', \"open\", [TMP_XXX2, 0o1 | 0o100, 0o666])\n                if u2i(ret_history[-1]) >= 0:\n                    fd_out = ret_history[-1]\n                    yield (\n                        \"sync_file_range(fd_out, 0, 4, SYNC_FILE_RANGE_WAIT_AFTER)\",\n                        \"sync_file_range\", [fd_out, 0, 4, 4],\n                    )\n                    yield (\n                        \"copy_file_range(fd_in, 0, fd_out, 0, 4, 0)\",\n                        \"copy_file_range\", [fd_in, 0, fd_out, 0, 4, 0],\n                    )\n                    yield (\"close(fd_out)\", \"close\", [fd_out])\n                    yield ('unlink(\"/tmp/xxx2\")', \"unlink\", [TMP_XXX2])\n                yield (\"close(fd_in)\", \"close\", [fd_in])\n\n            yield \"access -> utime -> stat -> statx -> truncate\"\n            yield ('access(\"/tmp/xxx\", F_OK)', \"access\", [TMP_XXX, 0])\n            self.skipped_syscall.add(\"faccessat\")\n            self.skipped_syscall.add(\"faccessat2\")\n            if u2i(ret_history[-1]) >= 0:\n                yield ('utime(\"/tmp/xxx\", NULL)', \"utime\", [TMP_XXX, 0])\n                self.skipped_syscall.add(\"utimes\")\n                self.skipped_syscall.add(\"futimesat\")\n                self.skipped_syscall.add(\"utimensat\")\n                buf = p64(0)      # st_dev\n                buf += p64(0)     # st_ino\n                buf += p64(0)     # st_nlink\n                buf += p32(0)     # st_mode\n                buf += p32(0)     # st_uid\n                buf += p32(0)     # st_gid\n                buf += p32(0)     # __pad0\n                buf += p64(0)     # st_rdev\n                buf += p64(0)     # st_size\n                buf += p64(0)     # st_blksize\n                buf += p64(0)     # st_blocks\n                buf += p64(0)     # st_atim.tv_sec\n                buf += p64(0)     # st_atim.tv_nsec\n                buf += p64(0)     # st_mtim.tv_sec\n                buf += p64(0)     # st_mtim.tv_nsec\n                buf += p64(0)     # st_ctim.tv_sec\n                buf += p64(0)     # st_ctim.tv_nsec\n                buf += p64(0) * 3 # __glibc_reserved[3]\n                yield ('stat(\"/tmp/xxx\", &buf)', \"stat\", [TMP_XXX, buf])\n                self.skipped_syscall.add(\"fstat\")\n                self.skipped_syscall.add(\"lstat\")\n                self.skipped_syscall.add(\"newfstatat\")\n                statxbuf = p32(0)  # stx_mask\n                statxbuf += p32(0) # stx_blksize\n                statxbuf += p64(0) # stx_attributes\n                statxbuf += p32(0) # stx_nlink\n                statxbuf += p32(0) # stx_uid\n                statxbuf += p32(0) # stx_gid\n                statxbuf += p16(0) # stx_mode\n                statxbuf += p16(0) # padding\n                statxbuf += p64(0) # stx_ino\n                statxbuf += p64(0) # stx_size\n                statxbuf += p64(0) # stx_blocks\n                statxbuf += p64(0) # stx_attributes_mask\n                statxbuf += p64(0) # stx_atime.tv_sec\n                statxbuf += p32(0) # stx_atime.tv_nsec\n                statxbuf += p32(0) # stx_atime.padding\n                statxbuf += p64(0) # stx_btime.tv_sec\n                statxbuf += p32(0) # stx_btime.tv_nsec\n                statxbuf += p32(0) # stx_btime.padding\n                statxbuf += p64(0) # stx_ctime.tv_sec\n                statxbuf += p32(0) # stx_ctime.tv_nsec\n                statxbuf += p32(0) # stx_ctime.padding\n                statxbuf += p64(0) # stx_mtime.tv_sec\n                statxbuf += p32(0) # stx_mtime.tv_nsec\n                statxbuf += p32(0) # stx_mtime.padding\n                statxbuf += p32(0) # stx_rdev_major\n                statxbuf += p32(0) # stx_rdev_minor\n                statxbuf += p32(0) # stx_dev_major\n                statxbuf += p32(0) # stx_dev_minor\n                statxbuf += p64(0) # stx_mnt_id\n                statxbuf += p32(0) # stx_dio_mem_align\n                statxbuf += p32(0) # stx_dio_offset_align\n                yield ('statx(0, \"/tmp/xxx\", 0, 0, &statxbuf)', \"statx\", [0, TMP_XXX, 0, 0, statxbuf])\n                yield ('truncate(\"/tmp/xxx\", 10)', \"truncate\", [TMP_XXX, 10])\n                self.skipped_syscall.add(\"ftruncate\")\n\n            yield \"access -> setxattr -> getxattr -> listxattr -> removexattr\"\n            yield ('access(\"/tmp/xxx\", F_OK)', \"access\", [TMP_XXX, 0])\n            if u2i(ret_history[-1]) >= 0:\n                buf = \"A\" * 0xff + \"\\0\"\n                userx = \"user.x\\0\"\n                yield (\n                    'setxattr(\"/tmp/xxx\", \"user.x\", &buf, sizeof(buf), 0)',\n                    \"setxattr\", [TMP_XXX, userx, buf, len(buf), 0],\n                )\n                self.skipped_syscall.add(\"lsetxattr\")\n                self.skipped_syscall.add(\"fsetxattr\")\n                if u2i(ret_history[-1]) >= 0:\n                    buf= \"\\0\" * 0x100\n                    yield (\n                        'getxattr(\"/tmp/xxx\", \"user.x\", &buf, sizeof(buf))',\n                        \"getxattr\", [TMP_XXX, userx, buf, len(buf)],\n                    )\n                    self.skipped_syscall.add(\"lgetxattr\")\n                    self.skipped_syscall.add(\"fgetxattr\")\n                    buf = \"\\0\" * 0x100\n                    yield ('listxattr(\"/tmp/xxx\", &buf, sizeof(buf))', \"listxattr\", [TMP_XXX, buf, len(buf)])\n                    self.skipped_syscall.add(\"llistxattr\")\n                    self.skipped_syscall.add(\"flistxattr\")\n                    yield ('removexattr(\"/tmp/xxx\", \"user.x\")', \"removexattr\", [TMP_XXX, userx])\n                    self.skipped_syscall.add(\"lremovexattr\")\n                    self.skipped_syscall.add(\"fremovexattr\")\n\n            yield \"link -> unlink\"\n            TMP_XXX3 = \"/tmp/xxx3\\0\"\n            yield ('link(\"/tmp/xxx\", \"/tmp/xxx3\")', \"link\", [TMP_XXX, TMP_XXX3])\n            self.skipped_syscall.add(\"linkat\")\n            if u2i(ret_history[-1]) >= 0:\n                yield ('unlink(\"/tmp/xxx3\")', \"unlink\", [TMP_XXX3])\n                self.skipped_syscall.add(\"unlinkat\")\n\n            yield \"symlink -> readlink -> rename -> unlink\"\n            TMP_XXX4 = \"/tmp/xxx4\\0\"\n            yield ('symlink(\"/tmp/xxx\", \"/tmp/xxx4\")', \"symlink\", [TMP_XXX, TMP_XXX4])\n            self.skipped_syscall.add(\"symlinkat\")\n            if u2i(ret_history[-1]) >= 0:\n                buf = \"\\0\" * 0x100\n                yield ('readlink(\"/tmp/xxx4\", &buf, sizeof(buf))', \"readlink\", [TMP_XXX4, buf, len(buf)])\n                self.skipped_syscall.add(\"readlinkat\")\n                TMP_XXX5 = \"/tmp/xxx5\\0\"\n                yield ('rename(\"/tmp/xxx4\", \"/tmp/xxx5\")', \"rename\", [TMP_XXX4, TMP_XXX5])\n                self.skipped_syscall.add(\"renameat\")\n                self.skipped_syscall.add(\"renameat2\")\n                if u2i(ret_history[-1]) >= 0:\n                    yield ('unlink(\"/tmp/xxx5\")', \"unlink\", [TMP_XXX5])\n                    self.skipped_syscall.add(\"unlinkat\")\n\n            yield \"inotify_init1 -> inotify_add_watch -> inotify_rm_watch -> close\"\n            yield (\"fd = inotify_init1(0)\", \"inotify_init1\", [0])\n            self.skipped_syscall.add(\"inotify_init\")\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\n                    'wd = inotify_add_watch(fd, \"/tmp/xxx\", IN_MOVE_SELF)',\n                    \"inotify_add_watch\", [fd, TMP_XXX, 0x800],\n                )\n                if u2i(ret_history[-1]) >= 0:\n                    wd = ret_history[-1]\n                    yield (\"inotify_rm_watch(fd, wd)\", \"inotify_rm_watch\", [fd, wd])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"open -> io_setup -> io_submit -> io_getevents -> close -> io_destroy\"\n            yield ('fd = open(\"/tmp/xxx\", 0_RDONLY)', \"open\", [TMP_XXX, 0o0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                ctx_idp = p64(0)\n                yield (\"io_setup(1, &ctx_idp)\", \"io_setup\", [1, ctx_idp])\n                ctx_id = read_int_from_memory(current_arch.sp)\n                iocb = p64(0)                       # aio_data\n                iocb += p32(0)                      # aio_key\n                iocb += p32(0)                      # aio_rw_flags\n                iocb += p16(0)                      # aio_lio_opcode: IOCB_CMD_PREAD\n                iocb += p16(0)                      # aio_reqprio\n                iocb += p32(fd)                     # aio_fildes\n                iocb += p64(current_arch.sp + 0x70) # aio_buf\n                iocb += p64(0x100)                  # aio_nbytes\n                iocb += p64(0)                      # aio_offset\n                iocb += p64(0)                      # aio_reserved2\n                iocb += p32(0)                      # aio_flags\n                iocb += p32(0)                      # aio_resfd\n                iocb += b\"\\0\" * 0x100               # data buffer <-- aio_buf\n                iocbp = p64(current_arch.sp + 0x30) # iocb\n                iocbp += p64(0) * 5                 # padding\n                iocbp += iocb\n                yield (\"io_submit(ctx_id, 1, &iocbp)\", \"io_submit\", [ctx_id, 1, iocbp])\n                events = p64(0)  # data\n                events += p64(0) # obj\n                events += p64(0) # res\n                events += p64(0) # res2\n                timeout = p64(0)  # tv_sec\n                timeout += p64(0) # tv_nsec\n                yield (\n                    \"io_getevents(ctx_id, 1, 1, &events, &timeout)\",\n                    \"io_getevents\", [ctx_id, 1, 1, events, timeout],\n                )\n                self.tested_syscall.add(\"io_pgetevents\")\n                yield (\"clode(fd)\", \"close\", [fd])\n                yield (\"io_destroy(ctx_id)\", \"io_destroy\", [ctx_id])\n\n            yield \"io_uring_setup -> mmap -> io_uring_enter -> io_uring_register -> munmap\"\n            params = p32(0)      # sq_entries\n            params += p32(0)     # cq_entries\n            params += p32(0)     # flags\n            params += p32(0)     # sq_thread_cpu\n            params += p32(0)     # sq_thread_idle\n            params += p32(0)     # features\n            params += p32(0)     # wq_fd\n            params += p32(0) * 3 # resv[3]\n            params += p32(0)     # sq_off.head\n            params += p32(0)     # sq_off.tail\n            params += p32(0)     # sq_off.ring_mask\n            params += p32(0)     # sq_off.ring_entries\n            params += p32(0)     # sq_off.flags\n            params += p32(0)     # sq_off.dropped\n            params += p32(0)     # sq_off.array\n            params += p32(0) * 3 # sq_off.resv[3]\n            params += p32(0)     # cq_off.head\n            params += p32(0)     # cq_off.tail\n            params += p32(0)     # cq_off.ring_mask\n            params += p32(0)     # cq_off.ring_entries\n            params += p32(0)     # cq_off.overflow\n            params += p32(0)     # cq_off.cqes\n            params += p32(0)     # cq_off.flags\n            params += p32(0) * 3 # cq_off.resv[3]\n            yield (\"ring_fd = io_uring_setup(1, &params)\", \"io_uring_setup\", [1, params])\n            params = slice_unpack(read_memory(current_arch.sp, len(params)), 4)\n            if u2i(ret_history[-1]) >= 0 and params[5] & 1: # IORING_FEAT_SINGLE_MMAP (available linux v5.4~)\n                ring_fd = ret_history[-1]\n                sring_sz = params[16] + params[0] * 4    # sq_off.array + sq_entries * sizeof(uint)\n                cring_sz = params[25] + params[1] * 0x10 # cq_off.cqes + cq_entries * sizeof(struct io_uring_cqe)\n                sring_sz = max(sring_sz, cring_sz)\n                yield (\n                    \"mmap(0, sring_sz, RW-, MAP_SHARED|MAP_POPULATE, ring_fd, IORING_OFF_SQ_RING)\",\n                    \"mmap\", [0, sring_sz, 3, 0x1 | 0x8000, ring_fd, 0],\n                )\n                if u2i(ret_history[-1]) >= 0:\n                    sq_ptr = ret_history[-1]\n                    yield (\n                        \"io_uring_enter(ring_fd, 0, 0, 0, NULL, 8)\",\n                        \"io_uring_enter\", [ring_fd, 0, 0, 0, 0, 8],\n                    )\n                    arg = p32(0)\n                    yield (\n                        \"io_uring_register(ring_fd, IORING_REGISTER_FILES, &arg, 1)\",\n                        \"io_uring_register\", [ring_fd, 2, arg, 1],\n                    )\n                    yield (\n                        \"io_uring_register(ring_fd, IORING_UNREGISTER_FILES, NULL, 0)\",\n                        \"io_uring_register\", [ring_fd, 3, 0, 0],\n                    )\n                    yield (\"munmap(sq_ptr, sring_sz)\", \"munmap\", [sq_ptr, sring_sz])\n                yield (\"close(ring_fd)\", \"close\", [ring_fd])\n\n            yield \"unshare\"\n            yield (\"unshare(CLONE_FS|CLONE_FILES)\", \"unshare\", [0x200 | 0x400])\n\n            yield \"name_to_handle_at -> unlink\"\n            handle = p32(0x80)     # handle_bytes: MAX_HANDLE_SZ\n            handle += p32(0)       # handle_type\n            handle += b\"\\0\" * 0x80 # f_handle\n            mntid = p32(0)\n            yield (\n                'name_to_handle_at(0, \"/tmp/xxx\", &handle, &mntid, 0)',\n                \"name_to_handle_at\", [0, TMP_XXX, handle, mntid, 0],\n            )\n            yield ('unlink(\"/tmp/xxx\")', \"unlink\", [TMP_XXX])\n\n            yield \"mkdir -> open_tree -> close -> chdir -> rmdir\"\n            TMP_YYY = \"/tmp/yyy\\0\"\n            yield ('mkdir(\"/tmp/yyy\", 0777)', \"mkdir\", [TMP_YYY, 0o777])\n            self.tested_syscall.add(\"mkdirat\")\n            if u2i(ret_history[-1]) >= 0:\n                yield ('fd = open_tree(-1, \"/tmp/yyy\", 0)', \"open_tree\", [-1, TMP_YYY, 0])\n                if u2i(ret_history[-1]) >= 0:\n                    fd = ret_history[-1]\n                    yield (\"close(fd)\", \"close\", [fd])\n                yield ('chdir(\"/tmp/yyy\")', \"chdir\", [TMP_YYY])\n                self.skipped_syscall.add(\"fchdir\")\n                yield ('chdir(\"..\")', \"chdir\", [\"..\\0\"])\n                yield ('rmdir(\"/tmp/yyy\")', \"rmdir\", [TMP_YYY])\n\n            yield \"statfs\"\n            buf = p64(0)      # f_type\n            buf += p64(0)     # f_bsize\n            buf += p64(0)     # f_blocks\n            buf += p64(0)     # f_bfree\n            buf += p64(0)     # f_bavail\n            buf += p64(0)     # f_files\n            buf += p64(0)     # f_ffree\n            buf += p64(0)     # f_fsid\n            buf += p64(0)     # f_namelen\n            buf += p64(0)     # f_frsize\n            buf += p64(0)     # f_flags\n            buf += p64(0) * 4 # f_spare[4]\n            yield ('statfs(\"/\", &buf)', \"statfs\", [\"/\\0\", buf])\n            self.skipped_syscall.add(\"fstatfs\")\n            self.skipped_syscall.add(\"ustat\")\n\n            yield \"open -> getdents -> fcntl -> close\"\n            yield ('fd = open(\"/\", 0_RDONLY)', \"open\", [\"/\\0\", 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                buf = \"\\0\" * 0x200\n                yield (\"getdents(fd, &buf, sizeof(buf))\", \"getdents\", [fd, buf, len(buf)])\n                self.skipped_syscall.add(\"getdents64\")\n                yield (\"fcntl(fd, F_GETFD)\", \"fcntl\", [fd, 1])\n                yield (\"fcntl(fd, F_GETFL)\", \"fcntl\", [fd, 3])\n                flock = \"\\0\" * 0x200\n                yield (\"fcntl(fd, F_GETLK, &flock)\", \"fcntl\", [fd, 5, flock])\n                yield (\"fcntl(fd, F_OFD_GETLK, &flock)\", \"fcntl\", [fd, 36, flock])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"invalid socket -> close\"\n            yield (\"socket(22, SOCK_STREAM, 0)\", \"socket\", [22, 1, 0])\n\n            yield \"socket AF_INET/TCP -> bind -> listen -> setsockopt -> getsockopt -> close\"\n            yield (\"fd = socket(AF_INET, SOCK_STREAM, 0)\", \"socket\", [2, 1, 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                import socket\n                sockaddr = p16(socket.AF_INET)          # sin_len, sin_family\n                sockaddr += p16(socket.htons(13337))    # sin_port\n                sockaddr += socket.inet_aton(\"0.0.0.0\") # sin_addr.s_addr\n                sockaddr += b\"\\0\" * 8                   # sin_zero[8]\n                yield (\"bind(fd, &sockaddr, sizeof(sockaddr))\", \"bind\", [fd, sockaddr, len(sockaddr)])\n                yield (\"listen(fd, 16)\", \"listen\", [fd, 16])\n                opt = p32(0)\n                yield (\n                    \"setsockopt(fd, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt))\",\n                    \"setsockopt\", [fd, 1, 1, opt, len(opt)],\n                )\n                optlen = p32(len(opt))\n                yield (\"getsockopt(fd, SOL_SOCKET, SO_DEBUG, &opt, &optlen)\", \"getsockopt\", [fd, 1, 1, opt, optlen])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"socket AF_INET/UDP -> connect -> getsockname -> getpeername -> close\"\n            yield (\"fd = socket(AF_INET, SOCK_DGRAM , 0)\", \"socket\", [2, 2, 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                import socket\n                sockaddr = p16(socket.AF_INET)          # sin_len, sin_family\n                sockaddr += p16(socket.htons(13337))    # sin_port\n                sockaddr += socket.inet_aton(\"0.0.0.0\") # sin_addr.s_addr\n                sockaddr += b\"\\0\" * 8                   # sin_zero[8]\n                yield (\"connect(fd, &sockaddr, sizeof(sockaddr))\", \"connect\", [fd, sockaddr, len(sockaddr)])\n                sockaddr = p16(0)     # sin_len, sin_family\n                sockaddr += p16(0)    # sin_port\n                sockaddr += p32(0)    # sin_addr.s_addr\n                sockaddr += b\"\\0\" * 8 # sin_zero[8]\n                addr_len = p64(len(sockaddr))\n                yield (\"getsockname(fd, &sockaddr, &addrlen)\", \"getsockname\", [fd, sockaddr, addr_len])\n                yield (\"getpeername(fd, &sockaddr, &addrlen)\", \"getpeername\", [fd, sockaddr, addr_len])\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"socketpair AF_UNIX -> sendto -> recvfrom -> sendmsg -> recvmsg -> shutdown -> close\"\n            sv_array = p32(0) * 2 # sv[2]\n            yield (\"socketpair(AF_UNIX, SOCK_STREAM, 0, &sv[])\", \"socketpair\", [1, 1, 0, sv_array])\n            if u2i(ret_history[-1]) >= 0:\n                sv0 = read_int32_from_memory(current_arch.sp)\n                sv1 = read_int32_from_memory(current_arch.sp + 4)\n                buf = \"A\" * 4\n                yield ('sendto(sv[0], \"AAAA\", 4, 0, NULL, 0)', \"sendto\", [sv0, buf, len(buf), 0, 0, 0])\n                buf = \"\\0\" * 4\n                yield (\"recvfrom(sv[1], buf, 4, 0, NULL, NULL)\", \"recvfrom\", [sv1, buf, len(buf), 0, 0, 0])\n                msg = p64(0)                       # msg_name\n                msg += p64(0)                      # msg_melen\n                msg += p64(current_arch.sp + 0x40) # msg_iov\n                msg += p64(1)                      # msg_iov_len\n                msg += p64(0)                      # msg_control\n                msg += p64(0)                      # msg_controllen\n                msg += p64(0)                      # msg_flags\n                msg += p64(0)                      # padding\n                msg += p64(current_arch.sp + 0x50) # iov_base\n                msg += p64(4)                      # iov_len\n                msg += b\"AAAA\"                     # data\n                yield (\"sendmsg(sv[0], &msg, 0)\", \"sendmsg\", [sv0, msg, 0])\n                self.skipped_syscall.add(\"sendmmsg\")\n                yield (\"recvmsg(sv[1], &msg, 0)\", \"sendmsg\", [sv1, msg, 0])\n                self.skipped_syscall.add(\"recvmmsg\")\n                yield (\"shutdown(sv[0], SHUT_RDWR)\", \"shutdown\", [sv0, 2])\n                yield (\"close(sv[0])\", \"close\", [sv0])\n                yield (\"close(sv[1])\", \"close\", [sv1])\n\n            yield \"memfd_create -> close\"\n            yield ('fd = memfd_create(\"test\", 0)', \"memfd_create\", [\"test\\0\", 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"add_key -> request_key -> keyctl\"\n            user = \"user\\0\"\n            tkey = \"test:testkey\\0\"\n            payload = \"payload\\0\"\n            yield ('add_key(\"user\", \"test:testkey\", \"payload\", plen, KEY_SPEC_PROCESS_KEYRING)',\n                   \"add_key\", [user, tkey, payload, len(payload) - 1, 0xffff_fffe])\n            callout_info = \"\\0\" * 0x100\n            yield ('request_key(\"user\", \"test:testkey\", &callout_info, KEY_SPEC_PROCESS_KEYRING)',\n                   \"request_key\", [user, tkey, callout_info, 0xffff_fffe])\n            if u2i(ret_history[-1]) >= 0:\n                key_serial = ret_history[-1]\n                yield (\"keyctl(KEYCTL_REVOKE, key_serial)\", \"keyctl\", [3, key_serial])\n\n            yield \"invalid add_key\"\n            tkey = \"A\" * 0x100\n            yield ('add_key(\"user\", \"AAAAAAAA...\", NULL, 0, KEY_SPEC_PROCESS_KEYRING)',\n                   \"add_key\", [user, tkey, 0, 0, 0xffff_fffe])\n\n            yield \"open /dev/ptmx -> close\"\n            yield ('fd = open(\"/dev/ptmx\", O_RDWR|O_NOCTTY)', \"open\", [\"/dev/ptmx\\0\", 0o2 | 0o400])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            yield \"open /proc/self/stat -> close\"\n            yield ('fd = open(\"/proc/self/stat\", O_RDONLY)', \"open\", [\"/proc/self/stat\\0\", 0])\n            if u2i(ret_history[-1]) >= 0:\n                fd = ret_history[-1]\n                yield (\"close(fd)\", \"close\", [fd])\n\n            self.skipped_syscall.add(\"restart_syscall\")   # difficult to implement generically\n            self.skipped_syscall.add(\"pause\")             # difficult to implement generically\n            self.skipped_syscall.add(\"rt_sigreturn\")      # difficult to implement generically\n            self.skipped_syscall.add(\"rt_sigsuspend\")     # difficult to implement generically\n            self.skipped_syscall.add(\"clone\")             # difficult to implement generically\n            self.skipped_syscall.add(\"clone3\")            # difficult to implement generically\n            self.skipped_syscall.add(\"execve\")            # difficult to implement generically\n            self.skipped_syscall.add(\"execveat\")          # difficult to implement generically\n            self.skipped_syscall.add(\"fork\")              # difficult to implement generically\n            self.skipped_syscall.add(\"vfork\")             # difficult to implement generically\n            self.skipped_syscall.add(\"exit\")              # difficult to implement generically\n            self.skipped_syscall.add(\"exit_group\")        # difficult to implement generically\n            self.skipped_syscall.add(\"wait4\")             # difficult to implement generically\n            self.skipped_syscall.add(\"waitid\")            # difficult to implement generically\n            self.skipped_syscall.add(\"accept\")            # difficult to implement generically\n            self.skipped_syscall.add(\"accept4\")           # difficult to implement generically\n            self.skipped_syscall.add(\"setsid\")            # difficult to implement generically\n            self.skipped_syscall.add(\"io_cancel\")         # difficult to implement generically\n            self.skipped_syscall.add(\"seccomp\")           # affect subsequent system calls\n            self.skipped_syscall.add(\"rseq\")              # affect subsequent system calls\n            self.skipped_syscall.add(\"pkey_alloc\")        # maybe unsupported by qemu HW\n            self.skipped_syscall.add(\"pkey_mprotect\")     # maybe unsupported by qemu HW\n            self.skipped_syscall.add(\"pkey_free\")         # maybe unsupported by qemu HW\n            self.skipped_syscall.add(\"modify_ldt\")        # supported i386 only\n            self.skipped_syscall.add(\"lookup_dcookie\")    # deprecated\n            self.skipped_syscall.add(\"quotactl\")          # supported ufs only\n            self.skipped_syscall.add(\"setgroups\")         # need CAP_SETGID\n            self.skipped_syscall.add(\"chroot\")            # need CAP_SYS_CHROOT\n            self.skipped_syscall.add(\"acct\")              # need CAP_SYS_PACCT\n            self.skipped_syscall.add(\"ptrace\")            # need CAP_SYS_PTRACE\n            self.skipped_syscall.add(\"iopl\")              # need CAP_SYS_RAWIO\n            self.skipped_syscall.add(\"ioperm\")            # need CAP_SYS_RAWIO\n            self.skipped_syscall.add(\"vhangup\")           # need CAP_SYS_TTY_CONFIG\n            self.skipped_syscall.add(\"reboot\")            # need CAP_SYS_BOOT\n            self.skipped_syscall.add(\"kexec_load\")        # need CAP_SYS_BOOT\n            self.skipped_syscall.add(\"kexec_file_load\")   # need CAP_SYS_BOOT\n            self.skipped_syscall.add(\"init_module\")       # need CAP_SYS_MODULE\n            self.skipped_syscall.add(\"finit_module\")      # need CAP_SYS_MODULE\n            self.skipped_syscall.add(\"delete_module\")     # need CAP_SYS_MODULE\n            self.skipped_syscall.add(\"syslog\")            # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"pivot_root\")        # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"mount\")             # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"umount2\")           # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"swapon\")            # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"swapoff\")           # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"sethostname\")       # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"setdomainname\")     # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"setns\")             # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"move_mount\")        # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fsopen\")            # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fspick\")            # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fsconfig\")          # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fsmount\")           # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fanotify_init\")     # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"fanotify_mark\")     # need CAP_SYS_ADMIN\n            self.skipped_syscall.add(\"clock_settime\")     # need CAP_SYS_TIME\n            self.skipped_syscall.add(\"settimeofday\")      # need CAP_SYS_TIME\n            self.skipped_syscall.add(\"open_by_handle_at\") # need CAP_DAC_READ_SEARCH\n            return None\n\n        self.scheduled_syscall = set()\n        self.tested_syscall = set()\n        self.skipped_syscall = set()\n\n        ret_history = []\n        for testcase in gen_testcase():\n            if isinstance(testcase, str):\n                gef_print(titlify(testcase, msg_color=\"bold\"))\n                self.scheduled_syscall |= set(testcase.split(\" -> \"))\n                continue\n\n            desc, syscall_name, args = testcase\n            gef_print(titlify(\"{:s};\".format(desc)))\n            self.setup_syscall(syscall_name, args)\n            for bp in breakpoints:\n                bp.enabled = True\n            gdb.execute(\"continue\")\n\n            # here, stop at hw breakpoint\n            ret = get_register(current_arch.return_register)\n            gef_print(\"ret: {:#x}\".format(ret))\n            if u2i(ret) < 0:\n                gef_print(Color.colorify(\"WARNING: r < 0\", \"bold red underline\"))\n                gdb.execute(\"errno {:#x}\".format(ret))\n            ret_history.append(ret)\n\n            for bp in breakpoints:\n                bp.enabled = False\n\n        self.dump_untested_syscall()\n\n        self.setup_syscall(\"exit\", [0])\n        return\n\n    def cleanup(self, hwbp, breakpoints):\n        # clean up\n        hwbp.delete()\n        for bp in breakpoints:\n            bp.delete()\n        KmallocTracerCommand.clear_disabled_breakpoints(\"KmallocRetBreakpoint\", force=True)\n        ContextCommand.unhide_context()\n        info(\"Exiting `sleep` process... (Please issue Ctrl+C)\")\n        gdb.execute(\"continue\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"x86_64\",))\n    @only_if_in_kernel\n    @only_if_kvm_disabled\n    @only_if_smp_disabled\n    def do_invoke(self, args):\n        info(\"Wait for memory scan\")\n\n        kversion = Kernel.kernel_version()\n        if kversion < \"3.0\":\n            err(\"Unsupported before v3.0\")\n            return\n\n        allocator = Kernel.get_slab_type()\n        if allocator == \"Unknown\":\n            err(\"Unsupported: Unknown allocator\")\n            return\n        if allocator != \"SLUB\":\n            warn(\"Unsupported viewing detailed information for SLAB, SLOB, SLUB_TINY\")\n            # fall through\n\n        # initialize\n        if not hasattr(self, \"initialized\"):\n            ret = KmallocTracerCommand.initialize(allocator, args.verbose)\n            if ret is False:\n                err(\"Failed to initialize\")\n                return\n            self.initialized = True\n            self.extra_info = ret # allow None\n        else:\n            if args.verbose and self.extra_info:\n                info(\"offsetof({:s}, slab_cache): {:#x}\".format(Kernel.slab_page_str(), self.extra_info.page_offset_slab_cache))\n                info(\"offsetof(kmem_cache, name): {:#x}\".format(self.extra_info.kmem_cache_offset_name))\n                info(\"offsetof(kmem_cache, size): {:#x}\".format(self.extra_info.kmem_cache_offset_size))\n\n        # get syscall table\n        syscall_table = get_syscall_table()\n        if syscall_table is None:\n            err(\"Could not find the syscall table\")\n            return\n        self.syscall_table = {e.name: n for n, e in syscall_table.nr_table.items() if n < 0x1000}\n        self.syscall_table_view_ret = gdb.execute(\"syscall-table-view --no-pager --quiet\", to_string=True)\n\n        # get task\n        res = gdb.execute(\"ktask --print-regs --no-pager --quiet --filter sleep\", to_string=True)\n        r = re.findall(r\"(?:^|\\n)(0x\\S+)\", res)\n        if not r:\n            err(\"Could not find `sleep` process, unable to continue\")\n            info(\"Do `/bin/sleep 5` in the guest (use full path), then `{:s}` again\".format(\n                self._cmdline_,\n            ))\n            return\n        if len(r) != 1:\n            err(\"Multiple sleep processes are found, unable to continue\")\n            return\n        target_task = int(r[0], 16)\n        info(\"The task of `sleep`: {:#x}\".format(target_task))\n\n        # create option_info\n        option_info = KmallocTracerCommand.create_option_info(args, target_task)\n\n        # get rip for breakpoint\n        # get rsp for checking process\n        r1 = re.search(r\"rip\\s*: (0x\\S+)\", res)\n        r2 = re.search(r\"rsp\\s*: (0x\\S+)\", res)\n        if not r1 or not r2:\n            err(\"Failed to get rip and rsp\")\n            return\n        rip_of_sleep = int(r1.group(1), 16)\n        rsp_of_sleep = int(r2.group(1), 16)\n        info(\"The sleep's $rip: {:#x}, rsp: {:#x} (after return from nanosleep syscall)\".format(\n            rip_of_sleep, rsp_of_sleep,\n        ))\n\n        # set a hw breakpoints\n        hwbp = KmallocAllocatedBy_UserlandHardwareBreakpoint(rip_of_sleep)\n\n        # set kmalloc breakpoints (but disabled)\n        breakpoints = KmallocTracerCommand.set_bp_to_kmalloc_kfree(option_info, self.extra_info)\n\n        # wait to stop at userland `sleep` process\n        ContextCommand.hide_context()\n        info(\"Setup is complete. continuing...\")\n        gdb.execute(\"continue\")\n\n        # here, stop in userland `sleep` process\n        if current_arch.sp != rsp_of_sleep:\n            err(\"Stack pointer is different from expected. Unable to continue\")\n            self.cleanup(hwbp, breakpoints)\n            return\n        # rsp align\n        gdb.execute(\"set $rsp = {:#x}\".format(rsp_of_sleep & ~0xf))\n        # For some reason, setting rsp can break rip. Here's a workaround for that.\n        gdb.execute(\"set $rip = {:#x}\".format(rip_of_sleep))\n\n        # do test\n        self.test_syscall(breakpoints)\n        info(\"Syscall test is complete, cleaning up...\")\n        self.cleanup(hwbp, breakpoints)\n        return\n\n\nclass KtraceBreakpoint(gdb.Breakpoint):\n    \"\"\"Create a breakpoint to print information for kernel functions.\"\"\"\n\n    def __init__(self, loc, sym, task_name_filter, task_addr_filter):\n        super().__init__(\"*{:#x}\".format(loc), gdb.BP_BREAKPOINT, internal=True)\n        self.loc = loc\n        self.sym = sym\n        self.task_name_filter = task_name_filter\n        self.task_addr_filter = task_addr_filter\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # check task\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.task_name_filter and task_name not in self.task_name_filter:\n            return False\n        if self.task_addr_filter and task_addr not in self.task_addr_filter:\n            return False\n\n        # get args\n        arg_key_color = Config.get_gef_setting(\"theme.registers_register_name\")\n        args = []\n        nb_argument = 6 # guessed\n        for i in range(nb_argument):\n            try:\n                key, value = current_arch.get_ith_parameter(i, in_func=True)\n                value = AddressUtil.recursive_dereference_to_string(value)\n            except Exception:\n                break\n            args.append(\"    {} = {}\".format(Color.colorify(key, arg_key_color), value))\n\n        # random id to distinguish between nested functions\n        import random\n        random_id = random.randint(1, 0xffff_ffff)\n\n        # print\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        gef_print(\"{:s} {:#x} <{:s}> ( // enter // random_id:{:#x}\".format(\n            task_prefix, self.loc, self.sym, random_id,\n        ))\n        for arg in args:\n            gef_print(arg)\n        gef_print(\")\")\n\n        # set bp for return value\n        try:\n            KtraceRetBreakpoint(self.loc, self.sym, self.task_name_filter, self.task_addr_filter, random_id)\n        except gdb.error:\n            # The case is following (why?):\n            #   Warning:\n            #   Cannot insert breakpoint -440.\n            #   Cannot access memory at address 0x0\n            pass\n        return False\n\n\nclass KtraceRetBreakpoint(gdb.FinishBreakpoint):\n    \"\"\"Create a breakpoint to print information for kernel functions.\"\"\"\n\n    def __init__(self, loc, sym, task_name_filter, task_addr_filter, random_id):\n        super().__init__(gdb.newest_frame(), internal=True)\n        self.loc = loc\n        self.sym = sym\n        self.task_name_filter = task_name_filter\n        self.task_addr_filter = task_addr_filter\n        self.random_id = random_id\n        KernelTraceCommand.finish_breakpoints.append(self)\n        return\n\n    def stop(self):\n        Cache.reset_gef_caches()\n\n        # check task\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        if self.task_name_filter and task_name not in self.task_name_filter:\n            return False\n        if self.task_addr_filter and task_addr not in self.task_addr_filter:\n            return False\n\n        # get return value\n        arg_key_color = Config.get_gef_setting(\"theme.registers_register_name\")\n        # self.return_value unavailable since no type information. use current_arch.return register\n        reg = current_arch.return_register\n        value = AddressUtil.recursive_dereference_to_string(get_register(reg))\n        msg = \"    {} = {}\".format(Color.colorify(reg, arg_key_color), value)\n\n        # print\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        gef_print(\"{:s} {:#x} <{:s}> ( // return // random_id:{:#x}\".format(\n            task_prefix, self.loc, self.sym, self.random_id,\n        ))\n        gef_print(msg)\n        gef_print(\")\")\n        return False\n\n    def out_of_scope(self): # noqa\n        if self.enabled:\n            self.enabled = False\n\n        # print\n        task_addr, task_name = KmallocTracerCommand.get_task()\n        task_prefix = Color.boldify(\"[task:{:#018x} {:16s}]\".format(task_addr, task_name))\n        warn(\"{:s} {:#x} <{:s}> (random_id{:#x}) has been disabled due to out of scope\".format(\n            task_prefix, self.loc, self.sym, self.random_id,\n        ))\n        return\n\n\n@register_command\nclass KernelTraceCommand(GenericCommand):\n    \"\"\"Trace kernel functions and arguments.\"\"\"\n\n    _cmdline_ = \"ktrace\"\n    _category_ = \"06-i. Qemu-system/KGDB Cooperation - Linux Dynamic Inspection\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--task-name\", action=\"append\", default=[],\n                        help=\"task name (from `ktask`) for filtering.\")\n    parser.add_argument(\"--task-addr\", action=\"append\", type=AddressUtil.parse_address, default=[],\n                        help=\"task address for filtering.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"function include filter (REGEXP).\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=re.compile, default=[],\n                        help=\"function exclude filter (REGEXP).\")\n    parser.add_argument(\"-c\", \"--commit\", action=\"store_true\", help=\"actually perform ktrace.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"skip tqdm and displaying function name.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"If you set breakpoints in some commonly called functions, it became too slow to be useful.\",\n        \"Use filtering options to reduce the number of functions targeted by breakpoints as much as possible.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    finish_breakpoints = []\n\n    def is_valid_addr(self, addr):\n        page_start = addr & get_pagesize_mask_low()\n\n        if page_start in self.addr_range_ok_cache:\n            return True\n        if page_start in self.addr_range_ng_cache:\n            return False\n\n        if is_valid_addr(addr):\n            self.addr_range_ok_cache.append(page_start)\n            return True\n        else:\n            self.addr_range_ng_cache.append(page_start)\n            return False\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\"))\n    @only_if_in_kernel\n    @only_if_kvm_disabled\n    def do_invoke(self, args):\n        info(\"Wait for memory scan\")\n\n        # check if text base is available\n        text_base = Symbol.get_ksymaddr(\"_stext\")\n        if text_base is None:\n            err(\"Failed to get kernel base (_stext)\")\n            return\n\n        self.addr_range_ok_cache = []\n        self.addr_range_ng_cache = []\n\n        # list target functions\n        res = gdb.execute(\"ksymaddr-remote --quiet --no-pager --type t\", to_string=True)\n        target_functions = []\n        tqdm = GefUtil.get_tqdm(not args.quiet)\n        for line in tqdm(res.splitlines(), leave=False):\n            func_addr, _, func_name = line.split()\n            func_addr = int(func_addr, 16)\n\n            # user specified filtering\n            if args.filter and not any(filt.search(func_name) for filt in args.filter):\n                continue\n            if args.exclude and any(filt.search(func_name) for filt in args.exclude):\n                continue\n\n            # lower address is percpu-relative.\n            if func_addr < text_base:\n                continue\n\n            # The function with `init` attribute may no longer exist.\n            if not self.is_valid_addr(func_addr):\n                continue\n\n            target_functions.append([func_addr, func_name])\n\n        # check num of breakpoints\n        info(\"Num of breakpoint targets: {:d}\".format(len(target_functions)))\n        if len(target_functions) > 1000:\n            err(\"Too many breakpoints cause this to not work properly (>1000)\")\n            return\n\n        if len(target_functions) > 100:\n            warn(\"Too many breakpoints may cause this to not work properly (>100)\")\n\n        # debug print\n        if not args.quiet:\n            for func_addr, func_name in target_functions:\n                info(\"{:#x} {:s}\".format(func_addr, func_name))\n\n        # not commit\n        if not args.commit:\n            warn('This dry run mode skips executing; add \"--commit\" to proceed')\n            return\n\n        # set break points\n        info(\"Set breakpoints in all functions that match the specified criteria\")\n        breakpoints = []\n        for func_addr, func_name in target_functions:\n            bp = KtraceBreakpoint(func_addr, func_name, args.task_name, args.task_addr)\n            breakpoints.append(bp)\n\n        # Locking a thread can have disadvantages: such as making it impossible to enter commands\n        # from the guest's terminal. Therefore, we decided not to disable it.\n\n        # doit\n        info(\"Setup is complete (set {:d} braekpoints). continuing...\".format(len(breakpoints)))\n        gdb.execute(\"continue\")\n\n        # clean up\n        info(\"ktrace is complete, cleaning up...\")\n        for bp in breakpoints:\n            bp.delete()\n        while KernelTraceCommand.finish_breakpoints:\n            bp = KernelTraceCommand.finish_breakpoints.pop()\n            if bp.is_valid():\n                bp.delete()\n        return\n\n\n@register_command\nclass UefiOvmfInfoCommand(GenericCommand):\n    \"\"\"Print UEFI OVMF info.\"\"\"\n\n    # https://github.com/tianocore/tianocore.github.io/wiki/OVMF-Boot-Overview\n    # https://github.com/tianocore/edk2/blob/master/OvmfPkg/Sec/SecMain.c\n    # https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c\n    # https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c\n    # https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/BdsDxe/BdsEntry.c\n    # https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf\n    _cmdline_ = \"uefi-ovmf-info\"\n    _category_ = \"06-k. Qemu-system/KGDB Cooperation - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    def check_crc32(self, addr):\n        import crccheck\n        size = u32(read_physmem(addr + 0xc, 0x4))\n        if size <= 0 or size > 0x1000:\n            return False\n        crc = u64(read_physmem(addr + 0x10, 0x8))\n        if crc == 0:\n            return False\n        data = read_physmem(addr, 0x10)\n        data += p64(0x0) # crc is zero when calculate\n        data += read_physmem(addr + 0x18, size - 0x18)\n        calculated_crc = crccheck.crc.Crc32().calc(data)\n        return calculated_crc == crc\n\n    def read_structure(self, addr, structure):\n        d = {}\n        d[\"__addr\"] = addr\n        for size, name in structure:\n            unpack = u32 if size == 4 else u64\n            d[name] = unpack(read_physmem(addr, size))\n            addr += size\n        return d\n\n    def search_mem_backward_iter(self, keyword):\n        # search backward for keyword from higher address (0x800_0000), it is more likely\n        START_ADDR = 0x800_0000\n        END_ADDR = 0x700_0000\n        current = START_ADDR - get_pagesize()\n        data = read_physmem(current, get_pagesize())\n        end = len(data)\n\n        while True:\n            pos = data.rfind(keyword, 0, end)\n            if pos == -1:\n                current -= get_pagesize()\n                if current < END_ADDR:\n                    return None\n\n                if len(data) > len(keyword):\n                    size_of_cut = len(data) - len(keyword)\n                    data = read_physmem(current, get_pagesize()) + data[:len(keyword)]\n                    end += get_pagesize() - size_of_cut\n                else:\n                    data = read_physmem(current, get_pagesize()) + data\n                    end += get_pagesize()\n                continue\n            yield current + pos\n            end = pos\n\n    def read_gPs(self):\n        for _addr in self.search_mem_backward_iter(b\"PEI SERV\"): # EFI_TABLE_HEADER.Signature\n            addr = _addr\n            break\n        else:\n            return None\n        structure = [\n            [8, \"Hdr.Signature\"],\n            [4, \"Hdr.Revision\"],\n            [4, \"Hdr.HeaderSize\"],\n            [4, \"Hdr.CRC32\"],\n            [4, \"Hdr.Reserved\"],\n            [8, \"InstallPpi\"],\n            [8, \"ReInstallPpi\"],\n            [8, \"LocatePpi\"],\n            [8, \"NotifyPpi\"],\n            [8, \"GetBootMode\"],\n            [8, \"SetBootMode\"],\n            [8, \"GetHobList\"],\n            [8, \"CreateHob\"],\n            [8, \"FfsFindNextVolume\"],\n            [8, \"FfsFindNextFile\"],\n            [8, \"FfsFindSectionData\"],\n            [8, \"InstallPeiMemory\"],\n            [8, \"AllocatePages\"],\n            [8, \"AllocatePool\"],\n            [8, \"CopyMem\"],\n            [8, \"SetMem\"],\n            [8, \"ReportStatusCode\"],\n            [8, \"ResetSystem\"],\n            [8, \"CpuIo\"],\n            [8, \"PciCfg\"],\n            [8, \"FfsFindFileByName\"],\n            [8, \"FfsGetFileInfo\"],\n            [8, \"FfsGetVolumeInfo\"],\n            [8, \"RegisterForShadow\"],\n            [8, \"FindSectionData3\"],\n            [8, \"FfsGetFileInfo2\"],\n            [8, \"ResetSystem2\"],\n            [8, \"FreePages\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def dump_gPs(self):\n        self.gPs = self.read_gPs()\n        if self.gPs is None:\n            err(\"Could not find gPs\")\n            return\n        info(\"gPs: {:#x}\".format(self.gPs[\"__addr\"]))\n        for k, v in self.gPs.items():\n            if k.startswith(\"__\"):\n                continue\n            if k == \"Hdr.Signature\":\n                gef_print(\"  {:40s}{:#x} ({!s})\".format(k + \":\", v, p64(v)))\n            else:\n                gef_print(\"  {:40s}{:#x}\".format(k + \":\", v))\n        return\n\n    def read_mBootServices(self):\n        for addr in self.search_mem_backward_iter(b\"BOOTSERV\"): # EFI_TABLE_HEADER.Signature\n            if self.check_crc32(addr):\n                break\n        else:\n            return None\n        structure = [\n            [8, \"Hdr.Signature\"],\n            [4, \"Hdr.Revision\"],\n            [4, \"Hdr.HeaderSize\"],\n            [4, \"Hdr.CRC32\"],\n            [4, \"Hdr.Reserved\"],\n            [8, \"RaiseTPL\"],\n            [8, \"RestoreTPL\"],\n            [8, \"AllocatePages\"],\n            [8, \"FreePages\"],\n            [8, \"GetMemoryMap\"],\n            [8, \"AllocatePool\"],\n            [8, \"FreePool\"],\n            [8, \"CreateEvent\"],\n            [8, \"SetTimer\"],\n            [8, \"WaitForEvent\"],\n            [8, \"SignalEvent\"],\n            [8, \"CloseEvent\"],\n            [8, \"CheckEvent\"],\n            [8, \"InstallProtocolInterface\"],\n            [8, \"ReinstallProtocolInterface\"],\n            [8, \"UninstallProtocolInterface\"],\n            [8, \"HandleProtocol\"],\n            [8, \"Reserved\"],\n            [8, \"RegisterProtocolNotify\"],\n            [8, \"LocateHandle\"],\n            [8, \"LocateDevicePath\"],\n            [8, \"InstallConfigurationTable\"],\n            [8, \"LoadImage\"],\n            [8, \"StartImage\"],\n            [8, \"Exit\"],\n            [8, \"UnloadImage\"],\n            [8, \"ExitBootServices\"],\n            [8, \"GetNextMonotonicCount\"],\n            [8, \"Stall\"],\n            [8, \"SetWatchdogTimer\"],\n            [8, \"ConnectController\"],\n            [8, \"DisconnectController\"],\n            [8, \"OpenProtocol\"],\n            [8, \"CloseProtocol\"],\n            [8, \"OpenProtocolInformation\"],\n            [8, \"ProtocolsPerHandle\"],\n            [8, \"LocateHandleBuffer\"],\n            [8, \"LocateProtocol\"],\n            [8, \"InstallMultipleProtocolInterfaces\"],\n            [8, \"UninstallMultipleProtocolInterfaces\"],\n            [8, \"CalculateCrc32\"],\n            [8, \"CopyMem\"],\n            [8, \"SetMem\"],\n            [8, \"CreateEventEx\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def dump_mBootServices(self):\n        self.mBootServices = self.read_mBootServices()\n        if self.mBootServices is None:\n            err(\"Could not find mBootServices\")\n            return\n        info(\"mBootServices: {:#x}\".format(self.mBootServices[\"__addr\"]))\n        for k, v in self.mBootServices.items():\n            if k.startswith(\"__\"):\n                continue\n            if k == \"Hdr.Signature\":\n                gef_print(\"  {:40s}{:#x} ({!s})\".format(k + \":\", v, p64(v)))\n            else:\n                gef_print(\"  {:40s}{:#x}\".format(k + \":\", v))\n        return\n\n    def read_mDxeServices(self):\n        for addr in self.search_mem_backward_iter(b\"DXE_SERV\"): # EFI_TABLE_HEADER.Signature\n            if self.check_crc32(addr):\n                break\n        else:\n            return None\n        structure = [\n            [8, \"Hdr.Signature\"],\n            [4, \"Hdr.Revision\"],\n            [4, \"Hdr.HeaderSize\"],\n            [4, \"Hdr.CRC32\"],\n            [4, \"Hdr.Reserved\"],\n            [8, \"AddMemorySpace\"],\n            [8, \"AllocateMemorySpace\"],\n            [8, \"FreeMemorySpace\"],\n            [8, \"RemoveMemorySpace\"],\n            [8, \"GetMemorySpaceDescriptor\"],\n            [8, \"SetMemorySpaceAttributes\"],\n            [8, \"GetMemorySpaceMap\"],\n            [8, \"AddIoSpace\"],\n            [8, \"AllocateIoSpace\"],\n            [8, \"FreeIoSpace\"],\n            [8, \"RemoveIoSpace\"],\n            [8, \"GetIoSpaceDescriptor\"],\n            [8, \"GetIoSpaceMap\"],\n            [8, \"Dispatch\"],\n            [8, \"Schedule\"],\n            [8, \"Trust\"],\n            [8, \"ProcessFirmwareVolume\"],\n            [8, \"SetMemorySpaceCapabilities\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def dump_mDxeServices(self):\n        self.mDxeServices = self.read_mDxeServices()\n        if self.mDxeServices is None:\n            err(\"Could not find mDxeServices\")\n            return\n        info(\"mDxeServices: {:#x}\".format(self.mDxeServices[\"__addr\"]))\n        for k, v in self.mDxeServices.items():\n            if k.startswith(\"__\"):\n                continue\n            if k == \"Hdr.Signature\":\n                gef_print(\"  {:40s}{:#x} ({!s})\".format(k + \":\", v, p64(v)))\n            else:\n                gef_print(\"  {:40s}{:#x}\".format(k + \":\", v))\n        return\n\n    def read_mEfiSystemTable(self):\n        for addr in self.search_mem_backward_iter(b\"IBI SYST\"): # EFI_TABLE_HEADER.Signature\n            if self.check_crc32(addr):\n                break\n        else:\n            return None\n        structure = [\n            [8, \"Hdr.Signature\"],\n            [4, \"Hdr.Revision\"],\n            [4, \"Hdr.HeaderSize\"],\n            [4, \"Hdr.CRC32\"],\n            [4, \"Hdr.Reserved\"],\n            [8, \"FirmwareVendor\"],\n            [8, \"FirmwareRevision\"],\n            [8, \"ConsoleInHandle\"],\n            [8, \"ConIn\"],\n            [8, \"ConsoleOutHandle\"],\n            [8, \"ConOut\"],\n            [8, \"StandardErrorHandle\"],\n            [8, \"StdErr\"],\n            [8, \"RuntimeServices\"],\n            [8, \"BootServices\"],\n            [8, \"NumberOfConfigurationTableEntries\"],\n            [8, \"ConfigurationTable\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def dump_mEfiSystemTable(self):\n        self.mEfiSystemTable = self.read_mEfiSystemTable()\n        if self.mEfiSystemTable is None:\n            err(\"Could not find *gDxeCoreST(=mEfiSystemTable)\")\n            return\n        info(\"*gDxeCoreST(=mEfiSystemTable): {:#x}\".format(self.mEfiSystemTable[\"__addr\"]))\n        for k, v in self.mEfiSystemTable.items():\n            if k.startswith(\"__\"):\n                continue\n            if k == \"Hdr.Signature\":\n                gef_print(\"  {:40s}{:#x} ({!s})\".format(k + \":\", v, p64(v)))\n            else:\n                gef_print(\"  {:40s}{:#x}\".format(k + \":\", v))\n        return\n\n    def read_mEfiRuntimeServicesTable(self):\n        for addr in self.search_mem_backward_iter(b\"RUNTSERV\"): # EFI_TABLE_HEADER.Signature\n            if self.check_crc32(addr):\n                break\n        else:\n            return None\n        structure = [\n            [8, \"Hdr.Signature\"],\n            [4, \"Hdr.Revision\"],\n            [4, \"Hdr.HeaderSize\"],\n            [4, \"Hdr.CRC32\"],\n            [4, \"Hdr.Reserved\"],\n            [8, \"GetTime\"],\n            [8, \"SetTime\"],\n            [8, \"GetWakeupTime\"],\n            [8, \"SetWakeupTime\"],\n            [8, \"SetVirtualAddressMap\"],\n            [8, \"ConvertPointer\"],\n            [8, \"GetVariable\"],\n            [8, \"GetNextVariableName\"],\n            [8, \"SetVariable\"],\n            [8, \"GetNextHighMonotonicCount\"],\n            [8, \"ResetSystem\"],\n            [8, \"UpdateCapsule\"],\n            [8, \"QueryCapsuleCapabilities\"],\n            [8, \"QueryVariableInfo\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def dump_mEfiRuntimeServicesTable(self):\n        self.mEfiRuntimeServicesTable = self.read_mEfiRuntimeServicesTable()\n        if self.mEfiRuntimeServicesTable is None:\n            err(\"Could not find *gDxeCoreRT(=mEfiRuntimeServicesTable)\")\n            return\n        info(\"*gDxeCoreRT(=mEfiRuntimeServicesTable): {:#x}\".format(self.mEfiRuntimeServicesTable[\"__addr\"]))\n        for k, v in self.mEfiRuntimeServicesTable.items():\n            if k.startswith(\"__\"):\n                continue\n            if k == \"Hdr.Signature\":\n                gef_print(\"  {:40s}{:#x} ({!s})\".format(k + \":\", v, p64(v)))\n            else:\n                gef_print(\"  {:40s}{:#x}\".format(k + \":\", v))\n        return\n\n    def read_gMemoryMap(self):\n        # gMemoryMap is just around mDxeServices\n        if not self.mDxeServices:\n            return None\n        base = self.mDxeServices[\"__addr\"] & ~0xf\n\n        for diff in range(-0x1000, 0x1000, 8):\n            addr = base + diff\n            try:\n                a = u64(read_physmem(addr, 8))\n                b = u64(read_physmem(a + 8, 8))\n                asig = u64(read_physmem(a - 8, 8))\n                c = u64(read_physmem(addr + 8, 8))\n                d = u64(read_physmem(c, 8))\n                csig = u64(read_physmem(c - 8, 8))\n                if addr == b == d and asig == csig == u32(b\"mmap\"):\n                    break\n            except (gdb.MemoryError, ValueError, OverflowError):\n                pass\n        else:\n            return None\n\n        structure = [\n            [8, \"ForwardLink\"],\n            [8, \"BackLink\"],\n        ]\n        return self.read_structure(addr, structure)\n\n    def read_Entry(self, addr):\n        structure = [\n            [8, \"Signature\"],\n            [8, \"Link.ForwardLink\"],\n            [8, \"Link.BackLink\"],\n            [4, \"FromPages\"], # with pad\n            [4, \"Type\"],\n            [8, \"Start\"],\n            [8, \"End\"],\n            [8, \"VirtualStart\"],\n            [8, \"Attribute\"],\n        ]\n        offset_of_link = 8\n        return self.read_structure(addr - offset_of_link, structure)\n\n    def dump_memory_map(self):\n        self.gMemoryMap = self.read_gMemoryMap()\n        if self.gMemoryMap is None:\n            err(\"Could not find gMemoryMap\")\n            return\n        info(\"gMemoryMap: {:#x}\".format(self.gMemoryMap[\"__addr\"]))\n\n        type_names = [\n            \"EfiReservedMemoryType\",\n            \"EfiLoaderCode\",\n            \"EfiLoaderData\",\n            \"EfiBootServicesCode\",\n            \"EfiBootServicesData\",\n            \"EfiRuntimeServicesCode\",\n            \"EfiRuntimeServicesData\",\n            \"EfiConventionalMemory\",\n            \"EfiUnusableMemory\",\n            \"EfiACPIReclaimMemory\",\n            \"EfiACPIMemoryNVS\",\n            \"EfiMemoryMappedIO\",\n            \"EfiMemoryMappedIOPortSpace\",\n            \"EfiPalCode\",\n            \"EfiPersistentMemory\",\n            \"EfiMaxMemoryType\",\n        ]\n\n        att_list = {\n            0x1: \"UC\",\n            0x2: \"WC\",\n            0x4: \"WT\",\n            0x8: \"WB\",\n            0x10: \"UCE\",\n            0x1000: \"WP\",\n            0x2000: \"RP\",\n            0x4000: \"XP\",\n            0x8000: \"NV\",\n            0x1_0000: \"MORE_RELIABLE\",\n            0x2_0000: \"RO\",\n            0x4_0000: \"SPM\",\n            0x8_0000: \"CPU_CRYPTO\",\n            0x8000_0000_0000_0000: \"RUNTIME\"\n        }\n\n        def att2str(att):\n            s = []\n            for k, v in att_list.items():\n                if k & att:\n                    s.append(v)\n            return \",\".join(s)\n\n        fmt = \"{:21s} {:10s} {:10s} {:30s} {:s}\"\n        legend = [\"Paddr Start-End\", \"Vaddr\", \"Size\", \"Type:TypeName\", \"Attribute\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        current = self.gMemoryMap[\"ForwardLink\"]\n        entries = []\n        while current != self.gMemoryMap[\"__addr\"]:\n            entry = self.read_Entry(current)\n\n            paddr_s = entry[\"Start\"]\n            paddr_e = entry[\"End\"] + 1\n            vaddr = entry[\"VirtualStart\"]\n            size = paddr_e - paddr_s\n            typ = entry[\"Type\"]\n            memtype = type_names[entry[\"Type\"]]\n            att = entry[\"Attribute\"]\n            att_s = att2str(att)\n            entry_text = \"{:#010x}-{:#010x} {:#010x} {:#010x} {:#x}:{:26s} {:#x}:[{:s}]\".format(\n                paddr_s, paddr_e, vaddr, size, typ, memtype, att, att_s,\n            )\n            entries.append(entry_text)\n\n            if entry[\"Signature\"] != u32(b\"mmap\"):\n                err(\"Signature does not match. Corrupted?\")\n                break\n            current = entry[\"Link.ForwardLink\"]\n\n        for entry_text in sorted(set(entries)):\n            gef_print(entry_text)\n\n        gef_print(\"Legend for attribute\")\n        gef_print(\"UC: It supports being configured as Un-Cacheable\")\n        gef_print(\"WC: It supports being configured as Write-Combining\")\n        gef_print(\"WT: It supports being configured as Write-Through\")\n        gef_print(\"WB: It supports being configured as Write-Back\")\n        gef_print(\"UCE: It supports being configured as Un-Cacheable and Exportable\")\n        gef_print(\"WP: It supports being configured as Write-Protected\")\n        gef_print(\"RP: It supports being configured as Read-Protected\")\n        gef_print(\"XP: It supports being configured as eXecute-Protected\")\n        gef_print(\"NV: It refers to persistent memory(Non-Volatile-Memory)\")\n        gef_print(\"MORE_RELIABLE: it has higher reliability than other\")\n        gef_print(\"RO: It supports being configured as Read-Only\")\n        gef_print(\"SP: Specific-Purpose memory\")\n        gef_print(\"CPU_CRYPTO: Encrypted and protected by CPU function\")\n        gef_print(\"RUNTIME: It will be mapped by OS when SetVirtualAddressMap() is called\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\",))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\"))\n    @ModuleLoader.load_crccheck\n    def do_invoke(self, args):\n        gef_print(titlify(\"SEC (Security) phase variables\"))\n        gef_print(\"Unimplemented\")\n        gef_print(titlify(\"PEI (Pre EFI Initialization) phase variables\"))\n        self.dump_gPs()\n        gef_print(titlify(\"DXE (Driver Execution Environment) phase variables\"))\n        self.dump_mBootServices()\n        self.dump_mDxeServices()\n        self.dump_mEfiSystemTable()\n        self.dump_mEfiRuntimeServicesTable()\n        gef_print(titlify(\"Memory map for UEFI\"))\n        self.dump_memory_map()\n        gef_print(titlify(\"BDS (Boot Device Selection) phase variables\"))\n        gef_print(\"gBS: See `mBootServices` in the DXE phase\")\n        gef_print(\"gST: See `mEfiSystemTable` in the DXE phase\")\n        gef_print(\"gRT: See `mEfiRuntimeServicesTable` in the DXE phase\")\n        return\n\n\n@register_command\nclass AddSymbolTemporaryCommand(GenericCommand):\n    \"\"\"Add symbol from command temporarily.\"\"\"\n\n    _cmdline_ = \"add-symbol-temporary\"\n    _category_ = \"01-i. Debugging Support - Other\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"function_name\", metavar=\"FUNCTION_NAME\", help=\"new symbol name to add.\")\n    parser.add_argument(\"function_start\", metavar=\"START_ADDR\", type=AddressUtil.parse_address,\n                        help=\"start address to add a symbol.\")\n    parser.add_argument(\"function_end\", metavar=\"END_ADDR\", type=AddressUtil.parse_address, nargs=\"?\",\n                        help=\"end address to add a symbol.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} your_func_name $rip $rip+0x20\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    @staticmethod\n    def create_blank_elf(text_base, text_end):\n        try:\n            objcopy = GefUtil.which(Config.get_gef_setting(\"gef.objcopy_command\"))\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return None\n\n        try:\n            gcc = GefUtil.which(\"gcc\")\n        except FileNotFoundError:\n            gcc = None\n\n        # create light ELF\n        if gcc:\n            fd, fname = GefUtil.mkstemp(prefix=\"add-symbol-temporary\", suffix=\".c\")\n            blank_elf = fname + \".elf\"\n            os.fdopen(fd, \"w\").write(\"int main() {}\")\n            # When adding symbols, it is not necessary to match the architecture of the ELF to be created\n            # and the architecture of the debugged kernel. Regardless of the architecture of the kernel\n            # you are debugging, create an ELF using gcc in the host environment.\n            os.system(\"{!r} {!r} -no-pie -o {!r}\".format(gcc, fname, blank_elf))\n            os.unlink(fname)\n            # delete unneeded section for faster (`ksymaddr-remote-apply` will embed many symbols)\n            os.system(\"{!r} --only-keep-debug {!r}\".format(objcopy, blank_elf))\n            os.system(\"{!r} --strip-all {!r}\".format(objcopy, blank_elf))\n            elf = Elf.get_elf(blank_elf)\n            for s in elf.shdrs:\n                if s.sh_name == \"\": # null, skip\n                    continue\n                if s.sh_name == \".text\": # .text is needed, don't remove\n                    continue\n                if s.sh_name == \".interp\": # broken if remove\n                    continue\n                if s.sh_name == \".rela.dyn\": # cannot remove\n                    continue\n                if s.sh_name == \".dynamic\": # cannot remove\n                    continue\n                if s.sh_name == \".data\": # broken if remove (e.g., add-symbol-temporary hoge 0x1234)\n                    continue\n                if s.sh_name == \".bss\": # broken if remove\n                    continue\n                os.system(\"{!r} --remove-section={!r} {!r} 2>/dev/null\".format(\n                    objcopy, s.sh_name, blank_elf,\n                ))\n        else:\n            # not found gcc. we use pre-built elf for x64\n            blank_elf_skelton = [\n                \"7f45 4c46 0201 0100 0000 0000 0000 0000 0200 3e00 0100 0000 2010 4000 0000 0000\",\n                \"4000 0000 0000 0000 1803 0000 0000 0000 0000 0000 4000 3800 0c00 4000 0800 0700\",\n                \"0600 0000 0400 0000 4000 0000 0000 0000 4000 4000 0000 0000 4000 4000 0000 0000\",\n                \"a002 0000 0000 0000 a002 0000 0000 0000 0800 0000 0000 0000 0300 0000 0400 0000\",\n                \"1803 0000 0000 0000 1803 4000 0000 0000 1803 4000 0000 0000 0000 0000 0000 0000\",\n                \"1c00 0000 0000 0000 0100 0000 0000 0000 0100 0000 0400 0000 0000 0000 0000 0000\",\n                \"0000 4000 0000 0000 0000 4000 0000 0000 e002 0000 0000 0000 a804 0000 0000 0000\",\n                \"0010 0000 0000 0000 0100 0000 0500 0000 2000 0000 0000 0000 2010 4000 0000 0000\",\n                \"2010 4000 0000 0000 0000 0000 0000 0000 f500 0000 0000 0000 0010 0000 0000 0000\",\n                \"0100 0000 0400 0000 e002 0000 0000 0000 2820 4000 0000 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 0100 0000 0600 0000\",\n                \"480e 0000 0000 0000 483e 4000 0000 0000 483e 4000 0000 0000 0000 0000 0000 0000\",\n                \"d001 0000 0000 0000 0010 0000 0000 0000 0200 0000 0600 0000 480e 0000 0000 0000\",\n                \"483e 4000 0000 0000 483e 4000 0000 0000 0000 0000 0000 0000 9001 0000 0000 0000\",\n                \"0800 0000 0000 0000 0400 0000 0400 0000 0000 0000 0000 0000 3803 4000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000\",\n                \"0400 0000 0400 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000 53e5 7464 0400 0000\",\n                \"0000 0000 0000 0000 3803 4000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0800 0000 0000 0000 50e5 7464 0400 0000 0000 0000 0000 0000\",\n                \"0420 4000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\",\n                \"0800 0000 0000 0000 51e5 7464 0600 0000 0000 0000 0000 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0800 0000 0000 0000\",\n                \"002e 7368 7374 7274 6162 002e 696e 7465 7270 002e 7265 6c61 2e64 796e 002e 7465\",\n                \"7874 002e 6479 6e61 6d69 6300 2e64 6174 6100 2e62 7373 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0b00 0000 0800 0000\",\n                \"0200 0000 0000 0000 1803 4000 0000 0000 1803 0000 0000 0000 1c00 0000 0000 0000\",\n                \"0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000 1300 0000 0800 0000\",\n                \"0200 0000 0000 0000 7804 4000 0000 0000 1803 0000 0000 0000 3000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0800 0000 0000 0000 1800 0000 0000 0000 1d00 0000 0800 0000\",\n                \"0600 0000 0000 0000 2010 4000 0000 0000 2010 0000 0000 0000 f500 0000 0000 0000\",\n                \"0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0000 2300 0000 0800 0000\",\n                \"0300 0000 0000 0000 483e 4000 0000 0000 480e 0000 0000 0000 9001 0000 0000 0000\",\n                \"0000 0000 0000 0000 0800 0000 0000 0000 1000 0000 0000 0000 2c00 0000 0800 0000\",\n                \"0300 0000 0000 0000 0040 4000 0000 0000 480e 0000 0000 0000 1000 0000 0000 0000\",\n                \"0000 0000 0000 0000 0800 0000 0000 0000 0000 0000 0000 0000 3200 0000 0800 0000\",\n                \"0300 0000 0000 0000 1040 4000 0000 0000 480e 0000 0000 0000 0800 0000 0000 0000\",\n                \"0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000 0100 0000 0300 0000\",\n                \"0000 0000 0000 0000 0000 0000 0000 0000 e002 0000 0000 0000 3700 0000 0000 0000\",\n                \"0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000\",\n            ]\n            blank_elf_skelton = bytes.fromhex(\"\".join(blank_elf_skelton).replace(\" \", \"\"))\n            fd, blank_elf = GefUtil.mkstemp(prefix=\"add-symbol-temporary\", suffix=\".elf\")\n            os.fdopen(fd, \"wb\").write(blank_elf_skelton)\n            elf = Elf.get_elf(blank_elf)\n\n        # fix .text base address\n        os.system(\"{!r} --change-section-address .text={:#x} {!r} 2>/dev/null\".format(\n            objcopy, text_base, blank_elf,\n        ))\n\n        # fix .text section size (objcopy doesn't support it, so fix it manually)\n        data = open(blank_elf, \"rb\").read()\n        new_size = text_end - text_base\n        if elf.e_class == Elf.ELF_64_BITS: # host is 64bit\n            seq_to_find = p64(text_base)\n            target_offset = data.rfind(seq_to_find) + 0x10\n            seq_to_write = p64(new_size)\n        else:\n            if text_base > 0xffff_ffff:\n                err(\"Unsupported adding 64 bit guest symbols when you use 32 bit host\")\n                return None\n            seq_to_find = p32(text_base)\n            target_offset = data.rfind(seq_to_find) + 0x8\n            seq_to_write = p32(new_size)\n        data = data[:target_offset] + seq_to_write + data[target_offset + len(seq_to_write):]\n        open(blank_elf, \"wb\").write(data)\n        return blank_elf\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            objcopy = GefUtil.which(Config.get_gef_setting(\"gef.objcopy_command\"))\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        # check address validity\n        max_address = AddressUtil.get_vmem_end_mask()\n        if args.function_start > max_address:\n            self.quiet_err(\"The function start address must be {:#x} or less\".format(max_address))\n            return\n        if args.function_end is not None:\n            if args.function_end > max_address:\n                self.quiet_err(\"The function end address must be {:#x} or less\".format(max_address))\n                return\n            if args.function_start > args.function_end:\n                self.quiet_err(\"The function start address must be equal or less than the function end address\")\n                return\n\n        # make blank ELF\n        text_base = args.function_start & get_pagesize_mask_high()\n        sym_elf = self.create_blank_elf(text_base, args.function_end or args.function_start + 1)\n        if sym_elf is None:\n            err(\"Failed to create blank ELF\")\n            return\n\n        self.quiet_info(\"1 entries will be added\")\n\n        # embedding symbols\n        relative_addr = args.function_start - text_base\n        os.system(\"{!r} --add-symbol {!r}=.text:{:#x},global,function {!r} 2>/dev/null\".format(\n            objcopy, args.function_name, relative_addr, sym_elf,\n        ))\n\n        self.quiet_info(\"1 entries were processed\")\n\n        # add symbol to gdb\n        try:\n            gdb.execute(\"add-symbol-file {!r} {:#x}\".format(sym_elf, text_base), to_string=True)\n        except gdb.error as e:\n            err(e)\n        os.unlink(sym_elf)\n        return\n\n\n@register_command\nclass KsymaddrRemoteApplyCommand(GenericCommand):\n    \"\"\"Apply symbol from kallsyms in memory.\"\"\"\n\n    _cmdline_ = \"ksymaddr-remote-apply\"\n    _category_ = \"06-e. Qemu-system/KGDB Cooperation - Linux Symbol/Type\"\n    _aliases_ = [\"ks-apply\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--rescan\", action=\"store_true\", help=\"do not use cache.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"enable quiet mode.\")\n    _syntax_ = parser.format_help()\n\n    def create_symboled_elf(self, sym_elf_path):\n        # get .kernel range\n        text_base = Symbol.get_ksymaddr(\"_stext\")\n        if text_base is None:\n            err(\"Failed to get kernel base (_stext)\")\n            return False\n        res = gdb.execute(\"ksymaddr-remote --quiet --no-pager\", to_string=True)\n        text_end = int(res.splitlines()[-1].split()[0], 16)\n\n        # make blank ELF\n        text_base &= get_pagesize_mask_high()\n        blank_elf = AddSymbolTemporaryCommand.create_blank_elf(text_base, text_end)\n        if blank_elf is None:\n            err(\"Failed to create blank ELF\")\n            return False\n\n        # parse kernel symbol\n        cmd_string_arr = []\n        for line in res.splitlines():\n            addr, typ, func_name = line.split()\n            addr = int(addr, 16)\n\n            if addr < text_base:\n                # lower address is percpu-relative. It is meaningless to import the address, so it is skipped.\n                continue\n\n            if typ in [\"T\", \"t\", \"W\", None]:\n                type_flag = \"function\"\n            else:\n                type_flag = \"object\"\n            if typ and typ in \"abcdefghijklmnopqrstuvwxyz\":\n                global_flag = \"local\"\n            else:\n                global_flag = \"global\"\n\n            # higher address needs relative\n            relative_addr = addr - text_base\n            cmd_string_arr.append(\"--add-symbol\")\n            cmd_string_arr.append(\"{:s}=.text:{:#x},{:s},{:s}\".format(func_name, relative_addr, global_flag, type_flag))\n\n        self.quiet_info(\"{:d} entries will be added\".format(len(cmd_string_arr) // 2))\n\n        # embedding symbols\n        objcopy = GefUtil.which(Config.get_gef_setting(\"gef.objcopy_command\"))\n        processed_count = 0\n        for cmd_string_arr_sliced in slicer(cmd_string_arr, 10000 * 2):\n            subprocess.check_output([objcopy] + cmd_string_arr_sliced + [blank_elf])\n            processed_count += len(cmd_string_arr_sliced) // 2\n\n            # debug print\n            if processed_count and processed_count % 10000 == 0:\n                self.quiet_info(\"{:d} entries were processed\".format(processed_count))\n\n        self.quiet_info(\"{:d} entries were processed\".format(processed_count))\n        os.rename(blank_elf, sym_elf_path)\n        return True\n\n    @parse_args\n    @only_if_gdb_running\n    @only_if_specific_gdb_mode(mode=(\"qemu-system\", \"vmware\"))\n    @only_if_specific_arch(arch=(\"x86_32\", \"x86_64\", \"ARM32\", \"ARM64\", \"RISCV32\", \"RISCV64\"))\n    @only_if_in_kernel\n    def do_invoke(self, args):\n        try:\n            GefUtil.which(Config.get_gef_setting(\"gef.objcopy_command\"))\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        self.quiet_info(\"Wait for memory scan\")\n\n        # resolve kversion for saved file name\n        kversion = Kernel.kernel_version()\n        h = hashlib.sha256(String.str2bytes(kversion.version_string)).hexdigest()[-16:]\n        sym_elf_path = os.path.join(GEF_TEMP_DIR, \"ks-apply-{:s}.elf\".format(h))\n        if (not args.rescan) and os.path.exists(sym_elf_path) and os.path.getsize(sym_elf_path) > 0:\n            self.quiet_info(\"A previously used file found, will be reused\")\n        else:\n            if os.path.exists(sym_elf_path):\n                os.unlink(sym_elf_path)\n            ret = self.create_symboled_elf(sym_elf_path)\n            if not ret:\n                return\n\n        # add symbol to gdb\n        text_base = Symbol.get_ksymaddr(\"_stext\") & get_pagesize_mask_high()\n        cmd = \"add-symbol-file {:s} {:#x}\".format(sym_elf_path, text_base)\n        self.quiet_warn(\"Execute `{:s}`\".format(cmd))\n        gdb.execute(cmd)\n        return\n\n\n@register_command\nclass WalkLinkListCommand(GenericCommand, BufferingOutput):\n    \"\"\"Walk the link list.\"\"\"\n\n    _cmdline_ = \"walk-link-list\"\n    _category_ = \"03-b. Memory - View\"\n    _aliases_ = [\"chain\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-o\", dest=\"next_offset\", type=AddressUtil.parse_address, default=0,\n                        help=\"offset of the next(or prev) pointer in the target structure.\")\n    parser.add_argument(\"-A\", dest=\"dump_bytes_after\", type=AddressUtil.parse_address, default=0,\n                        help=\"dump bytes after link-list location.\")\n    parser.add_argument(\"-B\", dest=\"dump_bytes_before\", type=AddressUtil.parse_address, default=0,\n                        help=\"dump bytes before link-list location.\")\n    parser.add_argument(\"--adjust-output\", type=AddressUtil.parse_address, default=0,\n                        help=\"displays the result of subtracting a specific value to the output.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"start address to walk.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0xffff9c60800597e0       # walk list_head.next\",\n        \"{0:s} -o 8 0xffff9c60800597e0  # walk list_head.prev\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_LOCATION)\n        return\n\n    def walk_link_list(self, head, offset):\n        indent = \" \" * 12\n        current = head\n        seen = [current]\n        idx = 1\n        while True:\n            try:\n                flink = read_int_from_memory(AddressUtil.align_address(current + offset))\n            except gdb.MemoryError:\n                self.err_add_out(\"memory corrupted\")\n                return\n            if self.args.dump_bytes_before:\n                source = read_memory(current - self.args.dump_bytes_before, self.args.dump_bytes_before)\n                dump = hexdump(source, base=current - self.args.dump_bytes_before, unit=current_arch.ptrsize)\n                for line in dump.splitlines():\n                    self.out.append(indent + line)\n            if self.args.dump_bytes_after:\n                source = read_memory(current, self.args.dump_bytes_after)\n                dump = hexdump(source, base=current, unit=current_arch.ptrsize)\n                for line in dump.splitlines():\n                    self.out.append(indent + line)\n            la_flink = ProcessMap.lookup_address(flink)\n            if self.args.adjust_output:\n                la_flink_adjusted = ProcessMap.lookup_address(flink - self.args.adjust_output)\n                self.out.append(\"[{:d}] -> {!s} (adjusted: {!s})\".format(idx, la_flink, la_flink_adjusted))\n            else:\n                self.out.append(\"[{:d}] -> {!s}\".format(idx, la_flink))\n            if flink == 0:\n                break\n            if flink == head:\n                self.out[-1] += \" (head)\"\n                break\n            if flink in seen[1:]:\n                self.err_add_out(\"loop detected\")\n                break\n            seen.append(current)\n            current = flink\n            idx += 1\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.info_add_out(\"head address: {:#x}\".format(args.address))\n        self.info_add_out(\"next pointer offset: {:#x}\".format(args.next_offset))\n        self.walk_link_list(args.address, args.next_offset)\n        self.print_output()\n        return\n\n\n@register_command\nclass PeekPageFrameCommand(GenericCommand, BufferingOutput):\n    \"\"\"Read page frame data from a single address or an address range.\"\"\"\n\n    _cmdline_ = \"peek-pageframe\"\n    _category_ = \"03-g. Memory - Investigation\"\n    _aliases_ = [\"ppf\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"address for which the pfn is read.\")\n    parser.add_argument(\"-f\", \"--from-addr\", type=AddressUtil.parse_address, help=\"start of range.\")\n    parser.add_argument(\"-t\", \"--to-addr\", type=AddressUtil.parse_address, help=\"end of range.\")\n    parser.add_argument(\"-i\", \"--ignore-non-present\", action=\"store_true\",\n                        help=\"ignores pages which are not present in the output.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x555555555060                       # read pagemap of single address\",\n        \"{0:s} -f 0x7ffffffdd000 -t 0x7ffffffff000  # read pagemap of an address range\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    ENTRY_SIZE = 8\n\n    def get_bit(self, x, bit):\n        return (x >> bit) & 1\n\n    def get_pfn(self, x):\n        return x & 0x7f_ffff_ffff_ffff\n\n    def append_pfn_zero_warn(self):\n        warn_messages = [\n            Color.yellowify(\"Pages are present but the PFN field is zeroed out\"),\n            Color.yellowify(\"Since kernel 4.0 only users with the CAP_SYS_ADMIN capability can get PFNs\"),\n            Color.yellowify(\"In kernel versions 4.2+ the PFN field is zeroed if the user does not have CAP_SYS_ADMIN\"),\n            Color.yellowify(\"Consider running gdb as root/sudo or adding the CAP_SYS_ADMIN capability to gdb via setcap\\n\"),\n        ]\n        self.out = warn_messages + self.out\n        return\n\n    def read_pagemap_with_virt_address(self, address, pid):\n        page_size = get_pagesize()\n        file_offset = (address // page_size) * self.ENTRY_SIZE\n        path = \"/proc/{:d}/pagemap\".format(pid)\n\n        try:\n            with open(path, \"rb\") as file:\n                file.seek(file_offset)\n                return file.read(8)\n        except FileNotFoundError:\n            err(\"Opening {:s} failed! Could not find file\".format(path))\n        except OSError as e:\n            if e.errno == 1: # 1 = EPERM\n                err(\"No permission to open the pagemap file\")\n                err(\"Only users with the CAP_SYS_ADMIN capability can get PFNs\")\n                err(\"In kernel versions 4.0 and 4.1 unprivileged opens fail with -EPERM\")\n            else:\n                err(\"Opening {:s} failed!\".format(path))\n        return None\n\n    def get_pagemap_entry(self, address, pid):\n        entry_bytes = self.read_pagemap_with_virt_address(address, pid)\n\n        if entry_bytes is None or len(entry_bytes) < 8:\n            err(\"Reading pagemap entry for address {:#x} wasn't successful\".format(address))\n            return None\n\n        entry = struct.unpack(\"Q\", entry_bytes)[0]\n        pfn = self.get_pfn(entry)\n\n        data = {\n            \"address\": address,\n            \"pfn\": pfn,\n            \"entry\": entry,\n            \"present\": self.get_bit(entry, 63),\n            \"swapped\": self.get_bit(entry, 62),\n            \"file_mapped\": self.get_bit(entry, 61),\n            \"uffd_wp\": self.get_bit(entry, 57),\n            \"exclusive\": self.get_bit(entry, 56),\n            \"soft_dirty\": self.get_bit(entry, 55),\n        }\n        return data\n\n    def handle_address(self, address, pid):\n        data = self.get_pagemap_entry(address, pid)\n        if data is None:\n            return\n\n        present = data[\"present\"]\n        swapped = data[\"swapped\"]\n        file_mapped = data[\"file_mapped\"]\n        uffd_wp = data[\"uffd_wp\"]\n        exclusive = data[\"exclusive\"]\n        soft_dirty = data[\"soft_dirty\"]\n\n        if self.args.ignore_non_present and not present:\n            self.out.append(\"Non-present page is ignored\")\n            return\n\n        pfn = data[\"pfn\"]\n        if pfn == 0 and present:\n            # Show the warning message only once\n            if not getattr(self, \"pfn_zero_warned\", False):\n                self.append_pfn_zero_warn()\n                self.pfn_zero_warned = True\n\n        green_yes = Color.greenify(\"yes\")\n        red_no = Color.redify(\"no\")\n\n        self.out.append(\"present:            {:s}\".format(green_yes if present else red_no))\n        self.out.append(\"swapped:            {:s}\".format(green_yes if swapped else red_no))\n        self.out.append(\"file-mapped:        {:s}\".format(green_yes if file_mapped else red_no))\n        self.out.append(\"soft-dirty:         {:s}\".format(green_yes if soft_dirty else red_no))\n        self.out.append(\"exclusively-mapped: {:s}\".format(green_yes if exclusive else red_no))\n        self.out.append(\"uffd-wp:            {:s}\".format(green_yes if uffd_wp else red_no))\n\n        if present:\n            self.out.append(Color.boldify(\"PFN:                {:#x}\").format(pfn))\n        return\n\n    def handle_address_range(self, from_addr, to_addr, pid):\n        page_size = get_pagesize()\n        start_page = from_addr // page_size\n        end_page = to_addr // page_size\n\n        for page_num in range(start_page, end_page + 1):\n            address = page_num * page_size\n            data = self.get_pagemap_entry(address, pid)\n\n            if data is None:\n                continue\n\n            if self.args.ignore_non_present and not data[\"present\"]:\n                continue\n\n            pfn = data[\"pfn\"]\n            if pfn == 0 and data[\"present\"]:\n                # Show the warning message only once\n                if not getattr(self, \"pfn_zero_warned\", False):\n                    self.append_pfn_zero_warn()\n                    self.pfn_zero_warned = True\n\n            flags = []\n            flags.append(\"P\" if data[\"present\"] else \"-\")\n            flags.append(\"S\" if data[\"swapped\"] else \"-\")\n            flags.append(\"F\" if data[\"file_mapped\"] else \"-\")\n            flags.append(\"D\" if data[\"soft_dirty\"] else \"-\")\n            flags.append(\"E\" if data[\"exclusive\"] else \"-\")\n            flags.append(\"U\" if data[\"uffd_wp\"] else \"-\")\n            flags_str = \"\".join(flags)\n\n            if data[\"pfn\"] != 0:\n                pfn_str = \"{:#x}\".format(data[\"pfn\"])\n            else:\n                pfn_str = \"0x0\"\n            self.out.append(\"{:#018x} {:>8} {:s}\".format(data[\"address\"], pfn_str, flags_str))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        pid = Pid.get_pid()\n        if pid is None:\n            err(\"Failed to read pid\")\n            return\n\n        self.out = []\n        if args.address is not None:\n            self.handle_address(args.address, pid)\n        elif args.from_addr is not None and args.to_addr is not None:\n            self.handle_address_range(args.from_addr, args.to_addr, pid)\n        else:\n            err(\"You must provide either a single address or both --from-addr and --to-addr\")\n            return\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass PeekPageFlagsCommand(GenericCommand, BufferingOutput):\n    \"\"\"Read the page flags of a page frame (needs root).\"\"\"\n\n    _cmdline_ = \"peek-pageflags\"\n    _category_ = \"03-g. Memory - Investigation\"\n    _aliases_ = [\"ppfl\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"pfn\", metavar=\"PFN\", type=AddressUtil.parse_address,\n                        help=\"pfn of which to read flags.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} 0x6b2ae3\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    class KPageFlags:\n        FLAGS = {\n            \"LOCKED\":        1 << 0,\n            \"ERROR\":         1 << 1,\n            \"REFERENCED\":    1 << 2,\n            \"UPTODATE\":      1 << 3, # codespell:ignore\n            \"DIRTY\":         1 << 4,\n            \"LRU\":           1 << 5,\n            \"ACTIVE\":        1 << 6,\n            \"SLAB\":          1 << 7,\n            \"WRITEBACK\":     1 << 8,\n            \"RECLAIM\":       1 << 9,\n            \"BUDDY\":         1 << 10,\n            \"MMAP\":          1 << 11,\n            \"ANON\":          1 << 12,\n            \"SWAPCACHE\":     1 << 13,\n            \"SWAPBACKED\":    1 << 14,\n            \"COMPOUND_HEAD\": 1 << 15,\n            \"COMPOUND_TAIL\": 1 << 16,\n            \"HUGE\":          1 << 17,\n            \"UNEVICTABLE\":   1 << 18,\n            \"HWPOISON\":      1 << 19,\n            \"NOPAGE\":        1 << 20,\n            \"KSM\":           1 << 21,\n            \"THP\":           1 << 22,\n            \"OFFLINE\":       1 << 23,\n            \"ZERO_PAGE\":     1 << 24,\n            \"IDLE\":          1 << 25,\n            \"PGTABLE\":       1 << 26,\n        }\n\n        def __init__(self, value):\n            self.value = value\n\n        def get_flag(self):\n            return self.value\n\n        def get_set_flags(self):\n            return [flag for flag, bit in self.FLAGS.items() if self.value & bit]\n\n    def read_file(self, path, pfn):\n        try:\n            with open(path, \"rb\") as f:\n                f.seek(pfn * 8)\n                data = f.read(8)\n                if len(data) == 8:\n                    return struct.unpack(\"Q\", data)[0]\n                else:\n                    raise ValueError(\"Could not read kpagecount for PFN {:#x}\".format(pfn))\n        except FileNotFoundError:\n            err(\"Could not open {:s}\".format(path))\n        except PermissionError:\n            err(\"No permissions to read {:s}\".format(path))\n            err(\"Only the owner of {:s} (root) is able to read it, rerun gdb with proper permissions\".format(path))\n        except Exception as e:\n            err(\"Error reading kpagecount: {}\".format(e))\n        return None\n\n    def read_kpagecount(self, pfn):\n        path = \"/proc/kpagecount\"\n        return self.read_file(path, pfn)\n\n    def read_kpageflags(self, pfn):\n        path = \"/proc/kpageflags\"\n        return self.read_file(path, pfn)\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\", \"wine\"))\n    def do_invoke(self, args):\n        if args.pfn is None:\n            err(\"You must provide a PFN\")\n            return\n\n        count = self.read_kpagecount(args.pfn)\n        if count is None:\n            return\n\n        flags_value = self.read_kpageflags(args.pfn)\n        if flags_value is None:\n            return\n\n        flags = self.KPageFlags(flags_value)\n        set_flags = flags.get_set_flags()\n\n        self.out = []\n        self.out.append(\"/proc/kpagecount: {:d}\".format(count))\n        self.out.append(\"Pageflags: {:#x}\".format(flags.get_flag()))\n        self.out.append(\"Flags:\")\n        for flag in set_flags:\n            self.out.append(\"  {:s}\".format(flag))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass StackFrameCommand(GenericCommand):\n    \"\"\"Display the entire stack of the current frame.\"\"\"\n\n    _cmdline_ = \"stack-frame\"\n    _category_ = \"02-d. Process Information - Trivial Information\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    @only_if_gdb_running\n    @require_arch_set\n    def do_invoke(self, args):\n        ptrsize = current_arch.ptrsize\n        try:\n            frame = gdb.selected_frame()\n        except gdb.error:\n            # gdb.selected_frame() may error for unknown reasons (often during kernel startup).\n            err(\"Failed to get frame information\")\n            return\n\n        if not frame.older():\n            reason_str = gdb.frame_stop_reason_string(frame.unwind_stop_reason())\n            warn(\"Cannot determine frame boundary, reason: {:s}\".format(reason_str))\n            return\n\n        saved_ip = frame.older().pc()\n        stack_hi = int(frame.older().read_register(\"sp\"))\n        stack_lo = int(frame.read_register(\"sp\"))\n        results = []\n\n        if not current_arch.stack_grow_down:\n            addr_lo = stack_lo\n            addr_hi = stack_hi\n        else:\n            addr_lo = stack_hi + current_arch.ptrsize\n            addr_hi = stack_lo + current_arch.ptrsize\n\n        for offset, address in enumerate(range(addr_lo, addr_hi, ptrsize)):\n            pprint_str = DereferenceCommand.pprint_dereferenced(addr_lo, offset)\n            if AddressUtil.dereference(address) == saved_ip:\n                pprint_str += \" ($savedip)\"\n            results.append(pprint_str)\n\n        if current_arch.stack_grow_down:\n            results.reverse()\n            gef_print(titlify(\"Stack top (higher address)\"))\n        else:\n            gef_print(titlify(\"Stack top (lower address)\"))\n\n        for res in results:\n            gef_print(res)\n\n        if current_arch.stack_grow_down:\n            gef_print(titlify(\"Stack bottom (lower address)\"))\n        else:\n            gef_print(titlify(\"Stack bottom (higher address)\"))\n        return\n\n\n@register_command\nclass XRefTelescopeCommand(SearchPatternCommand, BufferingOutput):\n    \"\"\"Recursively search for cross-references to a pattern in memory.\"\"\"\n\n    _cmdline_ = \"xref-telescope\"\n    _category_ = \"03-a. Memory - Search\"\n    _repeat_ = False # re-overwrite\n    _aliases_ = [] # re-overwrite\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"pattern\", metavar=\"PATTERN\", help=\"search pattern.\")\n    parser.add_argument(\"depth\", metavar=\"DEPTH\", nargs=\"?\", type=int, default=1,\n                        help=\"max recursive depth. (default: %(default)s)\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\",\n                        help=\"shows the section currently being searched.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} AAAA 2                    # search string with depth level 2\",\n        '{0:s} \"\\\\\\\\x41\\\\\\\\x41\\\\\\\\x41\\\\\\\\x41\" 2  # use double-escape string',\n        \"{0:s} 0x555555554000 2          # search value\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def xref_telescope(self, pattern, depth, history):\n        \"\"\"Recursively search for a pattern within the whole userland memory.\"\"\"\n        if depth <= 0:\n            # print history\n            for i, h in enumerate(history):\n                if i == 0:\n                    prefix = \"\"\n                else:\n                    prefix = \"  \" * i + \" -> \"\n                if isinstance(h, int):\n                    addr = ProcessMap.lookup_address(h)\n                    path = addr.section.path\n                    perm = addr.section.permission\n                    self.out.append(\"{:s}{!s} {:s} [{!s}]\".format(prefix, addr, path, perm))\n                else:\n                    self.out.append(\"{:s}{:s}\".format(prefix, h))\n            return\n\n        if String.is_hex(pattern):\n            if Endian.get_endian() == Elf.BIG_ENDIAN:\n                pattern = \"\".join([\"\\\\x\" + pattern[i:i + 2] for i in range(2, len(pattern), 2)])\n            else:\n                pattern = \"\".join([\"\\\\x\" + pattern[i:i + 2] for i in range(len(pattern) - 2, 0, -2)])\n\n        locs = []\n        for section in ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True):\n            if not section.permission & Permission.READ:\n                continue\n            locs += self.search_pattern_by_address(pattern, section.page_start, section.page_end)\n\n        for loc, _ustr in locs:\n            self.xref_telescope(AddressUtil.format_address(loc), depth - 1, [loc] + history)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        self.found_count = 0\n\n        # Since it inherits SearchPatternCommand, set the values to be used there.\n        args.aligned = False\n        args.interval = False\n        args.limit = False\n        args.phys = False\n        args.hex_regex = False\n\n        self.out = []\n        self.out.append(\"Recursively searching for '{:s}' in memory (depth: {:d})\".format(\n            Color.yellowify(args.pattern), args.depth,\n        ))\n        self.xref_telescope(args.pattern, args.depth, [args.pattern])\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass BytearrayCommand(GenericCommand):\n    \"\"\"Generate a bytearray to be compared with possible badchars (ported from mona.py).\"\"\"\n\n    _cmdline_ = \"bytearray\"\n    _category_ = \"07-c. Misc - Generation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-b\", dest=\"badchars\", default=[], action=\"append\", help=\"characters to exclude.\")\n    parser.add_argument(\"-d\", dest=\"dump\", action=\"store_true\", help=\"dump to /tmp/gef/bytearray.{txt,bin}.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} -b 414243 -b 51-53 -b 61..63\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def expand_hex(self, x):\n        \"\"\"4142..45 -> 4142434445\"\"\"\n        if \"..\" not in x:\n            return x\n\n        if len(x) < 6:\n            return False\n\n        if \"...\" in x:\n            return False\n\n        while \"..\" in x:\n            pos = x.find(\"..\")\n            if pos % 2 != 0:\n                return False\n\n            if pos < 2 or len(x) - 4 < pos:\n                return False\n\n            xa, xb = int(x[pos - 2:pos], 16), int(x[pos + 2:pos + 4], 16)\n            if xa >= xb:\n                return False\n            middle = \"\".join(\"{:02x}\".format(c) for c in range(xa, xb))\n            x = x[:pos - 2] + middle + x[pos + 2:]\n        return x\n\n    @parse_args\n    def do_invoke(self, args):\n        excluded = set()\n        for b in args.badchars:\n            b = b.lower().replace(\"-\", \"..\")\n\n            if not re.match(r\"[0-9a-f]+\", b):\n                err(\"{:s} is not valid hex (not match `[0-9a-f]+`)\".format(b))\n                return\n\n            if (len(b) % 2) != 0:\n                err(\"{:s} is not valid hex (odd length)\".format(b))\n                return\n\n            eb = self.expand_hex(b)\n            if eb is False:\n                err(\"{:s} is not valid hex (failed to expand `..`)\".format(b))\n                return\n\n            excluded |= {int(c, 16) for c in slicer(eb, 2)}\n\n        info(\"Generating table, excluding {:d} bad chars...\".format(len(excluded)))\n\n        included = sorted(set(range(0, 256)) - excluded)\n\n        if len(included) == 0:\n            info(\"Nothing to dump\")\n            return\n\n        info(\"Dumping table\")\n        outt_arr = []\n        outb_arr = []\n        for c in included:\n            outt_arr.append(\"\\\\x{:02x}\".format(c))\n            outb_arr.append(bytes([c]))\n\n        bytesperline = 32\n        outt = \"\"\n        for s in slicer(outt_arr, bytesperline):\n            outt += '\"{:s}\"\\n'.format(\"\".join(s))\n        outb = b\"\".join(outb_arr)\n\n        gef_print(outt.rstrip())\n\n        if args.dump:\n            arrayfile = os.path.join(GEF_TEMP_DIR, \"bytearray.txt\")\n            open(arrayfile, \"w\").write(outt)\n            info(\"Done, wrote {:d} bytes to file {:s}\".format(len(outt_arr), arrayfile))\n            binfilename = os.path.join(GEF_TEMP_DIR, \"bytearray.bin\")\n            open(binfilename, \"wb\").write(outb)\n            info(\"Binary output saved in {:s}\".format(binfilename))\n        return\n\n\n@register_command\nclass SixelMemoryCommand(GenericCommand):\n    \"\"\"Show image (png, jpg, bmp, etc.) to terminal by imagemagick.\"\"\"\n\n    _cmdline_ = \"sixel-memory\"\n    _category_ = \"03-g. Memory - Investigation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address of the image.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size of the image.\")\n    parser.add_argument(\"-b\", \"--decode-barcode\", action=\"store_true\", help=\"decode barcode if found.\")\n    _syntax_ = parser.format_help()\n\n    def get_jpg_size(self, start_address):\n        # parse header\n        pos = start_address + 2\n        while True:\n            marker = read_memory(pos, 2)\n            pos += 2\n            if marker[0] != 0xff:\n                return None\n            length = struct.unpack(\">H\", read_memory(pos, 2))[0]\n            pos += length\n            if marker == b\"\\xff\\xda\":\n                break\n        header_size = pos - start_address\n\n        # saerch EOI\n        if pos % get_pagesize():\n            read_size = get_pagesize() - (pos % get_pagesize())\n        else:\n            read_size = get_pagesize()\n\n        MAX_FILE_SIZE = get_pagesize() * 4096 # 16MB\n        jpg_data = b\"\" # except header\n        while len(jpg_data) < MAX_FILE_SIZE:\n            try:\n                jpg_data += read_memory(pos, read_size)\n            except (gdb.MemoryError, MemoryError):\n                return None\n            if b\"\\xff\\xd9\" in jpg_data:\n                image_data_size = jpg_data.index(b\"\\xff\\xd9\") + 2\n                return header_size + image_data_size\n            pos += read_size\n            read_size = get_pagesize()\n        return None\n\n    def get_png_size(self, start_address):\n        pos = start_address\n\n        if start_address % get_pagesize():\n            read_size = get_pagesize() - (start_address % get_pagesize())\n        else:\n            read_size = get_pagesize()\n\n        MAX_FILE_SIZE = get_pagesize() * 4096 # 16MB\n        png_data = b\"\"\n        while len(png_data) < MAX_FILE_SIZE:\n            try:\n                png_data += read_memory(pos, read_size)\n            except (gdb.MemoryError, MemoryError):\n                return None\n            if b\"IEND\" in png_data:\n                image_data_size = png_data.index(b\"IEND\") + 4\n                return image_data_size + 4 # crc\n            pos += read_size\n            read_size = get_pagesize()\n        return None\n\n    def decode_barcode(self, path):\n        try:\n            import PIL.Image\n            import pyzbar.pyzbar\n        except ImportError as e:\n            err(\"Import error {}\".format(e))\n            return\n\n        image = PIL.Image.open(path)\n        decoded = pyzbar.pyzbar.decode(image)\n        if decoded == []:\n            err(\"Not found\")\n            return\n\n        for i, data in enumerate(decoded):\n            gef_print(\"[{}] type:{} data:{}\".format(i, data.type, data.data))\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            convert_command = GefUtil.which(\"convert\") # imagemagick\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        if not is_valid_addr(args.location):\n            err(\"Memory read error\")\n            return\n\n        try:\n            if args.size is not None:\n                size = args.size\n            elif read_memory(args.location, 2) == b\"BM\": # BMP\n                size = read_int32_from_memory(args.location + 2)\n            elif read_memory(args.location, 2) == b\"\\xff\\xd8\": # JPG\n                size = self.get_jpg_size(args.location)\n            elif read_memory(args.location, 4) == b\"\\x89PNG\": # PNG\n                size = self.get_png_size(args.location)\n            else:\n                err(\"Specify the SIZE parameter\")\n                return\n            data = read_memory(args.location, size)\n        except (gdb.MemoryError, MemoryError, TypeError):\n            err(\"Memory read error\")\n            return\n\n        tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"sixel-memory\", suffix=\".img\")\n        os.fdopen(tmp_fd, \"wb\").write(data)\n        os.system(\"{!r} {!r} sixel:-\".format(convert_command, tmp_path))\n\n        if args.decode_barcode:\n            self.decode_barcode(tmp_path)\n\n        os.unlink(tmp_path)\n        return\n\n\n@register_command\nclass FrequencyAnalysisCommand(GenericCommand, BufferingOutput):\n    \"\"\"Visualize the frequency of occurrence of each byte.\"\"\"\n\n    _cmdline_ = \"freq-analysis\"\n    _category_ = \"03-g. Memory - Investigation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address to analyze.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size to analyze; if omitted, calculated from the end of the area.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", default=[], type=lambda x: int(x, 16),\n                        help=\"exclude character in hex.\")\n    parser.add_argument(\"-a\", \"--ascii-gradation\", action=\"store_true\",\n                        help=\"show heatmap with ascii range word.\")\n    parser.add_argument(\"-t\", \"--topn\", type=AddressUtil.parse_address, default=16,\n                        help=\"outputs the top N numbers. (default: %(default)s)\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rax 0x1000               # ragne: $rax ~ $rax + 0x1000\",\n        \"{0:s} $rax                      # range: $rax ~ end of the region to which $rax belongs\",\n        \"{0:s} $rax 0x1000 -a            # use ascii compatible result\",\n        \"{0:s} $rax 0x1000 -e 00 -e 01   # exclude some characters\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def hist256(self, data):\n        h = [0] * 256\n        for b in data:\n            if b in self.args.exclude:\n                continue\n            h[b] += 1\n        return h\n\n    def print_heatmap(self, h):\n        if self.args.ascii_gradation:\n            GRAD = \".:-=+*$#%@\"\n        else:\n            GRAD = u\" _\\u2582\\u2583\\u2584\\u2585\\u2586\\u2587\\u2588\"\n\n        def scale_to_grad(value, vmax):\n            if vmax <= 0:\n                return GRAD[0]\n            idx = int((value * (len(GRAD) - 1)) / vmax)\n            return GRAD[idx]\n\n        legend = \"Legend: [few] {!r} [many]\".format(GRAD)\n        self.out.append(legend)\n\n        col_labels = \"   \" + \" \".join(f\"{x:X}\" for x in range(16))\n        self.out.append(col_labels)\n\n        vmax = max(h) if h else 0\n        for hi in range(16):\n            line = [f\"{hi:X} \"]\n            for lo in range(16):\n                idx = (hi << 4) | lo\n                ch = scale_to_grad(h[idx], vmax)\n                line.append(ch * 1)\n            self.out.append(\" \".join(line))\n\n        self.out.append(f\"Total bytes: {sum(h)}  Max bin count: {vmax}\")\n        self.out.append(\"\")\n        return\n\n    def top_n(self, h, n):\n        order = sorted(range(256), key=lambda b: (-h[b], b))\n        rows = []\n        for i in range(min(n, 256)):\n            b = order[i]\n            c = h[b]\n            if c == 0:\n                break\n            rows.append((b, c))\n        return rows\n\n    def print_top_n(self, h, n):\n        rows = self.top_n(h, n)\n        if not rows:\n            self.out.append(\"No data.\")\n            return\n        maxc = rows[0][1]\n        width = 40\n        self.out.append(\"Top frequencies:\")\n        for b, c in rows:\n            bar_len = int(width * c / maxc) if maxc > 0 else 0\n            bar = \"#\" * bar_len\n            self.out.append(f\"  {b:02X}: {c:>10d} |{bar}\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n\n        if args.size is None:\n            loc = ProcessMap.lookup_address(args.location)\n            if loc.valid:\n                size = loc.section.page_end - args.location\n            else:\n                err(\"The size could not be calculated\")\n                return\n        else:\n            size = args.size\n\n        try:\n            data = read_memory(args.location, size)\n        except (gdb.MemoryError, MemoryError, TypeError):\n            err(\"Memory read error\")\n            return\n\n        self.out = []\n        hist = self.hist256(data)\n        self.print_heatmap(hist)\n        self.print_top_n(hist, self.args.topn)\n\n        self.print_output()\n        return\n\n\n@register_command\nclass VisualDumpCommand(GenericCommand):\n    \"\"\"Visualize memory data like an image.\"\"\"\n\n    _cmdline_ = \"vdump\"\n    _category_ = \"03-g. Memory - Investigation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"location\", metavar=\"LOCATION\", type=AddressUtil.parse_address,\n                        help=\"start address to dump.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"the size to dump; if omitted, calculated from the end of the area.\")\n    parser.add_argument(\"-d\", \"--disable-autoscale\", action=\"store_true\",\n                        help=\"disable autoscaling to fit the terminal.\")\n    parser.add_argument(\"-w\", \"--width\", type=AddressUtil.parse_address,\n                        help=\"the number of wrap bytes. (default: sqrt(len(content)))\")\n    parser.add_argument(\"-c\", \"--color\", choices=(\"r\", \"g\", \"b\"),\n                        help=\"convert the grayscale tone to either r,g,b.\")\n    parser.add_argument(\"-n\", \"--negate\", action=\"store_true\",\n                        help=\"negate the grayscale tone.\")\n    parser.add_argument(\"-A\", \"--auto-width-inclement\", action=\"store_true\",\n                        help=\"repeat the display while shifting the interpretation of the width.\")\n    parser.add_argument(\"-Ab\", \"--auto-inclement-begin-width\", type=AddressUtil.parse_address, default=16,\n                        help=\"auto inclement begin width. (default: %(default)s)\")\n    parser.add_argument(\"-Ae\", \"--auto-inclement-end-width\", type=AddressUtil.parse_address,\n                        help=\"auto inclement end width. (default: min(len(data) // begin_width, 512)\")\n    parser.add_argument(\"-As\", \"--auto-inclement-step-width\", type=AddressUtil.parse_address, default=2,\n                        help=\"auto inclement step width. (default: %(default)s)\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} $rsp 0x1000                                 # width =~ sqrt(len(content))\",\n        \"{0:s} -w 0x100 $rsp 0x1000                        # use fixed width\",\n        \"{0:s} -c r $rsp 0x1000                            # change color: gray -> red\",\n        \"{0:s} -c r -n $rsp 0x1000                         # change color: gray -> red and negate\",\n        \"{0:s} -A $rsp 0x1000                              # bruteforce the width\",\n        \"{0:s} -A -Ab 0x100 -Ae 0x200 -As 0x10 $rsp 0x1000 # bruteforce the width (w=0x100; w<0x200; w+=0x10)\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def make_command_line(self, img_width, img_height, tmp_path):\n        command_options = [\n            \"-size {:d}x{:d}\".format(img_width, img_height),\n            \"-depth 8\",\n        ]\n\n        if not self.args.disable_autoscale:\n            # terminal size (number of characters)\n            term_height, term_width = GefUtil.get_terminal_size()\n            # it's too tight, so make it slightly smaller.\n            term_width = int(term_width * 0.95)\n            term_height = int(term_height * 0.95)\n            # number of pixels per character\n            font_width_px = 6\n            font_height_px = 12\n            # pixel dimensions of the terminal\n            term_width_px = term_width * font_width_px\n            term_height_px = term_height * font_height_px\n            # scaling factor to fit the terminal\n            scale_width = term_width_px * 100 / img_width\n            scale_height = term_height_px * 100 / img_height\n            resize_scale = min(scale_height, scale_width)\n            # convert option\n            command_options.extend([\n                \"-filter Box\",\n                \"-resize {:d}%\".format(int(resize_scale)),\n            ])\n\n        if self.args.color == \"r\":\n            command_options.append(\"-colorspace Gray -colorize 0,100,100\")\n        elif self.args.color == \"g\":\n            command_options.append(\"-colorspace Gray -colorize 100,0,100\")\n        elif self.args.color == \"b\":\n            command_options.append(\"-colorspace Gray -colorize 100,100,0\")\n\n        if self.args.negate:\n            command_options.append(\"-negate\")\n\n        cmd = \"{!r} {:s} GRAY:{!r} sixel:-\".format(\n            GefUtil.which(\"convert\"),\n            \" \".join(command_options),\n            tmp_path,\n        )\n        return cmd\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        try:\n            GefUtil.which(\"convert\") # imagemagick\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        if args.size is None:\n            loc = ProcessMap.lookup_address(args.location)\n            if loc.valid:\n                size = loc.section.page_end - args.location\n            else:\n                err(\"The size could not be calculated\")\n                return\n        else:\n            size = args.size\n\n        try:\n            data = read_memory(args.location, size)\n        except (gdb.MemoryError, MemoryError, TypeError):\n            err(\"Memory read error\")\n            return\n\n        if args.width and args.width > 0:\n            img_width = args.width\n        else:\n            import math\n            img_width = int(math.sqrt(len(data)))\n        while len(data) % img_width:\n            data += b\"\\0\"\n        img_height = len(data) // img_width\n\n        tmp_fd, tmp_path = GefUtil.mkstemp(prefix=\"vhexdump\", suffix=\".raw\")\n        os.fdopen(tmp_fd, \"wb\").write(data)\n\n        if args.auto_width_inclement:\n            # if the width is too large, processing will be slow\n            min_width = args.auto_inclement_begin_width\n            if args.auto_inclement_end_width is not None:\n                max_width = args.auto_inclement_end_width\n            else:\n                max_width = min(len(data) // min_width, 512)\n            step = args.auto_inclement_step_width\n            # processing while changing the width\n            for img_width in range(min_width, max_width + 1, step):\n                img_height = len(data) // img_width\n                cmd = self.make_command_line(img_width, img_height, tmp_path)\n                info(cmd)\n                # Ctrl+C is consumed by os.system, so it cannot escape from the python loop.\n                # Therefore, it is judged by the execution result.\n                e = os.system(cmd)\n                if e != 0:\n                    break\n        else:\n            cmd = self.make_command_line(img_width, img_height, tmp_path)\n            info(cmd)\n            os.system(cmd)\n\n        os.unlink(tmp_path)\n        return\n\n\n@register_command\nclass FiletypeMemoryCommand(GenericCommand):\n    \"\"\"Scan memory by file and magika.\"\"\"\n\n    _cmdline_ = \"filetype-memory\"\n    _category_ = \"03-g. Memory - Investigation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"target address.\")\n    parser.add_argument(\"end_address\", metavar=\"END_ADDRESS\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"target end address. (default: the end of section of ADDRESS)\")\n    _syntax_ = parser.format_help()\n\n    def filetype_memory(self, start_address, end_address, size):\n        try:\n            data = read_memory(start_address, size)\n        except gdb.MemoryError:\n            err(\"Memory read error\")\n            return\n\n        dumpfile_name = \"filetype_{:#x}-{:#x}.dat\".format(start_address, end_address)\n        filepath = os.path.join(GEF_TEMP_DIR, dumpfile_name)\n        open(filepath, \"wb\").write(data)\n\n        try:\n            gef_print(titlify(\"file {!r}\".format(filepath)))\n            file_command = GefUtil.which(\"file\")\n            os.system(\"{!r} {!r}\".format(file_command, filepath))\n        except FileNotFoundError as e:\n            warn(\"{}\".format(e))\n\n        try:\n            gef_print(titlify(\"magika {!r}\".format(filepath)))\n            magika_command = GefUtil.which(\"magika\")\n            os.system(\"{!r} {!r}\".format(magika_command, filepath))\n        except FileNotFoundError as e:\n            warn(\"{}\".format(e))\n\n        os.unlink(filepath)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    def do_invoke(self, args):\n        if not is_valid_addr(args.address):\n            err(\"Memory read error\")\n            return\n\n        try:\n            start_address = args.address\n            if args.end_address is not None:\n                size = args.end_address - args.address\n            else:\n                section = ProcessMap.lookup_address(args.address).section\n                size = section.page_end - args.address\n            end_address = start_address + size\n        except (AttributeError, ValueError):\n            self.usage()\n            return\n\n        self.filetype_memory(start_address, end_address, size)\n        return\n\n\n@register_command\nclass BinwalkMemoryCommand(GenericCommand):\n    \"\"\"Scan memory by binwalk.\"\"\"\n\n    _cmdline_ = \"binwalk-memory\"\n    _category_ = \"03-g. Memory - Investigation\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP include filter.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP exclude filter.\")\n    parser.add_argument(\"-m\", \"--maxsize\", type=AddressUtil.parse_address, default=0x1000_0000,\n                        help=\"maximum size of a section to be dumped. (default: 256 MB)\")\n    parser.add_argument(\"-c\", \"--commit\", action=\"store_true\", help=\"actually perform binwalk.\")\n    _syntax_ = parser.format_help()\n\n    def memory_binwalk(self):\n        import binwalk\n\n        maps = ProcessMap.get_process_maps_exclude_special_regions(allow_vdso=True)\n        if maps is None:\n            err(\"Failed to get maps\")\n            return\n\n        addr_len = current_arch.ptrsize * 2\n        for entry in maps:\n            start = entry.page_start\n            end = entry.page_end\n            perm = str(entry.permission)\n\n            if entry.size > self.args.maxsize:\n                continue\n\n            if not entry.path.startswith((\"[\", \"<\")):\n                path = os.path.basename(entry.path)\n            else:\n                path = entry.path\n                path = path.replace(\"[\", \"\").replace(\"]\", \"\") # consider [heap], [stack], [vdso]\n                path = path.replace(\"<\", \"\").replace(\">\", \"\") # consider <tls-th1>, <explored>\n            path = path.replace(\" \", \"_\") # consider deleted case. e.g., /path/to/file (deleted)\n\n            dumpfile_name = \"binwalk-{:0{}x}-{:0{}x}_{:s}_{:s}.raw\".format(\n                start, addr_len, end, addr_len, perm, path,\n            )\n\n            if self.args.filter and not any(filt.search(dumpfile_name) for filt in self.args.filter):\n                continue\n\n            if self.args.exclude and any(ex.search(dumpfile_name) for ex in self.args.exclude):\n                continue\n\n            filepath = os.path.join(GEF_TEMP_DIR, dumpfile_name)\n\n            if self.args.commit:\n                gef_print(titlify(\"{:#x}-{:#x} [{}] {:s}\".format(\n                    entry.page_start, entry.page_end, entry.permission, entry.path,\n                )))\n                try:\n                    data = read_memory(start, end - start)\n                except gdb.MemoryError:\n                    continue\n                open(filepath, \"wb\").write(data)\n                binwalk.scan(filepath, signature=True)\n                os.unlink(filepath)\n            else:\n                gef_print(dumpfile_name)\n\n        if not self.args.commit:\n            warn('This dry run mode skips executing binwalk; add \"--commit\" to proceed')\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    @exclude_specific_gdb_mode(mode=(\"qemu-system\", \"kgdb\", \"vmware\"))\n    @ModuleLoader.load_binwalk\n    def do_invoke(self, args):\n        self.memory_binwalk()\n        return\n\n\n@register_command\nclass BincompareCommand(GenericCommand, BufferingOutput):\n    \"\"\"Compare an binary file with the memory position looking for badchars.\"\"\"\n\n    _cmdline_ = \"bincompare\"\n    _category_ = \"03-c. Memory - Compare\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"filename\", metavar=\"FILENAME\", help=\"specifies the binary file to be compared.\")\n    parser.add_argument(\"address\", metavar=\"ADDRESS\", type=AddressUtil.parse_address,\n                        help=\"specifies the memory address.\")\n    parser.add_argument(\"size\", metavar=\"SIZE\", nargs=\"?\", type=AddressUtil.parse_address,\n                        help=\"specifies the size.\")\n    parser.add_argument(\"--file-offset\", type=AddressUtil.parse_address, default=0,\n                        help=\"specifies the file offset.\")\n    parser.add_argument(\"-f\", \"--full\", action=\"store_true\", help=\"display the same line without omitting.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=gdb.COMPLETE_FILENAME)\n        return\n\n    def compare(self, from1data, from2data, size):\n        diff_found = False\n        asterisk = False\n\n        hex_pad_len = {\n            1: 37,\n            2: 35,\n            3: 32,\n            4: 30,\n            5: 27,\n            6: 25,\n            7: 22,\n            8: 20,\n            9: 17,\n            10: 15,\n            11: 12,\n            12: 9,\n            13: 7,\n            14: 5,\n            15: 2,\n            16: 0,\n        }\n\n        width = len(hex(size))\n\n        for pos in range(0, size, 16):\n            # determining continuity\n            f1_bin = from1data[pos : pos + 16]\n            f2_bin = from2data[pos : pos + 16]\n            if not self.args.full:\n                if f1_bin == f2_bin:\n                    if asterisk is False:\n                        self.out.append(\"*\")\n                        asterisk = True\n                    continue\n\n            diff_found = True\n            asterisk = False\n\n            # coloring\n            f1_hex = []\n            f2_hex = []\n            f1_ascii = []\n            f2_ascii = []\n            for i in range(min(len(f1_bin), 16)):\n                if f1_bin[i] == f2_bin[i]:\n                    color_func = lambda x: x\n                else:\n                    color_func = Color.boldify\n                f1_hex.append(color_func(\"{:02x}\".format(f1_bin[i])))\n                f2_hex.append(color_func(\"{:02x}\".format(f2_bin[i])))\n                f1_ascii.append(color_func(chr(f1_bin[i]) if 0x20 <= f1_bin[i] < 0x7f else \".\"))\n                f2_ascii.append(color_func(chr(f2_bin[i]) if 0x20 <= f2_bin[i] < 0x7f else \".\"))\n\n            # formatting\n            # [\"00\", \"00\", \"00\" \"00\", ...] -> [\"0000\", \"0000\", ...]\n            f1_hex2 = [\"\".join(x) for x in slicer(f1_hex, 2)]\n            f2_hex2 = [\"\".join(x) for x in slicer(f2_hex, 2)]\n\n            # padding\n            # [\"0000\", \"0000\", ...] -> \"0000 0000 ...\"\n            f1_hex_s = \" \".join(f1_hex2) + \" \" * hex_pad_len[len(f1_hex)]\n            f2_hex_s = \" \".join(f2_hex2) + \" \" * hex_pad_len[len(f2_hex)]\n            # [\".\", \".\", ...] -> \"................\"\n            f1_ascii_s = \"\".join(f1_ascii) + \" \" * (16 - len(f1_ascii))\n            f2_ascii_s = \"\".join(f2_ascii) + \" \" * (16 - len(f2_ascii))\n\n            # make line\n            addr1 = \"{:#{:d}x}\".format(self.args.file_offset + pos, width)\n            addr2 = ProcessMap.lookup_address(self.args.address + pos)\n            self.out.append(\"{:s}: {:s} |{:s}| {!s}: {:s} |{:s}|\".format(\n                addr1, f1_hex_s, f1_ascii_s,\n                addr2, f2_hex_s, f2_ascii_s,\n            ))\n\n        if diff_found is False:\n            self.info_add_out(\"No difference\")\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        # file_data\n        if not os.path.isfile(args.filename):\n            err(\"Specified file '{:s}' does not exist\".format(args.filename))\n            return\n        file_data = open(args.filename, \"rb\").read()\n        file_data = file_data[args.file_offset:]\n        file_size = len(file_data)\n\n        # size\n        if args.size is None:\n            size = file_size\n        else:\n            if args.size > file_size:\n                err(\"The file size is too short\")\n                return\n            size = args.size\n            file_data = file_data[:size]\n\n        if size == 0:\n            err(\"Comparing size is 0, nothing to do\")\n            return\n\n        # memory_data\n        try:\n            memory_data = read_memory(args.address, size)\n        except gdb.MemoryError:\n            err(\"Cannot reach memory {:#x}\".format(args.address))\n            return\n\n        self.out = []\n        self.compare(file_data, memory_data, size)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass SymbolsCommand(GenericCommand, BufferingOutput):\n    \"\"\"List all symbols (shortcut for `maintenance print msymbols`) with coloring.\"\"\"\n\n    _cmdline_ = \"symbols\"\n    _category_ = \"02-g. Process Information - Symbol\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-t\", \"--type\", action=\"append\", default=[], help=\"filter by symbol type.\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    def get_build_id(self, filename):\n        e = Elf.get_elf(filename)\n        if e is None or not e.is_valid():\n            return None\n        try:\n            build_id = e.read_shdr(\".note.gnu.build-id\")\n        except Exception:\n            return None\n        return build_id\n\n    def get_build_ids(self):\n        build_id_dict = {}\n        for filename in ProcessMap.get_loaded_files():\n            build_id = self.get_build_id(filename)\n            if build_id is None:\n                continue\n            build_id_dict[build_id] = filename\n        return build_id_dict\n\n    def get_symbols(self):\n        \"\"\"Parse and display symbol information from GDB, including file/object info\n        and symbol addresses, with filtering.\"\"\"\n        ret = gdb.execute(\"maintenance print msymbols\", to_string=True).strip()\n        SYMBOL_INFO_LINE_PATTERN = re.compile(r\"^(\\[ ?\\d+\\]) (.) (0x[0-9a-f]+) (.*)\")\n        SYMBOL_FILE_PATTERN = re.compile(r\"^Object file (/.*):$\")\n        build_id_dict = self.get_build_ids()\n\n        tqdm = GefUtil.get_tqdm(not self.args.quiet)\n        for line in tqdm(ret.splitlines(), leave=False):\n            line = line.strip()\n\n            # blank line\n            if not line:\n                self.out.append(line)\n                continue\n\n            # filename line\n            # e.g., Object file /root/.cache/debuginfod_client/1c8db5f83bba514f8fd5f1fb6d7be975be1bb855/debuginfo:\n            r = SYMBOL_FILE_PATTERN.search(line)\n            if r:\n                self.out.append(line)\n\n                filename = r.group(1)\n                build_id = self.get_build_id(filename)\n                if build_id in build_id_dict:\n                    if build_id_dict[build_id] != filename:\n                        self.out.append(\"(={:s})\".format(build_id_dict[build_id]))\n                continue\n\n            # symbol info line\n            # e.g., [2875] T 0x7ffff7cad650 malloc section .text  sofini.c\n            r = SYMBOL_INFO_LINE_PATTERN.search(line)\n            if r:\n                # type filtering\n                typ = r.group(2)\n                if self.args.type:\n                    if typ.lower() not in self.args.type:\n                        continue\n\n                # invalid address filtering\n                addr = int(r.group(3), 16)\n                if not is_valid_addr(addr):\n                    self.out.append(line)\n                    continue\n                addr = ProcessMap.lookup_address(addr)\n\n                index = r.group(1)\n                remain = r.group(4)\n                self.out.append(\"{:s} {:s} {!s} {:s}\".format(index, typ, addr, remain))\n                continue\n\n            # other line\n            self.out.append(line)\n\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.use_cache and hasattr(self, \"cache\") and self.cache:\n            self.out = self.cache[::]\n            self.print_output()\n            return\n\n        self.out = []\n        self.get_symbols()\n        self.print_output()\n        self.cache = self.out[::]\n        return\n\n\n@register_command\nclass TypesCommand(GenericCommand, BufferingOutput):\n    \"\"\"List all types (shortcut for `info types`) with compaction.\"\"\"\n\n    _cmdline_ = \"types\"\n    _category_ = \"02-h. Process Information - Type\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-s\", \"--smart\", action=\"store_true\",\n                        help=\"temporarily override by `context.smart_cpp_function_name = True`.\")\n    parser.add_argument(\"-f\", \"--filter\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP include filter.\")\n    parser.add_argument(\"-e\", \"--exclude\", action=\"append\", type=re.compile, default=[],\n                        help=\"REGEXP exclude filter.\")\n    parser.add_argument(\"-E\", \"--no-enum\", action=\"store_true\", help=\"without enum.\")\n    parser.add_argument(\"-S\", \"--no-struct\", action=\"store_true\", help=\"without struct.\")\n    parser.add_argument(\"-T\", \"--no-typedef\", action=\"store_true\", help=\"without typedef.\")\n    parser.add_argument(\"-U\", \"--no-union\", action=\"store_true\", help=\"without union.\")\n    parser.add_argument(\"-c\", \"--use-cache\", action=\"store_true\", help=\"use previous result.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\", help=\"with the output of `dt` command.\")\n    _syntax_ = parser.format_help()\n\n    def get_type_names(self):\n        \"\"\"Parse and filter type names from GDB's 'info types', skipping basic types and applying\n        user-specified filters.\"\"\"\n        basic_types = [\n            \"char\", \"unsigned char\", \"signed char\",\n            \"int\", \"unsigned int\", \"signed int\",\n            \"short\", \"unsigned short\", \"signed short\",\n            \"long\", \"unsigned long\", \"signed long\",\n            \"long long\", \"unsigned long long\", \"signed long long\",\n            \"float\",\n            \"double\", \"long double\",\n            \"void\",\n            \"bool\",\n        ]\n\n        ret = gdb.execute(\"info types\", to_string=True).strip()\n\n        type_names = []\n        for line in ret.splitlines():\n            if line == \"All defined types:\":\n                continue\n            if line == \"\":\n                continue\n            if line.startswith(\"File \"):\n                continue\n\n            line = re.sub(r\"^\\d+:|;$\", \"\", line).strip()\n            if line in basic_types:\n                continue\n            if self.args.filter and not any(filt.search(line) for filt in self.args.filter):\n                continue\n            if self.args.exclude and any(filt.search(line) for filt in self.args.exclude):\n                continue\n            if self.args.no_enum and line.startswith(\"enum \"):\n                continue\n            if self.args.no_struct and line.startswith(\"struct \"):\n                continue\n            if self.args.no_typedef and line.startswith(\"typedef \"):\n                continue\n            if self.args.no_union and line.startswith(\"union \"):\n                continue\n            type_names.append(line)\n\n        type_names = sorted(set(type_names))\n        return type_names\n\n    def get_types(self):\n        \"\"\"Display type information for each type name, optionally using verbose output and smart formatting.\"\"\"\n        type_names = self.get_type_names()\n\n        # temporarily changed\n        if self.args.smart:\n            old_smart_setting = Config.get_gef_setting(\"context.smart_cpp_function_name\")\n            Config.set_gef_setting(\"context.smart_cpp_function_name\", True)\n\n        # formatting typenames\n        tqdm = GefUtil.get_tqdm()\n        for type_name in tqdm(type_names, leave=False):\n            if self.args.verbose:\n                ret = gdb.execute(\"dt -n {!r}\".format(type_name), to_string=True)\n                if not ret or (\" is not struct or union\" in ret) or (\"Could not find \" in ret):\n                    self.out.append(Instruction.smartify_text(type_name))\n                    self.out.append(\"\")\n                    continue\n                self.out.append(ret)\n            else:\n                self.out.append(Instruction.smartify_text(type_name))\n\n        # revert\n        if self.args.smart:\n            Config.set_gef_setting(\"context.smart_cpp_function_name\", old_smart_setting)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        if args.use_cache and hasattr(self, \"cache\") and self.cache:\n            self.out = self.cache[::]\n            self.print_output()\n            return\n\n        self.out = []\n        self.get_types()\n        self.print_output()\n        self.cache = self.out[::]\n        return\n\n\n@register_command\nclass GefCommand(GenericCommand):\n    \"\"\"The base command of GEF maintenance.\"\"\"\n\n    _cmdline_ = \"gef\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"missing\")\n    subparsers.add_parser(\"config\")\n    subparsers.add_parser(\"save\")\n    subparsers.add_parser(\"restore\")\n    subparsers.add_parser(\"reload\")\n    subparsers.add_parser(\"reset-breakpoint\")\n    subparsers.add_parser(\"reset-cache\")\n    subparsers.add_parser(\"arch-list\")\n    subparsers.add_parser(\"raise-exception\")\n    subparsers.add_parser(\"pyobj-list\")\n    subparsers.add_parser(\"avail-comm-list\")\n    subparsers.add_parser(\"set-arch\")\n    subparsers.add_parser(\"status\")\n    subparsers.add_parser(\"version\")\n    subparsers.add_parser(\"check-update\")\n    subparsers.add_parser(\"tmux-setup\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=True)\n        self.add_setting(\"follow_child\", False, \"Automatically set GDB to follow child when forking\")\n        self.add_setting(\"disable_color\", False, \"Disable all colors in GEF\")\n        self.add_setting(\"always_no_pager\", False, \"Always disable pager in gef_print()\")\n        self.add_setting(\"pager_min_lines\", 11, \"Show pager only if output is longer than this value\")\n        self.add_setting(\"keep_pager_result\", False, \"Leaves temporary files in gef_print()\")\n        self.add_setting(\"less_option\", \"-Rf -j.5\", \"LESS command option used in gef_print()\")\n        # binutils for cross-arch\n        self.add_setting(\"nm_command\", \"nm\", \"nm command (executable name or path)\")\n        self.add_setting(\"objcopy_command\", \"objcopy\", \"objcopy command (executable name or path)\")\n        self.add_setting(\"objdump_command\", \"objdump\", \"objdump command (executable name or path)\")\n        self.add_setting(\"readelf_command\", \"readelf\", \"readelf command (executable name or path)\")\n        self.add_setting(\"cppfilt_command\", \"c++filt\", \"c++filt command (executable name or path)\")\n        # workarounds\n        self.add_setting(\"readline_compat\", False, \"Workaround for readline SOH/ETX issue (SEGV)\")\n        self.add_setting(\"read_memory_work_around_for_aarch64_secure_memory\", False,\n                         \"Workaround for AArch64 secure memory read_memory failures\")\n        self.add_setting(\"physmap_base_for_read_physmem_kgdb_work_around\", 0,\n                         \"Use this address as physmap_base to read physmem if read_physmem is slow in KGDB\")\n        # other\n        self.add_setting(\"kgdb_force\", False, \"Force-enable KGDB mode (for agent-proxy)\")\n        self.add_setting(\"kgdb_system_registers\", False, \"Whether KGDB provides access to system registers\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        gdb.execute(\"gef help\") # for frequent use\n        return\n\n\n@register_command\nclass GefHelpCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display GEF command list.\"\"\"\n\n    _cmdline_ = \"gef help\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def generate_help(self):\n        \"\"\"Generate builtin commands documentation.\"\"\"\n        # get maxlen of cmdline\n        maxlen = max(len(x) for x in __gef_command_instances__.keys())\n\n        # docs of each command\n        docs = []\n        for cmdline, instance in __gef_command_instances__.items():\n            # category\n            category = getattr(instance, \"_category_\", \"Uncategorized\")\n\n            # document\n            doc = getattr(instance.__class__, \"__doc__\", \"\").lstrip()\n            doc = [Color.greenify(x) for x in doc.splitlines()]\n            # Adjust the position assuming there are multiple lines\n            doc = (\"\\n{:<{:d}s}  \".format(\"\", maxlen)).join(doc).rstrip()\n\n            # alias\n            if hasattr(instance._aliases_, \"__iter__\"):\n                if not instance._aliases_:\n                    aliases = \"\"\n                elif isinstance(instance._aliases_, str):\n                    aliases = \" (alias: {:s})\".format(instance._aliases_)\n                else:\n                    aliases = \" (alias: {:s})\".format(\", \".join(instance._aliases_))\n            else:\n                aliases = \"\"\n\n            msg = \"  {:<{:d}s} -- {:s}{:s}\".format(cmdline, maxlen, doc, aliases)\n            docs.append([category, msg])\n\n        docs = sorted(docs)\n\n        def get_major_category(x):\n            if x is None:\n                return None\n            return x.split(\". \")[1].split(\" - \")[0]\n\n        # merging\n        output = []\n        old_category = None\n        for category, msg in docs:\n            # separator\n            draw_separator = False\n            if get_major_category(old_category) != get_major_category(category):\n                draw_separator = True\n            if draw_separator:\n                separator = titlify(get_major_category(category))\n                output.append(separator)\n\n            # headings\n            if old_category != category:\n                category_headings = \"[{:s}]\".format(Color.colorify(category, \"bold yellow\"))\n                output.append(category_headings)\n\n            old_category = category\n            output.append(msg)\n\n        return output\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.out.append(titlify(\"GEF - GDB Enhanced Features\"))\n        self.out.extend(self.generate_help())\n        self.print_output()\n        return\n\n\n@register_command\nclass GefConfigCommand(GenericCommand):\n    \"\"\"Display or change GEF configuration.\"\"\"\n\n    _cmdline_ = \"gef config\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"setting_name\", metavar=\"SETTING_NAME\", nargs=\"?\", help=\"setting name.\")\n    parser.add_argument(\"setting_value\", metavar=\"SETTING_VALUE\", nargs=\"?\", help=\"setting value.\")\n    parser.add_argument(\"-s\", \"--show-only-changes\", action=\"store_true\", help=\"show only changed settings.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(complete=\"use_user_complete\")\n        return\n\n    def print_setting(self, config_name, with_description=False, show_only_changes=False):\n        \"\"\"Print a GEF configuration setting, with optional description and original value,\n        highlighting changes.\"\"\"\n        res = Config.__gef_config__.get(config_name)\n        res_orig = Config.__gef_config_orig__.get(config_name)\n\n        # something is wrong\n        if not res or not res_orig:\n            return\n\n        string_color = Config.get_gef_setting(\"theme.dereference_string\")\n        misc_color = Config.get_gef_setting(\"theme.dereference_base_address\")\n\n        value, type_, desc = res\n        value_orig, _, _ = res_orig\n\n        setting = Color.colorify(config_name, \"green\")\n        type_name = type_.__name__\n        if type_name == \"str\":\n            value = '\"{:s}\"'.format(Color.colorify(value, string_color))\n            value_orig = '\"{:s}\"'.format(Color.colorify(value_orig, string_color))\n        else:\n            value = Color.colorify(value, misc_color)\n            value_orig = Color.colorify(value_orig, misc_color)\n\n        if show_only_changes:\n            if value != value_orig:\n                gef_print(\"{:s} ({:s}) = {:s}   (orig: {:s})\".format(setting, type_name, value, value_orig))\n            # do not print the description\n            return\n\n        gef_print(\"{:s} ({:s}) = {:s}\".format(setting, type_name, value))\n        if with_description:\n            if value != value_orig:\n                gef_print(\"\")\n                gef_print(Color.colorify(\"Original value:\", \"bold underline\"))\n                gef_print(\"{:s} ({:s}) = {:s}\".format(setting, type_name, value_orig))\n            gef_print(\"\")\n            gef_print(Color.colorify(\"Description:\", \"bold underline\"))\n            gef_print(\"{:s}\".format(desc))\n        return\n\n    def set_setting(self, config_name, config_value):\n        \"\"\"Set a GEF configuration value, validating type and command, and updating the cache.\"\"\"\n        if \".\" not in config_name:\n            err(\"Invalid command format\")\n            return\n\n        loaded_cmdlines = [x.replace(\" \", \"_\").replace(\"-\", \"_\") for x in __gef_command_instances__.keys()]\n        command_name = config_name.split(\".\", 1)[0]\n        if command_name not in loaded_cmdlines:\n            err(\"Unknown command '{:s}'\".format(command_name))\n            return\n\n        type_ = Config.__gef_config__.get(config_name, [None, None, None])[1]\n        if type_ is None:\n            err(\"Failed to get '{:s}' config setting\".format(config_name))\n            return\n\n        try:\n            if type_ is bool:\n                if config_value.upper() in (\"TRUE\", \"T\", \"1\"):\n                    newval = True\n                else:\n                    newval = False\n            else:\n                newval = type_(config_value)\n        except Exception:\n            err(\"{} expects type '{}'\".format(config_name, type_.__name__))\n            return\n\n        Config.__gef_config__[config_name][0] = newval\n        Cache.reset_gef_caches(all=True)\n        return\n\n    def complete(self, text, word): # noqa\n        \"\"\"Provide tab-completion suggestions for GEF config settings based on user input.\"\"\"\n        settings = sorted(Config.__gef_config__)\n\n        if text.strip() in settings:\n            # already matched\n            return []\n\n        if text == \"\":\n            # no prefix: example: `gef config TAB`\n            return [s for s in settings if ((word is None) or (s and word in s))]\n\n        if \".\" not in text:\n            # if looking for possible prefix\n            return [s for s in settings if s.startswith(text.strip())]\n\n        # finally, look for possible values for given prefix\n        return [s.split(\".\", 1)[1] for s in settings if s and s.startswith(text.strip())]\n\n    @parse_args\n    def do_invoke(self, args):\n        # list all configs\n        if (args.setting_name, args.setting_value) == (None, None):\n            gef_print(titlify(\"GEF configuration settings\"))\n            for name in sorted(Config.__gef_config__):\n                self.print_setting(name, show_only_changes=args.show_only_changes)\n            return\n\n        # show name-matched config(s)\n        if args.setting_name and args.setting_value is None:\n            names = [x for x in Config.__gef_config__.keys() if x.startswith(args.setting_name)]\n            if not names:\n                return\n            if len(names) == 1 or (args.setting_name in Config.__gef_config__): # uniquely identified or exact match\n                gef_print(titlify(\"GEF configuration setting: {:s}\".format(names[0])))\n                self.print_setting(names[0], with_description=True, show_only_changes=args.show_only_changes)\n            else:\n                gef_print(titlify(\"GEF configuration settings matching '{:s}'\".format(args.setting_name)))\n                for name in names:\n                    self.print_setting(name, show_only_changes=args.show_only_changes)\n            return\n\n        # set config value\n        self.set_setting(args.setting_name, args.setting_value)\n        return\n\n\n@register_command\nclass GefSaveCommand(GenericCommand):\n    \"\"\"Save the current settings to '~/.gef.rc'.\"\"\"\n\n    _cmdline_ = \"gef save\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        cfg = configparser.RawConfigParser()\n        old_sect = None\n\n        # save the configuration\n        for key in sorted(Config.__gef_config__):\n            sect, optname = key.split(\".\", 1)\n            value = Config.__gef_config__.get(key, None)\n            value = value[0] if value else None\n\n            if old_sect != sect:\n                cfg.add_section(sect)\n                old_sect = sect\n\n            cfg.set(sect, optname, value)\n\n        # save the aliases\n        cfg.add_section(\"user-defined-aliases\")\n        cfg.add_section(\"user-defined-aliases.repeat\")\n        for alias in __gef_alias_instances__.values():\n            # check pre-defined alias or not\n            if alias._command_ in __gef_command_instances__:\n                instance = __gef_command_instances__[alias._command_]\n                if alias._alias_ in instance._aliases_:\n                    continue\n\n            cfg.set(\"user-defined-aliases\", alias._alias_, alias._command_)\n            cfg.set(\"user-defined-aliases.repeat\", alias._alias_, str(alias._repeat_))\n\n        with open(GEF_RC, \"w\") as fd:\n            cfg.write(fd)\n\n        self.quiet_ok(\"Configuration saved to '{:s}'\".format(GEF_RC))\n        return\n\n\n@register_command\nclass GefRestoreCommand(GenericCommand):\n    \"\"\"Load settings from '~/.gef.rc'.\"\"\"\n\n    _cmdline_ = \"gef restore\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-q\", \"--quiet\", action=\"store_true\", help=\"quiet execution.\")\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        if not os.access(GEF_RC, os.R_OK):\n            self.quiet_info(\"Could not find {:s}, GEF uses default settings\".format(GEF_RC))\n            return\n\n        cfg = configparser.ConfigParser()\n        cfg.read(GEF_RC)\n\n        for section in cfg.sections():\n            if section == \"user-defined-aliases.repeat\":\n                continue\n\n            if section == \"user-defined-aliases\":\n                # load the aliases\n                for key in cfg.options(section):\n                    repeat = cfg.get(\"user-defined-aliases.repeat\", key)\n                    GefAlias(key, cfg.get(\"user-defined-aliases\", key), force_repeat=repeat)\n                continue\n\n            # load the other options\n            for optname in cfg.options(section):\n                # warn unused setting\n                key = \"{:s}.{:s}\".format(section, optname)\n                if key not in Config.__gef_config__:\n                    err(\"Config '{:s}' is no longer in use, skipping...\".format(Color.boldify(key)))\n                    continue\n\n                # restore type\n                Type = Config.__gef_config__.get(key)[1]\n                new_value = cfg.get(section, optname)\n                try:\n                    if Type is bool:\n                        if new_value == \"True\":\n                            new_value = True\n                        elif new_value == \"False\":\n                            new_value = False\n                        else:\n                            raise ValueError\n                    else:\n                        new_value = Type(new_value)\n                except ValueError:\n                    err(\"Config '{:s}' has bad value, skipping...\".format(Color.boldify(key)))\n                    continue\n\n                # set\n                Config.__gef_config__[key][0] = new_value\n\n        # ensure that the temporary directory always exists\n        abspath = os.path.expanduser(GEF_TEMP_DIR)\n        abspath = os.path.realpath(abspath)\n        if not os.path.isdir(abspath):\n            os.makedirs(abspath, mode=0o755, exist_ok=True)\n\n        self.quiet_ok(\"Configuration from '{:s}' restored\".format(Color.colorify(GEF_RC, \"bold blue\")))\n        return\n\n\n@register_command\nclass GefMissingCommand(GenericCommand):\n    \"\"\"Display the GEF commands that could not be loaded with the reason.\"\"\"\n\n    _cmdline_ = \"gef missing\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"This command only detects commands that could not be loaded when GEF started.\",\n        \"To speed up startup, some commands lazy load required modules and dependencies.\",\n        \"These command cannot be detected.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @parse_args\n    def do_invoke(self, args):\n        missing_commands = Gef.missing_commands.keys()\n        if not missing_commands:\n            ok(\"No missing command\")\n            return\n        for missing_command in missing_commands:\n            reason = Gef.missing_commands[missing_command]\n            warn(\"Command `{}` is missing, reason  ->  {}\".format(missing_command, reason))\n        return\n\n\n@register_command\nclass GefReloadCommand(GenericCommand):\n    \"\"\"Reload the GEF.\"\"\"\n\n    _cmdline_ = \"gef reload\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        info(\"Check syntax {:s}\".format(GEF_FILEPATH))\n\n        try:\n            pythonbin = GefUtil.which(\"python3\")\n        except FileNotFoundError as e:\n            err(\"{}, failed to reload\".format(e))\n            return\n\n        try:\n            subprocess.check_output([pythonbin, GEF_FILEPATH])\n        except subprocess.CalledProcessError:\n            err(\"Reload aborted\")\n            return\n\n        EventHooking.gef_on_continue_unhook(EventHandler.continue_handler)\n        EventHooking.gef_on_stop_unhook(EventHandler.hook_stop_handler)\n        EventHooking.gef_on_new_unhook(EventHandler.new_objfile_handler)\n        EventHooking.gef_on_exit_unhook(EventHandler.exit_handler)\n        EventHooking.gef_on_memchanged_unhook(EventHandler.memchanged_handler)\n        EventHooking.gef_on_regchanged_unhook(EventHandler.regchanged_handler)\n        Cache.reset_gef_caches(all=True)\n\n        info(\"Reload {:s}\".format(GEF_FILEPATH))\n        s = gdb.execute(\"source {:s}\".format(GEF_FILEPATH), to_string=True)\n        for line in s.splitlines():\n            if \".gnu_debugaltlink\" in line:\n                continue\n            if \"No debugging symbols\" in line:\n                continue\n            gef_print(line)\n\n        if current_arch is None:\n            set_arch(get_arch())\n\n        if not (is_qemu_user() or is_pin()):\n            gdb.execute(\"define c\\ncontinue\\nend\")\n\n        Cache.reset_gef_caches(all=True)\n        return\n\n\n@register_command\nclass GefResetCacheCommand(GenericCommand):\n    \"\"\"Reset all caches (both Cache.cache_until_next and Cache.cache_this_session).\"\"\"\n\n    _cmdline_ = \"gef reset-cache\"\n    _category_ = \"99. GEF Maintenance Command\"\n    _aliases_ = [\"reset-cache\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--hard\", action=\"store_true\", help=\"also delete under {:s}.\".format(GEF_TEMP_DIR))\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        Cache.reset_gef_caches(all=True)\n\n        if args.hard:\n            GefUtil.rmdir(GEF_TEMP_DIR, verbose=True, keep_root=True)\n        return\n\n\n@register_command\nclass GefResetBreakpointsCommand(GenericCommand):\n    \"\"\"Show and reset all breakpoints (include internal breakpoints).\"\"\"\n\n    _cmdline_ = \"gef reset-breakpoint\"\n    _category_ = \"99. GEF Maintenance Command\"\n    _aliases_ = [\"reset-breakpoint\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-c\", \"--commit\", action=\"store_true\", help=\"actually perform delete.\")\n    _syntax_ = parser.format_help()\n\n    def get_breakpoint(self, b):\n        if hasattr(b, \"locations\"): # gdb 13.1~\n            for bl in b.locations:\n                if bl and bl.address is not None:\n                    return bl.address\n        else: # for old gdb\n            if b.location and b.location.startswith(\"*\"):\n                pos = b.location.lstrip(\"*\")\n                try:\n                    return int(pos, 16)\n                except ValueError:\n                    pass\n        return None\n\n    @parse_args\n    def do_invoke(self, args):\n        breakpoints = gdb.breakpoints()\n        n = len(breakpoints)\n\n        for bp in breakpoints:\n            bp_str = repr(bp)\n            bp_addr = self.get_breakpoint(bp)\n            if args.commit:\n                bp.delete()\n                if bp_addr is not None:\n                    gef_print(\"Delete successfully: {:s} (@{:#x})\".format(bp_str, bp_addr))\n                else:\n                    gef_print(\"Delete successfully: {:s}\".format(bp_str))\n            else:\n                if bp_addr is not None:\n                    info(\"Breakpoint is found: {:s} (@{:#x})\".format(bp_str, bp_addr))\n                else:\n                    info(\"Breakpoint is found: {:s}\".format(bp_str))\n\n        if not args.commit and n > 0:\n            warn('This dry run mode skips deleting breakpoint; add \"--commit\" to proceed')\n        return\n\n\n@register_command\nclass GefArchListCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display defined architecture information.\"\"\"\n\n    _cmdline_ = \"gef arch-list\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def dump_arch_info(self, arch):\n        \"\"\"Display detailed architecture information, including bit length, endianness,\n        registers, and feature support.\"\"\"\n        if arch.arch == \"HPPA\" and arch.mode == \"64\":\n            # Currently, HPPA-64 is unsupported.\n            # A definition for displaying syscalls is provided, but it is provisional.\n            return\n\n        # title\n        if arch.arch == \"ARM\":\n            arch_name = \"ARM (ARM/THUMB)\"\n        elif arch.arch == arch.mode:\n            arch_name = arch.arch\n        else:\n            arch_name = \"{:s} {:s}\".format(arch.arch, arch.mode)\n        self.out.append(titlify(arch_name))\n\n        # settings\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"bit length\", arch.bit_length))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"endianness\", arch.endianness))\n\n        if arch.arch == \"ARM\":\n            inst_len = \"ARM:4 / THUMB:2or4\"\n        elif arch.instruction_length is None:\n            inst_len = \"variable length\"\n        else:\n            inst_len = str(arch.instruction_length)\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"instruction length\", inst_len))\n\n        if arch.return_register is None:\n            ret_regs = \"different for each system call\"\n        else:\n            ret_regs = str(arch.return_register)\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"return register\", ret_regs))\n\n        fparams = \", \".join(arch.function_parameters)\n        if len(arch.function_parameters) == 1:\n            fparams += \" (passing via stack)\"\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"function parameters\", fparams))\n\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"syscall register\", arch.syscall_register))\n\n        if arch.syscall_parameters is None:\n            sparams = \"different for each system call\"\n        else:\n            sparams = \", \".join(arch.syscall_parameters)\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"syscall parameters\", sparams))\n\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"Has a call/jump delay slot\", arch.has_delay_slot))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"Has a syscall delay slot\", arch.has_syscall_delay_slot))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"Has a ret delay slot\", arch.has_ret_delay_slot))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"Stack grow down\", arch.stack_grow_down))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"Thread Local Storage support\", arch.tls_supported))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"keystone support\", arch.keystone_support))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"capstone support\", arch.capstone_support))\n        self.out.append(\"{:30s}  ->  {!s}\".format(\"unicorn support\", arch.unicorn_support))\n        return\n\n    def listup_arch_info(self):\n        queue = Architecture.__subclasses__()\n        while queue:\n            cls = queue.pop(0)\n            self.dump_arch_info(cls())\n            queue = cls.__subclasses__() + queue\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.listup_arch_info()\n        self.print_output()\n        return\n\n\n@register_command\nclass GefRaiseExceptionCommand(GenericCommand):\n    \"\"\"Raise an exception for development.\"\"\"\n\n    _cmdline_ = \"gef raise-exception\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        raise RuntimeError(\"Test exception\")\n\n\n@register_command\nclass GefPyObjListCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display defined global python object.\"\"\"\n\n    _cmdline_ = \"gef pyobj-list\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def listup_pyobject(self):\n        skip_name_list = [\n            \"__name__\",\n            \"__loader__\",\n            \"__doc__\",\n            \"__spec__\",\n            \"__package__\",\n            \"__annotations__\",\n            \"__warningregistry__\",\n            \"GdbRemoveReadlineFinder\",\n        ]\n\n        skip_type_list = [\n            type(re.compile(\"\")), # regex object\n            type(sys), # module\n        ]\n\n        function_type = type(lambda x:x)\n        class_type = type(GefCommand)\n\n        arch_list = []\n        queue = Architecture.__subclasses__()\n        while queue:\n            cls = queue.pop(0)\n            arch_list.append(cls)\n            queue = cls.__subclasses__() + queue\n\n        global_configs = []\n        classes = []\n        command_classes = []\n        bp_classes = []\n        arch_classes = []\n        arch_determinations = []\n        gdb_mode_determinations = []\n        decorators = []\n        syscall_defines = []\n        gef_print_wrappers = []\n        read_write_mems = []\n        others = []\n\n        for gobj in dir(sys.modules[\"__main__\"]): # for global object\n            # skip specific\n            if gobj in skip_name_list:\n                continue\n\n            obj = getattr(sys.modules[\"__main__\"], gobj)\n            t = type(obj)\n\n            # skip specific type\n            if t in skip_type_list:\n                continue\n\n            # classify\n            if gobj.startswith(\"__\") and t is not function_type:\n                global_configs.append(\"{!s} {!s}\".format(t, gobj))\n            elif gobj in [\"current_arch\"]:\n                t = type(get_current_arch())\n                global_configs.append(\"{!s} {!s}\".format(t, gobj))\n            elif gobj.upper() == gobj and t is not class_type:\n                global_configs.append(\"{!s} {!s}\".format(t, gobj))\n            elif t is class_type:\n                if gobj.endswith(\"Command\"):\n                    command_classes.append(\"{!s} {!s}\".format(t, gobj))\n                elif gobj.endswith(\"Breakpoint\") or gobj.endswith(\"Watchpoint\"):\n                    bp_classes.append(\"{!s} {!s}\".format(t, gobj))\n                elif obj in arch_list:\n                    arch_classes.append(\"{!s} {!s}\".format(t, gobj))\n                else:\n                    classes.append(\"{!s} {!s}\".format(t, gobj))\n            elif obj.__doc__ and obj.__doc__.startswith(\"Architecture determination function\"):\n                arch_determinations.append(\"{!s} {!s}\".format(t, gobj))\n            elif obj.__doc__ and obj.__doc__.startswith(\"GDB mode determination function\"):\n                gdb_mode_determinations.append(\"{!s} {!s}\".format(t, gobj))\n            elif obj.__doc__ and obj.__doc__.startswith(\"Decorator\"):\n                decorators.append(\"{!s} {!s}\".format(t, gobj))\n            elif gobj.endswith((\"syscall_tbl\", \"syscall_list\")) or gobj.startswith(\"syscall_defs\"):\n                syscall_defines.append(\"{!s} {!s}\".format(t, gobj))\n            elif obj.__doc__ and obj.__doc__.startswith(\"The wrapper of gef_print\"):\n                gef_print_wrappers.append(\"{!s} {!s}\".format(t, gobj))\n            elif re.match(r\"(read|write)_.*(memory|physmem).*\", gobj):\n                read_write_mems.append(\"{!s} {!s}\".format(t, gobj))\n            else:\n                others.append(\"{!s} {!s}\".format(t, gobj))\n\n        self.out.append(titlify(\"GEF global configs\"))\n        self.out.extend(sorted(global_configs))\n        self.out.append(titlify(\"Command classes\"))\n        self.out.extend(sorted(command_classes))\n        self.out.append(titlify(\"Breakpoint classes\"))\n        self.out.extend(sorted(bp_classes))\n        self.out.append(titlify(\"Architecture classes\"))\n        self.out.extend(sorted(arch_classes))\n        self.out.append(titlify(\"Architecture determination function\"))\n        self.out.extend(sorted(arch_determinations))\n        self.out.append(titlify(\"GDB mode determination function\"))\n        self.out.extend(sorted(gdb_mode_determinations))\n        self.out.append(titlify(\"Classes\"))\n        self.out.extend(sorted(classes))\n        self.out.append(titlify(\"Syscall defines\"))\n        self.out.extend(sorted(syscall_defines))\n        self.out.append(titlify(\"Decorators\"))\n        self.out.extend(sorted(decorators))\n        self.out.append(titlify(\"gef_print wrapper\"))\n        self.out.extend(sorted(gef_print_wrappers))\n        self.out.append(titlify(\"read/write memory functions\"))\n        self.out.extend(sorted(read_write_mems))\n        self.out.append(titlify(\"Other functions\"))\n        self.out.extend(sorted(others))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.out = []\n        self.listup_pyobject()\n        self.print_output()\n        return\n\n\n@register_command\nclass GefAvailableCommandListCommand(GenericCommand, BufferingOutput):\n    \"\"\"Display a list of commands available for the current architecture and gdb execution mode.\"\"\"\n\n    _cmdline_ = \"gef avail-comm-list\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-s\", \"--sort\", action=\"store_true\", help=\"sort by command name.\")\n    parser.add_argument(\"-a\", \"--only-available\", action=\"store_true\", help=\"show only available commands.\")\n    parser.add_argument(\"-u\", \"--only-unavailable\", action=\"store_true\", help=\"show only unavailable commands.\")\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def check_require_arch_set(self, decorators):\n        for line in decorators:\n            if \"@require_arch_set\" in line:\n                return current_arch is None\n        return False\n\n    def check_include_mode(self, decorators):\n        for line in decorators:\n            if \"@only_if_specific_gdb_mode\" in line:\n                if is_pin():\n                    return '\"pin\"' in line\n                if is_qemu_system():\n                    return '\"qemu-system\"' in line\n                if is_qemu_user():\n                    return '\"qemu-user\"' in line\n                if is_vmware():\n                    return '\"vmware\"' in line\n                if is_qiling():\n                    return '\"qiling\"' in line\n                if is_rr():\n                    return '\"rr\"' in line\n                if is_wine():\n                    return '\"wine\"' in line\n                if is_kgdb():\n                    return '\"kgdb\"' in line\n                return False\n        return True\n\n    def check_exclude_mode(self, decorators):\n        for line in decorators:\n            if \"@exclude_specific_gdb_mode\" in line:\n                if is_pin():\n                    return '\"pin\"' in line\n                if is_qemu_system():\n                    return '\"qemu-system\"' in line\n                if is_qemu_user():\n                    return '\"qemu-user\"' in line\n                if is_vmware():\n                    return '\"vmware\"' in line\n                if is_qiling():\n                    return '\"qiling\"' in line\n                if is_rr():\n                    return '\"rr\"' in line\n                if is_wine():\n                    return '\"wine\"' in line\n                if is_kgdb():\n                    return '\"kgdb\"' in line\n                return False\n        return False\n\n    def get_arch_name(self):\n        s = GefUtil.get_source(only_if_specific_arch).replace(\"\\n\", \"\")\n        r = re.search(r\"dic = (\\{.*\\})\", s)\n        dic = eval(r.group(1))\n\n        for arch, func in dic.items():\n            if func():\n                return '\"{:s}\"'.format(arch)\n        return None\n\n    def check_include_arch(self, decorators, arch_name):\n        for line in decorators:\n            if \"@only_if_specific_arch\" in line:\n                return str(arch_name) in line\n        return True\n\n    def check_exclude_arch(self, decorators, arch_name):\n        for line in decorators:\n            if \"@exclude_specific_arch\" in line:\n                return str(arch_name) in line\n        return False\n\n    def check_load_package(self, decorators, dec_name, import_name):\n        for line in decorators:\n            if dec_name in line:\n                try:\n                    readline = sys.modules.get(\"readline\", None)\n                    sys.modules[\"readline\"] = None\n                    __import__(import_name)\n                    sys.modules[\"readline\"] = readline\n                except ImportError:\n                    return False\n                return True\n        return True\n\n    def add_out(self, cmdline, avail, msg=\"\"):\n        if self.args.only_available and not avail:\n            return\n        if self.args.only_unavailable and avail:\n            return\n        if avail:\n            self.out.append(\"{:<34s}: {:s}\".format(\n                cmdline, Color.colorify(\"Available\", \"bold green\"),\n            ))\n        else:\n            self.out.append(\"{:<34s}: {:s} ({:s})\".format(\n                cmdline, Color.colorify(\"Unavailable\", \"bold red\"), msg,\n            ))\n        return\n\n    def listup_avail_comms(self):\n        arch_name = self.get_arch_name()\n        for cmdline, instance in __gef_command_instances__.items():\n            s = GefUtil.get_source(instance.do_invoke)\n            decorators = [line for line in s.splitlines() if line.lstrip().startswith(\"@\")]\n            if self.check_require_arch_set(decorators):\n                self.add_out(cmdline, False, \"current_arch is None\")\n                continue\n            if not self.check_include_arch(decorators, arch_name):\n                self.add_out(cmdline, False, \"Unsupported arch\")\n                continue\n            if self.check_exclude_arch(decorators, arch_name):\n                self.add_out(cmdline, False, \"Unsupported arch\")\n                continue\n            if not self.check_include_mode(decorators):\n                self.add_out(cmdline, False, \"Unsupported gdb mode\")\n                continue\n            if self.check_exclude_mode(decorators):\n                self.add_out(cmdline, False, \"Unsupported gdb mode\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_capstone\", \"capstone\"):\n                self.add_out(cmdline, False, \"capstone package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_unicorn\", \"unicorn\"):\n                self.add_out(cmdline, False, \"unicorn package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_keystone\", \"keystone\"):\n                self.add_out(cmdline, False, \"keystone-engine package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_ropper\", \"ropper\"):\n                self.add_out(cmdline, False, \"ropper package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_binwalk\", \"binwalk\"):\n                self.add_out(cmdline, False, \"binwalk package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_crccheck\", \"crccheck\"):\n                self.add_out(cmdline, False, \"crccheck package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_codext\", \"codext\"):\n                self.add_out(cmdline, False, \"codext package is unavailable\")\n                continue\n            if not self.check_load_package(decorators, \"@ModuleLoader.load_angr\", \"angr\"):\n                self.add_out(cmdline, False, \"angr package is unavailable\")\n                continue\n            self.add_out(cmdline, True)\n        return\n\n    @parse_args\n    @only_if_gdb_running\n    def do_invoke(self, args):\n        self.out = []\n        self.listup_avail_comms()\n        if args.sort:\n            self.out = sorted(self.out)\n        self.print_output(check_terminal_size=True)\n        return\n\n\n@register_command\nclass GefSetArchCommand(GenericCommand):\n    \"\"\"Set a specific architecture to gef.\"\"\"\n\n    _cmdline_ = \"gef set-arch\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    group = parser.add_mutually_exclusive_group(required=True)\n    group.add_argument(\"arch\", metavar=\"ARCH\", nargs=\"?\", help=\"target architecture.\")\n    group.add_argument(\"-l\", \"--list\", action=\"store_true\", help=\"show supported architecture words.\")\n    _syntax_ = parser.format_help()\n\n    def arch_listup(self):\n        fmt = \"{:12s} {:s}\"\n        legend = [\"Arch\", \"Available names (Case insensitive)\"]\n        gef_print(GefUtil.make_legend(fmt.format(*legend)))\n\n        queue = Architecture.__subclasses__()\n        while queue:\n            cls = queue.pop(0)\n            queue = cls.__subclasses__() + queue\n\n            arch = Color.boldify(\"{:12s}\".format(cls.__name__))\n            words = \", \".join(filter(lambda x: isinstance(x, str), cls.load_condition))\n            gef_print(\"{:s} {:s}\".format(arch, words))\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.list:\n            self.arch_listup()\n            return\n\n        try:\n            set_arch(args.arch)\n            info(\"set_arch({:s}) is successfully\".format(args.arch))\n            Cache.reset_gef_caches(all=True)\n        except OSError:\n            err(\"set_arch({:s}) is failed\".format(args.arch))\n        return\n\n\n@register_command\nclass GefStatusCommand(GenericCommand):\n    \"\"\"Display current gef status.\"\"\"\n\n    _cmdline_ = \"gef status\"\n    _category_ = \"99. GEF Maintenance Command\"\n    _aliases_ = [\"arch-info\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        gef_print(titlify(\"GDB/ELF settings\"))\n        show_arch = gdb.execute(\"show architecture\", to_string=True).rstrip()\n        gef_print(\"{:30s}  ->  {:s}\".format(\"show architecture\", show_arch))\n        if is_64bit():\n            bit_str = \"64-bit\"\n        else:\n            bit_str = \"32-bit\"\n        if Endian.is_big_endian():\n            endian_str = \"big\"\n        else:\n            endian_str = \"little\"\n        gef_print(\"{:30s}  ->  {:s}\".format(\"bit\", bit_str))\n        gef_print(\"{:30s}  ->  {:s}\".format(\"endian\", endian_str))\n\n        gef_print(titlify(\"GDB mode\"))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_normal_run()\", is_normal_run()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_attach()\", is_attach()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_remote_debug()\", is_remote_debug()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_container_attach()\", is_container_attach()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_qemu_system()\", is_qemu_system()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_qemu_user()\", is_qemu_user()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_pin()\", is_pin()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_over_serial()\", is_over_serial()))\n        kgdb_forced = \" (forced)\" if Config.get_gef_setting(\"gef.kgdb_force\") is True else \"\"\n        gef_print(\"{:30s}  ->  {!s}{:s}\".format(\"is_kgdb()\", is_kgdb(), kgdb_forced))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_kdb()\", is_kdb()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_qiling()\", is_qiling()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_vmware()\", is_vmware()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_in_kernel()\", is_in_kernel()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_in_secure()\", is_in_secure()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_rr()\", is_rr()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_wine()\", is_wine()))\n\n        gef_print(titlify(\"Others\"))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_alive()\", is_alive()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_kvm_enabled()\", is_kvm_enabled()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_smp_enabled()\", is_smp_enabled()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_support_secure_world()\", is_support_secure_world()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"is_supported_physmode()\", is_supported_physmode()))\n        if is_supported_physmode():\n            gef_print(\"{:30s}  ->  {!s}\".format(\"get_current_mmu_mode()\", QemuMonitor.get_current_mmu_mode()))\n\n        gef_print(titlify(\"GEF architecture information\"))\n        if current_arch is None:\n            gef_print(\"{:30s}  ->  None\".format(\"current_arch\"))\n            gef_print(\"{:30s}  ->  {!s}\".format(\"ptrsize\", AddressUtil.ptr_width()))\n            return\n        gef_print(\"{:30s}  ->  {!s}\".format(\"current_arch.arch\", current_arch.arch))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"current_arch.mode\", current_arch.mode))\n        if is_arm32() or is_arm32_cortex_m():\n            gef_print(\"{:30s}  ->  {!s}\".format(\"current_arch.is_cortex_m()\", current_arch.is_cortex_m()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"current_arch.ptrsize\", current_arch.ptrsize))\n\n        if current_arch.instruction_length is None:\n            inst_len = \"variable length\"\n        else:\n            inst_len = str(current_arch.instruction_length)\n        gef_print(\"{:30s}  ->  {!s}\".format(\"instruction length\", inst_len))\n\n        if current_arch.return_register is None:\n            ret_regs = \"different for each system call\"\n        else:\n            ret_regs = str(current_arch.return_register)\n        gef_print(\"{:30s}  ->  {!s}\".format(\"return register\", ret_regs))\n\n        fparams = \", \".join(current_arch.function_parameters)\n        if len(current_arch.function_parameters) == 1:\n            fparams += \" (passing via stack)\"\n        gef_print(\"{:30s}  ->  {!s}\".format(\"function parameters\", fparams))\n\n        gef_print(\"{:30s}  ->  {!s}\".format(\"syscall register\", current_arch.syscall_register))\n\n        if current_arch.syscall_parameters is None:\n            sparams = \"different for each system call\"\n        else:\n            sparams = \", \".join(current_arch.syscall_parameters)\n        gef_print(\"{:30s}  ->  {!s}\".format(\"syscall parameters\", sparams))\n\n        if is_x86() or is_arm32() or is_arm64():\n            gef_print(\"{:30s}  ->  {!s}\".format(\"32bit-emulated (compat mode)\", is_emulated32()))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"Has a call/jump delay slot\", current_arch.has_delay_slot))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"Has a syscall delay slot\", current_arch.has_syscall_delay_slot))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"Has a ret delay slot\", current_arch.has_ret_delay_slot))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"Stack grow down\", current_arch.stack_grow_down))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"Thread Local Storage support\", current_arch.tls_supported))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"keystone support\", current_arch.keystone_support))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"capstone support\", current_arch.capstone_support))\n        gef_print(\"{:30s}  ->  {!s}\".format(\"unicorn support\", current_arch.unicorn_support))\n        return\n\n\n@register_command\nclass GefVersionCommand(GenericCommand):\n    \"\"\"Display GEF version info.\"\"\"\n\n    _cmdline_ = \"gef version\"\n    _category_ = \"99. GEF Maintenance Command\"\n    _aliases_ = [\"version\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"--compact\", action=\"store_true\", help=\"show compact style.\")\n    _syntax_ = parser.format_help()\n\n    def os_version(self):\n        try:\n            lsb_release_command = GefUtil.which(\"lsb_release\")\n            res = GefUtil.gef_execute_external([lsb_release_command, \"-d\"], as_list=True)\n            for line in res:\n                if line.startswith(\"Description:\"):\n                    return line.split(\":\")[1].strip()\n        except FileNotFoundError:\n            pass\n\n        if os.path.exists(\"/etc/issue.net\"):\n            content = open(\"/etc/issue.net\").read().strip()\n            if content:\n                return content\n\n        if os.path.exists(\"/etc/issue\"):\n            content = open(\"/etc/issue\").read().strip()\n            content = content.replace(\" \\\\n \\\\l\", \"\")\n            if content:\n                return content\n\n        if os.path.exists(\"/etc/os-release\"):\n            content = open(\"/etc/os-release\").read()\n            for line in content.splitlines():\n                r = re.search(r'PRETTY_NAME=\"(.+)\"', line)\n                if r:\n                    return r.group(1)\n\n        return \"Not found\"\n\n    def kernel_version_from_uname(self):\n        try:\n            uname_command = GefUtil.which(\"uname\")\n            res = GefUtil.gef_execute_external([uname_command, \"-a\"], as_list=True)\n            return res[0]\n        except FileNotFoundError:\n            return \"Not found\"\n\n    def kernel_version_from_proc(self):\n        try:\n            return open(\"/proc/version\").read().strip()\n        except FileNotFoundError:\n            return \"Not found\"\n\n    def system_libc_version(self):\n        res = GefUtil.gef_execute_external([\"cat\", \"/proc/self/maps\"], as_list=True)\n        libc_targets = (\"libc-2.\", \"libc.so.6\", \"libuClibc-\")\n        for line in res:\n            if not any(kw in line for kw in libc_targets):\n                continue\n            path = line.split()[-1]\n            if not os.path.exists(path):\n                continue\n            data = open(path, \"rb\").read()\n            pos = re.search(b\"(GNU C Library|uClibc-ng release) [\\x20-\\x7e]*\", data)\n            if pos:\n                return String.bytes2str(pos.group(0))\n        return \"Not found\"\n\n    def qemu_system_version(self):\n        return gdb.execute(\"monitor info version\", to_string=True).strip()\n\n    def qemu_user_version(self):\n        pid = Pid.get_pid()\n        try:\n            res = GefUtil.gef_execute_external([\"/proc/{:d}/exe\".format(pid), \"--version\"], as_list=True)\n            return res[0].strip()\n        except (IndexError, FileNotFoundError):\n            return \"Not recognized\"\n\n    def gef_version(self):\n        gef_hash = hashlib.sha1(open(GEF_FILEPATH, \"rb\").read()).hexdigest()\n        dt = datetime.datetime.fromtimestamp(os.stat(GEF_FILEPATH).st_mtime)\n        return \"Last modified: {} SHA1: {}\".format(dt.strftime(\"%Y-%m-%d %H:%M:%S\"), gef_hash)\n\n    def gdb_version(self):\n        try:\n            return gdb.VERSION # GDB >= 8.1 (or earlier?)\n        except AttributeError:\n            return gdb.execute(\"show version\", to_string=True).split(\"\\n\")[0]\n\n    def python_version(self):\n        return sys.version.replace(\"\\n\", \" \")\n\n    def capstone_version(self):\n\n        @ModuleLoader.load_capstone\n        def _capstone_version():\n            capstone = sys.modules[\"capstone\"]\n            return \".\".join(map(str, capstone.cs_version()))\n\n        try:\n            return _capstone_version()\n        except (KeyError, ImportWarning):\n            return \"Not found\"\n\n    def keystone_version(self):\n\n        @ModuleLoader.load_keystone\n        def _keystone_version():\n            keystone = sys.modules[\"keystone\"]\n            return \".\".join(map(str, keystone.ks_version()))\n\n        try:\n            return _keystone_version()\n        except (KeyError, ImportWarning):\n            return \"Not found\"\n\n    def unicorn_version(self):\n\n        @ModuleLoader.load_unicorn\n        def _unicorn_version():\n            unicorn = sys.modules[\"unicorn\"]\n            return unicorn.__version__\n\n        try:\n            return _unicorn_version()\n        except (KeyError, ImportWarning):\n            return \"Not found\"\n\n    def ropper_version(self):\n\n        @ModuleLoader.load_ropper\n        def _ropper_version():\n            ropper = sys.modules[\"ropper\"]\n            return \".\".join(map(str, ropper.VERSION))\n\n        try:\n            return _ropper_version()\n        except (KeyError, ImportWarning, AttributeError):\n            return \"Not found\"\n\n    def angr_version(self):\n\n        @ModuleLoader.load_angr\n        def _angr_version():\n            angr = sys.modules[\"angr\"]\n            return angr.__version__\n\n        try:\n            return _angr_version()\n        except (KeyError, ImportWarning, AttributeError):\n            return \"Not found\"\n\n    def gcc_version(self):\n        try:\n            gcc_command = GefUtil.which(\"gcc\")\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([gcc_command, \"--version\"], as_list=True)\n        return res[0]\n\n    def readelf_version(self):\n        try:\n            readelf_command = GefUtil.which(Config.get_gef_setting(\"gef.readelf_command\"))\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([readelf_command, \"-v\"], as_list=True)\n        return res[0]\n\n    def objdump_version(self):\n        try:\n            objdump_command = GefUtil.which(Config.get_gef_setting(\"gef.objdump_command\"))\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([objdump_command, \"-v\"], as_list=True)\n        return res[0]\n\n    def seccomp_tools_version(self):\n        try:\n            seccomp_tools_command = GefUtil.which(\"seccomp-tools\")\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([seccomp_tools_command, \"--version\"], as_list=True)\n        return res[0]\n\n    def ceccomp_version(self):\n        try:\n            ceccomp_command = GefUtil.which(\"ceccomp\")\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([ceccomp_command, \"version\"], as_list=True)\n        return res[0]\n\n    def one_gadget_version(self):\n        try:\n            one_gadget_command = GefUtil.which(\"one_gadget\")\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([one_gadget_command, \"--version\"], as_list=True)\n        return res[0]\n\n    def rp_version(self):\n        try:\n            rp_lin_command = GefUtil.which(\"rp-lin\")\n        except FileNotFoundError:\n            return \"Not found\"\n        res = GefUtil.gef_execute_external([rp_lin_command, \"--version\", \"--file\", \"a\"], as_list=True)\n        if \"You are currently using \" in res[0]:\n            return res[0].replace(\"You are currently using \", \"\")\n        return \"Not found\"\n\n    def show_compact_info(self):\n        gef_print(\"gdb:     {:s}\".format(self.gdb_version()))\n        gef_print(\"python:  {:s}\".format(self.python_version()))\n        gef_print(\"OS:      {:s}\".format(self.os_version()))\n        gef_print(\"kernel:  {:s}\".format(self.kernel_version_from_uname()))\n        if is_qemu_system():\n            gef_print(\"qemu:    {:s}\".format(self.qemu_system_version()))\n        return\n\n    def show_full_info(self):\n        gef_print(titlify(\"versions\"))\n        gef_print(\"OS:                     {:s}\".format(self.os_version()))\n        gef_print(\"kernel (uname -a):      {:s}\".format(self.kernel_version_from_uname()))\n        gef_print(\"kernel (/proc/version): {:s}\".format(self.kernel_version_from_proc()))\n        gef_print(\"System libc:            {:s}\".format(self.system_libc_version()))\n        if is_qemu_system():\n            gef_print(\"qemu:                   {:s}\".format(self.qemu_system_version()))\n        if is_qemu_user():\n            gef_print(\"qemu:                   {:s}\".format(self.qemu_user_version()))\n        gef_print(\"GEF:                    {:s}\".format(self.gef_version()))\n        gef_print(\"gdb:                    {:s}\".format(self.gdb_version()))\n        gef_print(\"python:                 {:s}\".format(self.python_version()))\n        gef_print(\"capstone:               {:s}\".format(self.capstone_version()))\n        gef_print(\"keystone:               {:s}\".format(self.keystone_version()))\n        gef_print(\"unicorn:                {:s}\".format(self.unicorn_version()))\n        gef_print(\"ropper:                 {:s}\".format(self.ropper_version()))\n        gef_print(\"angr:                   {:s}\".format(self.angr_version()))\n        gef_print(\"gcc:                    {:s}\".format(self.gcc_version()))\n        gef_print(\"readelf:                {:s}\".format(self.readelf_version()))\n        gef_print(\"objdump:                {:s}\".format(self.objdump_version()))\n        gef_print(\"seccomp-tools:          {:s}\".format(self.seccomp_tools_version()))\n        gef_print(\"ceccomp:                {:s}\".format(self.ceccomp_version()))\n        gef_print(\"one_gadget:             {:s}\".format(self.one_gadget_version()))\n        gef_print(\"rp:                     {:s}\".format(self.rp_version()))\n\n        gef_print(titlify(\"gdb build config\"))\n        gdb.execute(\"show configuration\")\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.compact:\n            self.show_compact_info()\n        else:\n            self.show_full_info()\n        return\n\n\n@register_command\nclass GefCheckUpdateCommand(GenericCommand):\n    \"\"\"Check for gef updates.\"\"\"\n\n    _cmdline_ = \"gef check-update\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    _syntax_ = parser.format_help()\n\n    @parse_args\n    def do_invoke(self, args):\n        gef_remote = \"https://raw.githubusercontent.com/bata24/gef/dev/gef.py\"\n        gef_remote_data = http_get(gef_remote)\n\n        if gef_remote_data is None:\n            err(\"[-] Failed to get remote gef\")\n            return\n\n        hash_gef_local = hashlib.sha512(open(GEF_FILEPATH, \"rb\").read()).digest()\n        hash_gef_remote = hashlib.sha512(gef_remote_data).digest()\n\n        if hash_gef_local == hash_gef_remote:\n            info(\"No update\")\n        else:\n            info(\"Update found, try `python3 {:s} --upgrade`\".format(GEF_FILEPATH))\n        return\n\n\n@register_command\nclass GefTmuxSetupCommand(GenericCommand):\n    \"\"\"Setup a comfortable tmux environment.\"\"\"\n\n    _cmdline_ = \"gef tmux-setup\"\n    _category_ = \"99. GEF Maintenance Command\"\n    _aliases_ = [\"tmux-setup\"]\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-r\", \"--reset\", action=\"store_true\", help=\"reset all panes.\")\n    _syntax_ = parser.format_help()\n\n    _note_ = [\n        \"- `screen` is no longer supported.\",\n        \"\",\n        \"- `tmux` settings are predefined and cannot be customized in this command.\",\n        \"- If you want to customize it, edit `tmux_setup.py` and run `source /path/to/tmux_setup.py`.\",\n        \"- It can be found in https://github.com/bata24/gef/blob/dev/dev/tmux/tmux_setup.py.\",\n        \"\",\n        \"- There is experimental support for `zellij` using a similar script.\",\n        \"- Try starting `zellij-wrapper.py` in your shell (before starting `zellij` and `gdb`).\",\n        \"- It can be found in https://github.com/bata24/gef/blob/dev/dev/zellij/zellij-wrapper.py.\",\n    ]\n    _note_ = \"\\n\".join(_note_)\n\n    @staticmethod\n    def get_redirect_configs():\n        configs = [\n            \"context.redirect\",\n            \"context_args.redirect\",\n            \"context_code.redirect\",\n            \"context_extra.redirect\",\n            \"context_legend.redirect\",\n            \"context_mem_access.redirect\",\n            \"context_mem_watch.redirect\",\n            \"context_regs.redirect\",\n            \"context_source.redirect\",\n            \"context_stack.redirect\",\n            \"context_threads.redirect\",\n            \"context_trace.redirect\",\n        ]\n        return configs\n\n    @staticmethod\n    def get_tty_gef_used():\n        \"\"\"Return a set of TTYs currently used by GEF for tmux redirection.\"\"\"\n        tty_gef_used = [Config.get_gef_setting(c) for c in GefTmuxSetupCommand.get_redirect_configs()]\n        tty_gef_used = [x for x in tty_gef_used if x] # filter \"\"\n        return set(tty_gef_used)\n\n    @staticmethod\n    def reset_panes():\n        \"\"\"Reset tmux panes used by GEF, killing relevant panes and clearing related configurations.\"\"\"\n        # list panes\n        tmux = GefUtil.which(\"tmux\")\n        res = subprocess.check_output([\n            tmux, \"list-panes\", \"-F#{pane_active}:#{pane_id}:#{pane_tty}\"\n        ]).decode(\"utf-8\").strip()\n\n        # kill panes\n        tty_gef_used = GefTmuxSetupCommand.get_tty_gef_used()\n        for line in res.splitlines():\n            pane_active, pane_id, pane_tty = line.split(\":\")\n            if pane_active == \"1\":\n                continue\n            if pane_tty not in tty_gef_used:\n                continue\n            subprocess.run([tmux, \"kill-pane\", \"-t\", pane_id])\n\n        # reset config\n        for config in GefTmuxSetupCommand.get_redirect_configs():\n            gdb.execute('gef config {:s} \"\"'.format(config))\n\n        # remove destructor\n        import atexit\n        try:\n            atexit.unregister(GefTmuxSetupCommand.reset_panes)\n        except Exception:\n            pass\n        return\n\n    def tmux_setup(self):\n        \"\"\"Prepare the tmux environment by vertically splitting and redirect context output.\"\"\"\n        # reset previous settings\n        tmux = GefUtil.which(\"tmux\")\n        if self.get_tty_gef_used():\n            warn(\"Since it is already split, discard previous screen\")\n            GefTmuxSetupCommand.reset_panes()\n\n        # split\n        ok(\"tmux session found, splitting window...\")\n        pane_id, pane_tty = subprocess.check_output([\n            tmux, \"splitw\", \"-h\", \"-F#{pane_id}:#{pane_tty}\", \"-P\",\n        ]).decode(\"utf-8\").strip().split(\":\")\n\n        # add destructor\n        import atexit\n        atexit.register(GefTmuxSetupCommand.reset_panes)\n\n        # clear the screen and let it wait for input forever\n        gdb.execute(f\"!'{tmux}' send-keys -t {pane_id} 'clear ; cat' C-m\")\n        gdb.execute(f\"!'{tmux}' select-pane -L\")\n\n        ok(f\"Setting `context.redirect` to '{pane_tty}'...\")\n        gdb.execute(f\"gef config context.redirect {pane_tty}\")\n\n        Cache.reset_gef_caches(all=True)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        try:\n            GefUtil.which(\"tmux\")\n        except FileNotFoundError as e:\n            err(\"{}\".format(e))\n            return\n\n        if args.reset:\n            GefTmuxSetupCommand.reset_panes()\n            return\n\n        if os.getenv(\"TMUX\"):\n            self.tmux_setup()\n            return\n\n        warn(\"Not in a tmux session\")\n        return\n\n\nclass GefAlias(gdb.Command):\n    \"\"\"Simple aliasing wrapper because GDB doesn't do what it should.\"\"\"\n\n    _category_ = \"99. GEF Maintenance Command\"\n\n    def __init__(self, alias, command, force_repeat=None, pre_defined=False):\n        p = command.split()\n        if not p:\n            return\n\n        # initialize\n        self._alias_ = alias\n        self._command_ = command\n        if force_repeat is None:\n            self._repeat_ = False\n        else:\n            self._repeat_ = force_repeat\n        self._pre_defined_ = pre_defined # default alias settings of GEF\n        self.__doc__ = \"Alias for '{:s}'\".format(Color.greenify(command))\n\n        # Inherit settings from the aliased command\n        instance = __gef_command_instances__.get(command, None)\n        if instance:\n            # repeat settings\n            if force_repeat is None:\n                self._repeat_ = instance._repeat_\n\n            # doc\n            self.__doc__ += \": {:s}\".format(instance.__doc__)\n\n            # complete settings\n            if hasattr(instance, \"complete\"):\n                self.complete = instance.complete\n\n        # define aliased command\n        if hasattr(instance, \"complete\"):\n            # Aliased commands support only user completion.\n            super().__init__(alias, gdb.COMMAND_NONE)\n        else:\n            super().__init__(alias, gdb.COMMAND_NONE, gdb.COMPLETE_NONE)\n\n        # add or overwrite\n        global __gef_alias_instances__\n        __gef_alias_instances__[alias] = self\n        return\n\n    def invoke(self, args, from_tty): # noqa\n        if not self._repeat_:\n            self.dont_repeat()\n        gdb.execute(\"{} {}\".format(self._command_, args), from_tty=from_tty)\n        return\n\n\n@register_command\nclass AliasesCommand(GenericCommand):\n    \"\"\"The base command to add, remove or list aliases.\"\"\"\n\n    _cmdline_ = \"aliases\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    if (sys.version_info.major, sys.version_info.minor) >= (3, 7):\n        subparsers = parser.add_subparsers(title=\"command\", required=True)\n    else:\n        subparsers = parser.add_subparsers(title=\"command\")\n    subparsers.add_parser(\"add\")\n    subparsers.add_parser(\"rm\")\n    subparsers.add_parser(\"ls\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self, *args, **kwargs):\n        prefix = kwargs.get(\"prefix\", True)\n        super().__init__(prefix=prefix)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        self.usage()\n        return\n\n\n@register_command\nclass AliasesAddCommand(AliasesCommand):\n    \"\"\"Add the command alias.\"\"\"\n\n    _cmdline_ = \"aliases add\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"alias\", metavar=\"ALIAS\", help=\"the name of new alias.\")\n    parser.add_argument(\"command\", metavar=\"COMMAND\", nargs=\"+\", help=\"the command of new alias.\")\n    parser.add_argument(\"-r\", \"--repeat\", action=\"store_true\", help=\"enforce repeat feature.\")\n    _syntax_ = parser.format_help()\n\n    _example_ = [\n        \"{0:s} scope telescope\",\n    ]\n    _example_ = \"\\n\".join(_example_).format(_cmdline_)\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        if args.alias in __gef_command_instances__:\n            err(\"Not allowed due to circular references\")\n            return\n        command = \" \".join(args.command)\n        GefAlias(args.alias, command, force_repeat=args.repeat)\n        gef_print(\"{:s} = {:s}\".format(args.alias, command))\n        return\n\n\n@register_command\nclass AliasesRmCommand(AliasesCommand):\n    \"\"\"Remove the command alias.\"\"\"\n\n    _cmdline_ = \"aliases rm\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"alias\", metavar=\"ALIAS\", help=\"the name of alias to be deleted.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        global __gef_alias_instances__\n\n        if args.alias in __gef_alias_instances__:\n            del __gef_alias_instances__[args.alias]\n        else:\n            err(\"Could not find {:s} in aliases\".format(args.alias))\n        return\n\n\n@register_command\nclass AliasesListCommand(AliasesCommand, BufferingOutput):\n    \"\"\"List the command alias.\"\"\"\n\n    _cmdline_ = \"aliases ls\"\n    _category_ = \"99. GEF Maintenance Command\"\n\n    parser = argparse.ArgumentParser(prog=_cmdline_)\n    parser.add_argument(\"-n\", \"--no-pager\", action=\"store_true\", help=\"do not use the pager.\")\n    _syntax_ = parser.format_help()\n\n    def __init__(self):\n        super().__init__(prefix=False)\n        return\n\n    @parse_args\n    def do_invoke(self, args):\n        width = max(len(x) for x in __gef_alias_instances__.keys())\n\n        self.out = []\n        self.out.append(titlify(\"Pre-defined aliases\"))\n        for _, a in sorted(__gef_alias_instances__.items(), key=lambda x:x[0]):\n            if a._pre_defined_:\n                self.out.append(\"{:{:d}s}  ->  {:s}\".format(a._alias_, width, a._command_))\n\n        self.out.append(titlify(\"User defined aliases\"))\n        for _, a in sorted(__gef_alias_instances__.items(), key=lambda x:x[0]):\n            if not a._pre_defined_:\n                self.out.append(\"{:{:d}s}  ->  {:s}\".format(a._alias_, width, a._command_))\n\n        self.print_output(check_terminal_size=True)\n        return\n\n\nclass GefUtil:\n    \"\"\"A collection of utility functions that are related to GEF basic features.\"\"\"\n\n    @staticmethod\n    @Cache.cache_until_next\n    def cached_lookup_type(_type):\n        \"\"\"Look up a GDB type by name and strip typedefs, returning None on failure.\"\"\"\n        try:\n            return gdb.lookup_type(_type).strip_typedefs()\n        except RuntimeError:\n            return None\n\n    @staticmethod\n    def get_tqdm(use_tqdm=True):\n        \"\"\"Return the tqdm progress bar if available and enabled;\n        otherwise returns a passthrough function.\"\"\"\n        tqdm = lambda x, leave=None, total=None, desc=None: x # noqa: F841\n        if not use_tqdm:\n            return tqdm\n        try:\n            from tqdm import tqdm\n        except ImportError:\n            pass\n        return tqdm\n\n    __gef_convenience_vars_index__ = 0 # $_gef1, $_gef2, ...\n\n    @staticmethod\n    def gef_convenience(value):\n        \"\"\"Define a new convenience value.\"\"\"\n        var_name = \"$_gef{:d}\".format(GefUtil.__gef_convenience_vars_index__)\n        GefUtil.__gef_convenience_vars_index__ += 1\n        gdb.execute('set {:s} = \"{:s}\"'.format(var_name, value))\n        return var_name\n\n    class ArgparseExitProxyException(Exception):\n        pass\n\n    @staticmethod\n    def get_terminal_size(redirect=\"\"):\n        \"\"\"Return the current terminal size.\"\"\"\n        if redirect and os.getenv(\"TMUX\"):\n            res = subprocess.check_output([\n                GefUtil.which(\"tmux\"), \"list-panes\", \"-F#{pane_tty}:#{pane_height}:#{pane_width}\",\n            ]).decode(\"utf-8\").strip()\n\n            for line in res.splitlines():\n                tty, height, width = line.split(\":\")\n                if tty == redirect:\n                    return int(height), int(width)\n\n        try:\n            tty_columns, tty_rows = os.get_terminal_size()\n            return tty_rows, tty_columns\n        except OSError:\n            return 600, 100\n\n    @staticmethod\n    def get_source(function):\n        \"\"\"Return the source of function.\"\"\"\n        import inspect\n        s = inspect.getsource(function)\n        return s.rstrip()\n\n    @staticmethod\n    @Cache.cache_this_session\n    def log2(x):\n        import math\n        return int(math.log2(x))\n\n    @staticmethod\n    def fromhex_ignore_invalid(value, to_str=False):\n        \"\"\"Convert a hex string to bytes or string, ignoring invalid characters.\"\"\"\n        sanitized_value = \"\"\n        for c in value.lower():\n            if c in \"0123456789abcdef\":\n                sanitized_value += c\n        if len(sanitized_value) % 2 != 0:\n            err(\"Hex value length is odd\")\n            return None\n        if to_str:\n            values = [\"\\\\x\" + hh for hh in slicer(sanitized_value, 2)]\n            values = \"\".join(values)\n        else:\n            values = bytes.fromhex(sanitized_value)\n        return values\n\n    @staticmethod\n    @Cache.cache_this_session\n    def which(program):\n        \"\"\"Locate a command on the filesystem.\"\"\"\n\n        def is_exe(fpath):\n            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)\n\n        if not program:\n            raise FileNotFoundError(\"Missing program name\")\n\n        if os.path.split(program)[0]: # check dirname\n            if is_exe(program):\n                return program\n        else:\n            # search from PATH\n            env_path_default = \"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"\n            env_path = os.getenv(\"PATH\", env_path_default)\n            env_path = env_path.split(os.pathsep)\n\n            if hasattr(Gef, \"GEF_VENV_BIN_PATH\"):\n                env_path.insert(0, Gef.GEF_VENV_BIN_PATH)\n\n            if \"/usr/local/bin\" not in env_path:\n                env_path.insert(0, \"/usr/local/bin\") # for rp-lin, vmlinux-to-elf\n\n            for path in env_path:\n                exe_file = os.path.join(path.strip('\"'), program)\n                if is_exe(exe_file):\n                    return exe_file\n\n        raise FileNotFoundError(\"Missing file `{:s}`\".format(program))\n\n    @staticmethod\n    def show_last_exception():\n        \"\"\"Display the last Python exception.\"\"\"\n\n        def _show_code_line(fname, idx):\n            fname = os.path.expanduser(os.path.expandvars(fname))\n            __data = open(fname, \"r\").read().splitlines()\n            return __data[idx - 1] if idx < len(__data) else \"\"\n\n        gef_print(\"\")\n        exc_type, exc_value, exc_traceback = sys.exc_info()\n\n        HORIZONTAL_LINE = \"-\"\n        gef_print(\" Exception raised \".center(80, HORIZONTAL_LINE))\n        gef_print(\"{}: {}\".format(Color.colorify(exc_type.__name__, \"bold red underline\"), exc_value))\n        gef_print(\" Detailed stacktrace \".center(80, HORIZONTAL_LINE))\n\n        for fs in traceback.extract_tb(exc_traceback)[::-1]:\n            filename, lineno, method, code = fs\n\n            if not code or not code.strip():\n                code = _show_code_line(filename, lineno)\n\n            filename_c = Color.yellowify(filename)\n            method_c = Color.greenify(method)\n            gef_print('File \"{}\", line {:d}, in {}()'.format(filename_c, lineno, method_c))\n            gef_print(\"    ->     {}\".format(code))\n\n        gef_print(\" Last 10 GDB commands \".center(80, HORIZONTAL_LINE))\n        gdb.execute(\"show commands\")\n        gef_print(\" Runtime environment \".center(80, HORIZONTAL_LINE))\n        gdb.execute(\"gef version --compact\")\n        gef_print(HORIZONTAL_LINE * 80)\n        gef_print(\"\")\n        return\n\n    @staticmethod\n    def gef_execute_external(command, as_list=False, *args, **kwargs):\n        \"\"\"Execute an external command and return the result.\"\"\"\n        env = os.environ.copy()\n        env[\"LANG\"] = \"C\"\n\n        res = subprocess.check_output(\n            command, stderr=subprocess.STDOUT, env=env,\n            shell=kwargs.get(\"shell\", False),\n        )\n        if as_list:\n            return [String.bytes2str(x) for x in res.splitlines()]\n        return String.bytes2str(res)\n\n    @staticmethod\n    def walk(directory):\n        \"\"\"Return all file path excluding directories and symbolic links.\"\"\"\n        for root, _dirs, files in os.walk(directory):\n            for f in sorted(files):\n                path = os.path.join(root, f)\n                if os.path.islink(path):\n                    continue\n                yield path\n        return\n\n    @staticmethod\n    def now_str():\n        \"\"\"Return formatted time.\"\"\"\n        dt = datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n        return dt\n\n    @staticmethod\n    def mkstemp(prefix=\"\", dir=None, suffix=None, dt=None):\n        \"\"\"Create a temporary file.\"\"\"\n        if dt is None:\n            dt = GefUtil.now_str()\n\n        s = []\n        if prefix:\n            s.append(prefix)\n        if dt:\n            s.append(dt)\n        real_prefix = \"-\".join(s)\n        if real_prefix:\n            real_prefix += \"-\"\n\n        if dir is None:\n            dir = GEF_TEMP_DIR\n        return tempfile.mkstemp(dir=dir, prefix=real_prefix, suffix=suffix)\n\n    @staticmethod\n    def rmdir(directory, verbose=False, keep_root=False):\n        \"\"\"Recursively delete the target directory.\"\"\"\n        for root, dirs, files in os.walk(directory, topdown=False):\n            for file in files:\n                file_path = os.path.join(root, file)\n                if verbose:\n                    info(\"Removed: {:s}\".format(file_path))\n                os.remove(file_path)\n\n            for dir in dirs:\n                dir_path = os.path.join(root, dir)\n                if verbose:\n                    info(\"Removed: {:s}\".format(dir_path))\n                os.rmdir(dir_path)\n\n        if not keep_root:\n            os.rmdir(directory)\n        return\n\n    @staticmethod\n    def make_legend(msg):\n        \"\"\"Apply color settings and generate legend string.\"\"\"\n        color = Config.get_gef_setting(\"theme.table_heading\")\n        return Color.colorify(msg.rstrip(), color)\n\n    @staticmethod\n    def get_size_str(size, enable_color=True):\n        if 0 <= size < 1024:\n            return \"{:5.1f} B\".format(size)\n        elif 1024 <= size < 1024 ** 2:\n            return \"{:5.1f} KB\".format(size / 1024)\n        elif 1024 ** 2 <= size < 100 * (1024 ** 2): # 1MB~100MB\n            return \"{:5.1f} MB\".format(size / 1024 / 1024)\n        elif 100 * (1024 ** 2) <= size < 1024 ** 3: # 100MB~1GB\n            if enable_color:\n                return Color.colorify(\"{:5.1f} MB\".format(size / 1024 / 1024), \"bold yellow\")\n            else:\n                return \"{:5.1f} MB\".format(size / 1024 / 1024)\n        elif 1024 ** 3 <= size:\n            if enable_color:\n                return Color.colorify(\"{:5.1f} GB\".format(size / 1024 / 1024 / 1024), \"bold red\")\n            else:\n                return \"{:5.1f} GB\".format(size / 1024 / 1024 / 1024)\n        return \"???\"\n\n\nclass Gef:\n    \"\"\"A collection of utility functions that are related to GEF start up.\"\"\"\n\n    missing_commands = {}\n\n    @staticmethod\n    def list_current_commands():\n        command_list = []\n        res = gdb.execute(\"help all\", to_string=True)\n        for line in res.splitlines():\n            line = line.strip()\n            if \" -- \" not in line:\n                continue\n            commands = line.split(\" -- \")[0]\n            commands = commands.split(\", \")\n            command_list.extend(commands)\n        return command_list\n\n    @staticmethod\n    def load_commands():\n        \"\"\"Load all the commands and functions defined by GEF into GDB.\"\"\"\n        global __gef_command_instances__\n\n        DEBUG_PERF_TIME = False\n        DEBUG_CHECK_COMMAND_CONFLICT = False\n\n        if DEBUG_CHECK_COMMAND_CONFLICT:\n            loaded_commands = Gef.list_current_commands()\n            FIRST_TIME = \"gef reload\" not in loaded_commands # skip check when `gef reload`\n\n        nb_missing = 0\n        time_elapsed = []\n        for cmd_class in __gef_commands__:\n            try:\n                if DEBUG_PERF_TIME:\n                    start_time_real = time.perf_counter()\n                    start_time_proc = time.process_time()\n\n                if DEBUG_CHECK_COMMAND_CONFLICT and FIRST_TIME:\n                    if cmd_class._cmdline_ in loaded_commands:\n                        warn(\"{:s} is already loaded\".format(Color.boldify(cmd_class._cmdline_)))\n\n                instance = cmd_class() # command loading is here\n                __gef_command_instances__[cmd_class._cmdline_] = instance\n\n                if DEBUG_PERF_TIME:\n                    end_time_real = time.perf_counter()\n                    end_time_proc = time.process_time()\n\n                    time_elapsed.append((\n                        cmd_class._cmdline_,\n                        end_time_real - start_time_real,\n                        end_time_proc - start_time_proc,\n                    ))\n\n                if hasattr(cmd_class._aliases_, \"__iter__\"):\n                    if isinstance(cmd_class._aliases_, str):\n                        cmd_class_aliases = [cmd_class._aliases_]\n                    elif isinstance(cmd_class._aliases_, list):\n                        cmd_class_aliases = cmd_class._aliases_\n                    else:\n                        cmd_class_aliases = []\n\n                    for alias in cmd_class_aliases:\n                        if DEBUG_CHECK_COMMAND_CONFLICT and FIRST_TIME:\n                            if alias in loaded_commands:\n                                warn(\"{:s} is already loaded\".format(Color.boldify(alias)))\n                        GefAlias(alias, cmd_class._cmdline_, pre_defined=True)\n\n            except Exception as reason:\n                Gef.missing_commands[cmd_class._cmdline_] = reason\n                nb_missing += 1\n\n        if DEBUG_PERF_TIME:\n            gef_print(titlify(\"Top 10 commands that took the longest to load\"))\n            for cmdline, real, cpu in sorted(time_elapsed, key=lambda x: x[1], reverse=True)[:10]:\n                gef_print(\"{:30s} Real:{:.10f} s, CPU:{:.10f} s\".format(cmdline, real, cpu))\n            gef_print(titlify(\"\"))\n\n        # print message\n        gef_print(\"{:s} is ready, type '{:s}' to start, '{:s}' to configure\".format(\n            Color.greenify(\"GEF\"),\n            Color.colorify(\"gef\", \"underline yellow\"),\n            Color.colorify(\"gef config\", \"underline magenta\")\n        ))\n\n        ver = \"{:d}.{:d}\".format(sys.version_info.major, sys.version_info.minor)\n        gef_print(\"Loaded {:s} commands (+{:s} aliases) for GDB {:s} using Python engine {:s}\".format(\n            Color.colorify(len(__gef_command_instances__), \"bold green\"),\n            Color.colorify(len(__gef_alias_instances__), \"bold green\"),\n            Color.colorify(gdb.VERSION, \"bold yellow\"),\n            Color.colorify(ver, \"bold red\")\n        ))\n\n        if nb_missing:\n            warn(\"{:s} command{} could not be loaded, run `{:s}` to know why.\".format(\n                Color.colorify(nb_missing, \"bold red\"),\n                \"s\" if nb_missing > 1 else \"\",\n                Color.colorify(\"gef missing\", \"underline magenta\")\n            ))\n        return\n\n    @staticmethod\n    def gef_prompt(_current_prompt):\n        \"\"\"GEF custom prompt function.\"\"\"\n        if Config.get_gef_setting(\"gef.readline_compat\") is True:\n            return \"gef> \"\n        if Color.disable_color():\n            return \"gef> \"\n        if is_alive():\n            return \"\\001\\033[1;32m\\002gef> \\001\\033[0m\\002\"\n        return \"\\001\\033[1;31m\\002gef> \\001\\033[0m\\002\"\n\n    @staticmethod\n    def fix_venv():\n        \"\"\"Detect if you are in a venv environment and adjust GEF settings.\"\"\"\n\n        def fast_path():\n            \"\"\"If you installed it with the latest installer, there should be a gev.venv.conf file.\n            Interpreting this file will speed up the process.\"\"\"\n            gef_venv_conf = os.path.join(os.path.dirname(GEF_FILEPATH), \"gef.venv.conf\")\n            if not os.path.exists(gef_venv_conf):\n                return False\n\n            content = open(gef_venv_conf, \"rb\").read().decode()\n            for line in content.splitlines():\n                if line.startswith(\"GEF_VENV_SYS_PATH=\"):\n                    Gef.GEF_VENV_SYS_PATH = line[len(\"GEF_VENV_SYS_PATH=\"):]\n                    to_add = []\n                    for path in Gef.GEF_VENV_SYS_PATH.split(\":\"):\n                        if path and path not in sys.path:\n                            to_add.append(path)\n                    sys.path = to_add + sys.path\n                    continue\n\n                if line.startswith(\"GEF_VENV_BIN_PATH=\"):\n                    Gef.GEF_VENV_BIN_PATH = line[len(\"GEF_VENV_BIN_PATH=\"):] # used by GefUtil.which()\n                    continue\n\n                if line.startswith(\"GEF_VENV_GEM_HOME=\"):\n                    Gef.GEF_VENV_GEM_HOME = line[len(\"GEF_VENV_GEM_HOME=\"):]\n                    os.environ[\"GEM_HOME\"] = Gef.GEF_VENV_GEM_HOME\n                    continue\n\n            if hasattr(Gef, \"GEF_VENV_SYS_PATH\"):\n                return True\n            return False\n\n        def create_skip_config():\n            # If .venv-gef is in the default location, it is likely that the user simply forgot to activate the venv.\n            # Therefore, for convenience, skip-venv-check is not created.\n            default_venv = os.path.join(os.path.dirname(GEF_FILEPATH), \".venv-gef\")\n            if os.path.exists(default_venv):\n                return\n\n            skip_config = os.path.join(GEF_TEMP_DIR, \"skip-venv-check\")\n            open(skip_config, \"w\").close()\n            return\n\n        def slow_path():\n            \"\"\"For those who used the old installer or installed manually.\n            It launches python via shell and collects and imports its configuration.\"\"\"\n            # venv check is very slow, so skip if unneeded\n            skip_config = os.path.join(GEF_TEMP_DIR, \"skip-venv-check\")\n            if os.path.exists(skip_config):\n                return\n\n            # GEF supports pyenv, venv, uv, etc.\n            # To achieve this, you need to run python outside of gdb.\n            # Modify sys.path based on the results of the execution.\n\n            # check python3 command to get prefix\n            try:\n                pythonbin = GefUtil.which(\"python3\")\n            except FileNotFoundError:\n                create_skip_config()\n                return\n\n            # check prefix\n            cmds = [pythonbin, \"-c\", \"import os,sys;print(sys.prefix)\"]\n            PREFIX = subprocess.check_output(cmds).decode(\"utf-8\").strip()\n            if PREFIX == sys.base_prefix:\n                create_skip_config()\n                return\n\n            # add path\n            cmds = [pythonbin, \"-c\", \"import os,sys;print(os.linesep.join(sys.path).strip())\"]\n            SITE_PACKAGES_DIRS = subprocess.check_output(cmds).decode(\"utf-8\").split()\n            to_add = []\n            for path in SITE_PACKAGES_DIRS:\n                if path not in sys.path:\n                    to_add.append(path)\n            sys.path = to_add + sys.path\n            return\n\n        fast_path() or slow_path()\n        return\n\n    @staticmethod\n    def main():\n        # check gdb version\n        GDB_VERSION = tuple(map(int, re.search(r\"(\\d+)[^\\d]+(\\d+)\", gdb.VERSION).groups()))\n        GDB_MIN_VERSION = (9, 2) # ubuntu 20.04\n        if GDB_VERSION < GDB_MIN_VERSION:\n            err(\"GDB version ({:s}) is too old (<{:d}.{:d}). Try upgrading it.\".format(\n                gdb.VERSION, GDB_MIN_VERSION[0], GDB_MIN_VERSION[1],\n            ))\n            return\n\n        # create tmp dir\n        if not os.path.exists(GEF_TEMP_DIR):\n            os.mkdir(GEF_TEMP_DIR) # 0o755\n            # GEF runs with root privileges, but it may attach to a normal privileges program.\n            # If you want to execute a command that involves stdout redirection for that program,\n            # you will need write permission to /tmp/gef.\n            os.chmod(GEF_TEMP_DIR, 0o777)\n\n        # check tmp dir access permission\n        # This check takes into account the cases where GEF is run with root privileges and with normal user privileges.\n        if not os.access(GEF_TEMP_DIR, os.W_OK|os.R_OK|os.X_OK):\n            err(\"Permission denied to {:s}. Please delete it first.\".format(GEF_TEMP_DIR))\n            return\n\n        # When using a python virtual environment (pyenv, venv, etc.), GDB still loads\n        # the system-installed python, so GEF doesn't load site-packages dir from environment.\n        # In order to fix it, from the shell we run the python3 binary,\n        # take and parse its path, add the path to the current python process.\n        Gef.fix_venv()\n\n        # setup prompt\n        gdb.prompt_hook = Gef.gef_prompt # noqa\n\n        # common config\n        gdb.execute(\"set confirm off\")\n        gdb.execute(\"set verbose off\")\n        gdb.execute(\"set pagination off\")\n        gdb.execute(\"set output-radix 0x10\")\n\n        # gdb history\n        gdb.execute(\"set history save on\")\n        gdb.execute(\"set history size 1000\")\n        gdb.execute(\"set history filename ~/.gdb_history\")\n\n        # print\n        gdb.execute(\"set print elements 0\") # remove element count limit\n        gdb.execute(\"set print pretty on\")\n        gdb.execute(\"set print array on\") # use multi-line when print\n        gdb.execute(\"set print array-indexes on\") # add index when print\n        gdb.execute(\"set print asm-demangle on\") # demangle\n        gdb.execute(\"set print object on\")\n        gdb.execute(\"set print vtbl on\")\n\n        try:\n            # this will raise a gdb.error unless we're on x86\n            gdb.execute(\"set disassembly-flavor intel\")\n        except gdb.error:\n            # we can safely ignore this\n            pass\n\n        # SIGALRM will simply display a message, but gdb won't forward the signal to the process\n        gdb.execute(\"handle SIGALRM print nopass\")\n\n        # SIGSEGV/SIGTERM/SIG32(for thread creation)\n        gdb.execute(\"handle SIGSEGV print nopass\")\n        gdb.execute(\"handle SIGTERM print nopass\")\n        gdb.execute(\"handle SIG32 nostop\")\n\n        # stops at first instruction of functions without debug info when stepping\n        gdb.execute(\"set step-mode on\")\n\n        # frame\n        gdb.execute(\"set backtrace past-main on\")\n        gdb.execute(\"set print frame-arguments all\")\n\n        # load all commands that has @register_command decorator.\n        Gef.load_commands()\n\n        # load the saved settings\n        gdb.execute(\"gef restore\")\n\n        # follow mode\n        if Config.get_gef_setting(\"gef.follow_child\"):\n            gdb.execute(\"set follow-fork-mode child\")\n\n        # index file\n        gdb.execute(\"save gdb-index {:s}\".format(GEF_TEMP_DIR)) # don't use {!r}\n\n        # gdb events configuration\n        EventHooking.gef_on_continue_hook(EventHandler.continue_handler)\n        EventHooking.gef_on_stop_hook(EventHandler.hook_stop_handler)\n        EventHooking.gef_on_new_hook(EventHandler.new_objfile_handler)\n        EventHooking.gef_on_exit_hook(EventHandler.exit_handler)\n        EventHooking.gef_on_memchanged_hook(EventHandler.memchanged_handler)\n        EventHooking.gef_on_regchanged_hook(EventHandler.regchanged_handler)\n\n        if gdb.current_progspace().filename is not None:\n            # if here, we are sourcing gef from a gdb session already attached\n            # we must force a call to the new_objfile handler\n            EventHandler.new_objfile_handler(None)\n\n        # python-interactive\n        hexon()\n\n        # If GEF is loaded after gdb is connected\n        if is_alive():\n            if current_arch is None:\n                set_arch(get_arch())\n        return\n\n\nif __name__ == \"__main__\":\n    Gef.main()\n"
  },
  {
    "path": "install-minimal.sh",
    "content": "#!/bin/sh -ex\n\necho \"[+] Initialize\"\nGDBINIT_PATH=\"/root/.gdbinit\"\nGEF_DIR=\"/root/.gef\"\nGEF_PATH=\"${GEF_DIR}/gef.py\"\n\necho \"[+] User check\"\nif [ \"$(id -u)\" != \"0\" ]; then\n    echo \"[-] Detected non-root user.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Check if another gef is installed\"\nif [ -e \"${GEF_PATH}\" ]; then\n    echo \"[-] ${GEF_PATH} already exists. Please delete or rename.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Create .gef directory\"\nif [ ! -e \"${GEF_DIR}\" ]; then\n    mkdir -p \"${GEF_DIR}\"\nfi\n\necho \"[+] Download gef\"\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/gef.py -O \"${GEF_PATH}\"\nif [ ! -s \"${GEF_PATH}\" ]; then\n    echo \"[-] Downloading ${GEF_PATH} failed.\"\n    rm -f \"${GEF_PATH}\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Setup gef\"\nSTARTUP_COMMAND=\"python sys.path.insert(0, \\\"${GEF_DIR}\\\"); from gef import *; Gef.main()\"\nif [ ! -e \"${GDBINIT_PATH}\" ] || [ -z \"$(grep \"from gef import\" \"${GDBINIT_PATH}\")\" ]; then\n    echo \"${STARTUP_COMMAND}\" >> \"${GDBINIT_PATH}\"\nfi\n\necho \"[+] INSTALLATION SUCCESSFUL\"\nexit 0\n"
  },
  {
    "path": "install-no-uv.sh",
    "content": "#!/bin/sh -ex\n\necho \"[+] Initialize\"\nGDBINIT_PATH=\"/root/.gdbinit\"\nGEF_DIR=\"/root/.gef\"\nGEF_PATH=\"${GEF_DIR}/gef.py\"\n\necho \"[+] User check\"\nif [ \"$(id -u)\" != \"0\" ]; then\n    echo \"[-] Detected non-root user.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Check if another gef is installed\"\nif [ -e \"${GEF_PATH}\" ]; then\n    echo \"[-] ${GEF_PATH} already exists. Please delete or rename.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Create .gef directory\"\nif [ ! -e \"${GEF_DIR}\" ]; then\n    mkdir -p \"${GEF_DIR}\"\nfi\n\necho \"[+] apt\"\napt-get update\nDEBIAN_FRONTEND=noninteractive apt-get install -y tzdata\napt-get install -y gdb-multiarch wget unzip\napt-get install -y binutils python3-pip ruby-dev git file colordiff imagemagick\n\n# Since installing bpftool fails inside a container, it is excluded.\nif [ ! -f /.dockerenv ]; then\n    apt-get install -y bpftool\nfi\n\n# Installing binwalk requires a large number of packages and takes a significant amount of time,\n# so please enable it only when necessary.\n#apt-get install -y binwalk\n\necho \"[+] pip3\"\npip3 install setuptools crccheck unicorn capstone ropper keystone-engine tqdm magika codext angr pillow pyzbar\n\n# The GEF installer installs `seccomp-tools` if neither `ceccomp` nor `seccomp-tools` is found.\n# I recomend `ceccomp`, but its build is not simple. Install it manually if needed.\necho \"[+] Install seccomp-tools\"\nif [ -z \"$(command -v seccomp-tools)\" ] && [ -z \"$(command -v ceccomp)\" ]; then\n    gem install seccomp-tools\nfi\n\necho \"[+] Install one_gadget\"\nif [ -z \"$(command -v one_gadget)\" ]; then\n    gem install one_gadget\nfi\n\necho \"[+] Install rp++\"\nif [ \"$(uname -m)\" = \"x86_64\" ]; then\n    if [ -z \"$(command -v rp-lin)\" ] && [ ! -e /usr/local/bin/rp-lin ]; then\n        wget -q https://github.com/0vercl0k/rp/releases/download/v2.1.5/rp-lin-clang.zip -P /tmp\n        unzip /tmp/rp-lin-clang.zip -d /usr/local/bin/\n        rm /tmp/rp-lin-clang.zip\n    fi\nfi\n\necho \"[+] Download gef\"\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/gef.py -O \"${GEF_PATH}\"\nif [ ! -s \"${GEF_PATH}\" ]; then\n    echo \"[-] Downloading ${GEF_PATH} failed.\"\n    rm -f \"${GEF_PATH}\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Setup gef\"\nSTARTUP_COMMAND=\"python sys.path.insert(0, \\\"${GEF_DIR}\\\"); from gef import *; Gef.main()\"\nif [ ! -e \"${GDBINIT_PATH}\" ] || [ -z \"$(grep \"from gef import\" \"${GDBINIT_PATH}\")\" ]; then\n    echo \"${STARTUP_COMMAND}\" >> \"${GDBINIT_PATH}\"\nfi\n\necho \"[+] INSTALLATION SUCCESSFUL\"\nexit 0\n"
  },
  {
    "path": "install-uv.sh",
    "content": "#!/bin/sh -ex\n\necho \"[+] Initialize\"\nGDBINIT_PATH=\"/root/.gdbinit\"\nGEF_DIR=\"/root/.gef\"\nGEF_PATH=\"${GEF_DIR}/gef.py\"\nGEF_VENV_CONF_PATH=\"${GEF_DIR}/gef.venv.conf\"\nGEF_VENV_PATH=\"${GEF_DIR}/.venv-gef\"\nGEF_VENV_BIN_PATH=\"${GEF_VENV_PATH}/bin\"\n\necho \"[+] User check\"\nif [ \"$(id -u)\" != \"0\" ]; then\n    echo \"[-] Detected non-root user.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Check if another gef is installed\"\nif [ -e \"${GEF_PATH}\" ]; then\n    echo \"[-] ${GEF_PATH} already exists. Please delete or rename.\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Create .gef directory\"\nif [ ! -e \"${GEF_DIR}\" ]; then\n    mkdir -p \"${GEF_DIR}\"\nfi\n\necho \"[+] apt\"\napt-get update\nDEBIAN_FRONTEND=noninteractive apt-get install -y tzdata\napt-get install -y gdb-multiarch wget unzip\napt-get install -y binutils python3-dev gcc make ruby-dev git file colordiff imagemagick\n\n# Since installing bpftool fails inside a container, it is excluded.\nif [ ! -f /.dockerenv ]; then\n    apt-get install -y bpftool\nfi\n\n# Installing binwalk requires a large number of packages and takes a significant amount of time,\n# so please enable it only when necessary.\n#apt-get install -y binwalk\n\necho \"[+] Install uv\"\nif [ -z \"$(command -v uv)\" ]; then\n    wget -qO- https://astral.sh/uv/install.sh | sh\n    . $HOME/.local/bin/env\nfi\n\necho \"[+] Setup venv\"\nif [ ! -e \"${GEF_VENV_PATH}\" ]; then\n    uv venv \"${GEF_VENV_PATH}\"\nfi\n. \"${GEF_VENV_PATH}/bin/activate\"\n\necho \"[+] pip3\"\nuv pip install setuptools crccheck unicorn capstone ropper keystone-engine tqdm magika codext angr pillow pyzbar\n\n# The GEF installer installs `seccomp-tools` if neither `ceccomp` nor `seccomp-tools` is found.\n# I recomend `ceccomp`, but its build is not simple. Install it manually if needed.\necho \"[+] Install seccomp-tools\"\nif [ -z \"$(command -v seccomp-tools)\" ] && [ -z \"$(command -v ceccomp)\" ]; then\n    gem install -i \"${GEF_VENV_PATH}\" seccomp-tools\nfi\n\necho \"[+] Install one_gadget\"\nif [ -z \"$(command -v one_gadget)\" ]; then\n    gem install -i \"${GEF_VENV_PATH}\" one_gadget\nfi\n\necho \"[+] Install rp++\"\nif [ \"$(uname -m)\" = \"x86_64\" ]; then\n    if [ -z \"$(command -v rp-lin)\" ]; then\n        wget -q https://github.com/0vercl0k/rp/releases/download/v2.1.5/rp-lin-clang.zip -P /tmp\n        unzip /tmp/rp-lin-clang.zip -d \"${GEF_VENV_BIN_PATH}\"\n        rm /tmp/rp-lin-clang.zip\n    fi\nfi\n\necho \"[+] Download gef\"\nwget -q https://raw.githubusercontent.com/bata24/gef/dev/gef.py -O \"${GEF_PATH}\"\nif [ ! -s \"${GEF_PATH}\" ]; then\n    echo \"[-] Downloading ${GEF_PATH} failed.\"\n    rm -f \"${GEF_PATH}\"\n    echo \"[-] INSTALLATION FAILED\"\n    exit 1\nfi\n\necho \"[+] Setup gef\"\nSTARTUP_COMMAND=\"python sys.path.insert(0, \\\"${GEF_DIR}\\\"); from gef import *; Gef.main()\"\nif [ ! -e \"${GDBINIT_PATH}\" ] || [ -z \"$(grep \"from gef import\" \"${GDBINIT_PATH}\")\" ]; then\n    echo \"${STARTUP_COMMAND}\" >> \"${GDBINIT_PATH}\"\nfi\n\necho \"[+] Setup venv path hint file\"\nGEF_VENV_SYS_PATH=$(python3 -c 'import sys,subprocess;a=subprocess.getoutput(\"gdb-multiarch -q -nx -ex \\\"pi sys.path\\\" -ex q\");print(\":\".join(set(sys.path)-set(eval(a))-set([\"\"])))')\necho \"GEF_VENV_GEM_HOME=${GEF_VENV_PATH}\" >> ${GEF_VENV_CONF_PATH}\necho \"GEF_VENV_SYS_PATH=${GEF_VENV_SYS_PATH}\" >> ${GEF_VENV_CONF_PATH}\necho \"GEF_VENV_BIN_PATH=${GEF_VENV_BIN_PATH}\" >> ${GEF_VENV_CONF_PATH}\n\necho \"[+] INSTALLATION SUCCESSFUL\"\nexit 0\n"
  }
]